refactor: improve Engine API
This commit is contained in:
parent
93973c12b1
commit
078d7ed95f
@ -1,170 +1,168 @@
|
|||||||
package me.topchetoeu.jscript;
|
package me.topchetoeu.jscript;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
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.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.NativeFunction;
|
||||||
import me.topchetoeu.jscript.engine.values.ObjectValue;
|
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;
|
||||||
import me.topchetoeu.jscript.exceptions.InterruptException;
|
import me.topchetoeu.jscript.exceptions.InterruptException;
|
||||||
import me.topchetoeu.jscript.exceptions.SyntaxException;
|
import me.topchetoeu.jscript.exceptions.SyntaxException;
|
||||||
import me.topchetoeu.jscript.filesystem.MemoryFilesystem;
|
import me.topchetoeu.jscript.filesystem.MemoryFilesystem;
|
||||||
import me.topchetoeu.jscript.filesystem.Mode;
|
import me.topchetoeu.jscript.filesystem.Mode;
|
||||||
import me.topchetoeu.jscript.filesystem.PhysicalFilesystem;
|
import me.topchetoeu.jscript.filesystem.PhysicalFilesystem;
|
||||||
import me.topchetoeu.jscript.lib.Internals;
|
import me.topchetoeu.jscript.lib.Internals;
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
public static class Printer implements Observer<Object> {
|
public static class Printer implements Observer<Object> {
|
||||||
public void next(Object data) {
|
public void next(Object data) {
|
||||||
Values.printValue(null, data);
|
Values.printValue(null, data);
|
||||||
System.out.println();
|
System.out.println();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void error(RuntimeException err) {
|
public void error(RuntimeException err) {
|
||||||
Values.printError(err, null);
|
Values.printError(err, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void finish() {
|
public void finish() {
|
||||||
engineTask.interrupt();
|
engineTask.interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Thread engineTask, debugTask;
|
static Thread engineTask, debugTask;
|
||||||
static Engine engine = new Engine(true);
|
static Engine engine = new Engine(true);
|
||||||
static DebugServer debugServer = new DebugServer();
|
static DebugServer debugServer = new DebugServer();
|
||||||
static Environment environment = new Environment(null, null, null);
|
static Environment environment = new Environment(null, null, null);
|
||||||
|
|
||||||
static int j = 0;
|
static int j = 0;
|
||||||
static boolean exited = false;
|
static boolean exited = false;
|
||||||
static String[] args;
|
static String[] args;
|
||||||
|
|
||||||
private static void reader() {
|
private static void reader() {
|
||||||
try {
|
try {
|
||||||
for (var arg : args) {
|
for (var arg : args) {
|
||||||
try {
|
try {
|
||||||
if (arg.equals("--ts")) initTypescript();
|
if (arg.equals("--ts")) initTypescript();
|
||||||
else {
|
else {
|
||||||
var file = Path.of(arg);
|
var file = Path.of(arg);
|
||||||
var raw = Files.readString(file);
|
var raw = Files.readString(file);
|
||||||
var res = engine.pushMsg(
|
var res = engine.pushMsg(
|
||||||
false, new Context(engine, environment),
|
false, environment,
|
||||||
Filename.fromFile(file.toFile()),
|
Filename.fromFile(file.toFile()),
|
||||||
raw, null
|
raw, null
|
||||||
).await();
|
).await();
|
||||||
Values.printValue(null, res);
|
Values.printValue(null, res);
|
||||||
System.out.println();
|
System.out.println();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (EngineException e) { Values.printError(e, null); }
|
catch (EngineException e) { Values.printError(e, null); }
|
||||||
}
|
}
|
||||||
for (var i = 0; ; i++) {
|
for (var i = 0; ; i++) {
|
||||||
try {
|
try {
|
||||||
var raw = Reading.read();
|
var raw = Reading.read();
|
||||||
|
|
||||||
if (raw == null) break;
|
if (raw == null) break;
|
||||||
var res = engine.pushMsg(
|
var res = engine.pushMsg(
|
||||||
false, new Context(engine, environment),
|
false, environment,
|
||||||
new Filename("jscript", "repl/" + i + ".js"),
|
new Filename("jscript", "repl/" + i + ".js"),
|
||||||
raw, null
|
raw, null
|
||||||
).await();
|
).await();
|
||||||
Values.printValue(null, res);
|
Values.printValue(null, res);
|
||||||
System.out.println();
|
System.out.println();
|
||||||
}
|
}
|
||||||
catch (EngineException e) { Values.printError(e, null); }
|
catch (EngineException e) { Values.printError(e, null); }
|
||||||
catch (SyntaxException e) { Values.printError(e, null); }
|
catch (SyntaxException e) { Values.printError(e, null); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
System.out.println(e.toString());
|
System.out.println(e.toString());
|
||||||
exited = true;
|
exited = true;
|
||||||
}
|
}
|
||||||
catch (RuntimeException ex) {
|
catch (RuntimeException ex) {
|
||||||
if (!exited) {
|
if (!exited) {
|
||||||
System.out.println("Internal error ocurred:");
|
System.out.println("Internal error ocurred:");
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (exited) {
|
if (exited) {
|
||||||
debugTask.interrupt();
|
debugTask.interrupt();
|
||||||
engineTask.interrupt();
|
engineTask.interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void initEnv() {
|
private static void initEnv() {
|
||||||
environment = Internals.apply(environment);
|
environment = Internals.apply(environment);
|
||||||
|
|
||||||
environment.global.define(false, new NativeFunction("exit", (_ctx, th, args) -> {
|
environment.global.define(false, new NativeFunction("exit", (_ctx, th, args) -> {
|
||||||
exited = true;
|
exited = true;
|
||||||
throw new InterruptException();
|
throw new InterruptException();
|
||||||
}));
|
}));
|
||||||
environment.global.define(false, new NativeFunction("go", (_ctx, th, args) -> {
|
environment.global.define(false, new NativeFunction("go", (_ctx, th, args) -> {
|
||||||
try {
|
try {
|
||||||
var f = Path.of("do.js");
|
var f = Path.of("do.js");
|
||||||
var func = _ctx.compile(new Filename("do", "do/" + j++ + ".js"), new String(Files.readAllBytes(f)));
|
var func = _ctx.compile(new Filename("do", "do/" + j++ + ".js"), new String(Files.readAllBytes(f)));
|
||||||
return func.call(_ctx);
|
return func.call(_ctx);
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
throw new EngineException("Couldn't open do.js");
|
throw new EngineException("Couldn't open do.js");
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
environment.filesystem.protocols.put("temp", new MemoryFilesystem(Mode.READ_WRITE));
|
environment.filesystem.protocols.put("temp", new MemoryFilesystem(Mode.READ_WRITE));
|
||||||
environment.filesystem.protocols.put("file", new PhysicalFilesystem(Path.of(".").toAbsolutePath()));
|
environment.filesystem.protocols.put("file", new PhysicalFilesystem(Path.of(".").toAbsolutePath()));
|
||||||
}
|
}
|
||||||
private static void initEngine() {
|
private static void initEngine() {
|
||||||
debugServer.targets.put("target", (ws, req) -> new SimpleDebugger(ws, engine));
|
debugServer.targets.put("target", (ws, req) -> new SimpleDebugger(ws, engine));
|
||||||
engineTask = engine.start();
|
engineTask = engine.start();
|
||||||
debugTask = debugServer.start(new InetSocketAddress("127.0.0.1", 9229), true);
|
debugTask = debugServer.start(new InetSocketAddress("127.0.0.1", 9229), true);
|
||||||
}
|
}
|
||||||
private static void initTypescript() {
|
private static void initTypescript() {
|
||||||
try {
|
try {
|
||||||
var tsEnv = Internals.apply(new Environment(null, null, null));
|
var tsEnv = Internals.apply(new Environment(null, null, null));
|
||||||
tsEnv.stackVisible = false;
|
tsEnv.stackVisible = false;
|
||||||
tsEnv.global.define(null, "module", false, new ObjectValue());
|
tsEnv.global.define(null, "module", false, new ObjectValue());
|
||||||
var bsEnv = Internals.apply(new Environment(null, null, null));
|
var bsEnv = Internals.apply(new Environment(null, null, null));
|
||||||
bsEnv.stackVisible = false;
|
bsEnv.stackVisible = false;
|
||||||
|
|
||||||
engine.pushMsg(
|
engine.pushMsg(
|
||||||
false, new Context(engine, tsEnv),
|
false, 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, bsEnv);
|
engine.pushMsg(
|
||||||
|
false, bsEnv,
|
||||||
engine.pushMsg(
|
new Filename("jscript", "bootstrap.js"), Reading.resourceToString("js/bootstrap.js"), null,
|
||||||
false, ctx,
|
tsEnv.global.get(new Context(engine, bsEnv), "ts"), environment, new ArrayValue(null, Reading.resourceToString("js/lib.d.ts"))
|
||||||
new Filename("jscript", "bootstrap.js"), Reading.resourceToString("js/bootstrap.js"), null,
|
).await();
|
||||||
tsEnv.global.get(ctx, "ts"), environment, new ArrayValue(null, Reading.resourceToString("js/lib.d.ts"))
|
}
|
||||||
).await();
|
catch (EngineException e) {
|
||||||
}
|
Values.printError(e, "(while initializing TS)");
|
||||||
catch (EngineException e) {
|
}
|
||||||
Values.printError(e, "(while initializing TS)");
|
}
|
||||||
}
|
|
||||||
}
|
public static void main(String args[]) {
|
||||||
|
System.out.println(String.format("Running %s v%s by %s", Metadata.name(), Metadata.version(), Metadata.author()));
|
||||||
public static void main(String args[]) {
|
|
||||||
System.out.println(String.format("Running %s v%s by %s", Metadata.name(), Metadata.version(), Metadata.author()));
|
Main.args = args;
|
||||||
|
var reader = new Thread(Main::reader);
|
||||||
Main.args = args;
|
|
||||||
var reader = new Thread(Main::reader);
|
initEnv();
|
||||||
|
initEngine();
|
||||||
initEnv();
|
|
||||||
initEngine();
|
reader.setDaemon(true);
|
||||||
|
reader.setName("STD Reader");
|
||||||
reader.setDaemon(true);
|
reader.start();
|
||||||
reader.setName("STD Reader");
|
}
|
||||||
reader.start();
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -119,7 +119,6 @@ public class Context {
|
|||||||
}
|
}
|
||||||
public Context(Engine engine, Environment env) {
|
public Context(Engine engine, Environment env) {
|
||||||
this(engine);
|
this(engine);
|
||||||
this.pushEnv(env);
|
if (env != null) this.pushEnv(env);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,13 +141,13 @@ public class Engine implements DebugController {
|
|||||||
return this.thread != null;
|
return this.thread != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Awaitable<Object> pushMsg(boolean micro, Context ctx, FunctionValue func, Object thisArg, Object ...args) {
|
public Awaitable<Object> pushMsg(boolean micro, Environment env, FunctionValue func, Object thisArg, Object ...args) {
|
||||||
var msg = new Task(ctx == null ? new Context(this) : ctx, func, thisArg, args, micro);
|
var msg = new Task(new Context(this, env), func, thisArg, args, micro);
|
||||||
tasks.add(msg);
|
tasks.add(msg);
|
||||||
return msg.notifier;
|
return msg.notifier;
|
||||||
}
|
}
|
||||||
public Awaitable<Object> pushMsg(boolean micro, Context ctx, Filename filename, String raw, Object thisArg, Object ...args) {
|
public Awaitable<Object> pushMsg(boolean micro, Environment env, Filename filename, String raw, Object thisArg, Object ...args) {
|
||||||
return pushMsg(micro, ctx, new UncompiledFunction(filename, raw), thisArg, args);
|
return pushMsg(micro, env, new UncompiledFunction(filename, raw), thisArg, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -53,7 +53,6 @@ public class Environment implements PermissionsProvider {
|
|||||||
res.defineProperty(ctx, "function", target.func(env));
|
res.defineProperty(ctx, "function", target.func(env));
|
||||||
res.defineProperty(ctx, "mapChain", new ArrayValue());
|
res.defineProperty(ctx, "mapChain", new ArrayValue());
|
||||||
|
|
||||||
|
|
||||||
if (isDebug) {
|
if (isDebug) {
|
||||||
res.defineProperty(ctx, "breakpoints", ArrayValue.of(ctx, target.breakpoints.stream().map(Location::toString).collect(Collectors.toList())));
|
res.defineProperty(ctx, "breakpoints", ArrayValue.of(ctx, target.breakpoints.stream().map(Location::toString).collect(Collectors.toList())));
|
||||||
}
|
}
|
||||||
@ -128,4 +127,7 @@ public class Environment implements PermissionsProvider {
|
|||||||
this.wrappers = nativeConverter;
|
this.wrappers = nativeConverter;
|
||||||
this.global = global;
|
this.global = global;
|
||||||
}
|
}
|
||||||
|
public Environment() {
|
||||||
|
this(null, null, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -483,7 +483,7 @@ public class SimpleDebugger implements Debugger {
|
|||||||
env.global = new GlobalScope(codeFrame.local);
|
env.global = new GlobalScope(codeFrame.local);
|
||||||
|
|
||||||
var ctx = new Context(engine).pushEnv(env);
|
var ctx = new Context(engine).pushEnv(env);
|
||||||
var awaiter = engine.pushMsg(false, ctx, new Filename("jscript", "eval"), code, codeFrame.frame.thisArg, codeFrame.frame.args);
|
var awaiter = engine.pushMsg(false, ctx.environment(), new Filename("jscript", "eval"), code, codeFrame.frame.thisArg, codeFrame.frame.args);
|
||||||
|
|
||||||
engine.run(true);
|
engine.run(true);
|
||||||
|
|
||||||
|
@ -1,221 +1,221 @@
|
|||||||
package me.topchetoeu.jscript.lib;
|
package me.topchetoeu.jscript.lib;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.Buffer;
|
import me.topchetoeu.jscript.Buffer;
|
||||||
import me.topchetoeu.jscript.Reading;
|
import me.topchetoeu.jscript.Reading;
|
||||||
import me.topchetoeu.jscript.engine.Context;
|
import me.topchetoeu.jscript.engine.Context;
|
||||||
import me.topchetoeu.jscript.engine.DataKey;
|
import me.topchetoeu.jscript.engine.DataKey;
|
||||||
import me.topchetoeu.jscript.engine.Environment;
|
import me.topchetoeu.jscript.engine.Environment;
|
||||||
import me.topchetoeu.jscript.engine.scope.GlobalScope;
|
import me.topchetoeu.jscript.engine.scope.GlobalScope;
|
||||||
import me.topchetoeu.jscript.engine.values.FunctionValue;
|
import me.topchetoeu.jscript.engine.values.FunctionValue;
|
||||||
import me.topchetoeu.jscript.engine.values.Values;
|
import me.topchetoeu.jscript.engine.values.Values;
|
||||||
import me.topchetoeu.jscript.exceptions.EngineException;
|
import me.topchetoeu.jscript.exceptions.EngineException;
|
||||||
import me.topchetoeu.jscript.interop.Native;
|
import me.topchetoeu.jscript.interop.Native;
|
||||||
import me.topchetoeu.jscript.interop.NativeGetter;
|
import me.topchetoeu.jscript.interop.NativeGetter;
|
||||||
import me.topchetoeu.jscript.parsing.Parsing;
|
import me.topchetoeu.jscript.parsing.Parsing;
|
||||||
|
|
||||||
public class Internals {
|
public class Internals {
|
||||||
private static final DataKey<HashMap<Integer, Thread>> THREADS = new DataKey<>();
|
private static final DataKey<HashMap<Integer, Thread>> THREADS = new DataKey<>();
|
||||||
private static final DataKey<Integer> I = new DataKey<>();
|
private static final DataKey<Integer> I = new DataKey<>();
|
||||||
|
|
||||||
|
|
||||||
@Native public static Object 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;
|
if (args.length == 0) return null;
|
||||||
else return args[0];
|
else return args[0];
|
||||||
}
|
}
|
||||||
@Native public static String readline(Context ctx) {
|
@Native public static String readline(Context ctx) {
|
||||||
try {
|
try {
|
||||||
return Reading.read();
|
return Reading.read();
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Native public static int setTimeout(Context ctx, FunctionValue func, int delay, Object ...args) {
|
@Native public static int setTimeout(Context ctx, FunctionValue func, int delay, Object ...args) {
|
||||||
var thread = new Thread(() -> {
|
var thread = new Thread(() -> {
|
||||||
var ms = (long)delay;
|
var ms = (long)delay;
|
||||||
var ns = (int)((delay - ms) * 10000000);
|
var ns = (int)((delay - ms) * 10000000);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Thread.sleep(ms, ns);
|
Thread.sleep(ms, ns);
|
||||||
}
|
}
|
||||||
catch (InterruptedException e) { return; }
|
catch (InterruptedException e) { return; }
|
||||||
|
|
||||||
ctx.engine.pushMsg(false, ctx, func, null, args);
|
ctx.engine.pushMsg(false, ctx.environment(), func, null, args);
|
||||||
});
|
});
|
||||||
thread.start();
|
thread.start();
|
||||||
|
|
||||||
int i = ctx.environment().data.increase(I, 1, 0);
|
int i = ctx.environment().data.increase(I, 1, 0);
|
||||||
var threads = ctx.environment().data.get(THREADS, new HashMap<>());
|
var threads = ctx.environment().data.get(THREADS, new HashMap<>());
|
||||||
threads.put(++i, thread);
|
threads.put(++i, thread);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
@Native public static int setInterval(Context ctx, FunctionValue func, int delay, Object ...args) {
|
@Native public static int setInterval(Context ctx, FunctionValue func, int delay, Object ...args) {
|
||||||
var thread = new Thread(() -> {
|
var thread = new Thread(() -> {
|
||||||
var ms = (long)delay;
|
var ms = (long)delay;
|
||||||
var ns = (int)((delay - ms) * 10000000);
|
var ns = (int)((delay - ms) * 10000000);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(ms, ns);
|
Thread.sleep(ms, ns);
|
||||||
}
|
}
|
||||||
catch (InterruptedException e) { return; }
|
catch (InterruptedException e) { return; }
|
||||||
|
|
||||||
ctx.engine.pushMsg(false, ctx, func, null, args);
|
ctx.engine.pushMsg(false, ctx.environment(), func, null, args);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
thread.start();
|
thread.start();
|
||||||
|
|
||||||
int i = ctx.environment().data.increase(I, 1, 0);
|
int i = ctx.environment().data.increase(I, 1, 0);
|
||||||
var threads = ctx.environment().data.get(THREADS, new HashMap<>());
|
var threads = ctx.environment().data.get(THREADS, new HashMap<>());
|
||||||
threads.put(++i, thread);
|
threads.put(++i, thread);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Native public static void clearTimeout(Context ctx, int i) {
|
@Native public static void clearTimeout(Context ctx, int i) {
|
||||||
var threads = ctx.environment().data.get(THREADS, new HashMap<>());
|
var threads = ctx.environment().data.get(THREADS, new HashMap<>());
|
||||||
|
|
||||||
var thread = threads.remove(i);
|
var thread = threads.remove(i);
|
||||||
if (thread != null) thread.interrupt();
|
if (thread != null) thread.interrupt();
|
||||||
}
|
}
|
||||||
@Native public static void clearInterval(Context ctx, int i) {
|
@Native public static void clearInterval(Context ctx, int i) {
|
||||||
clearTimeout(ctx, i);
|
clearTimeout(ctx, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Native public static double parseInt(Context ctx, String val) {
|
@Native public static double parseInt(Context ctx, String val) {
|
||||||
return NumberLib.parseInt(ctx, val);
|
return NumberLib.parseInt(ctx, val);
|
||||||
}
|
}
|
||||||
@Native public static double parseFloat(Context ctx, String val) {
|
@Native public static double parseFloat(Context ctx, String val) {
|
||||||
return NumberLib.parseFloat(ctx, val);
|
return NumberLib.parseFloat(ctx, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Native public static boolean isNaN(Context ctx, double val) {
|
@Native public static boolean isNaN(Context ctx, double val) {
|
||||||
return NumberLib.isNaN(ctx, val);
|
return NumberLib.isNaN(ctx, val);
|
||||||
}
|
}
|
||||||
@Native public static boolean isFinite(Context ctx, double val) {
|
@Native public static boolean isFinite(Context ctx, double val) {
|
||||||
return NumberLib.isFinite(ctx, val);
|
return NumberLib.isFinite(ctx, val);
|
||||||
}
|
}
|
||||||
@Native public static boolean isInfinite(Context ctx, double val) {
|
@Native public static boolean isInfinite(Context ctx, double val) {
|
||||||
return NumberLib.isInfinite(ctx, val);
|
return NumberLib.isInfinite(ctx, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NativeGetter public static double NaN(Context ctx) {
|
@NativeGetter public static double NaN(Context ctx) {
|
||||||
return Double.NaN;
|
return Double.NaN;
|
||||||
}
|
}
|
||||||
@NativeGetter public static double Infinity(Context ctx) {
|
@NativeGetter public static double Infinity(Context ctx) {
|
||||||
return Double.POSITIVE_INFINITY;
|
return Double.POSITIVE_INFINITY;
|
||||||
}
|
}
|
||||||
private static final String HEX = "0123456789ABCDEF";
|
private static final String HEX = "0123456789ABCDEF";
|
||||||
|
|
||||||
private static String encodeUriAny(String str, String keepAlphabet) {
|
private static String encodeUriAny(String str, String keepAlphabet) {
|
||||||
if (str == null) str = "undefined";
|
if (str == null) str = "undefined";
|
||||||
|
|
||||||
var bytes = str.getBytes();
|
var bytes = str.getBytes();
|
||||||
var sb = new StringBuilder(bytes.length);
|
var sb = new StringBuilder(bytes.length);
|
||||||
|
|
||||||
for (byte c : bytes) {
|
for (byte c : bytes) {
|
||||||
if (Parsing.isAlphanumeric((char)c) || Parsing.isAny((char)c, keepAlphabet)) sb.append((char)c);
|
if (Parsing.isAlphanumeric((char)c) || Parsing.isAny((char)c, keepAlphabet)) sb.append((char)c);
|
||||||
else {
|
else {
|
||||||
sb.append('%');
|
sb.append('%');
|
||||||
sb.append(HEX.charAt(c / 16));
|
sb.append(HEX.charAt(c / 16));
|
||||||
sb.append(HEX.charAt(c % 16));
|
sb.append(HEX.charAt(c % 16));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
private static String decodeUriAny(String str, String keepAlphabet) {
|
private static String decodeUriAny(String str, String keepAlphabet) {
|
||||||
if (str == null) str = "undefined";
|
if (str == null) str = "undefined";
|
||||||
|
|
||||||
var res = new Buffer();
|
var res = new Buffer();
|
||||||
var bytes = str.getBytes();
|
var bytes = str.getBytes();
|
||||||
|
|
||||||
for (var i = 0; i < bytes.length; i++) {
|
for (var i = 0; i < bytes.length; i++) {
|
||||||
var c = bytes[i];
|
var c = bytes[i];
|
||||||
if (c == '%') {
|
if (c == '%') {
|
||||||
if (i >= bytes.length - 2) throw EngineException.ofError("URIError", "URI malformed.");
|
if (i >= bytes.length - 2) throw EngineException.ofError("URIError", "URI malformed.");
|
||||||
var b = Parsing.fromHex((char)bytes[i + 1]) * 16 | Parsing.fromHex((char)bytes[i + 2]);
|
var b = Parsing.fromHex((char)bytes[i + 1]) * 16 | Parsing.fromHex((char)bytes[i + 2]);
|
||||||
if (!Parsing.isAny((char)b, keepAlphabet)) {
|
if (!Parsing.isAny((char)b, keepAlphabet)) {
|
||||||
i += 2;
|
i += 2;
|
||||||
res.append((byte)b);
|
res.append((byte)b);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res.append(c);
|
res.append(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new String(res.data());
|
return new String(res.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Native public static String encodeURIComponent(String str) {
|
@Native public static String encodeURIComponent(String str) {
|
||||||
return encodeUriAny(str, ".-_!~*'()");
|
return encodeUriAny(str, ".-_!~*'()");
|
||||||
}
|
}
|
||||||
@Native public static String decodeURIComponent(String str) {
|
@Native public static String decodeURIComponent(String str) {
|
||||||
return decodeUriAny(str, "");
|
return decodeUriAny(str, "");
|
||||||
}
|
}
|
||||||
@Native public static String encodeURI(String str) {
|
@Native public static String encodeURI(String str) {
|
||||||
return encodeUriAny(str, ";,/?:@&=+$#.-_!~*'()");
|
return encodeUriAny(str, ";,/?:@&=+$#.-_!~*'()");
|
||||||
}
|
}
|
||||||
@Native public static String decodeURI(String str) {
|
@Native public static String decodeURI(String str) {
|
||||||
return decodeUriAny(str, ",/?:@&=+$#.");
|
return decodeUriAny(str, ",/?:@&=+$#.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Environment 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));
|
||||||
|
|
||||||
glob.define(null, "Math", false, wp.getNamespace(MathLib.class));
|
glob.define(null, "Math", false, wp.getNamespace(MathLib.class));
|
||||||
glob.define(null, "JSON", false, wp.getNamespace(JSONLib.class));
|
glob.define(null, "JSON", false, wp.getNamespace(JSONLib.class));
|
||||||
glob.define(null, "Encoding", false, wp.getNamespace(EncodingLib.class));
|
glob.define(null, "Encoding", false, wp.getNamespace(EncodingLib.class));
|
||||||
glob.define(null, "Filesystem", false, wp.getNamespace(FilesystemLib.class));
|
glob.define(null, "Filesystem", false, wp.getNamespace(FilesystemLib.class));
|
||||||
|
|
||||||
glob.define(false, wp.getConstr(DateLib.class));
|
glob.define(false, wp.getConstr(DateLib.class));
|
||||||
glob.define(false, wp.getConstr(ObjectLib.class));
|
glob.define(false, wp.getConstr(ObjectLib.class));
|
||||||
glob.define(false, wp.getConstr(FunctionLib.class));
|
glob.define(false, wp.getConstr(FunctionLib.class));
|
||||||
glob.define(false, wp.getConstr(ArrayLib.class));
|
glob.define(false, wp.getConstr(ArrayLib.class));
|
||||||
|
|
||||||
glob.define(false, wp.getConstr(BooleanLib.class));
|
glob.define(false, wp.getConstr(BooleanLib.class));
|
||||||
glob.define(false, wp.getConstr(NumberLib.class));
|
glob.define(false, wp.getConstr(NumberLib.class));
|
||||||
glob.define(false, wp.getConstr(StringLib.class));
|
glob.define(false, wp.getConstr(StringLib.class));
|
||||||
glob.define(false, wp.getConstr(SymbolLib.class));
|
glob.define(false, wp.getConstr(SymbolLib.class));
|
||||||
|
|
||||||
glob.define(false, wp.getConstr(PromiseLib.class));
|
glob.define(false, wp.getConstr(PromiseLib.class));
|
||||||
glob.define(false, wp.getConstr(RegExpLib.class));
|
glob.define(false, wp.getConstr(RegExpLib.class));
|
||||||
glob.define(false, wp.getConstr(MapLib.class));
|
glob.define(false, wp.getConstr(MapLib.class));
|
||||||
glob.define(false, wp.getConstr(SetLib.class));
|
glob.define(false, wp.getConstr(SetLib.class));
|
||||||
|
|
||||||
glob.define(false, wp.getConstr(ErrorLib.class));
|
glob.define(false, wp.getConstr(ErrorLib.class));
|
||||||
glob.define(false, wp.getConstr(SyntaxErrorLib.class));
|
glob.define(false, wp.getConstr(SyntaxErrorLib.class));
|
||||||
glob.define(false, wp.getConstr(TypeErrorLib.class));
|
glob.define(false, wp.getConstr(TypeErrorLib.class));
|
||||||
glob.define(false, wp.getConstr(RangeErrorLib.class));
|
glob.define(false, wp.getConstr(RangeErrorLib.class));
|
||||||
|
|
||||||
env.setProto("object", wp.getProto(ObjectLib.class));
|
env.setProto("object", wp.getProto(ObjectLib.class));
|
||||||
env.setProto("function", wp.getProto(FunctionLib.class));
|
env.setProto("function", wp.getProto(FunctionLib.class));
|
||||||
env.setProto("array", wp.getProto(ArrayLib.class));
|
env.setProto("array", wp.getProto(ArrayLib.class));
|
||||||
|
|
||||||
env.setProto("bool", wp.getProto(BooleanLib.class));
|
env.setProto("bool", wp.getProto(BooleanLib.class));
|
||||||
env.setProto("number", wp.getProto(NumberLib.class));
|
env.setProto("number", wp.getProto(NumberLib.class));
|
||||||
env.setProto("string", wp.getProto(StringLib.class));
|
env.setProto("string", wp.getProto(StringLib.class));
|
||||||
env.setProto("symbol", wp.getProto(SymbolLib.class));
|
env.setProto("symbol", wp.getProto(SymbolLib.class));
|
||||||
|
|
||||||
env.setProto("error", wp.getProto(ErrorLib.class));
|
env.setProto("error", wp.getProto(ErrorLib.class));
|
||||||
env.setProto("syntaxErr", wp.getProto(SyntaxErrorLib.class));
|
env.setProto("syntaxErr", wp.getProto(SyntaxErrorLib.class));
|
||||||
env.setProto("typeErr", wp.getProto(TypeErrorLib.class));
|
env.setProto("typeErr", wp.getProto(TypeErrorLib.class));
|
||||||
env.setProto("rangeErr", wp.getProto(RangeErrorLib.class));
|
env.setProto("rangeErr", wp.getProto(RangeErrorLib.class));
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -253,7 +253,7 @@ import me.topchetoeu.jscript.interop.Native;
|
|||||||
this.val = val;
|
this.val = val;
|
||||||
this.state = STATE_FULFILLED;
|
this.state = STATE_FULFILLED;
|
||||||
|
|
||||||
ctx.engine.pushMsg(true, ctx, new NativeFunction((_ctx, _thisArg, _args) -> {
|
ctx.engine.pushMsg(true, ctx.environment(), new NativeFunction((_ctx, _thisArg, _args) -> {
|
||||||
for (var handle : handles) {
|
for (var handle : handles) {
|
||||||
handle.fulfilled.call(handle.ctx, null, val);
|
handle.fulfilled.call(handle.ctx, null, val);
|
||||||
}
|
}
|
||||||
@ -288,7 +288,7 @@ import me.topchetoeu.jscript.interop.Native;
|
|||||||
this.val = val;
|
this.val = val;
|
||||||
this.state = STATE_REJECTED;
|
this.state = STATE_REJECTED;
|
||||||
|
|
||||||
ctx.engine.pushMsg(true, ctx, new NativeFunction((_ctx, _thisArg, _args) -> {
|
ctx.engine.pushMsg(true, ctx.environment(), new NativeFunction((_ctx, _thisArg, _args) -> {
|
||||||
for (var handle : handles) handle.rejected.call(handle.ctx, null, val);
|
for (var handle : handles) handle.rejected.call(handle.ctx, null, val);
|
||||||
if (!handled) {
|
if (!handled) {
|
||||||
Values.printError(new EngineException(val).setCtx(ctx.environment(), ctx.engine), "(in promise)");
|
Values.printError(new EngineException(val).setCtx(ctx.environment(), ctx.engine), "(in promise)");
|
||||||
@ -305,9 +305,9 @@ import me.topchetoeu.jscript.interop.Native;
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handle(Context ctx, FunctionValue fulfill, FunctionValue reject) {
|
private void handle(Context ctx, FunctionValue fulfill, FunctionValue reject) {
|
||||||
if (state == STATE_FULFILLED) ctx.engine.pushMsg(true, ctx, fulfill, null, val);
|
if (state == STATE_FULFILLED) ctx.engine.pushMsg(true, ctx.environment(), fulfill, null, val);
|
||||||
else if (state == STATE_REJECTED) {
|
else if (state == STATE_REJECTED) {
|
||||||
ctx.engine.pushMsg(true, ctx, reject, null, val);
|
ctx.engine.pushMsg(true, ctx.environment(), reject, null, val);
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
else handles.add(new Handle(ctx, fulfill, reject));
|
else handles.add(new Handle(ctx, fulfill, reject));
|
||||||
|
Loading…
Reference in New Issue
Block a user