diff --git a/src/main/java/org/dynjs/debugger/Debugger.java b/src/main/java/org/dynjs/debugger/Debugger.java index 7ba8d1b72..8be60f97e 100644 --- a/src/main/java/org/dynjs/debugger/Debugger.java +++ b/src/main/java/org/dynjs/debugger/Debugger.java @@ -8,6 +8,7 @@ import org.dynjs.debugger.requests.Response; import org.dynjs.parser.Statement; import org.dynjs.runtime.ExecutionContext; +import org.dynjs.runtime.SourceProvider; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; @@ -43,6 +44,8 @@ public enum StepAction { private ReferenceManager referenceManager = new ReferenceManager(); + private Set sources = new HashSet<>(); + private boolean paused = false; private Statement currentStatement = null; @@ -95,12 +98,17 @@ public ExecutionContext getCurrentContext() { public void enterContext(ExecutionContext context) { this.contextStack.add(0, context); + this.sources.add(context.getSource()); } public void exitContext(ExecutionContext context) { this.contextStack.remove(0); } + public Set getSources() { + return this.sources; + } + public boolean isRunning() { return ! this.paused; } diff --git a/src/main/java/org/dynjs/debugger/agent/JSONEncoder.java b/src/main/java/org/dynjs/debugger/agent/JSONEncoder.java index 15c594052..ff9c1ec13 100644 --- a/src/main/java/org/dynjs/debugger/agent/JSONEncoder.java +++ b/src/main/java/org/dynjs/debugger/agent/JSONEncoder.java @@ -7,6 +7,7 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import org.dynjs.debugger.Debugger; +import org.dynjs.debugger.agent.serializers.*; import org.dynjs.debugger.events.ConnectEvent; import org.dynjs.debugger.events.EventWrapper; import org.dynjs.debugger.requests.ResponseWrapper; @@ -32,6 +33,7 @@ public JSONEncoder(Debugger debugger) { this.module.addSerializer( new ResponseWrapperSerializer( handleSerializer ) ); this.module.addSerializer( new EvaluateResponseSerializer( handleSerializer ) ); this.module.addSerializer( new LookupResponseSerializer( handleSerializer ) ); + this.module.addSerializer( new ScriptsResponseSerializer( handleSerializer ) ); } @Override diff --git a/src/main/java/org/dynjs/debugger/agent/EvaluateResponseSerializer.java b/src/main/java/org/dynjs/debugger/agent/serializers/EvaluateResponseSerializer.java similarity index 88% rename from src/main/java/org/dynjs/debugger/agent/EvaluateResponseSerializer.java rename to src/main/java/org/dynjs/debugger/agent/serializers/EvaluateResponseSerializer.java index 4d9a099ce..f01b5107f 100644 --- a/src/main/java/org/dynjs/debugger/agent/EvaluateResponseSerializer.java +++ b/src/main/java/org/dynjs/debugger/agent/serializers/EvaluateResponseSerializer.java @@ -1,4 +1,4 @@ -package org.dynjs.debugger.agent; +package org.dynjs.debugger.agent.serializers; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; @@ -15,7 +15,7 @@ public class EvaluateResponseSerializer extends StdSerializer private final HandleSerializer handleSerializer; - EvaluateResponseSerializer(HandleSerializer handleSerializer) { + public EvaluateResponseSerializer(HandleSerializer handleSerializer) { super(EvaluateResponse.class); this.handleSerializer = handleSerializer; } diff --git a/src/main/java/org/dynjs/debugger/agent/HandleSerializer.java b/src/main/java/org/dynjs/debugger/agent/serializers/HandleSerializer.java similarity index 82% rename from src/main/java/org/dynjs/debugger/agent/HandleSerializer.java rename to src/main/java/org/dynjs/debugger/agent/serializers/HandleSerializer.java index 080e22367..43014bfc2 100644 --- a/src/main/java/org/dynjs/debugger/agent/HandleSerializer.java +++ b/src/main/java/org/dynjs/debugger/agent/serializers/HandleSerializer.java @@ -1,14 +1,11 @@ -package org.dynjs.debugger.agent; +package org.dynjs.debugger.agent.serializers; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import org.dynjs.debugger.Debugger; -import org.dynjs.runtime.JSObject; -import org.dynjs.runtime.NameEnumerator; -import org.dynjs.runtime.PropertyDescriptor; -import org.dynjs.runtime.Types; +import org.dynjs.runtime.*; import java.io.IOException; @@ -19,7 +16,7 @@ public class HandleSerializer extends JsonSerializer { private Debugger debugger; - HandleSerializer(Debugger debugger) { + public HandleSerializer(Debugger debugger) { super(); this.debugger = debugger; } @@ -33,8 +30,8 @@ public void serialize(Object value, JsonGenerator jgen, SerializerProvider provi public void serializeAsMapEntry(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { int ref = this.debugger.getReferenceManager().getReference(value); - jgen.writeFieldName( "" + ref ); - serialize( value, jgen, provider ); + jgen.writeFieldName("" + ref); + serialize(value, jgen, provider); } public void serializeBody(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { @@ -60,9 +57,24 @@ public void serializeBody(Object value, JsonGenerator jgen, SerializerProvider p } else if (value instanceof JSObject) { jgen.writeStringField("type", "object"); serializeJSObject((JSObject) value, jgen, provider); + } else if (value instanceof SourceProvider) { + serializeScript((SourceProvider) value, false, jgen, provider); } } + public void serializeScript(SourceProvider value, boolean includeSource, JsonGenerator jgen, SerializerProvider provider) throws IOException { + jgen.writeStringField("type", "script"); + jgen.writeStringField("name", value.getName()); + jgen.writeNumberField("id", value.getId()); + if (includeSource) { + jgen.writeStringField("source", value.getSource()); + } + jgen.writeNumberField("sourceLength", value.getSourceLength()); + jgen.writeNumberField("lineCount", value.getLineCount()); + jgen.writeNumberField("scriptType", 2); + jgen.writeNumberField("compilationType", 0); + } + private void serializeJSObject(JSObject result, JsonGenerator jgen, SerializerProvider provider) throws IOException { jgen.writeFieldName("properties"); diff --git a/src/main/java/org/dynjs/debugger/agent/LookupResponseSerializer.java b/src/main/java/org/dynjs/debugger/agent/serializers/LookupResponseSerializer.java similarity index 86% rename from src/main/java/org/dynjs/debugger/agent/LookupResponseSerializer.java rename to src/main/java/org/dynjs/debugger/agent/serializers/LookupResponseSerializer.java index 6fd148fbe..3e3e872ad 100644 --- a/src/main/java/org/dynjs/debugger/agent/LookupResponseSerializer.java +++ b/src/main/java/org/dynjs/debugger/agent/serializers/LookupResponseSerializer.java @@ -1,10 +1,9 @@ -package org.dynjs.debugger.agent; +package org.dynjs.debugger.agent.serializers; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.std.StdSerializer; -import org.dynjs.debugger.requests.EvaluateResponse; import org.dynjs.debugger.requests.LookupResponse; import java.io.IOException; @@ -16,7 +15,7 @@ public class LookupResponseSerializer extends StdSerializer { private final HandleSerializer handleSerializer; - LookupResponseSerializer(HandleSerializer handleSerializer) { + public LookupResponseSerializer(HandleSerializer handleSerializer) { super(LookupResponse.class); this.handleSerializer = handleSerializer; } diff --git a/src/main/java/org/dynjs/debugger/agent/ResponseWrapperSerializer.java b/src/main/java/org/dynjs/debugger/agent/serializers/ResponseWrapperSerializer.java similarity index 88% rename from src/main/java/org/dynjs/debugger/agent/ResponseWrapperSerializer.java rename to src/main/java/org/dynjs/debugger/agent/serializers/ResponseWrapperSerializer.java index 81a8583b4..7520d5f7d 100644 --- a/src/main/java/org/dynjs/debugger/agent/ResponseWrapperSerializer.java +++ b/src/main/java/org/dynjs/debugger/agent/serializers/ResponseWrapperSerializer.java @@ -1,13 +1,13 @@ -package org.dynjs.debugger.agent; +package org.dynjs.debugger.agent.serializers; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.std.StdSerializer; -import org.dynjs.debugger.requests.EvaluateResponse; import org.dynjs.debugger.requests.ResponseWrapper; import java.io.IOException; +import java.util.Collection; import java.util.List; /** @@ -17,7 +17,7 @@ public class ResponseWrapperSerializer extends StdSerializer { private final HandleSerializer handleSerializer; - ResponseWrapperSerializer(HandleSerializer handleSerializer) { + public ResponseWrapperSerializer(HandleSerializer handleSerializer) { super(ResponseWrapper.class); this.handleSerializer = handleSerializer; } @@ -39,7 +39,7 @@ public void serialize(ResponseWrapper value, JsonGenerator jgen, SerializerProvi jgen.writeFieldName( "refs" ); jgen.writeStartArray(); - List refs = value.getRefs(); + Collection refs = value.getRefs(); for ( Object each : refs ) { this.handleSerializer.serialize(each, jgen, provider ); } diff --git a/src/main/java/org/dynjs/debugger/agent/serializers/ScriptsResponseSerializer.java b/src/main/java/org/dynjs/debugger/agent/serializers/ScriptsResponseSerializer.java new file mode 100644 index 000000000..1583554dd --- /dev/null +++ b/src/main/java/org/dynjs/debugger/agent/serializers/ScriptsResponseSerializer.java @@ -0,0 +1,37 @@ +package org.dynjs.debugger.agent.serializers; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import org.dynjs.debugger.requests.ScriptsResponse; +import org.dynjs.runtime.SourceProvider; + +import java.io.IOException; + +/** + * @author Bob McWhirter + */ +public class ScriptsResponseSerializer extends StdSerializer { + + private final HandleSerializer handleSerializer; + + public ScriptsResponseSerializer(HandleSerializer handleSerializer) { + super(ScriptsResponse.class); + this.handleSerializer = handleSerializer; + } + + @Override + public void serialize(ScriptsResponse value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { + + jgen.writeStartArray(); + + for ( SourceProvider each : value.getScripts() ) { + this.handleSerializer.serializeScript( each, value.isIncludeSource(), jgen, provider ); + } + + jgen.writeEndArray(); + } + + +} diff --git a/src/main/java/org/dynjs/debugger/commands/Scripts.java b/src/main/java/org/dynjs/debugger/commands/Scripts.java index db5a56a13..c4e12aa04 100644 --- a/src/main/java/org/dynjs/debugger/commands/Scripts.java +++ b/src/main/java/org/dynjs/debugger/commands/Scripts.java @@ -3,6 +3,10 @@ import org.dynjs.debugger.Debugger; import org.dynjs.debugger.requests.ScriptsRequest; import org.dynjs.debugger.requests.ScriptsResponse; +import org.dynjs.runtime.SourceProvider; + +import java.util.HashSet; +import java.util.Set; /** * @author Bob McWhirter @@ -15,6 +19,28 @@ public Scripts(Debugger debugger) { @Override public ScriptsResponse handle(ScriptsRequest request) { - return new ScriptsResponse(request, true, true); + Set allScripts = this.debugger.getSources(); + Set selectedScripts = null; + + if (request.getArguments().getIds() == null) { + selectedScripts = allScripts; + } else { + selectedScripts = new HashSet<>(); + + int[] ids = request.getArguments().getIds(); + + for (SourceProvider each : allScripts) { + LOOKUP: + for (int i = 0; i < ids.length; ++i) { + if (each.getId() == ids[i]) { + selectedScripts.add(each); + break LOOKUP; + } + } + } + + } + + return new ScriptsResponse(request, selectedScripts, request.getArguments().isIncludeSource(), true, true); } } diff --git a/src/main/java/org/dynjs/debugger/requests/AbstractResponse.java b/src/main/java/org/dynjs/debugger/requests/AbstractResponse.java index 61afff8e3..a05504b71 100644 --- a/src/main/java/org/dynjs/debugger/requests/AbstractResponse.java +++ b/src/main/java/org/dynjs/debugger/requests/AbstractResponse.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import java.util.Collection; import java.util.Collections; import java.util.List; @@ -47,7 +48,7 @@ public boolean isRunning() { @Override @JsonIgnore - public List getRefs() { + public Collection getRefs() { return Collections.emptyList(); } } diff --git a/src/main/java/org/dynjs/debugger/requests/EvaluateResponse.java b/src/main/java/org/dynjs/debugger/requests/EvaluateResponse.java index 9913cd06b..9aae54236 100644 --- a/src/main/java/org/dynjs/debugger/requests/EvaluateResponse.java +++ b/src/main/java/org/dynjs/debugger/requests/EvaluateResponse.java @@ -6,6 +6,7 @@ import org.dynjs.runtime.Types; import java.util.ArrayList; +import java.util.Collection; import java.util.List; /** @@ -25,7 +26,7 @@ public Object getResult() { } @Override - public List getRefs() { + public Collection getRefs() { List refs = new ArrayList<>(); getRefs( this.result, refs ); diff --git a/src/main/java/org/dynjs/debugger/requests/Response.java b/src/main/java/org/dynjs/debugger/requests/Response.java index 507c69ee2..bc0ae83c4 100644 --- a/src/main/java/org/dynjs/debugger/requests/Response.java +++ b/src/main/java/org/dynjs/debugger/requests/Response.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import org.dynjs.debugger.Message; +import java.util.Collection; import java.util.List; /** @@ -16,5 +17,5 @@ public interface Response extends Message { boolean isRunning(); @JsonIgnore - List getRefs(); + Collection getRefs(); } diff --git a/src/main/java/org/dynjs/debugger/requests/ResponseWrapper.java b/src/main/java/org/dynjs/debugger/requests/ResponseWrapper.java index fe04e3f60..a7be0a74c 100644 --- a/src/main/java/org/dynjs/debugger/requests/ResponseWrapper.java +++ b/src/main/java/org/dynjs/debugger/requests/ResponseWrapper.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import org.dynjs.debugger.agent.handlers.WrappingHandler; +import java.util.Collection; import java.util.List; /** @@ -42,7 +43,7 @@ public int getSeq() { return this.seq; } - public List getRefs() { + public Collection getRefs() { return this.body.getRefs(); } diff --git a/src/main/java/org/dynjs/debugger/requests/ScriptsRequest.java b/src/main/java/org/dynjs/debugger/requests/ScriptsRequest.java index 90af902ec..248a640ab 100644 --- a/src/main/java/org/dynjs/debugger/requests/ScriptsRequest.java +++ b/src/main/java/org/dynjs/debugger/requests/ScriptsRequest.java @@ -12,6 +12,7 @@ public static class Arguments { private boolean includeSource; private int types; + private int[] ids; public void setIncludeSource(boolean includeSource) { this.includeSource = includeSource; @@ -29,6 +30,14 @@ public int getTypes() { return this.types; } + public void setIds(int[] ids) { + this.ids = ids; + } + + public int[] getIds() { + return this.ids; + } + } private Arguments arguments; diff --git a/src/main/java/org/dynjs/debugger/requests/ScriptsResponse.java b/src/main/java/org/dynjs/debugger/requests/ScriptsResponse.java index 013f87603..564f636e6 100644 --- a/src/main/java/org/dynjs/debugger/requests/ScriptsResponse.java +++ b/src/main/java/org/dynjs/debugger/requests/ScriptsResponse.java @@ -1,11 +1,35 @@ package org.dynjs.debugger.requests; +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.dynjs.runtime.SourceProvider; + +import java.util.Collection; +import java.util.List; +import java.util.Set; + /** * @author Bob McWhirter */ public class ScriptsResponse extends AbstractResponse { - public ScriptsResponse(ScriptsRequest request, boolean success, boolean running) { + private final Set scripts; + private final boolean includeSource; + + public ScriptsResponse(ScriptsRequest request, Set scripts, boolean includeSource, boolean success, boolean running) { super(request, success, running); + this.scripts = scripts; + this.includeSource = includeSource; + } + + @JsonIgnore + public Collection getScripts() { + return this.scripts; } + + @JsonIgnore + public boolean isIncludeSource() { + return this.includeSource; + } + + } diff --git a/src/main/java/org/dynjs/runtime/Compiler.java b/src/main/java/org/dynjs/runtime/Compiler.java index bd2035795..23345dfe0 100644 --- a/src/main/java/org/dynjs/runtime/Compiler.java +++ b/src/main/java/org/dynjs/runtime/Compiler.java @@ -59,7 +59,7 @@ public Compiler withSource(SourceProvider source) { return this; } - public Compiler withSource(File source) throws FileNotFoundException { + public Compiler withSource(File source) throws IOException { this.sourceProvider = new FileSourceProvider(source); this.fileName = source.getName(); return this; diff --git a/src/main/java/org/dynjs/runtime/DynJS.java b/src/main/java/org/dynjs/runtime/DynJS.java index 610280692..ac3d6ce6f 100644 --- a/src/main/java/org/dynjs/runtime/DynJS.java +++ b/src/main/java/org/dynjs/runtime/DynJS.java @@ -45,15 +45,19 @@ public DynJS(Config config, JSObject globalObject) { private void loadKernel() { // FIXME only works for non-IR atm if (!Config.CompileMode.IR.equals(this.config.getCompileMode())) { - switch (this.config.getKernelMode()) { - case INTERNAL: - // Load pure-JS kernel - //this.evaluate(getClass().getResourceAsStream("/dynjs/kernel.js")); - this.evaluate(new ClassLoaderSourceProvider(getClass().getClassLoader(), "dynjs/kernel.js")); - break; - case EXTERNAL: - this.evaluate(new FileSourceProvider(new File("src/main/resources/dynjs/kernel.js"))); - break; + try { + switch (this.config.getKernelMode()) { + case INTERNAL: + // Load pure-JS kernel + //this.evaluate(getClass().getResourceAsStream("/dynjs/kernel.js")); + this.evaluate(new ClassLoaderSourceProvider(getClass().getClassLoader(), "dynjs/kernel.js")); + break; + case EXTERNAL: + this.evaluate(new FileSourceProvider(new File("src/main/resources/dynjs/kernel.js"))); + break; + } + } catch (IOException e) { + e.printStackTrace(); } } } diff --git a/src/main/java/org/dynjs/runtime/Runner.java b/src/main/java/org/dynjs/runtime/Runner.java index 4c898f0c3..78fc81be7 100644 --- a/src/main/java/org/dynjs/runtime/Runner.java +++ b/src/main/java/org/dynjs/runtime/Runner.java @@ -83,7 +83,7 @@ public Runner withSource(SourceProvider source) { return this; } - public Runner withSource(File source) throws FileNotFoundException { + public Runner withSource(File source) throws IOException { this.compiler.withSource(source); return this; } diff --git a/src/main/java/org/dynjs/runtime/SourceProvider.java b/src/main/java/org/dynjs/runtime/SourceProvider.java index 2a85c7c88..cc54cc860 100644 --- a/src/main/java/org/dynjs/runtime/SourceProvider.java +++ b/src/main/java/org/dynjs/runtime/SourceProvider.java @@ -10,5 +10,13 @@ public interface SourceProvider { String getName(); + long getSourceLength(); + + long getLineCount(); + + int getId(); + Reader openReader() throws IOException; + + String getSource() throws IOException; } diff --git a/src/main/java/org/dynjs/runtime/source/ClassLoaderSourceProvider.java b/src/main/java/org/dynjs/runtime/source/ClassLoaderSourceProvider.java index 41e37ca4c..c2147c0bf 100644 --- a/src/main/java/org/dynjs/runtime/source/ClassLoaderSourceProvider.java +++ b/src/main/java/org/dynjs/runtime/source/ClassLoaderSourceProvider.java @@ -1,33 +1,13 @@ package org.dynjs.runtime.source; -import org.dynjs.runtime.SourceProvider; - -import java.io.*; +import java.io.IOException; /** * @author Bob McWhirter */ -public class ClassLoaderSourceProvider implements SourceProvider { - - private final ClassLoader classLoader; - private final String path; - - public ClassLoaderSourceProvider(ClassLoader classLoader, String path) { - this.classLoader = classLoader; - this.path = path; - } - - @Override - public String getName() { - return this.path; - } - - public Reader openReader() throws IOException { - InputStream in = this.classLoader.getResourceAsStream(this.path); - if ( in == null ) { - throw new FileNotFoundException( this.path ); - } +public class ClassLoaderSourceProvider extends InputStreamSourceProvider { - return new InputStreamReader( in ); + public ClassLoaderSourceProvider(ClassLoader classLoader, String path) throws IOException { + super(classLoader.getResourceAsStream(path), path); } } diff --git a/src/main/java/org/dynjs/runtime/source/FileSourceProvider.java b/src/main/java/org/dynjs/runtime/source/FileSourceProvider.java index 82c739b0f..d6d850ab3 100644 --- a/src/main/java/org/dynjs/runtime/source/FileSourceProvider.java +++ b/src/main/java/org/dynjs/runtime/source/FileSourceProvider.java @@ -7,19 +7,10 @@ /** * @author Bob McWhirter */ -public class FileSourceProvider implements SourceProvider { +public class FileSourceProvider extends InputStreamSourceProvider { - private final File file; - - public FileSourceProvider(File file) { - this.file = file; - } - - public String getName() { - return file.getAbsolutePath(); + public FileSourceProvider(File file) throws IOException { + super( new FileInputStream( file ), file.getAbsolutePath() ); } - public Reader openReader() throws IOException { - return new FileReader( this.file ); - } } diff --git a/src/main/java/org/dynjs/runtime/source/StringSourceProvider.java b/src/main/java/org/dynjs/runtime/source/StringSourceProvider.java index f210ebeb7..2edac30fd 100644 --- a/src/main/java/org/dynjs/runtime/source/StringSourceProvider.java +++ b/src/main/java/org/dynjs/runtime/source/StringSourceProvider.java @@ -9,8 +9,11 @@ */ public class StringSourceProvider implements SourceProvider { + private static int COUNTER = 0; + private final String source; private final String name; + private final int id; public StringSourceProvider(String source) { this( source, "