Compare commits
3 Commits
v0.4.0-alp
...
v0.4.2-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
fdfa8d7713
|
|||
|
f5d1287948
|
|||
|
15f4278cb1
|
5
.github/workflows/tagged-release.yml
vendored
5
.github/workflows/tagged-release.yml
vendored
@@ -11,6 +11,11 @@ jobs:
|
|||||||
runs-on: "ubuntu-latest"
|
runs-on: "ubuntu-latest"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
- name: Setup Java
|
||||||
|
uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
distribution: 'adopt'
|
||||||
|
java-version: '11'
|
||||||
- name: Clone repository
|
- name: Clone repository
|
||||||
uses: GuillaumeFalourd/clone-github-repo-action@main
|
uses: GuillaumeFalourd/clone-github-repo-action@main
|
||||||
with:
|
with:
|
||||||
|
|||||||
37
README.md
37
README.md
@@ -4,31 +4,42 @@
|
|||||||
|
|
||||||
**WARNING: Currently, this code is mostly undocumented. Proceed with caution and a psychiatrist.**
|
**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
|
## 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`:
|
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
|
```java
|
||||||
var engine = new PolyfillEngine(new File("."));
|
var engine = new Engine(true /* false if you dont want debugging */);
|
||||||
var in = new BufferedReader(new InputStreamReader(System.in));
|
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();
|
engine.start();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
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();
|
// Push a message to the engine with the raw REPL code
|
||||||
Values.printValue(engine.context(), res);
|
var res = engine.pushMsg(
|
||||||
System.out.println();
|
false, new Context(engine).pushEnv(env),
|
||||||
|
new Filename("jscript", "repl.js"), raw, null
|
||||||
|
).await();
|
||||||
|
|
||||||
|
Values.printValue(null, res);
|
||||||
}
|
}
|
||||||
catch (EngineException e) {
|
catch (EngineException e) { Values.printError(e, ""); }
|
||||||
try {
|
catch (SyntaxException ex) {
|
||||||
System.out.println("Uncaught " + e.toString(engine.context()));
|
System.out.println("Syntax error:" + ex.msg);
|
||||||
}
|
|
||||||
catch (InterruptedException _e) { return; }
|
|
||||||
}
|
}
|
||||||
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.Context;
|
||||||
import me.topchetoeu.jscript.engine.Engine;
|
import me.topchetoeu.jscript.engine.Engine;
|
||||||
import me.topchetoeu.jscript.engine.Environment;
|
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.DebugServer;
|
||||||
import me.topchetoeu.jscript.engine.debug.SimpleDebugger;
|
import me.topchetoeu.jscript.engine.debug.SimpleDebugger;
|
||||||
import me.topchetoeu.jscript.engine.values.ArrayValue;
|
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.engine.values.Values;
|
||||||
import me.topchetoeu.jscript.events.Observer;
|
import me.topchetoeu.jscript.events.Observer;
|
||||||
import me.topchetoeu.jscript.exceptions.EngineException;
|
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));
|
System.out.println(String.format("Running %s v%s by %s", Metadata.NAME, Metadata.VERSION, Metadata.AUTHOR));
|
||||||
engine = new Engine(true);
|
engine = new Engine(true);
|
||||||
|
|
||||||
env = new Environment(null, null, null);
|
|
||||||
var exited = new boolean[1];
|
var exited = new boolean[1];
|
||||||
var server = new DebugServer();
|
var server = new DebugServer();
|
||||||
server.targets.put("target", (ws, req) -> new SimpleDebugger(ws, engine));
|
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();
|
engineTask = engine.start();
|
||||||
debugTask = server.start(new InetSocketAddress("127.0.0.1", 9229), true);
|
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 {
|
try {
|
||||||
var tsEnv = env.child();
|
var tsEnv = Internals.apply(new Environment(null, null, null));
|
||||||
tsEnv.global.define(null, "module", false, new ObjectValue());
|
var bsEnv = Internals.apply(new Environment(null, null, null));
|
||||||
|
|
||||||
engine.pushMsg(
|
engine.pushMsg(
|
||||||
false, new Context(engine).pushEnv(tsEnv),
|
false, new Context(engine, tsEnv),
|
||||||
new Filename("jscript", "ts.js"),
|
new Filename("jscript", "ts.js"),
|
||||||
Reading.resourceToString("js/ts.js"), null
|
Reading.resourceToString("js/ts.js"), null
|
||||||
).await();
|
).await();
|
||||||
System.out.println("Loaded typescript!");
|
System.out.println("Loaded typescript!");
|
||||||
|
|
||||||
var ctx = new Context(engine).pushEnv(env.child());
|
var ctx = new Context(engine, bsEnv);
|
||||||
|
|
||||||
engine.pushMsg(
|
engine.pushMsg(
|
||||||
false, ctx,
|
false, ctx,
|
||||||
|
|||||||
@@ -24,9 +24,7 @@ public class CompoundStatement extends Statement {
|
|||||||
public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) {
|
public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) {
|
||||||
for (var stm : statements) {
|
for (var stm : statements) {
|
||||||
if (stm instanceof FunctionStatement) {
|
if (stm instanceof FunctionStatement) {
|
||||||
int start = target.size();
|
|
||||||
((FunctionStatement)stm).compile(target, scope, null, true);
|
((FunctionStatement)stm).compile(target, scope, null, true);
|
||||||
target.setDebug(start);
|
|
||||||
target.add(Instruction.discard());
|
target.add(Instruction.discard());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,11 @@ public class Context {
|
|||||||
this.engine = engine;
|
this.engine = engine;
|
||||||
}
|
}
|
||||||
public Context(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);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ public class Engine implements DebugController {
|
|||||||
private LinkedBlockingDeque<Task> microTasks = new LinkedBlockingDeque<>();
|
private LinkedBlockingDeque<Task> microTasks = new LinkedBlockingDeque<>();
|
||||||
|
|
||||||
public final int id = ++nextId;
|
public final int id = ++nextId;
|
||||||
public final Data data = new Data().set(StackData.MAX_FRAMES, 200);
|
public final Data data = new Data().set(StackData.MAX_FRAMES, 10000);
|
||||||
public final boolean debugging;
|
public final boolean debugging;
|
||||||
private final HashMap<Filename, String> sources = new HashMap<>();
|
private final HashMap<Filename, String> sources = new HashMap<>();
|
||||||
private final HashMap<Filename, TreeSet<Location>> bpts = new HashMap<>();
|
private final HashMap<Filename, TreeSet<Location>> bpts = new HashMap<>();
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ public class StackData {
|
|||||||
public static void pushFrame(Context ctx, CodeFrame frame) {
|
public static void pushFrame(Context ctx, CodeFrame frame) {
|
||||||
var frames = ctx.data.get(FRAMES, new ArrayList<>());
|
var frames = ctx.data.get(FRAMES, new ArrayList<>());
|
||||||
frames.add(frame);
|
frames.add(frame);
|
||||||
if (frames.size() > ctx.data.get(MAX_FRAMES, 10000)) throw EngineException.ofRange("Stack overflow!");
|
if (frames.size() > ctx.data.get(MAX_FRAMES, 10000))
|
||||||
|
throw EngineException.ofRange("Stack overflow!");
|
||||||
ctx.pushEnv(frame.function.environment);
|
ctx.pushEnv(frame.function.environment);
|
||||||
}
|
}
|
||||||
public static boolean popFrame(Context ctx, CodeFrame frame) {
|
public static boolean popFrame(Context ctx, CodeFrame frame) {
|
||||||
|
|||||||
@@ -112,7 +112,6 @@ public class SimpleDebugger implements Debugger {
|
|||||||
this.frame = frame;
|
this.frame = frame;
|
||||||
this.func = frame.function;
|
this.func = frame.function;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.local = new ObjectValue();
|
|
||||||
this.location = frame.function.loc();
|
this.location = frame.function.loc();
|
||||||
|
|
||||||
this.global = frame.function.environment.global.obj;
|
this.global = frame.function.environment.global.obj;
|
||||||
|
|||||||
@@ -596,6 +596,16 @@ public class Values {
|
|||||||
return fromJavaIterator(ctx, it.iterator());
|
return fromJavaIterator(ctx, it.iterator());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isEmptyFunc(ObjectValue val) {
|
||||||
|
if (!(val instanceof FunctionValue)) return false;
|
||||||
|
if (!val.values.containsKey("prototype") || val.values.size() + val.properties.size() > 1) return false;
|
||||||
|
var proto = val.values.get("prototype");
|
||||||
|
if (!(proto instanceof ObjectValue)) return false;
|
||||||
|
var protoObj = (ObjectValue)proto;
|
||||||
|
if (protoObj.values.get("constructor") != val) return false;
|
||||||
|
if (protoObj.values.size() + protoObj.properties.size() != 1) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
private static void printValue(Context ctx, Object val, HashSet<Object> passed, int tab) {
|
private static void printValue(Context ctx, Object val, HashSet<Object> passed, int tab) {
|
||||||
if (tab == 0 && val instanceof String) {
|
if (tab == 0 && val instanceof String) {
|
||||||
System.out.print(val);
|
System.out.print(val);
|
||||||
@@ -643,7 +653,7 @@ public class Values {
|
|||||||
passed.add(val);
|
passed.add(val);
|
||||||
|
|
||||||
var obj = (ObjectValue)val;
|
var obj = (ObjectValue)val;
|
||||||
if (obj.values.size() + obj.properties.size() == 0) {
|
if (obj.values.size() + obj.properties.size() == 0 || isEmptyFunc(obj)) {
|
||||||
if (!printed) System.out.println("{}");
|
if (!printed) System.out.println("{}");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -661,12 +671,13 @@ public class Values {
|
|||||||
printValue(ctx, el.getKey(), passed, tab + 1);
|
printValue(ctx, el.getKey(), passed, tab + 1);
|
||||||
System.out.println(": [prop],");
|
System.out.println(": [prop],");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < tab; i++) System.out.print(" ");
|
for (int i = 0; i < tab; i++) System.out.print(" ");
|
||||||
System.out.print("}");
|
System.out.print("}");
|
||||||
|
|
||||||
passed.remove(val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
passed.remove(val);
|
||||||
}
|
}
|
||||||
else if (val == null) System.out.print("undefined");
|
else if (val == null) System.out.print("undefined");
|
||||||
else if (val == Values.NULL) System.out.print("null");
|
else if (val == Values.NULL) System.out.print("null");
|
||||||
|
|||||||
15
src/me/topchetoeu/jscript/js/bootstrap.js
vendored
15
src/me/topchetoeu/jscript/js/bootstrap.js
vendored
@@ -1,6 +1,6 @@
|
|||||||
(function (_arguments) {
|
(function (_arguments) {
|
||||||
var ts = _arguments[0];
|
var ts = _arguments[0];
|
||||||
var src = '', lib = _arguments[2].concat([ 'declare const exit: never;' ]).join(''), decls = '', version = 0;
|
var src = '', lib = _arguments[2].concat([ 'declare const exit: never; declare const go: any;' ]).join(''), decls = '', version = 0;
|
||||||
var libSnapshot = ts.ScriptSnapshot.fromString(lib);
|
var libSnapshot = ts.ScriptSnapshot.fromString(lib);
|
||||||
|
|
||||||
var settings = {
|
var settings = {
|
||||||
@@ -20,11 +20,11 @@
|
|||||||
var reg = ts.createDocumentRegistry();
|
var reg = ts.createDocumentRegistry();
|
||||||
var service = ts.createLanguageService({
|
var service = ts.createLanguageService({
|
||||||
getCurrentDirectory: function() { return "/"; },
|
getCurrentDirectory: function() { return "/"; },
|
||||||
getDefaultLibFileName: function() { return "/lib_.d.ts"; },
|
getDefaultLibFileName: function() { return "/lib.d.ts"; },
|
||||||
getScriptFileNames: function() { return [ "/src.ts", "/lib.d.ts", "/glob.d.ts" ]; },
|
getScriptFileNames: function() { return [ "/src.ts", "/lib.d.ts", "/glob.d.ts" ]; },
|
||||||
getCompilationSettings: function () { return settings; },
|
getCompilationSettings: function () { return settings; },
|
||||||
fileExists: function(filename) { return filename === "/lib.d.ts" || filename === "/src.ts" || filename === "/glob.d.ts"; },
|
fileExists: function(filename) { return filename === "/lib.d.ts" || filename === "/src.ts" || filename === "/glob.d.ts"; },
|
||||||
|
|
||||||
getScriptSnapshot: function(filename) {
|
getScriptSnapshot: function(filename) {
|
||||||
if (filename === "/lib.d.ts") return libSnapshot;
|
if (filename === "/lib.d.ts") return libSnapshot;
|
||||||
if (filename === "/src.ts") return ts.ScriptSnapshot.fromString(src);
|
if (filename === "/src.ts") return ts.ScriptSnapshot.fromString(src);
|
||||||
@@ -37,11 +37,12 @@
|
|||||||
},
|
},
|
||||||
}, reg);
|
}, reg);
|
||||||
|
|
||||||
service.getEmitOutput('/lib.d.ts');
|
service.getEmitOutput("/lib.d.ts");
|
||||||
log('Loaded libraries!');
|
log("Loaded libraries!");
|
||||||
|
|
||||||
function compile(code, filename) {
|
function compile(code, filename) {
|
||||||
src = code, version++;
|
src = code;
|
||||||
|
version++;
|
||||||
|
|
||||||
var emit = service.getEmitOutput("/src.ts");
|
var emit = service.getEmitOutput("/src.ts");
|
||||||
|
|
||||||
@@ -61,7 +62,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (diagnostics.length > 0) {
|
if (diagnostics.length > 0) {
|
||||||
throw new SyntaxError(diagnostics.join('\n'));
|
throw new SyntaxError(diagnostics.join("\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -309,8 +309,9 @@ import me.topchetoeu.jscript.interop.NativeSetter;
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Native(thisArg = true) public static ArrayValue splice(Context ctx, ArrayValue arr, int start, int deleteCount, Object ...items) {
|
@Native(thisArg = true) public static ArrayValue splice(Context ctx, ArrayValue arr, int start, Object _deleteCount, Object ...items) {
|
||||||
start = normalizeI(arr.size(), start, true);
|
start = normalizeI(arr.size(), start, true);
|
||||||
|
int deleteCount = _deleteCount == null ? arr.size() - 1 : (int)Values.toNumber(ctx, _deleteCount);
|
||||||
deleteCount = normalizeI(arr.size(), deleteCount, true);
|
deleteCount = normalizeI(arr.size(), deleteCount, true);
|
||||||
if (start + deleteCount >= arr.size()) deleteCount = arr.size() - start;
|
if (start + deleteCount >= arr.size()) deleteCount = arr.size() - start;
|
||||||
|
|
||||||
@@ -323,9 +324,6 @@ import me.topchetoeu.jscript.interop.NativeSetter;
|
|||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@Native(thisArg = true) public static ArrayValue splice(Context ctx, ArrayValue arr, int start) {
|
|
||||||
return splice(ctx, arr, start, arr.size() - start);
|
|
||||||
}
|
|
||||||
@Native(thisArg = true) public static String toString(Context ctx, ArrayValue arr) {
|
@Native(thisArg = true) public static String toString(Context ctx, ArrayValue arr) {
|
||||||
return join(ctx, arr, ",");
|
return join(ctx, arr, ",");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,15 @@ public class Internals {
|
|||||||
private static final DataKey<Integer> I = new DataKey<>();
|
private static final DataKey<Integer> I = new DataKey<>();
|
||||||
|
|
||||||
|
|
||||||
@Native public static void log(Context ctx, Object ...args) {
|
@Native public static Object log(Context ctx, Object ...args) {
|
||||||
for (var arg : args) {
|
for (var arg : args) {
|
||||||
Values.printValue(ctx, arg);
|
Values.printValue(ctx, arg);
|
||||||
System.out.print(" ");
|
System.out.print(" ");
|
||||||
}
|
}
|
||||||
System.out.println();
|
System.out.println();
|
||||||
|
|
||||||
|
if (args.length == 0) return null;
|
||||||
|
else return args[0];
|
||||||
}
|
}
|
||||||
@Native public static String readline(Context ctx) {
|
@Native public static String readline(Context ctx) {
|
||||||
try {
|
try {
|
||||||
@@ -110,7 +113,7 @@ public class Internals {
|
|||||||
return Double.POSITIVE_INFINITY;
|
return Double.POSITIVE_INFINITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void apply(Environment env) {
|
public static Environment apply(Environment env) {
|
||||||
var wp = env.wrappers;
|
var wp = env.wrappers;
|
||||||
var glob = env.global = new GlobalScope(wp.getNamespace(Internals.class));
|
var glob = env.global = new GlobalScope(wp.getNamespace(Internals.class));
|
||||||
|
|
||||||
@@ -154,6 +157,6 @@ public class Internals {
|
|||||||
wp.getProto(ObjectLib.class).setPrototype(null, null);
|
wp.getProto(ObjectLib.class).setPrototype(null, null);
|
||||||
env.regexConstructor = wp.getConstr(RegExpLib.class);
|
env.regexConstructor = wp.getConstr(RegExpLib.class);
|
||||||
|
|
||||||
System.out.println("Loaded polyfills!");
|
return env;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user