use of com.oracle.truffle.api.debug.DebugException in project graal by oracle.
the class InspectorRuntime method evaluate.
@Override
public Params evaluate(String expression, String objectGroup, boolean includeCommandLineAPI, boolean silent, int contextId, boolean returnByValue, boolean generatePreview, boolean awaitPromise) throws CommandProcessException {
if (expression == null) {
throw new CommandProcessException("An expression required.");
}
JSONObject json = new JSONObject();
DebuggerSuspendedInfo suspendedInfo = context.getSuspendedInfo();
if (suspendedInfo != null) {
try {
context.executeInSuspendThread(new SuspendThreadExecutable<Void>() {
@Override
public Void executeCommand() throws CommandProcessException {
suspendedInfo.lastEvaluatedValue.set(null);
LanguageInfo languageInfo = context.getSuspendedInfo().getSuspendedEvent().getTopStackFrame().getLanguage();
if (languageInfo == null || !languageInfo.isInteractive()) {
fillExceptionDetails(json, InspectorDebugger.getEvalNonInteractiveMessage());
return null;
}
JSONObject result;
DebugValue value = null;
if (suspendedInfo.getCallFrames().length > 0) {
value = InspectorDebugger.getVarValue(expression, suspendedInfo.getCallFrames()[0]);
}
if (value == null) {
value = suspendedInfo.getSuspendedEvent().getTopStackFrame().eval(expression);
suspendedInfo.refreshFrames();
}
if (returnByValue) {
result = RemoteObject.createJSONResultValue(value, context.areToStringSideEffectsAllowed(), context.getErr());
} else {
RemoteObject ro = new RemoteObject(value, generatePreview, context);
context.getRemoteObjectsHandler().register(ro, objectGroup);
result = ro.toJSON();
if (!ro.isReplicable()) {
suspendedInfo.lastEvaluatedValue.set(Pair.create(value, ro.getRawValue()));
}
}
json.put("result", result);
return null;
}
@Override
public Void processException(DebugException ex) {
fillExceptionDetails(json, ex);
return null;
}
});
} catch (NoSuspendedThreadException ex) {
fillExceptionDetails(json, ex.getLocalizedMessage());
}
} else {
fillExceptionDetails(json, "<Not suspended>");
}
return new Params(json);
}
use of com.oracle.truffle.api.debug.DebugException in project graal by oracle.
the class InspectorRuntime method callFunctionOn.
@Override
public Params callFunctionOn(String objectId, String functionDeclaration, JSONArray arguments, boolean silent, boolean returnByValue, boolean generatePreview, boolean awaitPromise, int executionContextId, String objectGroup) throws CommandProcessException {
if (objectId == null) {
throw new CommandProcessException("An objectId required.");
}
RemoteObject object = context.getRemoteObjectsHandler().getRemote(objectId);
JSONObject json = new JSONObject();
if (object != null) {
DebugValue value = object.getDebugValue();
DebugScope scope = object.getScope();
RemoteObject.IndexRange indexRange = object.getIndexRange();
DebuggerSuspendedInfo suspendedInfo = context.getSuspendedInfo();
if (suspendedInfo != null) {
try {
String functionTrimmed = functionDeclaration.trim();
String functionNoWS = eliminateWhiteSpaces(functionDeclaration);
context.executeInSuspendThread(new SuspendThreadExecutable<Void>() {
@Override
public Void executeCommand() throws CommandProcessException {
JSONObject result;
if (functionNoWS.startsWith(FUNCTION_COMPLETION)) {
result = createCodecompletion(value, scope, context, true);
} else if (functionNoWS.equals(FUNCTION_SET_PROPERTY)) {
// Set of an array element, or object property
if (arguments == null || arguments.length() < 2) {
throw new CommandProcessException("Insufficient number of arguments: " + (arguments != null ? arguments.length() : 0) + ", expecting: 2");
}
Object property = ((JSONObject) arguments.get(0)).get("value");
CallArgument newValue = CallArgument.get((JSONObject) arguments.get(1));
setPropertyValue(value, scope, property, object.getTypeMark(), newValue, suspendedInfo.lastEvaluatedValue.getAndSet(null));
result = new JSONObject();
} else if (functionNoWS.equals(FUNCTION_GET_ARRAY_NUM_PROPS)) {
if (!value.isArray()) {
throw new CommandProcessException("Expecting an Array the function is called on.");
}
JSONArray arr = new JSONArray();
if (indexRange != null && !indexRange.isNamed()) {
List<DebugValue> array = value.getArray();
if (indexRange.start() < 0 || indexRange.end() > array.size()) {
throw new CommandProcessException("Array range out of bounds.");
}
arr.put(indexRange.end() - indexRange.start());
} else {
arr.put(value.getArray().size());
}
Collection<DebugValue> props = value.getProperties();
if (props == null) {
arr.put(0);
} else if (indexRange != null && indexRange.isNamed()) {
ArrayList<DebugValue> list = new ArrayList<>(props);
if (indexRange.start() < 0 || indexRange.end() > list.size()) {
throw new CommandProcessException("Named range out of bounds.");
}
arr.put(indexRange.end() - indexRange.start());
} else if (LanguageChecks.isJS(value.getOriginalLanguage())) {
// +1 for __proto__
arr.put(props.size() + 1);
} else {
arr.put(props.size());
}
result = new JSONObject();
result.put("value", arr);
} else if (functionNoWS.equals(FUNCTION_GET_BUFFER_NUM_PROPS)) {
if (!value.isArray()) {
throw new CommandProcessException("Expecting a Buffer the function is called on.");
}
JSONArray arr = new JSONArray();
if (indexRange != null && !indexRange.isNamed()) {
List<DebugValue> array = value.getArray();
if (indexRange.start() < 0 || indexRange.end() > array.size()) {
throw new CommandProcessException("Array range out of bounds.");
}
arr.put(indexRange.end() - indexRange.start());
} else {
arr.put(value.getArray().size());
}
if (LanguageChecks.isJS(value.getOriginalLanguage())) {
// +1 for __proto__
arr.put(1);
} else {
arr.put(0);
}
result = new JSONObject();
result.put("value", arr);
} else if (functionNoWS.equals(FUNCTION_GET_COLLECTION_NUM_PROPS)) {
Collection<DebugValue> props = value.getProperties();
if (props == null) {
throw new CommandProcessException("Expecting an Object the function is called on.");
}
JSONArray arr = new JSONArray();
arr.put(0);
if (indexRange != null && indexRange.isNamed()) {
ArrayList<DebugValue> list = new ArrayList<>(props);
if (indexRange.start() < 0 || indexRange.end() > list.size()) {
throw new CommandProcessException("Named range out of bounds.");
}
arr.put(indexRange.end() - indexRange.start());
} else if (LanguageChecks.isJS(value.getOriginalLanguage())) {
// +1 for __proto__
arr.put(props.size() + 1);
} else {
arr.put(props.size());
}
result = new JSONObject();
result.put("value", arr);
} else if (FUNCTION_GETTER_PATTERN1.matcher(functionTrimmed).matches()) {
if (arguments == null || arguments.length() < 1) {
throw new CommandProcessException("Expecting an argument to invokeGetter function.");
}
String propertyNames = ((JSONObject) arguments.get(0)).getString("value");
JSONArray properties = new JSONArray(propertyNames);
DebugValue v = value;
for (int i = 0; i < properties.length() && (i == 0 || v != null); i++) {
String propertyName = properties.getString(i);
if (v != null) {
v = v.getProperty(propertyName);
} else {
v = scope.getDeclaredValue(propertyName);
}
}
result = asResult(v);
} else if (FUNCTION_GETTER_PATTERN2.matcher(functionTrimmed).matches()) {
if (arguments == null || arguments.length() < 1) {
throw new CommandProcessException("Expecting an argument to invokeGetter function.");
}
String propertyName = ((JSONObject) arguments.get(0)).getString("value");
DebugValue p;
if (value != null) {
p = value.getProperty(propertyName);
} else {
p = scope.getDeclaredValue(propertyName);
}
result = asResult(p);
} else if (FUNCTION_GET_INDEXED_VARS_PATTERN.matcher(functionTrimmed).matches()) {
if (!value.isArray()) {
throw new CommandProcessException("Expecting an Array the function is called on.");
}
if (arguments == null || arguments.length() < 2) {
throw new CommandProcessException("Insufficient number of arguments: " + (arguments != null ? arguments.length() : 0) + ", expecting: 2");
}
int start = ((JSONObject) arguments.get(0)).getInt("value");
int count = ((JSONObject) arguments.get(1)).getInt("value");
RemoteObject ro = new RemoteObject(value, true, generatePreview, context, new RemoteObject.IndexRange(start, start + count, false));
context.getRemoteObjectsHandler().register(ro, objectGroup);
result = ro.toJSON();
} else if (FUNCTION_GET_NAMED_VARS_PATTERN.matcher(functionTrimmed).matches()) {
Collection<DebugValue> props = value.getProperties();
if (props == null) {
throw new CommandProcessException("Expecting an Object the function is called on.");
}
if (arguments == null || arguments.length() < 2) {
throw new CommandProcessException("Insufficient number of arguments: " + (arguments != null ? arguments.length() : 0) + ", expecting: 2");
}
int start = ((JSONObject) arguments.get(0)).getInt("value");
int count = ((JSONObject) arguments.get(1)).getInt("value");
RemoteObject ro = new RemoteObject(value, true, generatePreview, context, new RemoteObject.IndexRange(start, start + count, true));
context.getRemoteObjectsHandler().register(ro, objectGroup);
result = ro.toJSON();
} else {
// Process CustomPreview body:
if (arguments != null && arguments.length() > 0) {
Object arg0 = arguments.get(0);
if (arg0 instanceof JSONObject) {
JSONObject argObj = (JSONObject) arg0;
Object id = argObj.opt("objectId");
if (id instanceof String) {
DebugValue body = context.getRemoteObjectsHandler().getCustomPreviewBody((String) id);
if (body != null) {
// The config is not provided as an argument.
// Get the cached config:
DebugValue config = context.getRemoteObjectsHandler().getCustomPreviewConfig(objectId);
DebugValue bodyML = (config != null) ? body.execute(object.getDebugValue(), config) : body.execute(object.getDebugValue());
Object bodyjson = CustomPreview.value2JSON(bodyML, context);
result = new JSONObject();
result.put("type", "object");
result.put("value", bodyjson);
json.put("result", result);
return null;
}
}
}
}
StringBuilder code = new StringBuilder();
code.append("(").append(functionTrimmed).append(").apply(").append(value != null ? value.getName() : "null");
if (arguments != null) {
code.append(",[");
for (int i = 0; i < arguments.length(); i++) {
JSONObject arg = arguments.getJSONObject(i);
if (i > 0) {
code.append(",");
}
Object id = arg.opt("objectId");
if (id instanceof String) {
RemoteObject remoteArg = context.getRemoteObjectsHandler().getRemote((String) id);
if (remoteArg == null) {
throw new CommandProcessException("Cannot resolve argument by its objectId: " + id);
}
code.append(remoteArg.getDebugValue().getName());
} else {
code.append(JSONObject.valueToString(arg.get("value")));
}
}
code.append("]");
}
code.append(")");
DebugValue eval = suspendedInfo.getSuspendedEvent().getTopStackFrame().eval(code.toString());
suspendedInfo.refreshFrames();
result = asResult(eval);
}
json.put("result", result);
return null;
}
@Override
public Void processException(DebugException ex) {
fillExceptionDetails(json, ex);
return null;
}
private JSONObject asResult(DebugValue v) {
JSONObject result;
if (v == null) {
LanguageInfo language = suspendedInfo.getSuspendedEvent().getTopStackFrame().getLanguage();
result = RemoteObject.createNullObject(context.getEnv(), language).toJSON();
} else {
if (!returnByValue) {
RemoteObject ro = new RemoteObject(v, true, generatePreview, context);
context.getRemoteObjectsHandler().register(ro, objectGroup);
result = ro.toJSON();
} else {
result = RemoteObject.createJSONResultValue(v, context.areToStringSideEffectsAllowed(), context.getErr());
}
}
return result;
}
});
} catch (NoSuspendedThreadException ex) {
json.put("result", new JSONObject());
}
}
}
return new Params(json);
}
use of com.oracle.truffle.api.debug.DebugException in project graal by oracle.
the class InspectorDebugger method createCallFrames.
private CallFrame[] createCallFrames(Iterable<DebugStackFrame> frames, SuspendAnchor topAnchor, DebugValue returnValue, CallFrame[] oldFrames) {
List<CallFrame> cfs = new ArrayList<>();
int depth = 0;
int depthAll = -1;
if (scriptsHandler == null || debuggerSession == null) {
return new CallFrame[0];
}
for (DebugStackFrame frame : frames) {
depthAll++;
SourceSection sourceSection = frame.getSourceSection();
if (sourceSection == null || !sourceSection.isAvailable()) {
continue;
}
if (!context.isInspectInternal() && frame.isInternal()) {
continue;
}
Source source = sourceSection.getSource();
if (!context.isInspectInternal() && source.isInternal()) {
// should not be, double-check
continue;
}
Script script = scriptsHandler.assureLoaded(source);
List<Scope> scopes = new ArrayList<>();
DebugScope dscope;
try {
dscope = frame.getScope();
} catch (DebugException ex) {
PrintWriter err = context.getErr();
if (err != null) {
err.println("getScope() has caused " + ex);
ex.printStackTrace(err);
}
dscope = null;
}
String scopeType = "block";
boolean wasFunction = false;
SourceSection functionSourceSection = null;
if (dscope == null) {
functionSourceSection = sourceSection;
}
Scope[] oldScopes;
if (oldFrames != null && oldFrames.length > depth) {
oldScopes = oldFrames[depth].getScopeChain();
} else {
oldScopes = null;
}
List<DebugValue> receivers = new ArrayList<>();
// index of "this" receiver in `receivers` array
int thisIndex = -1;
// index of language implementation scope
int scopeIndex = 0;
TriState isJS = TriState.UNDEFINED;
while (dscope != null) {
if (wasFunction) {
scopeType = "closure";
} else if (dscope.isFunctionScope()) {
scopeType = "local";
functionSourceSection = dscope.getSourceSection();
wasFunction = true;
}
boolean scopeAdded = addScope(scopes, dscope, scopeType, scopeIndex, oldScopes);
if (scopeAdded) {
DebugValue receiver = dscope.getReceiver();
receivers.add(receiver);
if (receiver != null) {
if (thisIndex == -1 && "this".equals(receiver.getName())) {
// There is one receiver named "this".
thisIndex = scopes.size() - 1;
} else {
// we'll add the receiver(s) to scope variables instead.
if (TriState.UNDEFINED == isJS) {
isJS = TriState.valueOf(LanguageChecks.isJS(receiver.getOriginalLanguage()));
}
// therefore we need to keep the index for JS.
if (TriState.FALSE == isJS) {
thisIndex = -2;
}
}
}
}
dscope = getParent(dscope);
scopeIndex++;
}
try {
dscope = debuggerSession.getTopScope(source.getLanguage());
} catch (DebugException ex) {
PrintWriter err = context.getErr();
if (err != null) {
err.println("getTopScope() has caused " + ex);
ex.printStackTrace(err);
}
}
while (dscope != null) {
addScope(scopes, dscope, "global", scopeIndex, oldScopes);
dscope = getParent(dscope);
scopeIndex++;
}
RemoteObject returnObj = null;
if (depthAll == 0 && returnValue != null) {
returnObj = context.getRemoteObjectsHandler().getRemote(returnValue);
}
RemoteObject thisObj;
if (thisIndex < -1) {
for (int i = 0; i < receivers.size(); i++) {
DebugValue receiver = receivers.get(i);
if (receiver != null) {
scopes.get(i).getObject().setScopeReceiver(receiver);
}
}
thisObj = null;
} else if (thisIndex == -1) {
// no added scope, no receiver
thisObj = null;
} else {
thisObj = context.getRemoteObjectsHandler().getRemote(receivers.get(thisIndex));
}
SuspendAnchor anchor = (depthAll == 0) ? topAnchor : SuspendAnchor.BEFORE;
CallFrame cf = new CallFrame(frame, depth++, script, sourceSection, anchor, functionSourceSection, thisObj, returnObj, scopes.toArray(new Scope[scopes.size()]));
cfs.add(cf);
}
return cfs.toArray(new CallFrame[cfs.size()]);
}
use of com.oracle.truffle.api.debug.DebugException in project graal by oracle.
the class InspectorDebugger method setVariableValue.
@Override
public void setVariableValue(int scopeNumber, String variableName, CallArgument newValue, String callFrameId) throws CommandProcessException {
if (variableName == null) {
throw new CommandProcessException("A variableName required.");
}
if (newValue == null) {
throw new CommandProcessException("A newValue required.");
}
if (callFrameId == null) {
throw new CommandProcessException("A callFrameId required.");
}
int frameId;
try {
frameId = Integer.parseInt(callFrameId);
} catch (NumberFormatException ex) {
throw new CommandProcessException(ex.getLocalizedMessage());
}
try {
context.executeInSuspendThread(new SuspendThreadExecutable<Void>() {
@Override
public Void executeCommand() throws CommandProcessException {
DebuggerSuspendedInfo susp = suspendedInfo;
if (susp != null) {
if (frameId >= susp.getCallFrames().length) {
throw new CommandProcessException("Too big callFrameId: " + frameId);
}
CallFrame cf = susp.getCallFrames()[frameId];
Scope[] scopeChain = cf.getScopeChain();
if (scopeNumber < 0 || scopeNumber >= scopeChain.length) {
throw new CommandProcessException("Wrong scopeNumber: " + scopeNumber + ", there are " + scopeChain.length + " scopes.");
}
Scope scope = scopeChain[scopeNumber];
DebugScope debugScope = scope.getObject().getScope();
DebugValue debugValue = debugScope.getDeclaredValue(variableName);
Pair<DebugValue, Object> evaluatedValue = susp.lastEvaluatedValue.getAndSet(null);
try {
if (evaluatedValue != null && Objects.equals(evaluatedValue.getRight(), newValue.getPrimitiveValue())) {
debugValue.set(evaluatedValue.getLeft());
} else {
context.setValue(debugValue, newValue);
}
} catch (DebugException ex) {
PrintWriter err = context.getErr();
if (err != null) {
err.println("set of " + debugValue.getName() + " has caused " + ex);
ex.printStackTrace(err);
}
throw ex;
}
}
return null;
}
@Override
public Void processException(DebugException dex) {
return null;
}
});
} catch (NoSuspendedThreadException ex) {
throw new CommandProcessException(ex.getLocalizedMessage());
}
}
use of com.oracle.truffle.api.debug.DebugException in project graal by oracle.
the class InspectorExecutionContext method executeInSuspendThread.
<T> T executeInSuspendThread(SuspendThreadExecutable<T> executable) throws NoSuspendedThreadException, CommandProcessException {
if (synchronous) {
try {
return executable.executeCommand();
} catch (ThreadDeath td) {
throw td;
} catch (DebugException dex) {
return executable.processException(dex);
}
}
CompletableFuture<T> cf = new CompletableFuture<>();
suspendThreadExecutor.execute(new CancellableRunnable() {
@Override
public void run() {
T params = null;
try {
params = executable.executeCommand();
cf.complete(params);
} catch (ThreadDeath td) {
cf.completeExceptionally(td);
throw td;
} catch (DebugException dex) {
cf.complete(executable.processException(dex));
} catch (Throwable t) {
cf.completeExceptionally(t);
}
}
@Override
public void cancel() {
cf.completeExceptionally(new NoSuspendedThreadException("Resuming..."));
}
});
T params;
try {
params = cf.get();
} catch (ExecutionException ex) {
Throwable cause = ex.getCause();
if (cause instanceof CommandProcessException) {
throw (CommandProcessException) cause;
}
if (cause instanceof NoSuspendedThreadException) {
throw (NoSuspendedThreadException) cause;
}
if (err != null) {
cause.printStackTrace(err);
}
throw new CommandProcessException(ex.getLocalizedMessage());
} catch (InterruptedException ex) {
throw new CommandProcessException(ex.getLocalizedMessage());
}
return params;
}
Aggregations