refactor: some minor fixes, rewrite README example
This commit is contained in:
parent
f5d1287948
commit
fdfa8d7713
37
README.md
37
README.md
@ -4,31 +4,42 @@
|
||||
|
||||
**WARNING: Currently, this code is mostly undocumented. Proceed with caution and a psychiatrist.**
|
||||
|
||||
JScript is an engine, capable of running EcmaScript 5, written entirely in Java. This engine has been developed with the goal of being easy to integrate with your preexisting codebase, **THE GOAL OF THIS ENGINE IS NOT PERFORMANCE**. My crude experiments show that this engine is 50x-100x slower than V8, which, although bad, is acceptable for most simple scripting purposes.
|
||||
JScript is an engine, capable of running EcmaScript 5, written entirely in Java. This engine has been developed with the goal of being easy to integrate with your preexisting codebase, **THE GOAL OF THIS ENGINE IS NOT PERFORMANCE**. My crude experiments show that this engine is 50x-100x slower than V8, which, although bad, is acceptable for most simple scripting purposes. Note that although the codebase has a Main class, this isn't meant to be a standalone program, but instead a library for running JavaScript code.
|
||||
|
||||
## Example
|
||||
|
||||
The following will create a REPL using the engine as a backend. Not that this won't properly log errors. I recommend checking out the implementation in `Main.main`:
|
||||
|
||||
```java
|
||||
var engine = new PolyfillEngine(new File("."));
|
||||
var in = new BufferedReader(new InputStreamReader(System.in));
|
||||
var engine = new Engine(true /* false if you dont want debugging */);
|
||||
var env = new Environment(null, null, null);
|
||||
var debugger = new DebugServer();
|
||||
|
||||
// Create one target for the engine and start debugging server
|
||||
debugger.targets.put("target", (socket, req) -> new SimpleDebugger(socket, engine));
|
||||
debugger.start(new InetSocketAddress("127.0.0.1", 9229), true);
|
||||
|
||||
// Queue code to load internal libraries and start engine
|
||||
engine.pushMsg(false, null, new Internals().getApplier(env));
|
||||
engine.start();
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
var raw = in.readLine();
|
||||
var raw = Reading.read();
|
||||
if (raw == null) break;
|
||||
|
||||
var res = engine.pushMsg(false, engine.global(), Map.of(), "<stdio>", raw, null).await();
|
||||
Values.printValue(engine.context(), res);
|
||||
System.out.println();
|
||||
// Push a message to the engine with the raw REPL code
|
||||
var res = engine.pushMsg(
|
||||
false, new Context(engine).pushEnv(env),
|
||||
new Filename("jscript", "repl.js"), raw, null
|
||||
).await();
|
||||
|
||||
Values.printValue(null, res);
|
||||
}
|
||||
catch (EngineException e) {
|
||||
try {
|
||||
System.out.println("Uncaught " + e.toString(engine.context()));
|
||||
}
|
||||
catch (InterruptedException _e) { return; }
|
||||
catch (EngineException e) { Values.printError(e, ""); }
|
||||
catch (SyntaxException ex) {
|
||||
System.out.println("Syntax error:" + ex.msg);
|
||||
}
|
||||
catch (IOException | InterruptedException e) { return; }
|
||||
catch (IOException e) { }
|
||||
}
|
||||
```
|
||||
|
@ -8,12 +8,9 @@ import java.nio.file.Path;
|
||||
import me.topchetoeu.jscript.engine.Context;
|
||||
import me.topchetoeu.jscript.engine.Engine;
|
||||
import me.topchetoeu.jscript.engine.Environment;
|
||||
import me.topchetoeu.jscript.engine.StackData;
|
||||
import me.topchetoeu.jscript.engine.debug.DebugServer;
|
||||
import me.topchetoeu.jscript.engine.debug.SimpleDebugger;
|
||||
import me.topchetoeu.jscript.engine.values.ArrayValue;
|
||||
import me.topchetoeu.jscript.engine.values.NativeFunction;
|
||||
import me.topchetoeu.jscript.engine.values.ObjectValue;
|
||||
import me.topchetoeu.jscript.engine.values.Values;
|
||||
import me.topchetoeu.jscript.events.Observer;
|
||||
import me.topchetoeu.jscript.exceptions.EngineException;
|
||||
@ -47,61 +44,42 @@ public class Main {
|
||||
System.out.println(String.format("Running %s v%s by %s", Metadata.NAME, Metadata.VERSION, Metadata.AUTHOR));
|
||||
engine = new Engine(true);
|
||||
|
||||
env = new Environment(null, null, null);
|
||||
var exited = new boolean[1];
|
||||
var server = new DebugServer();
|
||||
server.targets.put("target", (ws, req) -> new SimpleDebugger(ws, engine));
|
||||
|
||||
env = Internals.apply(new Environment(null, null, null));
|
||||
|
||||
env.global.define("exit", _ctx -> {
|
||||
exited[0] = true;
|
||||
throw new InterruptException();
|
||||
});
|
||||
env.global.define("go", _ctx -> {
|
||||
try {
|
||||
var f = Path.of("do.js");
|
||||
var func = _ctx.compile(new Filename("do", "do/" + j++ + ".js"), new String(Files.readAllBytes(f)));
|
||||
return func.call(_ctx);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new EngineException("Couldn't open do.js");
|
||||
}
|
||||
});
|
||||
|
||||
engineTask = engine.start();
|
||||
debugTask = server.start(new InetSocketAddress("127.0.0.1", 9229), true);
|
||||
|
||||
engine.pushMsg(false, null, new NativeFunction((ctx, thisArg, _a) -> {
|
||||
new Internals().apply(env);
|
||||
|
||||
env.global.define("exit", _ctx -> {
|
||||
exited[0] = true;
|
||||
throw new InterruptException();
|
||||
});
|
||||
env.global.define("go", _ctx -> {
|
||||
try {
|
||||
var f = Path.of("do.js");
|
||||
var func = _ctx.compile(new Filename("do", "do/" + j++ + ".js"), new String(Files.readAllBytes(f)));
|
||||
return func.call(_ctx);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new EngineException("Couldn't open do.js");
|
||||
}
|
||||
});
|
||||
// TODO: make better API
|
||||
env.global.define(true, new NativeFunction("include", (_ctx, th, __args) -> {
|
||||
try {
|
||||
var currFilename = StackData.peekFrame(_ctx).function.loc().filename();
|
||||
var loc = Path.of("").toAbsolutePath();
|
||||
if (currFilename.protocol.equals("file")) loc = Path.of(currFilename.path).getParent();
|
||||
var path = loc.resolve(Path.of(__args.length >= 1 ? Values.toString(_ctx, __args[0]) : ""));
|
||||
var src = Files.readString(path);
|
||||
var func = _ctx.compile(Filename.fromFile(path.toFile()), src);
|
||||
var callArgs = new ArrayValue();
|
||||
if (__args.length >= 2 && __args[1] instanceof ArrayValue) callArgs = (ArrayValue)__args[1];
|
||||
return func.call(_ctx, null, callArgs);
|
||||
}
|
||||
catch (IOException e) { throw EngineException.ofError("IOError", "Couldn't open file."); }
|
||||
}));
|
||||
|
||||
return null;
|
||||
}), null).await();
|
||||
|
||||
try {
|
||||
var tsEnv = env.child();
|
||||
tsEnv.global.define(null, "module", false, new ObjectValue());
|
||||
var tsEnv = Internals.apply(new Environment(null, null, null));
|
||||
var bsEnv = Internals.apply(new Environment(null, null, null));
|
||||
|
||||
engine.pushMsg(
|
||||
false, new Context(engine).pushEnv(tsEnv),
|
||||
false, new Context(engine, tsEnv),
|
||||
new Filename("jscript", "ts.js"),
|
||||
Reading.resourceToString("js/ts.js"), null
|
||||
).await();
|
||||
System.out.println("Loaded typescript!");
|
||||
|
||||
var ctx = new Context(engine).pushEnv(env.child());
|
||||
var ctx = new Context(engine, bsEnv);
|
||||
|
||||
engine.pushMsg(
|
||||
false, ctx,
|
||||
|
@ -24,9 +24,7 @@ public class CompoundStatement extends Statement {
|
||||
public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) {
|
||||
for (var stm : statements) {
|
||||
if (stm instanceof FunctionStatement) {
|
||||
int start = target.size();
|
||||
((FunctionStatement)stm).compile(target, scope, null, true);
|
||||
target.setDebug(start);
|
||||
target.add(Instruction.discard());
|
||||
}
|
||||
}
|
||||
|
@ -54,6 +54,11 @@ public class Context {
|
||||
this.engine = engine;
|
||||
}
|
||||
public Context(Engine engine) {
|
||||
this(engine, null);
|
||||
this(engine, (Data)null);
|
||||
}
|
||||
public Context(Engine engine, Environment env) {
|
||||
this(engine, (Data)null);
|
||||
this.pushEnv(env);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -112,7 +112,6 @@ public class SimpleDebugger implements Debugger {
|
||||
this.frame = frame;
|
||||
this.func = frame.function;
|
||||
this.id = id;
|
||||
this.local = new ObjectValue();
|
||||
this.location = frame.function.loc();
|
||||
|
||||
this.global = frame.function.environment.global.obj;
|
||||
|
File diff suppressed because one or more lines are too long
@ -113,7 +113,7 @@ public class Internals {
|
||||
return Double.POSITIVE_INFINITY;
|
||||
}
|
||||
|
||||
public void apply(Environment env) {
|
||||
public static Environment apply(Environment env) {
|
||||
var wp = env.wrappers;
|
||||
var glob = env.global = new GlobalScope(wp.getNamespace(Internals.class));
|
||||
|
||||
@ -157,6 +157,6 @@ public class Internals {
|
||||
wp.getProto(ObjectLib.class).setPrototype(null, null);
|
||||
env.regexConstructor = wp.getConstr(RegExpLib.class);
|
||||
|
||||
System.out.println("Loaded polyfills!");
|
||||
return env;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user