fix: reprogram standard library for env api

This commit is contained in:
2023-08-27 21:21:25 +03:00
parent 54c6af52cf
commit a1e07a8046
44 changed files with 2207 additions and 2333 deletions

View File

@@ -1,7 +1,6 @@
package me.topchetoeu.jscript;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
@@ -13,8 +12,6 @@ import me.topchetoeu.jscript.engine.values.Values;
import me.topchetoeu.jscript.events.Observer;
import me.topchetoeu.jscript.exceptions.EngineException;
import me.topchetoeu.jscript.exceptions.SyntaxException;
import me.topchetoeu.jscript.polyfills.PolyfillEngine;
import me.topchetoeu.jscript.polyfills.TypescriptEngine;
public class Main {
static Thread task;
@@ -54,7 +51,7 @@ public class Main {
public static void main(String args[]) {
var in = new BufferedReader(new InputStreamReader(System.in));
engine = new TypescriptEngine(new File("."));
engine = new Engine();
var scope = engine.global().globalChild();
var exited = new boolean[1];

View File

@@ -6,7 +6,6 @@ import me.topchetoeu.jscript.Location;
import me.topchetoeu.jscript.compilation.Instruction;
import me.topchetoeu.jscript.compilation.Statement;
import me.topchetoeu.jscript.compilation.control.ThrowStatement;
import me.topchetoeu.jscript.engine.CallContext;
import me.topchetoeu.jscript.engine.Operation;
import me.topchetoeu.jscript.engine.scope.ScopeRecord;
import me.topchetoeu.jscript.engine.values.Values;
@@ -52,40 +51,7 @@ public class OperationStatement extends Statement {
}
try {
var ctx = new CallContext(null);
switch (operation) {
case ADD: return new ConstantStatement(loc(), Values.add(ctx, vals[0], vals[1]));
case SUBTRACT: return new ConstantStatement(loc(), Values.subtract(ctx, vals[0], vals[1]));
case DIVIDE: return new ConstantStatement(loc(), Values.divide(ctx, vals[0], vals[1]));
case MULTIPLY: return new ConstantStatement(loc(), Values.multiply(ctx, vals[0], vals[1]));
case MODULO: return new ConstantStatement(loc(), Values.modulo(ctx, vals[0], vals[1]));
case AND: return new ConstantStatement(loc(), Values.and(ctx, vals[0], vals[1]));
case OR: return new ConstantStatement(loc(), Values.or(ctx, vals[0], vals[1]));
case XOR: return new ConstantStatement(loc(), Values.xor(ctx, vals[0], vals[1]));
case EQUALS: return new ConstantStatement(loc(), Values.strictEquals(vals[0], vals[1]));
case NOT_EQUALS: return new ConstantStatement(loc(), !Values.strictEquals(vals[0], vals[1]));
case LOOSE_EQUALS: return new ConstantStatement(loc(), Values.looseEqual(ctx, vals[0], vals[1]));
case LOOSE_NOT_EQUALS: return new ConstantStatement(loc(), !Values.looseEqual(ctx, vals[0], vals[1]));
case GREATER: return new ConstantStatement(loc(), Values.compare(ctx, vals[0], vals[1]) < 0);
case GREATER_EQUALS: return new ConstantStatement(loc(), Values.compare(ctx, vals[0], vals[1]) <= 0);
case LESS: return new ConstantStatement(loc(), Values.compare(ctx, vals[0], vals[1]) > 0);
case LESS_EQUALS: return new ConstantStatement(loc(), Values.compare(ctx, vals[0], vals[1]) >= 0);
case INVERSE: return new ConstantStatement(loc(), Values.bitwiseNot(ctx, vals[0]));
case NOT: return new ConstantStatement(loc(), Values.not(vals[0]));
case POS: return new ConstantStatement(loc(), Values.toNumber(ctx, vals[0]));
case NEG: return new ConstantStatement(loc(), Values.negative(ctx, vals[0]));
case SHIFT_LEFT: return new ConstantStatement(loc(), Values.shiftLeft(ctx, vals[0], vals[1]));
case SHIFT_RIGHT: return new ConstantStatement(loc(), Values.shiftRight(ctx, vals[0], vals[1]));
case USHIFT_RIGHT: return new ConstantStatement(loc(), Values.unsignedShiftRight(ctx, vals[0], vals[1]));
default: break;
}
return new ConstantStatement(loc(), Values.operation(null, operation, vals));
}
catch (EngineException e) {
return new ThrowStatement(loc(), new ConstantStatement(loc(), e.value));

View File

@@ -142,13 +142,6 @@ public class Engine {
}
}
public void exposeClass(String name, Class<?> clazz) {
global.define(name, true, typeRegister.getConstr(clazz));
}
public void exposeNamespace(String name, Class<?> clazz) {
global.define(name, true, NativeTypeRegister.makeNamespace(clazz));
}
public Thread start() {
if (this.thread == null) {
this.thread = new Thread(this::run, "JavaScript Runner #" + id);
@@ -176,6 +169,9 @@ public class Engine {
public ObjectValue getPrototype(Class<?> clazz) {
return typeRegister.getProto(clazz);
}
public FunctionValue getConstructor(Class<?> clazz) {
return typeRegister.getConstr(clazz);
}
public CallContext context() { return new CallContext(this).mergeData(callCtxVals); }
public Awaitable<Object> pushMsg(boolean micro, FunctionValue func, Map<DataKey<?>, Object> data, Object thisArg, Object... args) {

View File

@@ -93,13 +93,13 @@ public class CodeFrame {
return res;
}
public void push(Object val) {
public void push(CallContext ctx, Object val) {
if (stack.length <= stackPtr) {
var newStack = new Object[stack.length * 2];
System.arraycopy(stack, 0, newStack, 0, stack.length);
stack = newStack;
}
stack[stackPtr++] = Values.normalize(val);
stack[stackPtr++] = Values.normalize(ctx, val);
}
public void start(CallContext ctx) {
@@ -150,7 +150,7 @@ public class CodeFrame {
try {
this.jumpFlag = false;
return Runners.exec(debugCmd, instr, this, ctx);
return Runners.exec(ctx, debugCmd, instr, this);
}
catch (EngineException e) {
throw e.add(function.name, prevLoc);
@@ -307,13 +307,13 @@ public class CodeFrame {
}
}
public CodeFrame(Object thisArg, Object[] args, CodeFunction func) {
public CodeFrame(CallContext ctx, Object thisArg, Object[] args, CodeFunction func) {
this.args = args.clone();
this.scope = new LocalScope(func.localsN, func.captures);
this.scope.get(0).set(null, thisArg);
var argsObj = new ArrayValue();
for (var i = 0; i < args.length; i++) {
argsObj.set(i, args[i]);
argsObj.set(ctx, i, args[i]);
}
this.scope.get(1).value = argsObj;

View File

@@ -18,62 +18,62 @@ import me.topchetoeu.jscript.exceptions.EngineException;
public class Runners {
public static final Object NO_RETURN = new Object();
public static Object execReturn(Instruction instr, CodeFrame frame, CallContext ctx) {
public static Object execReturn(CallContext ctx, Instruction instr, CodeFrame frame) {
frame.codePtr++;
return frame.pop();
}
public static Object execSignal(Instruction instr, CodeFrame frame, CallContext ctx) {
public static Object execSignal(CallContext ctx, Instruction instr, CodeFrame frame) {
frame.codePtr++;
return new SignalValue(instr.get(0));
}
public static Object execThrow(Instruction instr, CodeFrame frame, CallContext ctx) {
public static Object execThrow(CallContext ctx, Instruction instr, CodeFrame frame) {
throw new EngineException(frame.pop());
}
public static Object execThrowSyntax(Instruction instr, CodeFrame frame, CallContext ctx) {
public static Object execThrowSyntax(CallContext ctx, Instruction instr, CodeFrame frame) {
throw EngineException.ofSyntax((String)instr.get(0));
}
private static Object call(DebugCommand state, CallContext ctx, Object func, Object thisArg, Object... args) throws InterruptedException {
private static Object call(CallContext ctx, DebugCommand state, Object func, Object thisArg, Object... args) throws InterruptedException {
ctx.setData(CodeFrame.STOP_AT_START_KEY, state == DebugCommand.STEP_INTO);
return Values.call(ctx, func, thisArg, args);
}
public static Object execCall(DebugCommand state, Instruction instr, CodeFrame frame, CallContext ctx) throws InterruptedException {
public static Object execCall(CallContext ctx, DebugCommand state, Instruction instr, CodeFrame frame) throws InterruptedException {
var callArgs = frame.take(instr.get(0));
var func = frame.pop();
var thisArg = frame.pop();
frame.push(call(state, ctx, func, thisArg, callArgs));
frame.push(ctx, call(ctx, state, func, thisArg, callArgs));
frame.codePtr++;
return NO_RETURN;
}
public static Object execCallNew(DebugCommand state, Instruction instr, CodeFrame frame, CallContext ctx) throws InterruptedException {
public static Object execCallNew(CallContext ctx, DebugCommand state, Instruction instr, CodeFrame frame) throws InterruptedException {
var callArgs = frame.take(instr.get(0));
var funcObj = frame.pop();
if (Values.isFunction(funcObj) && Values.function(funcObj).special) {
frame.push(call(state, ctx, funcObj, null, callArgs));
frame.push(ctx, call(ctx, state, funcObj, null, callArgs));
}
else {
var proto = Values.getMember(ctx, funcObj, "prototype");
var obj = new ObjectValue();
obj.setPrototype(ctx, proto);
call(state, ctx, funcObj, obj, callArgs);
frame.push(obj);
call(ctx, state, funcObj, obj, callArgs);
frame.push(ctx, obj);
}
frame.codePtr++;
return NO_RETURN;
}
public static Object execMakeVar(Instruction instr, CodeFrame frame, CallContext ctx) throws InterruptedException {
public static Object execMakeVar(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
var name = (String)instr.get(0);
frame.function.globals.define(name);
frame.codePtr++;
return NO_RETURN;
}
public static Object execDefProp(Instruction instr, CodeFrame frame, CallContext ctx) throws InterruptedException {
public static Object execDefProp(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
var setter = frame.pop();
var getter = frame.pop();
var name = frame.pop();
@@ -82,28 +82,28 @@ public class Runners {
if (getter != null && !Values.isFunction(getter)) throw EngineException.ofType("Getter must be a function or undefined.");
if (setter != null && !Values.isFunction(setter)) throw EngineException.ofType("Setter must be a function or undefined.");
if (!Values.isObject(obj)) throw EngineException.ofType("Property apply target must be an object.");
Values.object(obj).defineProperty(name, Values.function(getter), Values.function(setter), false, false);
Values.object(obj).defineProperty(ctx, name, Values.function(getter), Values.function(setter), false, false);
frame.push(obj);
frame.push(ctx, obj);
frame.codePtr++;
return NO_RETURN;
}
public static Object execInstanceof(Instruction instr, CodeFrame frame, CallContext ctx) throws InterruptedException {
public static Object execInstanceof(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
var type = frame.pop();
var obj = frame.pop();
if (!Values.isPrimitive(type)) {
var proto = Values.getMember(ctx, type, "prototype");
frame.push(Values.isInstanceOf(ctx, obj, proto));
frame.push(ctx, Values.isInstanceOf(ctx, obj, proto));
}
else {
frame.push(false);
frame.push(ctx, false);
}
frame.codePtr++;
return NO_RETURN;
}
public static Object execKeys(Instruction instr, CodeFrame frame, CallContext ctx) throws InterruptedException {
public static Object execKeys(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
var val = frame.pop();
var arr = new ObjectValue();
@@ -113,81 +113,81 @@ public class Runners {
Collections.reverse(members);
for (var el : members) {
if (el instanceof Symbol) continue;
arr.defineProperty(i++, el);
arr.defineProperty(ctx, i++, el);
}
arr.defineProperty("length", i);
arr.defineProperty(ctx, "length", i);
frame.push(arr);
frame.push(ctx, arr);
frame.codePtr++;
return NO_RETURN;
}
public static Object execTry(DebugCommand state, Instruction instr, CodeFrame frame, CallContext ctx) throws InterruptedException {
public static Object execTry(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
frame.addTry(instr.get(0), instr.get(1), instr.get(2));
frame.codePtr++;
return NO_RETURN;
}
public static Object execDup(Instruction instr, CodeFrame frame, CallContext ctx) {
public static Object execDup(CallContext ctx, Instruction instr, CodeFrame frame) {
int offset = instr.get(0), count = instr.get(1);
for (var i = 0; i < count; i++) {
frame.push(frame.peek(offset + count - 1));
frame.push(ctx, frame.peek(offset + count - 1));
}
frame.codePtr++;
return NO_RETURN;
}
public static Object execMove(Instruction instr, CodeFrame frame, CallContext ctx) {
public static Object execMove(CallContext ctx, Instruction instr, CodeFrame frame) {
int offset = instr.get(0), count = instr.get(1);
var tmp = frame.take(offset);
var res = frame.take(count);
for (var i = 0; i < offset; i++) frame.push(tmp[i]);
for (var i = 0; i < count; i++) frame.push(res[i]);
for (var i = 0; i < offset; i++) frame.push(ctx, tmp[i]);
for (var i = 0; i < count; i++) frame.push(ctx, res[i]);
frame.codePtr++;
return NO_RETURN;
}
public static Object execLoadUndefined(Instruction instr, CodeFrame frame, CallContext ctx) {
frame.push(null);
public static Object execLoadUndefined(CallContext ctx, Instruction instr, CodeFrame frame) {
frame.push(ctx, null);
frame.codePtr++;
return NO_RETURN;
}
public static Object execLoadValue(Instruction instr, CodeFrame frame, CallContext ctx) {
frame.push(instr.get(0));
public static Object execLoadValue(CallContext ctx, Instruction instr, CodeFrame frame) {
frame.push(ctx, instr.get(0));
frame.codePtr++;
return NO_RETURN;
}
public static Object execLoadVar(Instruction instr, CodeFrame frame, CallContext ctx) throws InterruptedException {
public static Object execLoadVar(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
var i = instr.get(0);
if (i instanceof String) frame.push(frame.function.globals.get(ctx, (String)i));
else frame.push(frame.scope.get((int)i).get(ctx));
if (i instanceof String) frame.push(ctx, frame.function.globals.get(ctx, (String)i));
else frame.push(ctx, frame.scope.get((int)i).get(ctx));
frame.codePtr++;
return NO_RETURN;
}
public static Object execLoadObj(Instruction instr, CodeFrame frame, CallContext ctx) {
frame.push(new ObjectValue());
public static Object execLoadObj(CallContext ctx, Instruction instr, CodeFrame frame) {
frame.push(ctx, new ObjectValue());
frame.codePtr++;
return NO_RETURN;
}
public static Object execLoadGlob(Instruction instr, CodeFrame frame, CallContext ctx) {
frame.push(frame.function.globals.obj);
public static Object execLoadGlob(CallContext ctx, Instruction instr, CodeFrame frame) {
frame.push(ctx, frame.function.globals.obj);
frame.codePtr++;
return NO_RETURN;
}
public static Object execLoadArr(Instruction instr, CodeFrame frame, CallContext ctx) {
public static Object execLoadArr(CallContext ctx, Instruction instr, CodeFrame frame) {
var res = new ArrayValue();
res.setSize(instr.get(0));
frame.push(res);
frame.push(ctx, res);
frame.codePtr++;
return NO_RETURN;
}
public static Object execLoadFunc(Instruction instr, CodeFrame frame, CallContext ctx) {
public static Object execLoadFunc(CallContext ctx, Instruction instr, CodeFrame frame) {
int n = (Integer)instr.get(0);
int localsN = (Integer)instr.get(1);
int len = (Integer)instr.get(2);
@@ -203,18 +203,18 @@ public class Runners {
System.arraycopy(frame.function.body, start, body, 0, end - start);
var func = new CodeFunction("", localsN, len, frame.function.globals, captures, body);
frame.push(func);
frame.push(ctx, func);
frame.codePtr += n;
return NO_RETURN;
}
public static Object execLoadMember(DebugCommand state, Instruction instr, CodeFrame frame, CallContext ctx) throws InterruptedException {
public static Object execLoadMember(CallContext ctx, DebugCommand state, Instruction instr, CodeFrame frame) throws InterruptedException {
var key = frame.pop();
var obj = frame.pop();
try {
ctx.setData(CodeFrame.STOP_AT_START_KEY, state == DebugCommand.STEP_INTO);
frame.push(Values.getMember(ctx, obj, key));
frame.push(ctx, Values.getMember(ctx, obj, key));
}
catch (IllegalArgumentException e) {
throw EngineException.ofType(e.getMessage());
@@ -222,33 +222,33 @@ public class Runners {
frame.codePtr++;
return NO_RETURN;
}
public static Object execLoadKeyMember(DebugCommand state, Instruction instr, CodeFrame frame, CallContext ctx) throws InterruptedException {
frame.push(instr.get(0));
return execLoadMember(state, instr, frame, ctx);
public static Object execLoadKeyMember(CallContext ctx, DebugCommand state, Instruction instr, CodeFrame frame) throws InterruptedException {
frame.push(ctx, instr.get(0));
return execLoadMember(ctx, state, instr, frame);
}
public static Object execLoadRegEx(Instruction instr, CodeFrame frame, CallContext ctx) throws InterruptedException {
frame.push(ctx.engine().makeRegex(instr.get(0), instr.get(1)));
public static Object execLoadRegEx(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
frame.push(ctx, ctx.engine().makeRegex(instr.get(0), instr.get(1)));
frame.codePtr++;
return NO_RETURN;
}
public static Object execDiscard(Instruction instr, CodeFrame frame, CallContext ctx) {
public static Object execDiscard(CallContext ctx, Instruction instr, CodeFrame frame) {
frame.pop();
frame.codePtr++;
return NO_RETURN;
}
public static Object execStoreMember(DebugCommand state, Instruction instr, CodeFrame frame, CallContext ctx) throws InterruptedException {
public static Object execStoreMember(CallContext ctx, DebugCommand state, Instruction instr, CodeFrame frame) throws InterruptedException {
var val = frame.pop();
var key = frame.pop();
var obj = frame.pop();
ctx.setData(CodeFrame.STOP_AT_START_KEY, state == DebugCommand.STEP_INTO);
if (!Values.setMember(ctx, obj, key, val)) throw EngineException.ofSyntax("Can't set member '" + key + "'.");
if ((boolean)instr.get(0)) frame.push(val);
if ((boolean)instr.get(0)) frame.push(ctx, val);
frame.codePtr++;
return NO_RETURN;
}
public static Object execStoreVar(Instruction instr, CodeFrame frame, CallContext ctx) throws InterruptedException {
public static Object execStoreVar(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
var val = (boolean)instr.get(1) ? frame.peek() : frame.pop();
var i = instr.get(0);
@@ -258,18 +258,18 @@ public class Runners {
frame.codePtr++;
return NO_RETURN;
}
public static Object execStoreSelfFunc(Instruction instr, CodeFrame frame, CallContext ctx) {
public static Object execStoreSelfFunc(CallContext ctx, Instruction instr, CodeFrame frame) {
frame.scope.locals[(int)instr.get(0)].set(ctx, frame.function);
frame.codePtr++;
return NO_RETURN;
}
public static Object execJmp(Instruction instr, CodeFrame frame, CallContext ctx) {
public static Object execJmp(CallContext ctx, Instruction instr, CodeFrame frame) {
frame.codePtr += (int)instr.get(0);
frame.jumpFlag = true;
return NO_RETURN;
}
public static Object execJmpIf(Instruction instr, CodeFrame frame, CallContext ctx) throws InterruptedException {
public static Object execJmpIf(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
if (Values.toBoolean(frame.pop())) {
frame.codePtr += (int)instr.get(0);
frame.jumpFlag = true;
@@ -277,7 +277,7 @@ public class Runners {
else frame.codePtr ++;
return NO_RETURN;
}
public static Object execJmpIfNot(Instruction instr, CodeFrame frame, CallContext ctx) throws InterruptedException {
public static Object execJmpIfNot(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
if (Values.not(frame.pop())) {
frame.codePtr += (int)instr.get(0);
frame.jumpFlag = true;
@@ -286,15 +286,15 @@ public class Runners {
return NO_RETURN;
}
public static Object execIn(Instruction instr, CodeFrame frame, CallContext ctx) throws InterruptedException {
public static Object execIn(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
var obj = frame.pop();
var index = frame.pop();
frame.push(Values.hasMember(ctx, obj, index, false));
frame.push(ctx, Values.hasMember(ctx, obj, index, false));
frame.codePtr++;
return NO_RETURN;
}
public static Object execTypeof(Instruction instr, CodeFrame frame, CallContext ctx) throws InterruptedException {
public static Object execTypeof(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
String name = instr.get(0);
Object obj;
@@ -306,12 +306,12 @@ public class Runners {
}
else obj = frame.pop();
frame.push(Values.type(obj));
frame.push(ctx, Values.type(obj));
frame.codePtr++;
return NO_RETURN;
}
public static Object execNop(Instruction instr, CodeFrame frame, CallContext ctx) {
public static Object execNop(CallContext ctx, Instruction instr, CodeFrame frame) {
if (instr.is(0, "dbg_names")) {
var names = new String[instr.params.length - 1];
for (var i = 0; i < instr.params.length - 1; i++) {
@@ -325,67 +325,67 @@ public class Runners {
return NO_RETURN;
}
public static Object execDelete(Instruction instr, CodeFrame frame, CallContext ctx) throws InterruptedException {
public static Object execDelete(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
var key = frame.pop();
var val = frame.pop();
if (!Values.deleteMember(ctx, val, key)) throw EngineException.ofSyntax("Can't delete member '" + key + "'.");
frame.push(true);
frame.push(ctx, true);
frame.codePtr++;
return NO_RETURN;
}
public static Object execOperation(Instruction instr, CodeFrame frame, CallContext ctx) throws InterruptedException {
public static Object execOperation(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
Operation op = instr.get(0);
var args = new Object[op.operands];
for (var i = op.operands - 1; i >= 0; i--) args[i] = frame.pop();
frame.push(Values.operation(ctx, op, args));
frame.push(ctx, Values.operation(ctx, op, args));
frame.codePtr++;
return NO_RETURN;
}
public static Object exec(DebugCommand state, Instruction instr, CodeFrame frame, CallContext ctx) throws InterruptedException {
public static Object exec(CallContext ctx, DebugCommand state, Instruction instr, CodeFrame frame) throws InterruptedException {
// System.out.println(instr + "@" + instr.location);
switch (instr.type) {
case NOP: return execNop(instr, frame, ctx);
case RETURN: return execReturn(instr, frame, ctx);
case SIGNAL: return execSignal(instr, frame, ctx);
case THROW: return execThrow(instr, frame, ctx);
case THROW_SYNTAX: return execThrowSyntax(instr, frame, ctx);
case CALL: return execCall(state, instr, frame, ctx);
case CALL_NEW: return execCallNew(state, instr, frame, ctx);
case TRY: return execTry(state, instr, frame, ctx);
case NOP: return execNop(ctx, instr, frame);
case RETURN: return execReturn(ctx, instr, frame);
case SIGNAL: return execSignal(ctx, instr, frame);
case THROW: return execThrow(ctx, instr, frame);
case THROW_SYNTAX: return execThrowSyntax(ctx, instr, frame);
case CALL: return execCall(ctx, state, instr, frame);
case CALL_NEW: return execCallNew(ctx, state, instr, frame);
case TRY: return execTry(ctx, instr, frame);
case DUP: return execDup(instr, frame, ctx);
case MOVE: return execMove(instr, frame, ctx);
case LOAD_VALUE: return execLoadValue(instr, frame, ctx);
case LOAD_VAR: return execLoadVar(instr, frame, ctx);
case LOAD_OBJ: return execLoadObj(instr, frame, ctx);
case LOAD_ARR: return execLoadArr(instr, frame, ctx);
case LOAD_FUNC: return execLoadFunc(instr, frame, ctx);
case LOAD_MEMBER: return execLoadMember(state, instr, frame, ctx);
case LOAD_VAL_MEMBER: return execLoadKeyMember(state, instr, frame, ctx);
case LOAD_REGEX: return execLoadRegEx(instr, frame, ctx);
case LOAD_GLOB: return execLoadGlob(instr, frame, ctx);
case DUP: return execDup(ctx, instr, frame);
case MOVE: return execMove(ctx, instr, frame);
case LOAD_VALUE: return execLoadValue(ctx, instr, frame);
case LOAD_VAR: return execLoadVar(ctx, instr, frame);
case LOAD_OBJ: return execLoadObj(ctx, instr, frame);
case LOAD_ARR: return execLoadArr(ctx, instr, frame);
case LOAD_FUNC: return execLoadFunc(ctx, instr, frame);
case LOAD_MEMBER: return execLoadMember(ctx, state, instr, frame);
case LOAD_VAL_MEMBER: return execLoadKeyMember(ctx, state, instr, frame);
case LOAD_REGEX: return execLoadRegEx(ctx, instr, frame);
case LOAD_GLOB: return execLoadGlob(ctx, instr, frame);
case DISCARD: return execDiscard(instr, frame, ctx);
case STORE_MEMBER: return execStoreMember(state, instr, frame, ctx);
case STORE_VAR: return execStoreVar(instr, frame, ctx);
case STORE_SELF_FUNC: return execStoreSelfFunc(instr, frame, ctx);
case MAKE_VAR: return execMakeVar(instr, frame, ctx);
case DISCARD: return execDiscard(ctx, instr, frame);
case STORE_MEMBER: return execStoreMember(ctx, state, instr, frame);
case STORE_VAR: return execStoreVar(ctx, instr, frame);
case STORE_SELF_FUNC: return execStoreSelfFunc(ctx, instr, frame);
case MAKE_VAR: return execMakeVar(ctx, instr, frame);
case KEYS: return execKeys(instr, frame, ctx);
case DEF_PROP: return execDefProp(instr, frame, ctx);
case TYPEOF: return execTypeof(instr, frame, ctx);
case DELETE: return execDelete(instr, frame, ctx);
case KEYS: return execKeys(ctx, instr, frame);
case DEF_PROP: return execDefProp(ctx, instr, frame);
case TYPEOF: return execTypeof(ctx, instr, frame);
case DELETE: return execDelete(ctx, instr, frame);
case JMP: return execJmp(instr, frame, ctx);
case JMP_IF: return execJmpIf(instr, frame, ctx);
case JMP_IFN: return execJmpIfNot(instr, frame, ctx);
case JMP: return execJmp(ctx, instr, frame);
case JMP_IF: return execJmpIf(ctx, instr, frame);
case JMP_IFN: return execJmpIfNot(ctx, instr, frame);
case OPERATION: return execOperation(instr, frame, ctx);
case OPERATION: return execOperation(ctx, instr, frame);
default: throw EngineException.ofSyntax("Invalid instruction " + instr.type.name() + ".");
}

View File

@@ -39,7 +39,7 @@ public class Module {
executing = true;
var scope = ctx.engine().global().globalChild();
scope.define("module", true, this);
scope.define(null, "module", true, this);
scope.define("exports", new ExportsVariable());
var parent = new File(filename).getParentFile();

View File

@@ -38,24 +38,24 @@ public class GlobalScope implements ScopeRecord {
Thread.currentThread().interrupt();
return name;
}
obj.defineProperty(name, null);
obj.defineProperty(null, name, null);
return name;
}
public void define(String name, Variable val) {
obj.defineProperty(name,
obj.defineProperty(null, name,
new NativeFunction("get " + name, (ctx, th, a) -> val.get(ctx)),
new NativeFunction("set " + name, (ctx, th, args) -> { val.set(ctx, args.length > 0 ? args[0] : null); return null; }),
true, true
);
}
public void define(String name, boolean readonly, Object val) {
obj.defineProperty(name, val, readonly, true, true);
public void define(CallContext ctx, String name, boolean readonly, Object val) {
obj.defineProperty(ctx, name, val, readonly, true, true);
}
public void define(String... names) {
for (var n : names) define(n);
}
public void define(boolean readonly, FunctionValue val) {
define(val.name, readonly, val);
define(null, val.name, readonly, val);
}
public Object get(CallContext ctx, String name) throws InterruptedException {

View File

@@ -18,7 +18,7 @@ public class ValueVariable implements Variable {
@Override
public void set(CallContext ctx, Object val) {
if (readonly) return;
this.value = Values.normalize(val);
this.value = Values.normalize(ctx, val);
}
public ValueVariable(boolean readonly, Object val) {

View File

@@ -29,14 +29,14 @@ public class ArrayValue extends ObjectValue {
if (res == EMPTY) return null;
else return res;
}
public void set(int i, Object val) {
public void set(CallContext ctx, int i, Object val) {
if (i < 0) return;
while (values.size() <= i) {
values.add(EMPTY);
}
values.set(i, Values.normalize(val));
values.set(i, Values.normalize(ctx, val));
}
public boolean has(int i) {
return i >= 0 && i < values.size() && values.get(i) != EMPTY;
@@ -102,7 +102,7 @@ public class ArrayValue extends ObjectValue {
if (key instanceof Number) {
var i = Values.number(key);
if (i >= 0 && i - Math.floor(i) == 0) {
set((int)i, val);
set(ctx, (int)i, val);
return true;
}
}
@@ -149,12 +149,12 @@ public class ArrayValue extends ObjectValue {
nonEnumerableSet.add("length");
nonConfigurableSet.add("length");
}
public ArrayValue(Object ...values) {
public ArrayValue(CallContext ctx, Object ...values) {
this();
for (var i = 0; i < values.length; i++) this.values.add(values[i]);
for (var i = 0; i < values.length; i++) this.values.add(Values.normalize(ctx, values[i]));
}
public static ArrayValue of(Collection<Object> values) {
return new ArrayValue(values.toArray(Object[]::new));
public static ArrayValue of(CallContext ctx, Collection<Object> values) {
return new ArrayValue(ctx, values.toArray(Object[]::new));
}
}

View File

@@ -34,7 +34,7 @@ public class CodeFunction extends FunctionValue {
@Override
public Object call(CallContext ctx, Object thisArg, Object... args) throws InterruptedException {
return new CodeFrame(thisArg, args, this).run(ctx);
return new CodeFrame(ctx, thisArg, args, this).run(ctx);
}
public CodeFunction(String name, int localsN, int length, GlobalScope globals, ValueVariable[] captures, Instruction[] body) {

View File

@@ -63,8 +63,8 @@ public abstract class FunctionValue extends ObjectValue {
nonEnumerableSet.add("length");
var proto = new ObjectValue();
proto.defineProperty("constructor", this, true, false, false);
this.defineProperty("prototype", proto, true, false, false);
proto.defineProperty(null, "constructor", this, true, false, false);
this.defineProperty(null, "prototype", proto, true, false, false);
}
}

View File

@@ -78,8 +78,8 @@ public class ObjectValue {
state = State.FROZEN;
}
public final boolean defineProperty(Object key, Object val, boolean writable, boolean configurable, boolean enumerable) {
key = Values.normalize(key); val = Values.normalize(val);
public final boolean defineProperty(CallContext ctx, Object key, Object val, boolean writable, boolean configurable, boolean enumerable) {
key = Values.normalize(ctx, key); val = Values.normalize(ctx, val);
boolean reconfigured =
writable != memberWritable(key) ||
configurable != memberConfigurable(key) ||
@@ -118,11 +118,11 @@ public class ObjectValue {
values.put(key, val);
return true;
}
public final boolean defineProperty(Object key, Object val) {
return defineProperty(Values.normalize(key), Values.normalize(val), true, true, true);
public final boolean defineProperty(CallContext ctx, Object key, Object val) {
return defineProperty(ctx, key, val, true, true, true);
}
public final boolean defineProperty(Object key, FunctionValue getter, FunctionValue setter, boolean configurable, boolean enumerable) {
key = Values.normalize(key);
public final boolean defineProperty(CallContext ctx, Object key, FunctionValue getter, FunctionValue setter, boolean configurable, boolean enumerable) {
key = Values.normalize(ctx, key);
if (
properties.containsKey(key) &&
properties.get(key).getter == getter &&
@@ -162,7 +162,7 @@ public class ObjectValue {
return (ObjectValue)prototype;
}
public final boolean setPrototype(CallContext ctx, Object val) {
val = Values.normalize(val);
val = Values.normalize(ctx, val);
if (!extensible()) return false;
if (val == null || val == Values.NULL) prototype = null;
@@ -228,7 +228,7 @@ public class ObjectValue {
}
public final Object getMember(CallContext ctx, Object key, Object thisArg) throws InterruptedException {
key = Values.normalize(key);
key = Values.normalize(ctx, key);
if (key.equals("__proto__")) {
var res = getPrototype(ctx);
@@ -239,7 +239,7 @@ public class ObjectValue {
if (prop != null) {
if (prop.getter == null) return null;
else return prop.getter.call(ctx, Values.normalize(thisArg));
else return prop.getter.call(ctx, Values.normalize(ctx, thisArg));
}
else return getField(ctx, key);
}
@@ -248,12 +248,12 @@ public class ObjectValue {
}
public final boolean setMember(CallContext ctx, Object key, Object val, Object thisArg, boolean onlyProps) throws InterruptedException {
key = Values.normalize(key); val = Values.normalize(val);
key = Values.normalize(ctx, key); val = Values.normalize(ctx, val);
var prop = getProperty(ctx, key);
if (prop != null) {
if (prop.setter == null) return false;
prop.setter.call(ctx, Values.normalize(thisArg), val);
prop.setter.call(ctx, Values.normalize(ctx, thisArg), val);
return true;
}
else if (onlyProps) return false;
@@ -267,11 +267,11 @@ public class ObjectValue {
else return setField(ctx, key, val);
}
public final boolean setMember(CallContext ctx, Object key, Object val, boolean onlyProps) throws InterruptedException {
return setMember(ctx, Values.normalize(key), Values.normalize(val), this, onlyProps);
return setMember(ctx, Values.normalize(ctx, key), Values.normalize(ctx, val), this, onlyProps);
}
public final boolean hasMember(CallContext ctx, Object key, boolean own) throws InterruptedException {
key = Values.normalize(key);
key = Values.normalize(ctx, key);
if (key != null && key.equals("__proto__")) return true;
if (hasField(ctx, key)) return true;
@@ -280,7 +280,7 @@ public class ObjectValue {
return prototype != null && getPrototype(ctx).hasMember(ctx, key, own);
}
public final boolean deleteMember(CallContext ctx, Object key) throws InterruptedException {
key = Values.normalize(key);
key = Values.normalize(ctx, key);
if (!memberConfigurable(key)) return false;
properties.remove(key);
@@ -291,21 +291,21 @@ public class ObjectValue {
}
public final ObjectValue getMemberDescriptor(CallContext ctx, Object key) throws InterruptedException {
key = Values.normalize(key);
key = Values.normalize(ctx, key);
var prop = properties.get(key);
var res = new ObjectValue();
res.defineProperty("configurable", memberConfigurable(key));
res.defineProperty("enumerable", memberEnumerable(key));
res.defineProperty(ctx, "configurable", memberConfigurable(key));
res.defineProperty(ctx, "enumerable", memberEnumerable(key));
if (prop != null) {
res.defineProperty("get", prop.getter);
res.defineProperty("set", prop.setter);
res.defineProperty(ctx, "get", prop.getter);
res.defineProperty(ctx, "set", prop.setter);
}
else if (hasField(ctx, key)) {
res.defineProperty("value", values.get(key));
res.defineProperty("writable", memberWritable(key));
res.defineProperty(ctx, "value", values.get(key));
res.defineProperty(ctx, "writable", memberWritable(key));
}
else return null;
return res;
@@ -326,10 +326,10 @@ public class ObjectValue {
return res;
}
public ObjectValue(Map<?, ?> values) {
public ObjectValue(CallContext ctx, Map<?, ?> values) {
this(PlaceholderProto.OBJECT);
for (var el : values.entrySet()) {
defineProperty(el.getKey(), el.getValue());
defineProperty(ctx, el.getKey(), el.getValue());
}
}
public ObjectValue(PlaceholderProto proto) {

View File

@@ -88,7 +88,7 @@ public class Values {
}
public static Object toPrimitive(CallContext ctx, Object obj, ConvertHint hint) throws InterruptedException {
obj = normalize(obj);
obj = normalize(ctx, obj);
if (isPrimitive(obj)) return obj;
var first = hint == ConvertHint.VALUEOF ? "valueOf" : "toString";
@@ -231,8 +231,8 @@ public class Values {
case OR: return or(ctx, args[0], args[1]);
case XOR: return xor(ctx, args[0], args[1]);
case EQUALS: return strictEquals(args[0], args[1]);
case NOT_EQUALS: return !strictEquals(args[0], args[1]);
case EQUALS: return strictEquals(ctx, args[0], args[1]);
case NOT_EQUALS: return !strictEquals(ctx, args[0], args[1]);
case LOOSE_EQUALS: return looseEqual(ctx, args[0], args[1]);
case LOOSE_NOT_EQUALS: return !looseEqual(ctx, args[0], args[1]);
@@ -261,7 +261,7 @@ public class Values {
}
public static Object getMember(CallContext ctx, Object obj, Object key) throws InterruptedException {
obj = normalize(obj); key = normalize(key);
obj = normalize(ctx, obj); key = normalize(ctx, key);
if (obj == null) throw new IllegalArgumentException("Tried to access member of undefined.");
if (obj == NULL) throw new IllegalArgumentException("Tried to access member of null.");
if (isObject(obj)) return object(obj).getMember(ctx, key);
@@ -281,7 +281,7 @@ public class Values {
else return proto.getMember(ctx, key, obj);
}
public static boolean setMember(CallContext ctx, Object obj, Object key, Object val) throws InterruptedException {
obj = normalize(obj); key = normalize(key); val = normalize(val);
obj = normalize(ctx, obj); key = normalize(ctx, key); val = normalize(ctx, val);
if (obj == null) throw EngineException.ofType("Tried to access member of undefined.");
if (obj == NULL) throw EngineException.ofType("Tried to access member of null.");
if (key.equals("__proto__")) return setPrototype(ctx, obj, val);
@@ -292,7 +292,7 @@ public class Values {
}
public static boolean hasMember(CallContext ctx, Object obj, Object key, boolean own) throws InterruptedException {
if (obj == null || obj == NULL) return false;
obj = normalize(obj); key = normalize(key);
obj = normalize(ctx, obj); key = normalize(ctx, key);
if (key.equals("__proto__")) return true;
if (isObject(obj)) return object(obj).hasMember(ctx, key, own);
@@ -310,14 +310,14 @@ public class Values {
}
public static boolean deleteMember(CallContext ctx, Object obj, Object key) throws InterruptedException {
if (obj == null || obj == NULL) return false;
obj = normalize(obj); key = normalize(key);
obj = normalize(ctx, obj); key = normalize(ctx, key);
if (isObject(obj)) return object(obj).deleteMember(ctx, key);
else return false;
}
public static ObjectValue getPrototype(CallContext ctx, Object obj) throws InterruptedException {
if (obj == null || obj == NULL) return null;
obj = normalize(obj);
obj = normalize(ctx, obj);
if (isObject(obj)) return object(obj).getPrototype(ctx);
if (ctx == null) return null;
@@ -329,7 +329,7 @@ public class Values {
return null;
}
public static boolean setPrototype(CallContext ctx, Object obj, Object proto) throws InterruptedException {
obj = normalize(obj); proto = normalize(proto);
obj = normalize(ctx, obj); proto = normalize(ctx, proto);
return isObject(obj) && object(obj).setPrototype(ctx, proto);
}
public static List<Object> getMembers(CallContext ctx, Object obj, boolean own, boolean includeNonEnumerable) throws InterruptedException {
@@ -359,8 +359,8 @@ public class Values {
return function(func).call(ctx, thisArg, args);
}
public static boolean strictEquals(Object a, Object b) {
a = normalize(a); b = normalize(b);
public static boolean strictEquals(CallContext ctx, Object a, Object b) {
a = normalize(ctx, a); b = normalize(ctx, b);
if (a == null || b == null) return a == null && b == null;
if (isNan(a) || isNan(b)) return false;
@@ -370,7 +370,7 @@ public class Values {
return a == b || a.equals(b);
}
public static boolean looseEqual(CallContext ctx, Object a, Object b) throws InterruptedException {
a = normalize(a); b = normalize(b);
a = normalize(ctx, a); b = normalize(ctx, b);
// In loose equality, null is equivalent to undefined
if (a == NULL) a = null;
@@ -387,13 +387,13 @@ public class Values {
// Compare symbols by reference
if (a instanceof Symbol || b instanceof Symbol) return a == b;
if (a instanceof Boolean || b instanceof Boolean) return toBoolean(a) == toBoolean(b);
if (a instanceof Number || b instanceof Number) return strictEquals(toNumber(ctx, a), toNumber(ctx, b));
if (a instanceof Number || b instanceof Number) return strictEquals(ctx, toNumber(ctx, a), toNumber(ctx, b));
// Default to strings
return toString(ctx, a).equals(toString(ctx, b));
}
public static Object normalize(Object val) {
public static Object normalize(CallContext ctx, Object val) {
if (val instanceof Number) return number(val);
if (isPrimitive(val) || val instanceof ObjectValue) return val;
if (val instanceof Character) return val + "";
@@ -402,7 +402,7 @@ public class Values {
var res = new ObjectValue();
for (var entry : ((Map<?, ?>)val).entrySet()) {
res.defineProperty(entry.getKey(), entry.getValue());
res.defineProperty(ctx, entry.getKey(), entry.getValue());
}
return res;
@@ -412,12 +412,17 @@ public class Values {
var res = new ArrayValue();
for (var entry : ((Iterable<?>)val)) {
res.set(res.size(), entry);
res.set(ctx, res.size(), entry);
}
return res;
}
if (val instanceof Class) {
if (ctx == null) return null;
else return ctx.engine.getConstructor((Class<?>)val);
}
return new NativeWrapper(val);
}
@@ -562,14 +567,14 @@ public class Values {
var it = iterable.iterator();
try {
var key = getMember(ctx, getMember(ctx, ctx.engine().symbolProto(), "constructor"), "iterable");
res.defineProperty(key, new NativeFunction("", (_ctx, thisArg, args) -> fromJavaIterable(ctx, iterable)));
var key = getMember(ctx, getMember(ctx, ctx.engine().symbolProto(), "constructor"), "iterator");
res.defineProperty(ctx, key, new NativeFunction("", (_ctx, thisArg, args) -> thisArg));
}
catch (IllegalArgumentException | NullPointerException e) { }
res.defineProperty("next", new NativeFunction("", (_ctx, _th, _args) -> {
if (!it.hasNext()) return new ObjectValue(Map.of("done", true));
else return new ObjectValue(Map.of("value", it.next()));
res.defineProperty(ctx, "next", new NativeFunction("", (_ctx, _th, _args) -> {
if (!it.hasNext()) return new ObjectValue(ctx, Map.of("done", true));
else return new ObjectValue(ctx, Map.of("value", it.next()));
}));
return res;

View File

@@ -41,7 +41,7 @@ public class EngineException extends RuntimeException {
private static Object err(String msg, PlaceholderProto proto) {
var res = new ObjectValue(proto);
res.defineProperty("message", msg);
res.defineProperty(null, "message", msg);
return res;
}

View File

@@ -25,7 +25,7 @@ public class NativeTypeRegister {
var val = target.values.get(name);
if (name.equals("")) name = method.getName();
if (!(val instanceof OverloadFunction)) target.defineProperty(name, val = new OverloadFunction(name));
if (!(val instanceof OverloadFunction)) target.defineProperty(null, name, val = new OverloadFunction(name));
((OverloadFunction)val).overloads.add(Overload.fromMethod(method));
}
@@ -40,7 +40,7 @@ public class NativeTypeRegister {
else getter = new OverloadFunction("get " + name);
getter.overloads.add(Overload.fromMethod(method));
target.defineProperty(name, getter, setter, true, true);
target.defineProperty(null, name, getter, setter, true, true);
}
if (set != null) {
var name = set.value();
@@ -52,7 +52,7 @@ public class NativeTypeRegister {
else setter = new OverloadFunction("set " + name);
setter.overloads.add(Overload.fromMethod(method));
target.defineProperty(name, getter, setter, true, true);
target.defineProperty(null, name, getter, setter, true, true);
}
}
}
@@ -67,7 +67,7 @@ public class NativeTypeRegister {
if (name.equals("")) name = field.getName();
var getter = new OverloadFunction("get " + name).add(Overload.getterFromField(field));
var setter = new OverloadFunction("set " + name).add(Overload.setterFromField(field));
target.defineProperty(name, getter, setter, true, false);
target.defineProperty(null, name, getter, setter, true, false);
}
}
}
@@ -84,7 +84,7 @@ public class NativeTypeRegister {
return ctx.engine().typeRegister().getConstr(cl);
}));
target.defineProperty(name, getter, null, true, false);
target.defineProperty(null, name, getter, null, true, false);
}
}
}

View File

@@ -47,7 +47,7 @@ public class OverloadFunction extends FunctionValue {
Object _this = overload.thisArg == null ? null : Values.convert(ctx, thisArg, overload.thisArg);
try {
return Values.normalize(overload.runner.run(ctx, _this, newArgs));
return Values.normalize(ctx, overload.runner.run(ctx, _this, newArgs));
}
catch (InstantiationException e) {
throw EngineException.ofError("The class may not be instantiated.");

View File

@@ -22,13 +22,13 @@ public class GeneratorFunction extends FunctionValue {
if (done) {
if (inducedError != Runners.NO_RETURN) throw new EngineException(inducedError);
var res = new ObjectValue();
res.defineProperty("done", true);
res.defineProperty("value", inducedReturn == Runners.NO_RETURN ? null : inducedReturn);
res.defineProperty(ctx, "done", true);
res.defineProperty(ctx, "value", inducedReturn == Runners.NO_RETURN ? null : inducedReturn);
return res;
}
Object res = null;
if (inducedValue != Runners.NO_RETURN) frame.push(inducedValue);
if (inducedValue != Runners.NO_RETURN) frame.push(ctx, inducedValue);
frame.start(ctx);
yielding = false;
while (!yielding) {
@@ -51,8 +51,8 @@ public class GeneratorFunction extends FunctionValue {
else res = frame.pop();
var obj = new ObjectValue();
obj.defineProperty("done", done);
obj.defineProperty("value", res);
obj.defineProperty(ctx, "done", done);
obj.defineProperty(ctx, "value", res);
return obj;
}
@@ -84,11 +84,11 @@ public class GeneratorFunction extends FunctionValue {
}
@Override
public Object call(CallContext _ctx, Object thisArg, Object... args) throws InterruptedException {
public Object call(CallContext ctx, Object thisArg, Object... args) throws InterruptedException {
var handler = new Generator();
var func = factory.call(_ctx, thisArg, new NativeFunction("yield", handler::yield));
var func = factory.call(ctx, thisArg, new NativeFunction("yield", handler::yield));
if (!(func instanceof CodeFunction)) throw EngineException.ofType("Return value of argument must be a js function.");
handler.frame = new CodeFrame(thisArg, args, (CodeFunction)func);
handler.frame = new CodeFrame(ctx, thisArg, args, (CodeFunction)func);
return handler;
}

View File

@@ -38,12 +38,12 @@ public class Internals {
return func.call(ctx, th, args.toArray());
}
@Native
public boolean defineProp(ObjectValue obj, Object key, FunctionValue getter, FunctionValue setter, boolean enumerable, boolean configurable) {
return obj.defineProperty(key, getter, setter, configurable, enumerable);
public boolean defineProp(CallContext ctx, ObjectValue obj, Object key, FunctionValue getter, FunctionValue setter, boolean enumerable, boolean configurable) {
return obj.defineProperty(ctx, key, getter, setter, configurable, enumerable);
}
@Native
public boolean defineField(ObjectValue obj, Object key, Object val, boolean writable, boolean enumerable, boolean configurable) {
return obj.defineProperty(key, val, writable, configurable, enumerable);
public boolean defineField(CallContext ctx, ObjectValue obj, Object key, Object val, boolean writable, boolean enumerable, boolean configurable) {
return obj.defineProperty(ctx, key, val, writable, configurable, enumerable);
}
@Native
@@ -209,7 +209,7 @@ public class Internals {
for (var el : list) {
if (el instanceof Symbol && onlyString) continue;
res.set(i++, el);
res.set(ctx, i++, el);
}
return res;
@@ -223,7 +223,7 @@ public class Internals {
var list = Values.object(obj).keys(true);
for (var el : list) {
if (el instanceof Symbol == symbols) res.set(i++, el);
if (el instanceof Symbol == symbols) res.set(ctx, i++, el);
}
}

View File

@@ -19,11 +19,11 @@ public class JSON {
if (val.isBoolean()) return val.bool();
if (val.isString()) return val.string();
if (val.isNumber()) return val.number();
if (val.isList()) return ArrayValue.of(val.list().stream().map(JSON::toJS).collect(Collectors.toList()));
if (val.isList()) return ArrayValue.of(null, val.list().stream().map(JSON::toJS).collect(Collectors.toList()));
if (val.isMap()) {
var res = new ObjectValue();
for (var el : val.map().entrySet()) {
res.defineProperty(el.getKey(), toJS(el.getValue()));
res.defineProperty(null, el.getKey(), toJS(el.getValue()));
}
return res;
}

View File

@@ -53,7 +53,7 @@ public class Map {
return Values.fromJavaIterable(ctx, objs
.entrySet()
.stream()
.map(v -> new ArrayValue(v.getKey(), v.getValue()))
.map(v -> new ArrayValue(ctx, v.getKey(), v.getValue()))
.collect(Collectors.toList())
);
}

View File

@@ -8,10 +8,6 @@ import java.io.InputStreamReader;
import me.topchetoeu.jscript.engine.Engine;
import me.topchetoeu.jscript.engine.modules.ModuleManager;
import me.topchetoeu.jscript.engine.values.FunctionValue;
import me.topchetoeu.jscript.engine.values.NativeFunction;
import me.topchetoeu.jscript.engine.values.Values;
import me.topchetoeu.jscript.parsing.Parsing;
public class PolyfillEngine extends Engine {
public static String streamToString(InputStream in) {
@@ -52,59 +48,58 @@ public class PolyfillEngine extends Engine {
this.modules = new ModuleManager(root);
exposeNamespace("Math", Math.class);
exposeNamespace("JSON", JSON.class);
exposeClass("Promise", Promise.class);
exposeClass("RegExp", RegExp.class);
exposeClass("Date", Date.class);
exposeClass("Map", Map.class);
exposeClass("Set", Set.class);
// exposeNamespace("Math", Math.class);
// exposeNamespace("JSON", JSON.class);
// exposeClass("Promise", Promise.class);
// exposeClass("RegExp", RegExp.class);
// exposeClass("Date", Date.class);
// exposeClass("Map", Map.class);
// exposeClass("Set", Set.class);
global().define("Object", "Function", "String", "Number", "Boolean", "Symbol");
global().define("Array", "require");
global().define("Error", "SyntaxError", "TypeError", "RangeError");
global().define("setTimeout", "setInterval", "clearTimeout", "clearInterval");
// global().define("process", true, "trololo");
global().define("debugger");
// global().define("Object", "Function", "String", "Number", "Boolean", "Symbol");
// global().define("Array", "require");
// global().define("Error", "SyntaxError", "TypeError", "RangeError");
// global().define("setTimeout", "setInterval", "clearTimeout", "clearInterval");
// global().define("debugger");
global().define(true, new NativeFunction("measure", (ctx, thisArg, values) -> {
var start = System.nanoTime();
try {
return Values.call(ctx, values[0], ctx);
}
finally {
System.out.println(String.format("Function took %s ms", (System.nanoTime() - start) / 1000000.));
}
}));
global().define(true, new NativeFunction("isNaN", (ctx, thisArg, args) -> {
if (args.length == 0) return true;
else return Double.isNaN(Values.toNumber(ctx, args[0]));
}));
global().define(true, new NativeFunction("log", (el, t, args) -> {
for (var obj : args) Values.printValue(el, obj);
System.out.println();
return null;
}));
// global().define(true, new NativeFunction("measure", (ctx, thisArg, values) -> {
// var start = System.nanoTime();
// try {
// return Values.call(ctx, values[0], ctx);
// }
// finally {
// System.out.println(String.format("Function took %s ms", (System.nanoTime() - start) / 1000000.));
// }
// }));
// global().define(true, new NativeFunction("isNaN", (ctx, thisArg, args) -> {
// if (args.length == 0) return true;
// else return Double.isNaN(Values.toNumber(ctx, args[0]));
// }));
// global().define(true, new NativeFunction("log", (el, t, args) -> {
// for (var obj : args) Values.printValue(el, obj);
// System.out.println();
// return null;
// }));
var scope = global().globalChild();
scope.define("gt", true, global().obj);
scope.define("lgt", true, scope.obj);
scope.define("setProps", "setConstr");
scope.define("internals", true, new Internals());
scope.define(true, new NativeFunction("run", (ctx, thisArg, args) -> {
var filename = (String)args[0];
boolean pollute = args.length > 1 && args[1].equals(true);
FunctionValue func;
var src = resourceToString("js/" + filename);
if (src == null) throw new RuntimeException("The source '" + filename + "' doesn't exist.");
// var scope = global().globalChild();
// scope.define("gt", true, global().obj);
// scope.define("lgt", true, scope.obj);
// scope.define("setProps", "setConstr");
// scope.define("internals", true, new Internals());
// scope.define(true, new NativeFunction("run", (ctx, thisArg, args) -> {
// var filename = (String)args[0];
// boolean pollute = args.length > 1 && args[1].equals(true);
// FunctionValue func;
// var src = resourceToString("js/" + filename);
// if (src == null) throw new RuntimeException("The source '" + filename + "' doesn't exist.");
if (pollute) func = Parsing.compile(global(), filename, src);
else func = Parsing.compile(scope.globalChild(), filename, src);
// if (pollute) func = Parsing.compile(global(), filename, src);
// else func = Parsing.compile(scope.globalChild(), filename, src);
func.call(ctx);
return null;
}));
// func.call(ctx);
// return null;
// }));
pushMsg(false, scope.globalChild(), java.util.Map.of(), "core.js", resourceToString("js/core.js"), null);
// pushMsg(false, scope.globalChild(), java.util.Map.of(), "core.js", resourceToString("js/core.js"), null);
}
}

View File

@@ -27,10 +27,10 @@ public class Promise {
}
@Native("resolve")
public static Promise ofResolved(CallContext engine, Object val) {
public static Promise ofResolved(CallContext ctx, Object val) {
if (Values.isWrapper(val, Promise.class)) return Values.wrapper(val, Promise.class);
var res = new Promise();
res.fulfill(engine, val);
res.fulfill(ctx, val);
return res;
}
public static Promise ofResolved(Object val) {
@@ -41,9 +41,9 @@ public class Promise {
}
@Native("reject")
public static Promise ofRejected(CallContext engine, Object val) {
public static Promise ofRejected(CallContext ctx, Object val) {
var res = new Promise();
res.reject(engine, val);
res.reject(ctx, val);
return res;
}
public static Promise ofRejected(Object val) {
@@ -53,7 +53,7 @@ public class Promise {
}
@Native
public static Promise any(CallContext engine, Object _promises) {
public static Promise any(CallContext ctx, Object _promises) {
if (!Values.isArray(_promises)) throw EngineException.ofType("Expected argument for any to be an array.");
var promises = Values.array(_promises);
if (promises.size() == 0) return ofResolved(new ArrayValue());
@@ -66,17 +66,17 @@ public class Promise {
var index = i;
var val = promises.get(i);
if (Values.isWrapper(val, Promise.class)) Values.wrapper(val, Promise.class).then(
engine,
ctx,
new NativeFunction(null, (e, th, args) -> { res.fulfill(e, args[0]); return null; }),
new NativeFunction(null, (e, th, args) -> {
errors.set(index, args[0]);
errors.set(ctx, index, args[0]);
n[0]--;
if (n[0] <= 0) res.reject(e, errors);
return null;
})
);
else {
res.fulfill(engine, val);
res.fulfill(ctx, val);
break;
}
}
@@ -84,7 +84,7 @@ public class Promise {
return res;
}
@Native
public static Promise race(CallContext engine, Object _promises) {
public static Promise race(CallContext ctx, Object _promises) {
if (!Values.isArray(_promises)) throw EngineException.ofType("Expected argument for any to be an array.");
var promises = Values.array(_promises);
if (promises.size() == 0) return ofResolved(new ArrayValue());
@@ -93,7 +93,7 @@ public class Promise {
for (var i = 0; i < promises.size(); i++) {
var val = promises.get(i);
if (Values.isWrapper(val, Promise.class)) Values.wrapper(val, Promise.class).then(
engine,
ctx,
new NativeFunction(null, (e, th, args) -> { res.fulfill(e, args[0]); return null; }),
new NativeFunction(null, (e, th, args) -> { res.reject(e, args[0]); return null; })
);
@@ -106,7 +106,7 @@ public class Promise {
return res;
}
@Native
public static Promise all(CallContext engine, Object _promises) {
public static Promise all(CallContext ctx, Object _promises) {
if (!Values.isArray(_promises)) throw EngineException.ofType("Expected argument for any to be an array.");
var promises = Values.array(_promises);
if (promises.size() == 0) return ofResolved(new ArrayValue());
@@ -119,9 +119,9 @@ public class Promise {
var index = i;
var val = promises.get(i);
if (Values.isWrapper(val, Promise.class)) Values.wrapper(val, Promise.class).then(
engine,
ctx,
new NativeFunction(null, (e, th, args) -> {
result.set(index, args[0]);
result.set(ctx, index, args[0]);
n[0]--;
if (n[0] <= 0) res.fulfill(e, result);
return null;
@@ -129,17 +129,17 @@ public class Promise {
new NativeFunction(null, (e, th, args) -> { res.reject(e, args[0]); return null; })
);
else {
result.set(i, val);
result.set(ctx, i, val);
break;
}
}
if (n[0] <= 0) res.fulfill(engine, result);
if (n[0] <= 0) res.fulfill(ctx, result);
return res;
}
@Native
public static Promise allSettled(CallContext engine, Object _promises) {
public static Promise allSettled(CallContext ctx, Object _promises) {
if (!Values.isArray(_promises)) throw EngineException.ofType("Expected argument for any to be an array.");
var promises = Values.array(_promises);
if (promises.size() == 0) return ofResolved(new ArrayValue());
@@ -152,9 +152,9 @@ public class Promise {
var index = i;
var val = promises.get(i);
if (Values.isWrapper(val, Promise.class)) Values.wrapper(val, Promise.class).then(
engine,
ctx,
new NativeFunction(null, (e, th, args) -> {
result.set(index, new ObjectValue(Map.of(
result.set(ctx, index, new ObjectValue(ctx, Map.of(
"status", "fulfilled",
"value", args[0]
)));
@@ -163,7 +163,7 @@ public class Promise {
return null;
}),
new NativeFunction(null, (e, th, args) -> {
result.set(index, new ObjectValue(Map.of(
result.set(ctx, index, new ObjectValue(ctx, Map.of(
"status", "rejected",
"reason", args[0]
)));
@@ -173,7 +173,7 @@ public class Promise {
})
);
else {
result.set(i, new ObjectValue(Map.of(
result.set(ctx, i, new ObjectValue(ctx, Map.of(
"status", "fulfilled",
"value", val
)));
@@ -181,7 +181,7 @@ public class Promise {
}
}
if (n[0] <= 0) res.fulfill(engine, result);
if (n[0] <= 0) res.fulfill(ctx, result);
return res;
}

View File

@@ -119,7 +119,7 @@ public class RegExp {
for (var el : namedGroups) {
try {
groups.defineProperty(el, matcher.group(el));
groups.defineProperty(null, el, matcher.group(el));
}
catch (IllegalArgumentException e) { }
}
@@ -127,23 +127,23 @@ public class RegExp {
for (int i = 0; i < matcher.groupCount() + 1; i++) {
obj.set(i, matcher.group(i));
obj.set(null, i, matcher.group(i));
}
obj.defineProperty("groups", groups);
obj.defineProperty("index", matcher.start());
obj.defineProperty("input", str);
obj.defineProperty(null, "groups", groups);
obj.defineProperty(null, "index", matcher.start());
obj.defineProperty(null, "input", str);
if (hasIndices) {
var indices = new ArrayValue();
for (int i = 0; i < matcher.groupCount() + 1; i++) {
indices.set(i, new ArrayValue(matcher.start(i), matcher.end(i)));
indices.set(null, i, new ArrayValue(null, matcher.start(i), matcher.end(i)));
}
var groupIndices = new ObjectValue();
for (var el : namedGroups) {
groupIndices.defineProperty(el, new ArrayValue(matcher.start(el), matcher.end(el)));
groupIndices.defineProperty(null, el, new ArrayValue(null, matcher.start(el), matcher.end(el)));
}
indices.defineProperty("groups", groupIndices);
obj.defineProperty("indices", indices);
indices.defineProperty(null, "groups", groupIndices);
obj.defineProperty(null, "indices", indices);
}
return obj;

View File

@@ -6,7 +6,6 @@ import java.util.stream.Collectors;
import me.topchetoeu.jscript.engine.CallContext;
import me.topchetoeu.jscript.engine.values.ArrayValue;
import me.topchetoeu.jscript.engine.values.FunctionValue;
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.exceptions.EngineException;
@@ -44,55 +43,20 @@ public class Set {
}
@Native
public ObjectValue entries() {
var it = objs.stream().collect(Collectors.toList()).iterator();
var next = new NativeFunction("next", (ctx, thisArg, args) -> {
if (it.hasNext()) {
var val = it.next();
return new ObjectValue(java.util.Map.of(
"value", new ArrayValue(val, val),
"done", false
));
}
else return new ObjectValue(java.util.Map.of("done", true));
});
return new ObjectValue(java.util.Map.of("next", next));
public ObjectValue entries(CallContext ctx) throws InterruptedException {
return Values.fromJavaIterable(ctx, objs
.stream()
.map(v -> new ArrayValue(ctx, v, v))
.collect(Collectors.toList())
);
}
@Native
public ObjectValue keys() {
var it = objs.stream().collect(Collectors.toList()).iterator();
var next = new NativeFunction("next", (ctx, thisArg, args) -> {
if (it.hasNext()) {
var val = it.next();
return new ObjectValue(java.util.Map.of(
"value", val,
"done", false
));
}
else return new ObjectValue(java.util.Map.of("done", true));
});
return new ObjectValue(java.util.Map.of("next", next));
public ObjectValue keys(CallContext ctx) throws InterruptedException {
return Values.fromJavaIterable(ctx, objs);
}
@Native
public ObjectValue values() {
var it = objs.stream().collect(Collectors.toList()).iterator();
var next = new NativeFunction("next", (ctx, thisArg, args) -> {
if (it.hasNext()) {
var val = it.next();
return new ObjectValue(java.util.Map.of(
"value", val,
"done", false
));
}
else return new ObjectValue(java.util.Map.of("done", true));
});
return new ObjectValue(java.util.Map.of("next", next));
public ObjectValue values(CallContext ctx) throws InterruptedException {
return Values.fromJavaIterable(ctx, objs);
}
@NativeGetter("size")

View File

@@ -1,61 +1,61 @@
package me.topchetoeu.jscript.polyfills;
import java.io.File;
import java.util.ArrayList;
import java.util.Map;
import me.topchetoeu.jscript.engine.scope.GlobalScope;
import me.topchetoeu.jscript.engine.values.ArrayValue;
import me.topchetoeu.jscript.engine.values.FunctionValue;
import me.topchetoeu.jscript.engine.values.NativeFunction;
import me.topchetoeu.jscript.engine.values.Values;
public class TypescriptEngine extends PolyfillEngine {
private FunctionValue ts;
@Override
public FunctionValue compile(GlobalScope scope, String filename, String raw) throws InterruptedException {
if (ts != null) {
var res = Values.array(ts.call(context(), null, filename, raw));
var src = Values.toString(context(), res.get(0));
var func = Values.function(res.get(1));
var compiled = super.compile(scope, filename, src);
return new NativeFunction(null, (ctx, thisArg, args) -> {
return func.call(context(), null, compiled, thisArg, new ArrayValue(args));
});
}
return super.compile(scope, filename, raw);
}
public TypescriptEngine(File root) {
super(root);
var scope = global().globalChild();
var decls = new ArrayList<Object>();
decls.add(resourceToString("dts/core.d.ts"));
decls.add(resourceToString("dts/iterators.d.ts"));
decls.add(resourceToString("dts/map.d.ts"));
decls.add(resourceToString("dts/promise.d.ts"));
decls.add(resourceToString("dts/regex.d.ts"));
decls.add(resourceToString("dts/require.d.ts"));
decls.add(resourceToString("dts/set.d.ts"));
decls.add(resourceToString("dts/values/array.d.ts"));
decls.add(resourceToString("dts/values/boolean.d.ts"));
decls.add(resourceToString("dts/values/number.d.ts"));
decls.add(resourceToString("dts/values/errors.d.ts"));
decls.add(resourceToString("dts/values/function.d.ts"));
decls.add(resourceToString("dts/values/object.d.ts"));
decls.add(resourceToString("dts/values/string.d.ts"));
decls.add(resourceToString("dts/values/symbol.d.ts"));
scope.define("libs", true, ArrayValue.of(decls));
scope.define(true, new NativeFunction("init", (el, t, args) -> {
ts = Values.function(args[0]);
return null;
}));
pushMsg(false, scope, Map.of(), "bootstrap.js", resourceToString("js/bootstrap.js"), null);
}
}
package me.topchetoeu.jscript.polyfills;
import java.io.File;
import java.util.ArrayList;
import java.util.Map;
import me.topchetoeu.jscript.engine.scope.GlobalScope;
import me.topchetoeu.jscript.engine.values.ArrayValue;
import me.topchetoeu.jscript.engine.values.FunctionValue;
import me.topchetoeu.jscript.engine.values.NativeFunction;
import me.topchetoeu.jscript.engine.values.Values;
public class TypescriptEngine extends PolyfillEngine {
private FunctionValue ts;
@Override
public FunctionValue compile(GlobalScope scope, String filename, String raw) throws InterruptedException {
if (ts != null) {
var res = Values.array(ts.call(context(), null, filename, raw));
var src = Values.toString(context(), res.get(0));
var func = Values.function(res.get(1));
var compiled = super.compile(scope, filename, src);
return new NativeFunction(null, (ctx, thisArg, args) -> {
return func.call(context(), null, compiled, thisArg, new ArrayValue(args));
});
}
return super.compile(scope, filename, raw);
}
public TypescriptEngine(File root) {
super(root);
var scope = global().globalChild();
var decls = new ArrayList<Object>();
decls.add(resourceToString("dts/core.d.ts"));
decls.add(resourceToString("dts/iterators.d.ts"));
decls.add(resourceToString("dts/map.d.ts"));
decls.add(resourceToString("dts/promise.d.ts"));
decls.add(resourceToString("dts/regex.d.ts"));
decls.add(resourceToString("dts/require.d.ts"));
decls.add(resourceToString("dts/set.d.ts"));
decls.add(resourceToString("dts/values/array.d.ts"));
decls.add(resourceToString("dts/values/boolean.d.ts"));
decls.add(resourceToString("dts/values/number.d.ts"));
decls.add(resourceToString("dts/values/errors.d.ts"));
decls.add(resourceToString("dts/values/function.d.ts"));
decls.add(resourceToString("dts/values/object.d.ts"));
decls.add(resourceToString("dts/values/string.d.ts"));
decls.add(resourceToString("dts/values/symbol.d.ts"));
scope.define("libs", true, ArrayValue.of(decls));
scope.define(true, new NativeFunction("init", (el, t, args) -> {
ts = Values.function(args[0]);
return null;
}));
pushMsg(false, scope, Map.of(), "bootstrap.js", resourceToString("js/bootstrap.js"), null);
}
}