blob: 49cc162d261240845e1b89b727f9451752d39762 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.lib.v8debug;
import java.util.Map;
import org.json.simple.JSONArray;
import org.json.simple.JSONAware;
import org.json.simple.JSONObject;
import static org.netbeans.lib.v8debug.JSONConstants.*;
import org.netbeans.lib.v8debug.commands.Backtrace;
import org.netbeans.lib.v8debug.commands.ChangeBreakpoint;
import org.netbeans.lib.v8debug.commands.ChangeLive;
import org.netbeans.lib.v8debug.commands.ClearBreakpoint;
import org.netbeans.lib.v8debug.commands.ClearBreakpointGroup;
import org.netbeans.lib.v8debug.commands.Continue;
import org.netbeans.lib.v8debug.commands.Evaluate;
import org.netbeans.lib.v8debug.commands.Flags;
import org.netbeans.lib.v8debug.commands.Frame;
import org.netbeans.lib.v8debug.commands.GC;
import org.netbeans.lib.v8debug.commands.ListBreakpoints;
import org.netbeans.lib.v8debug.commands.Lookup;
import org.netbeans.lib.v8debug.commands.References;
import org.netbeans.lib.v8debug.commands.RestartFrame;
import org.netbeans.lib.v8debug.commands.Scope;
import org.netbeans.lib.v8debug.commands.Scopes;
import org.netbeans.lib.v8debug.commands.Scripts;
import org.netbeans.lib.v8debug.commands.SetBreakpoint;
import org.netbeans.lib.v8debug.commands.SetExceptionBreak;
import org.netbeans.lib.v8debug.commands.SetVariableValue;
import org.netbeans.lib.v8debug.commands.Source;
import org.netbeans.lib.v8debug.commands.Threads;
import org.netbeans.lib.v8debug.commands.V8Flags;
import org.netbeans.lib.v8debug.commands.Version;
import org.netbeans.lib.v8debug.connection.LinkedJSONObject;
import org.netbeans.lib.v8debug.events.AfterCompileEventBody;
import org.netbeans.lib.v8debug.events.BreakEventBody;
import org.netbeans.lib.v8debug.events.CompileErrorEventBody;
import org.netbeans.lib.v8debug.events.ExceptionEventBody;
import org.netbeans.lib.v8debug.events.ScriptCollectedEventBody;
import org.netbeans.lib.v8debug.vars.NewValue;
import org.netbeans.lib.v8debug.vars.ReferencedValue;
import org.netbeans.lib.v8debug.vars.V8Boolean;
import org.netbeans.lib.v8debug.vars.V8Function;
import org.netbeans.lib.v8debug.vars.V8Generator;
import org.netbeans.lib.v8debug.vars.V8Number;
import org.netbeans.lib.v8debug.vars.V8Object;
import org.netbeans.lib.v8debug.vars.V8ScriptValue;
import org.netbeans.lib.v8debug.vars.V8String;
import org.netbeans.lib.v8debug.vars.V8Value;
/**
* Translator of Java API classes into the corresponding JSON objects.
*
* @author Martin Entlicher
*/
@SuppressWarnings("unchecked")
public class JSONWriter {
private JSONWriter() {}
public static JSONObject store(V8Request request) {
JSONObject obj = newJSONObject();
obj.put(SEQ, request.getSequence());
obj.put(TYPE, V8Type.request.toString());
V8Command command = request.getCommand();
obj.put(COMMAND, command.toString());
V8Arguments arguments = request.getArguments();
if (arguments != null) {
obj.put(ARGUMENTS, store(command, arguments));
}
return obj;
}
public static JSONObject store(V8Response response) {
JSONObject obj = newJSONObject();
obj.put(SEQ, response.getSequence());
obj.put(SEQ_REQUEST, response.getRequestSequence());
obj.put(TYPE, V8Type.response.toString());
V8Command command = response.getCommand();
obj.put(COMMAND, command.toString());
boolean success = response.isSuccess();
obj.put(SUCCESS, success);
if (success) {
V8Body body = response.getBody();
if (body != null) {
obj.put(BODY, store(command, body));
}
} else {
obj.put(MESSAGE, response.getErrorMessage());
}
ReferencedValue[] referencedValues = response.getReferencedValues();
if (referencedValues != null) {
obj.put(REFS, store(referencedValues));
}
obj.put(RUNNING, response.isRunning());
return obj;
}
public static JSONObject store(V8Event event) {
JSONObject obj = newJSONObject();
obj.put(SEQ, event.getSequence());
obj.put(TYPE, V8Type.event.toString());
V8Event.Kind eventKind = event.getKind();
obj.put(EVENT, eventKind.toString());
V8Body body = event.getBody();
JSONObject bodyObj = newJSONObject();
switch (eventKind) {
case AfterCompile:
AfterCompileEventBody aceb = (AfterCompileEventBody) body;
bodyObj.put(EVT_SCRIPT, store(aceb.getScript()));
break;
case CompileError:
CompileErrorEventBody ceeb = (CompileErrorEventBody) body;
bodyObj.put(EVT_SCRIPT, store(ceeb.getScript()));
break;
case ScriptCollected:
ScriptCollectedEventBody sceb = (ScriptCollectedEventBody) body;
bodyObj.put(EVT_SCRIPT, sceb.getScriptId());
break;
case Break:
BreakEventBody beb = (BreakEventBody) body;
storeIf(beb.getInvocationText(), bodyObj, EVT_INVOCATION_TEXT);
bodyObj.put(EVT_SOURCE_LINE, beb.getSourceLine());
bodyObj.put(EVT_SOURCE_COLUMN, beb.getSourceColumn());
storeIf(beb.getSourceLineText(), bodyObj, EVT_SOURCE_LINE_TEXT);
V8ScriptLocation scriptLocation = beb.getScript();
if (scriptLocation != null) {
bodyObj.put(EVT_SCRIPT, store(scriptLocation));
}
long[] breakpoints = beb.getBreakpoints();
if (breakpoints != null) {
bodyObj.put(EVT_BREAKPOINTS, array(breakpoints));
}
break;
case Exception:
ExceptionEventBody eeb = (ExceptionEventBody) body;
bodyObj.put(EVT_UNCAUGHT, eeb.isUncaught());
bodyObj.put(EVT_EXCEPTION, store(eeb.getException()));
bodyObj.put(EVT_SOURCE_LINE, eeb.getSourceLine());
bodyObj.put(EVT_SOURCE_COLUMN, eeb.getSourceColumn());
storeIf(eeb.getSourceLineText(), bodyObj, EVT_SOURCE_LINE_TEXT);
bodyObj.put(EVT_SCRIPT, store(eeb.getScript(), false));
break;
default:
throw new IllegalArgumentException("Unknown event kind: "+eventKind);
}
if (event.getSuccess().hasValue()) {
obj.put(SUCCESS, event.getSuccess().getValue());
}
obj.put(BODY, bodyObj);
ReferencedValue[] referencedValues = event.getReferencedValues();
if (referencedValues != null) {
obj.put(REFS, store(referencedValues));
}
PropertyBoolean running = event.isRunning();
if (running.hasValue()) {
obj.put(RUNNING, running.getValue());
}
return obj;
}
private static JSONObject newJSONObject() {
return new LinkedJSONObject();
}
private static Object store(V8Command command, V8Arguments arguments) {
JSONObject obj = newJSONObject();
switch(command) {
case Backtrace:
Backtrace.Arguments btargs = (Backtrace.Arguments) arguments;
storeIf(btargs.getFromFrame(), obj, FROM_FRAME);
storeIf(btargs.getToFrame(), obj, TO_FRAME);
storeIf(btargs.isBottom(), obj, BOTTOM);
storeIf(btargs.isInlineRefs(), obj, INLINE_REFS);
return obj;
case Continue:
Continue.Arguments cargs = (Continue.Arguments) arguments;
obj.put(ARGS_STEP_ACTION, cargs.getStepAction().toString());
storeIf(cargs.getStepCount(), obj, ARGS_STEP_COUNT);
return obj;
case Setbreakpoint:
SetBreakpoint.Arguments sbargs = (SetBreakpoint.Arguments) arguments;
String bpType;
if (V8Breakpoint.Type.scriptName.equals(sbargs.getType())) {
bpType = "script";
} else {
bpType = sbargs.getType().toString();
}
obj.put(TYPE, bpType);
obj.put(TARGET, sbargs.getTarget());
storeIf(sbargs.getLine(), obj, LINE);
storeIf(sbargs.getColumn(), obj, COLUMN);
storeIf(sbargs.isEnabled(), obj, BREAK_ENABLED);
storeIf(sbargs.getCondition(), obj, BREAK_CONDITION);
storeIf(sbargs.getIgnoreCount(), obj, BREAK_IGNORE_COUNT);
storeIf(sbargs.getGroupId(), obj, BREAK_GROUP_ID);
return obj;
case Changebreakpoint:
ChangeBreakpoint.Arguments chbargs = (ChangeBreakpoint.Arguments) arguments;
obj.put(BREAK_POINT, chbargs.getBreakpoint());
storeIf(chbargs.isEnabled(), obj, BREAK_ENABLED);
obj.put(BREAK_CONDITION, chbargs.getCondition());
storeIf(chbargs.getIgnoreCount(), obj, BREAK_IGNORE_COUNT);
return obj;
case Clearbreakpoint:
ClearBreakpoint.Arguments cbargs = (ClearBreakpoint.Arguments) arguments;
obj.put(BREAK_POINT, cbargs.getBreakpoint());
return obj;
case Clearbreakpointgroup:
ClearBreakpointGroup.Arguments cbgargs = (ClearBreakpointGroup.Arguments) arguments;
obj.put(BREAK_GROUP_ID, cbgargs.getGroupId());
return obj;
case Setexceptionbreak:
SetExceptionBreak.Arguments sebargs = (SetExceptionBreak.Arguments) arguments;
obj.put(TYPE, sebargs.getType().toString());
obj.put(BREAK_ENABLED, sebargs.isEnabled());
return obj;
case Evaluate:
Evaluate.Arguments eargs = (Evaluate.Arguments) arguments;
obj.put(EVAL_EXPRESSION, eargs.getExpression());
storeIf(eargs.getFrame(), obj, FRAME);
storeIf(eargs.isGlobal(), obj, EVAL_GLOBAL);
storeIf(eargs.isDisableBreak(), obj, EVAL_DISABLE_BREAK);
JSONArray additionalContexts = store(eargs.getAdditionalContext());
if (additionalContexts != null) {
obj.put(EVAL_ADDITIONAL_CONTEXT, additionalContexts);
}
return obj;
case Frame:
Frame.Arguments fargs = (Frame.Arguments) arguments;
storeIf(fargs.getFrameNumber(), obj, NUMBER);
return obj;
case Restartframe:
RestartFrame.Arguments ra = (RestartFrame.Arguments) arguments;
PropertyLong frame = ra.getFrame();
if (frame.hasValue()) {
obj.put(FRAME, frame.getValue());
}
return obj;
case Lookup:
Lookup.Arguments largs = (Lookup.Arguments) arguments;
obj.put(HANDLES, array(largs.getHandles()));
storeIf(largs.isIncludeSource(), obj, INCLUDE_SOURCE);
return obj;
case References:
References.Arguments rargs = (References.Arguments) arguments;
obj.put(TYPE, rargs.getType().name());
obj.put(HANDLE, rargs.getHandle());
return obj;
case Scope:
Scope.Arguments sargs = (Scope.Arguments) arguments;
obj.put(NUMBER, sargs.getScopeNumber());
storeIf(sargs.getFrameNumber(), obj, FRAME_NUMBER);
return obj;
case Scopes:
Scopes.Arguments ssargs = (Scopes.Arguments) arguments;
storeIf(ssargs.getFrameNumber(), obj, FRAME_NUMBER);
return obj;
case Scripts:
Scripts.Arguments scargs = (Scripts.Arguments) arguments;
if (scargs.getTypes() != null) {
obj.put(TYPES, scargs.getTypes().getIntTypes());
}
if (scargs.getIds() != null) {
obj.put(IDs, array(scargs.getIds()));
}
storeIf(scargs.isIncludeSource(), obj, INCLUDE_SOURCE);
storeIf(scargs.getNameFilter(), obj, FILTER);
storeIf(scargs.getIdFilter(), obj, FILTER);
return obj;
case Source:
Source.Arguments srcargs = (Source.Arguments) arguments;
storeIf(srcargs.getFrame(), obj, FRAME);
storeIf(srcargs.getFromLine(), obj, FROM_LINE);
storeIf(srcargs.getToLine(), obj, TO_LINE);
return obj;
case SetVariableValue:
SetVariableValue.Arguments svargs = (SetVariableValue.Arguments) arguments;
obj.put(NAME, svargs.getName());
obj.put(NEW_VALUE, store(svargs.getNewValue()));
JSONObject scope = newJSONObject();
scope.put(NUMBER, svargs.getScopeNumber());
storeIf(svargs.getScopeFrameNumber(), scope, FRAME_NUMBER);
obj.put(SCOPE, scope);
return obj;
case Changelive:
ChangeLive.Arguments chlargs = (ChangeLive.Arguments) arguments;
obj.put(SCRIPT_ID, chlargs.getScriptId());
storeIf(chlargs.isPreviewOnly(), obj, PREVIEW_ONLY);
obj.put(NEW_SOURCE, chlargs.getNewSource());
return obj;
case Gc:
GC.Arguments gcargs = (GC.Arguments) arguments;
obj.put(TYPE, gcargs.getType());
return obj;
case V8flags:
V8Flags.Arguments v8flargs = (V8Flags.Arguments) arguments;
obj.put(FLAGS, v8flargs.getFlags());
return obj;
case Flags:
Flags.Arguments flargs = (Flags.Arguments) arguments;
Map<String, Boolean> flags = flargs.getFlags();
if (flags != null) {
JSONArray arr = new JSONArray();
for (Map.Entry<String, Boolean> flagEntry : flags.entrySet()) {
JSONObject f = newJSONObject();
f.put(NAME, flagEntry.getKey());
f.put(VALUE, flagEntry.getValue());
arr.add(f);
}
obj.put(FLAGS, arr);
}
return obj;
default:
return null;
}
}
private static JSONAware store(V8Command command, V8Body body) {
switch (command) {
case Listbreakpoints:
JSONObject obj = newJSONObject();
ListBreakpoints.ResponseBody lbrb = (ListBreakpoints.ResponseBody) body;
obj.put(BREAK_POINTS, store(lbrb.getBreakpoints()));
obj.put(BREAK_ON_EXCEPTIONS, lbrb.isBreakOnExceptions());
obj.put(BREAK_ON_UNCAUGHT_EXCEPTIONS, lbrb.isBreakOnUncaughtExceptions());
return obj;
case Setbreakpoint:
obj = newJSONObject();
SetBreakpoint.ResponseBody sbrb = (SetBreakpoint.ResponseBody) body;
obj.put(TYPE, sbrb.getType().toString());
obj.put(BREAK_POINT, sbrb.getBreakpoint());
if (V8Breakpoint.Type.scriptId.equals(sbrb.getType())) {
storeIf(sbrb.getScriptName(), obj, SCRIPT_ID);
} else {
storeIf(sbrb.getScriptName(), obj, SCRIPT_NAME);
}
obj.put(LINE, getLongOrNull(sbrb.getLine()));
obj.put(COLUMN, getLongOrNull(sbrb.getColumn()));
obj.put(BREAK_ACTUAL_LOCATIONS, store(sbrb.getActualLocations()));
return obj;
case Setexceptionbreak:
obj = newJSONObject();
SetExceptionBreak.ResponseBody sebrb = (SetExceptionBreak.ResponseBody) body;
obj.put(TYPE, sebrb.getType().toString());
obj.put(BREAK_ENABLED, sebrb.isEnabled());
return obj;
case Clearbreakpoint:
obj = newJSONObject();
ClearBreakpoint.ResponseBody cbrb = (ClearBreakpoint.ResponseBody) body;
obj.put(BREAK_POINT, cbrb.getBreakpoint());
return obj;
case Clearbreakpointgroup:
obj = newJSONObject();
ClearBreakpointGroup.ResponseBody cbgrb = (ClearBreakpointGroup.ResponseBody) body;
obj.put(BREAK_POINTS, array(cbgrb.getBreakpointsCleared()));
return obj;
case Backtrace:
obj = newJSONObject();
Backtrace.ResponseBody brb = (Backtrace.ResponseBody) body;
obj.put(FROM_FRAME, brb.getFromFrame());
obj.put(TO_FRAME, brb.getToFrame());
obj.put(TOTAL_FRAMES, brb.getTotalFrames());
if (brb.getFrames() != null) {
obj.put(FRAMES, store(brb.getFrames()));
}
return obj;
case Frame:
Frame.ResponseBody frb = (Frame.ResponseBody) body;
obj = store(frb.getFrame());
return obj;
case Restartframe:
obj = newJSONObject();
RestartFrame.ResponseBody rfrb = (RestartFrame.ResponseBody) body;
obj.put(RESULT, store(rfrb.getResult()));
return obj;
case Changelive:
obj = newJSONObject();
ChangeLive.ResponseBody clrb = (ChangeLive.ResponseBody) body;
obj.put(CHANGE_LOG, store(clrb.getChangeLog()));
obj.put(RESULT, store(clrb.getResult()));
storeIf(clrb.getStepInRecommended(), obj, STEP_IN_RECOMMENDED);
return obj;
case Lookup:
Lookup.ResponseBody lrb = (Lookup.ResponseBody) body;
obj = storeValues(lrb.getValuesByHandle());
return obj;
case Evaluate:
Evaluate.ResponseBody erb = (Evaluate.ResponseBody) body;
obj = store(erb.getValue());
return obj;
case References:
References.ResponseBody rrb = (References.ResponseBody) body;
JSONArray arrayRefs = new JSONArray();
for (V8Value vr : rrb.getReferences()) {
arrayRefs.add(store(vr));
}
return arrayRefs;
case Scripts:
Scripts.ResponseBody scrrb = (Scripts.ResponseBody) body;
return store(scrrb.getScripts());
case SetVariableValue:
obj = newJSONObject();
SetVariableValue.ResponseBody svvrb = (SetVariableValue.ResponseBody) body;
obj.put(NEW_VALUE, store(svvrb.getNewValue()));
return obj;
case Scope:
Scope.ResponseBody srb = (Scope.ResponseBody) body;
obj = store(srb.getScope());
return obj;
case Scopes:
obj = newJSONObject();
Scopes.ResponseBody ssrb = (Scopes.ResponseBody) body;
obj.put(FROM_SCOPE, ssrb.getFromScope());
obj.put(TO_SCOPE, ssrb.getToScope());
obj.put(TOTAL_SCOPES, ssrb.getTotalScopes());
obj.put(SCOPES, store(ssrb.getScopes()));
return obj;
case Source:
obj = newJSONObject();
Source.ResponseBody srcrb = (Source.ResponseBody) body;
storeIf(srcrb.getSource(), obj, SOURCE);
obj.put(FROM_LINE, srcrb.getFromLine());
obj.put(TO_LINE, srcrb.getToLine());
obj.put(FROM_POSITION, srcrb.getFromPosition());
obj.put(TO_POSITION, srcrb.getToPosition());
obj.put(TOTAL_LINES, srcrb.getTotalLines());
return obj;
case Threads:
obj = newJSONObject();
Threads.ResponseBody trb = (Threads.ResponseBody) body;
obj.put(TOTAL_THREADS, trb.getNumThreads());
obj.put(THREADS, storeThreads(trb.getIds()));
return obj;
case Gc:
obj = newJSONObject();
GC.ResponseBody gcrb = (GC.ResponseBody) body;
obj.put(GC_BEFORE, gcrb.getBefore());
obj.put(GC_AFTER, gcrb.getAfter());
return obj;
case Version:
obj = newJSONObject();
Version.ResponseBody vrb = (Version.ResponseBody) body;
obj.put(BODY_VERSION, vrb.getVersion());
return obj;
case Flags:
obj = newJSONObject();
Flags.ResponseBody flrb = (Flags.ResponseBody) body;
obj.put(FLAGS, storeFlags(flrb.getFlags()));
return obj;
}
return null;
}
private static Object getLongOrNull(PropertyLong pl) {
if (pl.hasValue()) {
return pl.getValue();
} else {
return null;
}
}
private static JSONArray store(ReferencedValue[] rvs) {
JSONArray array = new JSONArray();
for (ReferencedValue rv : rvs) {
array.add(store(rv, false, false));
}
return array;
}
private static JSONObject store(ReferencedValue rv, boolean storeRefNotHandle, boolean noTextAndLength) {
JSONObject obj = newJSONObject();
//obj.put(REF, rv.getReference());
if (rv.hasValue()) {
if (storeRefNotHandle) {
obj.put(REF, rv.getReference());
store(rv.getValue(), obj, false, noTextAndLength);
} else {
store(rv.getValue(), obj, true, noTextAndLength);
}
} else {
obj.put(REF, rv.getReference());
}
return obj;
}
private static JSONArray store(V8Script[] scripts) {
JSONArray array = new JSONArray();
for (V8Script scr : scripts) {
array.add(store(scr));
}
return array;
}
private static JSONObject store(V8Script script) {
return store(script, true);
}
private static JSONObject store(V8Script script, boolean storeHandle) {
JSONObject obj = newJSONObject();
storeTo(script, obj, storeHandle);
return obj;
}
private static void storeTo(V8Script script, JSONObject obj, boolean storeHandle) {
if (storeHandle) {
obj.put(HANDLE, script.getHandle());
obj.put(TYPE, script.getType().toString());
}
if (storeHandle) {
if (script.getName() != null) {
obj.put(NAME, script.getName());
}
obj.put(ID, script.getId());
} else { // Just different order for easy comparison with V8 debug protocol.
obj.put(ID, script.getId());
if (script.getName() != null) {
obj.put(NAME, script.getName());
}
}
obj.put(SCRIPT_LINE_OFFSET, script.getLineOffset());
obj.put(SCRIPT_COLUMN_OFFSET, script.getColumnOffset());
obj.put(SCRIPT_LINE_COUNT, script.getLineCount());
if (script.getData() != null) {
obj.put(DATA, script.getData());
}
storeIf(script.getSource(), obj, SOURCE);
storeIf(script.getSourceStart(), obj, SOURCE_START);
storeIf(script.getSourceLength(), obj, SOURCE_LENGTH);
V8Script.Type scriptType = script.getScriptType();
if (scriptType != null) {
obj.put(SCRIPT_TYPE, scriptType.ordinal());
}
V8Script.CompilationType compilationType = script.getCompilationType();
if (compilationType != null) {
obj.put(COMPILATION_TYPE, compilationType.ordinal());
}
storeIf(script.getContext(), obj, CONTEXT);
if (script.getText() != null) {
obj.put(TEXT, script.getText());
}
storeIf(script.getEvalFromScript(), obj, EVAL_FROM_SCRIPT);
if (V8Script.CompilationType.EVAL.equals(compilationType) && script.getEvalFromLocation() != null) {
obj.put(LINE, script.getEvalFromLocation().getLine());
obj.put(COLUMN, script.getEvalFromLocation().getColumn());
}
}
private static JSONObject store(V8ScriptLocation scriptLocation) {
JSONObject obj = newJSONObject();
obj.put(ID, scriptLocation.getId());
obj.put(NAME, scriptLocation.getName());
obj.put(SCRIPT_LINE_OFFSET, scriptLocation.getLine());
obj.put(SCRIPT_COLUMN_OFFSET, scriptLocation.getColumn());
obj.put(SCRIPT_LINE_COUNT, scriptLocation.getLineCount());
return obj;
}
private static JSONArray store(V8Breakpoint[] breakpoints) {
JSONArray array = new JSONArray();
for (V8Breakpoint bp : breakpoints) {
array.add(store(bp));
}
return array;
}
private static JSONObject store(V8Breakpoint bp) {
JSONObject obj = newJSONObject();
obj.put(NUMBER, bp.getNumber());
storeIf(bp.getLine(), obj, LINE);
//storeIf(bp.getColumn(), obj, COLUMN);
obj.put(COLUMN, getLongOrNull(bp.getColumn()));
PropertyLong groupId = bp.getGroupId();
obj.put(BREAK_GROUP_ID, getLongOrNull(groupId));
if (bp.getHitCount() != 0) {
obj.put(BREAK_HIT_COUNT, bp.getHitCount());
}
obj.put(BREAK_ACTIVE, bp.isActive());
obj.put(BREAK_CONDITION, bp.getCondition());
if (bp.getIgnoreCount() != 0) {
obj.put(BREAK_IGNORE_COUNT, bp.getIgnoreCount());
}
obj.put(BREAK_ACTUAL_LOCATIONS, store(bp.getActualLocations()));
obj.put(TYPE, bp.getType().toString());
storeIf(bp.getScriptId(), obj, SCRIPT_ID);
storeIf(bp.getScriptName(), obj, SCRIPT_NAME);
return obj;
}
private static JSONArray store(V8Breakpoint.ActualLocation[] actualLocations) {
JSONArray array = new JSONArray();
if (actualLocations != null) {
for (V8Breakpoint.ActualLocation al : actualLocations) {
JSONObject obj = newJSONObject();
obj.put(LINE, al.getLine());
obj.put(COLUMN, al.getColumn());
storeIf(al.getScriptId(), obj, SCRIPT_ID);
storeIf(al.getScriptName(), obj, SCRIPT_NAME);
array.add(obj);
}
}
return array;
}
private static JSONArray store(V8Frame[] frames) {
JSONArray array = new JSONArray();
for (V8Frame frame : frames) {
array.add(store(frame));
}
return array;
}
private static JSONObject store(V8Frame frame) {
JSONObject obj = newJSONObject();
obj.put(TYPE, V8Value.Type.Frame.toString());
PropertyLong index = frame.getIndex();
obj.put(INDEX, getLongOrNull(index));
obj.put(FRAME_RECEIVER, store(frame.getReceiver(), true, false));
obj.put(FRAME_FUNC, store(frame.getFunction(), true, false));
storeReference(frame.getScriptRef(), obj, SCRIPT);
obj.put(FRAME_CONSTRUCT_CALL, frame.isConstructCall());
obj.put(FRAME_AT_RETURN, frame.isAtReturn());
obj.put(FRAME_DEBUGGER, frame.isDebuggerFrame());
storeReferences(frame.getArgumentRefs(), obj, FRAME_ARGUMENTS, true);
storeReferences(frame.getLocalRefs(), obj, FRAME_LOCALS, true);
obj.put(POSITION, frame.getPosition());
obj.put(LINE, frame.getLine());
obj.put(COLUMN, frame.getColumn());
obj.put(EVT_SOURCE_LINE_TEXT, frame.getSourceLineText());
obj.put(SCOPES, store(frame.getScopes()));
obj.put(TEXT, frame.getText());
return obj;
}
private static JSONArray store(ChangeLive.ChangeLog changeLog) {
JSONArray array = new JSONArray();
if (changeLog != null) {
ChangeLive.ChangeLog.BreakpointUpdate[] breakpointsUpdate = changeLog.getBreakpointsUpdate();
if (breakpointsUpdate != null) {
JSONObject obj = newJSONObject();
obj.put(BREAK_POINTS_UPDATE, store(breakpointsUpdate));
array.add(obj);
}
String[] droppedFrames = changeLog.getDroppedFrames();
if (droppedFrames != null) {
JSONObject obj = newJSONObject();
obj.put(DROPPED_FROM_STACK, storeStringValues(droppedFrames, NAME));
array.add(obj);
}
String[] namesLinkedToOldScript = changeLog.getNamesLinkedToOldScript();
if (namesLinkedToOldScript != null) {
JSONObject obj = newJSONObject();
obj.put(LINKED_TO_OLD_SCRIPT, storeStringValues(namesLinkedToOldScript, NAME));
array.add(obj);
}
ChangeLive.ChangeLog.FunctionPatched functionPatched = changeLog.getFunctionPatched();
if (functionPatched != null) {
JSONObject obj = newJSONObject();
obj.put(FUNCTION_PATCHED, functionPatched.getFunction());
storeIf(functionPatched.getFunctionInfoNotFound(), obj, FUNCTION_INFO_NOT_FOUND);
array.add(obj);
}
ChangeLive.ChangeLog.PositionPatched[] patchedPositions = changeLog.getPatchedPositions();
if (patchedPositions != null) {
JSONObject obj = newJSONObject();
obj.put(POSITION_PATCHED, store(patchedPositions));
array.add(obj);
}
}
return array;
}
private static JSONArray store(ChangeLive.ChangeLog.BreakpointUpdate[] breakpointsUpdate) {
JSONArray array = new JSONArray();
for (ChangeLive.ChangeLog.BreakpointUpdate bpu : breakpointsUpdate) {
JSONObject obj = newJSONObject();
obj.put(ID, bpu.getId());
storeIf(bpu.getNewId(), obj, NEW_ID);
storeIf(bpu.getNewPositions(), obj, NEW_POSITIONS);
storeIf(bpu.getOldPositions(), obj, POSITIONS);
obj.put(TYPE, bpu.getType().toString());
array.add(obj);
}
return array;
}
private static JSONArray store(ChangeLive.ChangeLog.PositionPatched[] patchedPositions) {
JSONArray array = new JSONArray();
for (ChangeLive.ChangeLog.PositionPatched pp : patchedPositions) {
JSONObject obj = newJSONObject();
storeIf(pp.getName(), obj, NAME);
storeIf(pp.getInfoNotFound(), obj, INFO_NOT_FOUND);
array.add(obj);
}
return array;
}
private static JSONObject store(ChangeLive.Result result) {
JSONObject obj = newJSONObject();
obj.put(CHANGE_TREE, store(result.getChangeTree()));
obj.put(TEXTUAL_DIFF, store(result.getDiff()));
obj.put(UPDATED, result.isUpdated());
storeIf(result.getStackModified(), obj, STACK_MODIFIED);
storeIf(result.getStackUpdateNeedsStepIn(), obj, STACK_UPDATE_NEEDS_STEP_IN);
storeIf(result.getCreatedScriptName(), obj, CREATED_SCRIPT_NAME);
return obj;
}
private static JSONObject store(ChangeLive.Result.ChangeTree changeTree) {
JSONObject obj = newJSONObject();
obj.put(NAME, changeTree.getName());
storeIf(changeTree.getPositions(), obj, POSITIONS);
if (changeTree.getStatus() != null) {
obj.put(STATUS, changeTree.getStatus().toString());
}
obj.put(CHILDREN, store(changeTree.getChildren()));
if (changeTree.getNewChildren() != null) {
obj.put(NEW_CHILDREN, store(changeTree.getNewChildren()));
}
storeIf(changeTree.getStatusExplanation(), obj, STATUS_EXPLANATION);
storeIf(changeTree.getNewPositions(), obj, NEW_POSITIONS);
return obj;
}
private static JSONObject store(ChangeLive.Result.TextualDiff diff) {
JSONObject obj = newJSONObject();
obj.put(OLD_LEN, diff.getOldLength());
obj.put(NEW_LEN, diff.getNewLength());
obj.put(CHUNKS, array(diff.getChunks()));
return obj;
}
private static void storeIf(ChangeLive.ChangeLog.BreakpointUpdate.Position position, JSONObject obj, String propName) {
if (position != null) {
JSONObject pos = newJSONObject();
pos.put(POSITION, position.getPosition());
pos.put(LINE, position.getLine());
pos.put(COLUMN, position.getColumn());
obj.put(propName, pos);
}
}
private static JSONArray store(ChangeLive.Result.ChangeTree[] children) {
JSONArray array = new JSONArray();
if (children != null) {
for (ChangeLive.Result.ChangeTree ct : children) {
array.add(store(ct));
}
}
return array;
}
private static void storeIf(ChangeLive.Result.ChangeTree.Positions positions, JSONObject obj, String propName) {
if (positions != null) {
JSONObject pos = newJSONObject();
pos.put(START_POSITION, positions.getStartPosition());
pos.put(END_POSITION, positions.getEndPosition());
obj.put(propName, pos);
}
}
private static JSONObject storeValues(Map<Long, V8Value> values) {
JSONObject obj = newJSONObject();
for (V8Value vv : values.values()) {
obj.put(Long.toString(vv.getHandle()), store(vv));
}
return obj;
}
private static JSONArray store(V8Scope[] scopes) {
JSONArray array = new JSONArray();
for (V8Scope scope : scopes) {
array.add(store(scope));
}
return array;
}
private static JSONObject store(V8Scope scope) {
JSONObject obj = newJSONObject();
obj.put(TYPE, scope.getType().ordinal());
obj.put(SCOPE_INDEX, scope.getIndex());
storeIf(scope.getFrameIndex(), obj, FRAME_INDEX);
if (scope.getObject() != null) {
obj.put(OBJECT, store(scope.getObject(), false, true));
}
storeIf(scope.getText(), obj, TEXT);
return obj;
}
private static JSONArray storeThreads(Map<Long, Boolean> threads) {
JSONArray array = new JSONArray();
for (Map.Entry<Long, Boolean> thread : threads.entrySet()) {
JSONObject obj = newJSONObject();
obj.put(CURRENT, thread.getValue());
obj.put(ID, thread.getKey());
array.add(obj);
}
return array;
}
private static JSONArray storeFlags(Map<String, Boolean> flags) {
JSONArray array = new JSONArray();
for (Map.Entry<String, Boolean> flag : flags.entrySet()) {
JSONObject obj = newJSONObject();
obj.put(NAME, flag.getKey());
obj.put(VALUE, flag.getValue());
array.add(obj);
}
return array;
}
private static JSONObject store(Map<String, Object> map) {
JSONObject obj = newJSONObject();
obj.putAll(map);
return obj;
}
private static JSONArray array(long[] array) {
JSONArray jsArray = new JSONArray();
for (int i = 0; i < array.length; i++) {
jsArray.add(array[i]);
}
return jsArray;
}
private static JSONArray storeStringValues(String[] ss, String propName) {
JSONArray array = new JSONArray();
for (String s : ss) {
JSONObject obj = newJSONObject();
obj.put(NAME, s);
array.add(obj);
}
return array;
}
private static void storeIf(PropertyBoolean prop, JSONObject obj, String propertyName) {
if (prop.hasValue()) {
obj.put(propertyName, prop.getValue());
}
}
private static void storeIf(PropertyLong prop, JSONObject obj, String propertyName) {
if (prop.hasValue()) {
obj.put(propertyName, prop.getValue());
}
}
private static void storeIf(String prop, JSONObject obj, String propertyName) {
if (prop != null) {
obj.put(propertyName, prop);
}
}
private static void storeIf(ReferencedValue rv, JSONObject obj, String propertyName) {
if (rv == null) {
return ;
}
JSONObject ref = newJSONObject();
ref.put(REF, rv.getReference());
if (rv.hasValue()) {
store(rv.getValue(), ref, false, false);
}
obj.put(propertyName, ref);
}
private static JSONArray store(Evaluate.Arguments.Context[] contexts) {
if (contexts == null) {
return null;
}
JSONArray array = new JSONArray();
for (Evaluate.Arguments.Context c : contexts) {
array.add(store(c));
}
return array;
}
private static JSONObject store(Evaluate.Arguments.Context context) {
JSONObject obj = newJSONObject();
obj.put(NAME, context.getName());
obj.put(HANDLE, context.getHandle());
return obj;
}
private static JSONObject store(NewValue value) {
JSONObject obj = newJSONObject();
if (value.getHandle().hasValue()) {
obj.put(HANDLE, value.getHandle().getValue());
} else {
obj.put(TYPE, value.getType().toString());
storeIf(value.getDescription(), obj, STRING_DESCRIPTION);
}
return obj;
}
private static JSONObject store(V8Value value) {
JSONObject obj = newJSONObject();
store(value, obj, true, false);
return obj;
}
private static void store(V8Value value, JSONObject obj, boolean storeHandle, boolean noTextAndLength) {
if (storeHandle) {
obj.put(HANDLE, value.getHandle());
}
V8Value.Type type = value.getType();
obj.put(TYPE, type.toString());
switch (type) {
case Boolean:
V8Boolean vb = (V8Boolean) value;
obj.put(VALUE, vb.getValue());
break;
case Number:
V8Number vn = (V8Number) value;
V8Number.Kind kind = vn.getKind();
switch (kind) {
case Double:
double dv = vn.getDoubleValue();
if (dv == Double.POSITIVE_INFINITY) {
obj.put(VALUE, INFINITY);
} else if (dv == Double.NEGATIVE_INFINITY) {
obj.put(VALUE, "-"+INFINITY);
} else if (Double.isNaN(dv)) {
obj.put(VALUE, NaN);
} else {
obj.put(VALUE, dv);
}
break;
case Long:
obj.put(VALUE, vn.getLongValue());
break;
default:
throw new IllegalArgumentException("Unhandled number kind: "+kind);
}
break;
case String:
V8String vs = (V8String) value;
String vss = vs.getValue();
obj.put(VALUE, vss);
if (!noTextAndLength) {
obj.put(LENGTH, vss.length());
}
break;
case Function:
V8Function vf = (V8Function) value;
if (vf.isResolved().hasValue()) { // Hack to be compliant with original V8 protocol
obj.put(VALUE_CLASS_NAME, vf.getClassName());
}
storeReferenceIf(vf.getConstructorFunctionHandle(), obj, VALUE_CONSTRUCTOR_FUNCTION);
storeReferenceIf(vf.getProtoObjectHandle(), obj, VALUE_PROTO_OBJECT);
storeReferenceIf(vf.getPrototypeObjectHandle(), obj, VALUE_PROTOTYPE_OBJECT);
storeIf(vf.getName(), obj, NAME);
storeIf(vf.getInferredName(), obj, FUNCTION_INFERRED_NAME);
storeIf(vf.isResolved(), obj, FUNCTION_RESOLVED);
storeIf(vf.getSource(), obj, SOURCE);
storeReferenceIf(vf.getScriptRef(), obj, SCRIPT);
storeIf(vf.getScriptId(), obj, SCRIPTID);
storeIf(vf.getPosition(), obj, POSITION);
storeIf(vf.getLine(), obj, LINE);
storeIf(vf.getColumn(), obj, COLUMN);
V8Scope[] scopes = vf.getScopes();
if (scopes != null) {
obj.put(SCOPES, store(scopes));
}
if (vf.getProperties() != null || vf.getArray() != null && vf.getArray().getLength() > 0) {
obj.put(VALUE_PROPERTIES, storeProperties(vf.getProperties(), vf.getArray()));
}
break;
case Generator:
V8Generator gf = (V8Generator) value;
obj.put(VALUE_CLASS_NAME, gf.getClassName());
storeReferenceIf(gf.getConstructorFunctionHandle(), obj, VALUE_CONSTRUCTOR_FUNCTION);
storeReferenceIf(gf.getProtoObjectHandle(), obj, VALUE_PROTO_OBJECT);
storeReferenceIf(gf.getPrototypeObjectHandle(), obj, VALUE_PROTOTYPE_OBJECT);
storeReferenceIf(gf.getFunctionHandle(), obj, FRAME_FUNC);
storeReferenceIf(gf.getReceiverHandle(), obj, FRAME_RECEIVER);
if (gf.getProperties() != null) {
obj.put(VALUE_PROPERTIES, storeProperties(gf.getProperties(), null));
}
break;
case Object:
case Error:
case Regexp:
V8Object vo = (V8Object) value;
obj.put(VALUE_CLASS_NAME, vo.getClassName());
storeReferenceIf(vo.getConstructorFunctionHandle(), obj, VALUE_CONSTRUCTOR_FUNCTION);
storeReferenceIf(vo.getProtoObjectHandle(), obj, VALUE_PROTO_OBJECT);
storeReferenceIf(vo.getPrototypeObjectHandle(), obj, VALUE_PROTOTYPE_OBJECT);
if (vo.getProperties() != null || vo.getArray() != null && vo.getArray().getLength() > 0) {
obj.put(VALUE_PROPERTIES, storeProperties(vo.getProperties(), vo.getArray()));
}
break;
case Frame:
// ? TODO
break;
case Script:
V8ScriptValue vsv = (V8ScriptValue) value;
storeTo(vsv.getScript(), obj, true);
break;
case Null:
if (noTextAndLength) {
obj.put(VALUE, null);
}
break;
}
if (value.getText() != null && !noTextAndLength) {
obj.put(TEXT, value.getText());
}
}
private static void storeReferenceIf(PropertyLong ref, JSONObject obj, String propertyName) {
if (ref.hasValue()) {
storeReference(ref.getValue(), obj, propertyName);
}
}
private static void storeReference(long ref, JSONObject obj, String propertyName) {
JSONObject refObj = newJSONObject();
refObj.put(REF, ref);
obj.put(propertyName, refObj);
}
private static void storeReferences(Map<String, ReferencedValue> rvals,
JSONObject obj, String propertyName,
boolean storeRefNotHandle) {
if (rvals == null) {
return ;
}
JSONArray array = new JSONArray();
for (Map.Entry<String, ReferencedValue> rval : rvals.entrySet()) {
JSONObject elm = newJSONObject();
if (rval.getKey() != null) {
elm.put(NAME, rval.getKey());
}
elm.put(VALUE, store(rval.getValue(), storeRefNotHandle, true));
array.add(elm);
}
obj.put(propertyName, array);
}
private static JSONArray storeProperties(Map<String, V8Object.Property> properties, V8Object.Array array) {
JSONArray arrObj = new JSONArray();
if (properties != null) {
for (String propName : properties.keySet()) {
V8Object.Property prop = properties.get(propName);
JSONObject propObj = newJSONObject();
propObj.put(NAME, propName);
if (prop.getAttributes() != 0) {
propObj.put(ATTRIBUTES, prop.getAttributes());
}
V8Object.Property.Type type = prop.getType();
if (type != null) {
propObj.put(PROPERTY_TYPE, type.ordinal());
} else {
propObj.put(PROPERTY_TYPE, 0);
}
propObj.put(REF, prop.getReference());
arrObj.add(propObj);
}
}
if (array != null) {
V8Object.IndexIterator indexIterator = array.getIndexIterator();
while (indexIterator.hasNextIndex()) {
JSONObject arrElm = newJSONObject();
long index = indexIterator.nextIndex();
arrElm.put(NAME, index);
arrElm.put(PROPERTY_TYPE, 0);
arrElm.put(REF, array.getReferenceAt(index));
arrObj.add(arrElm);
}
}
return arrObj;
}
}