refactor: clean up assigning

This commit is contained in:
TopchetoEU 2024-09-06 15:48:22 +03:00
parent 5f88061ee7
commit 8e64d13c87
Signed by: topchetoeu
GPG Key ID: 6531B8583E5F6ED4
16 changed files with 180 additions and 151 deletions

View File

@ -404,10 +404,10 @@ public class Instruction {
return new Instruction(Type.LOAD_ARR, count); return new Instruction(Type.LOAD_ARR, count);
} }
public static Instruction dup() { public static Instruction dup() {
return new Instruction(Type.DUP, 1); return new Instruction(Type.DUP, 1, 0);
} }
public static Instruction dup(int count) { public static Instruction dup(int count, int offset) {
return new Instruction(Type.DUP, count); return new Instruction(Type.DUP, count, offset);
} }
public static Instruction storeVar(int i) { public static Instruction storeVar(int i) {

View File

@ -1,7 +1,9 @@
package me.topchetoeu.jscript.compilation; package me.topchetoeu.jscript.compilation;
import me.topchetoeu.jscript.common.Operation;
public interface AssignableNode { public interface AssignableNode {
public abstract Node toAssign(Node val, Operation operation); public void compileBeforeAssign(CompileResult target, boolean operator);
public void compileAfterAssign(CompileResult target, boolean operator, boolean pollute);
public default String assignName() {
return null;
}
} }

View File

@ -33,7 +33,7 @@ public abstract class FunctionNode extends Node {
return new CompileResult(env, scope, params.params.size(), target -> { return new CompileResult(env, scope, params.params.size(), target -> {
if (params.params.size() > 0) { if (params.params.size() > 0) {
target.add(Instruction.loadArgs(true)); target.add(Instruction.loadArgs(true));
if (params.params.size() > 1) target.add(Instruction.dup(params.params.size() - 1)); if (params.params.size() > 1) target.add(Instruction.dup(params.params.size() - 1, 0));
var i = 0; var i = 0;
for (var param : params.params) { for (var param : params.params) {

View File

@ -39,6 +39,7 @@ import me.topchetoeu.jscript.compilation.values.operations.ChangeNode;
import me.topchetoeu.jscript.compilation.values.operations.DiscardNode; import me.topchetoeu.jscript.compilation.values.operations.DiscardNode;
import me.topchetoeu.jscript.compilation.values.operations.IndexNode; import me.topchetoeu.jscript.compilation.values.operations.IndexNode;
import me.topchetoeu.jscript.compilation.values.operations.OperationNode; import me.topchetoeu.jscript.compilation.values.operations.OperationNode;
import me.topchetoeu.jscript.compilation.values.operations.PostfixNode;
import me.topchetoeu.jscript.compilation.values.operations.TypeofNode; import me.topchetoeu.jscript.compilation.values.operations.TypeofNode;
import me.topchetoeu.jscript.runtime.exceptions.SyntaxException; import me.topchetoeu.jscript.runtime.exceptions.SyntaxException;
@ -140,8 +141,8 @@ public final class JavaScript {
ParseRes<Node> res = ParseRes.first(src, i + n, ParseRes<Node> res = ParseRes.first(src, i + n,
(s, j) -> OperationNode.parseInstanceof(s, j, _prev, precedence), (s, j) -> OperationNode.parseInstanceof(s, j, _prev, precedence),
(s, j) -> OperationNode.parseIn(s, j, _prev, precedence), (s, j) -> OperationNode.parseIn(s, j, _prev, precedence),
(s, j) -> ChangeNode.parsePostfixIncrease(s, j, _prev, precedence), (s, j) -> PostfixNode.parsePostfixIncrease(s, j, _prev, precedence),
(s, j) -> ChangeNode.parsePostfixDecrease(s, j, _prev, precedence), (s, j) -> PostfixNode.parsePostfixDecrease(s, j, _prev, precedence),
(s, j) -> OperationNode.parseOperator(s, j, _prev, precedence), (s, j) -> OperationNode.parseOperator(s, j, _prev, precedence),
(s, j) -> IfNode.parseTernary(s, j, _prev, precedence), (s, j) -> IfNode.parseTernary(s, j, _prev, precedence),
(s, j) -> IndexNode.parseMember(s, j, _prev, precedence), (s, j) -> IndexNode.parseMember(s, j, _prev, precedence),

View File

@ -4,7 +4,6 @@ import java.util.function.IntFunction;
import java.util.function.Supplier; import java.util.function.Supplier;
import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Instruction;
import me.topchetoeu.jscript.common.Operation;
import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.jscript.common.parsing.Location;
import me.topchetoeu.jscript.common.parsing.ParseRes; import me.topchetoeu.jscript.common.parsing.ParseRes;
import me.topchetoeu.jscript.common.parsing.Parsing; import me.topchetoeu.jscript.common.parsing.Parsing;
@ -13,14 +12,20 @@ import me.topchetoeu.jscript.compilation.AssignableNode;
import me.topchetoeu.jscript.compilation.CompileResult; import me.topchetoeu.jscript.compilation.CompileResult;
import me.topchetoeu.jscript.compilation.JavaScript; import me.topchetoeu.jscript.compilation.JavaScript;
import me.topchetoeu.jscript.compilation.Node; import me.topchetoeu.jscript.compilation.Node;
import me.topchetoeu.jscript.compilation.values.operations.VariableAssignNode;
import me.topchetoeu.jscript.runtime.exceptions.SyntaxException; import me.topchetoeu.jscript.runtime.exceptions.SyntaxException;
public class VariableNode extends Node implements AssignableNode { public class VariableNode extends Node implements AssignableNode {
public final String name; public final String name;
@Override public Node toAssign(Node val, Operation operation) { @Override public String assignName() { return name; }
return new VariableAssignNode(loc(), name, val, operation);
@Override public void compileBeforeAssign(CompileResult target, boolean operator) {
if (operator) {
target.add(VariableNode.toGet(target, loc(), name));
}
}
@Override public void compileAfterAssign(CompileResult target, boolean operator, boolean pollute) {
target.add(VariableNode.toSet(target, loc(), name, pollute, false));
} }
@Override public void compile(CompileResult target, boolean pollute) { @Override public void compile(CompileResult target, boolean pollute) {

View File

@ -0,0 +1,23 @@
package me.topchetoeu.jscript.compilation.values.operations;
import me.topchetoeu.jscript.common.parsing.Location;
import me.topchetoeu.jscript.compilation.AssignableNode;
import me.topchetoeu.jscript.compilation.CompileResult;
import me.topchetoeu.jscript.compilation.Node;
public class AssignNode extends Node {
public final AssignableNode assignable;
public final Node value;
@Override public void compile(CompileResult target, boolean pollute) {
assignable.compileBeforeAssign(target, false);
value.compile(target, true);
assignable.compileAfterAssign(target, false, pollute);
}
public AssignNode(Location loc, AssignableNode assignable, Node value) {
super(loc);
this.assignable = assignable;
this.value = value;
}
}

View File

@ -13,24 +13,22 @@ import me.topchetoeu.jscript.compilation.Node;
import me.topchetoeu.jscript.compilation.values.constants.NumberNode; import me.topchetoeu.jscript.compilation.values.constants.NumberNode;
public class ChangeNode extends Node { public class ChangeNode extends Node {
public final AssignableNode value; public final AssignableNode assignable;
public final double addAmount; public final Node value;
public final boolean postfix; public final Operation op;
@Override public void compile(CompileResult target, boolean pollute) { @Override public void compile(CompileResult target, boolean pollute) {
value.toAssign(new NumberNode(loc(), -addAmount), Operation.SUBTRACT).compile(target, true); assignable.compileBeforeAssign(target, true);
if (!pollute) target.add(Instruction.discard()); value.compile(target, true);
else if (postfix) { target.add(Instruction.operation(op));
target.add(Instruction.pushValue(addAmount)); assignable.compileAfterAssign(target, true, pollute);
target.add(Instruction.operation(Operation.SUBTRACT));
}
} }
public ChangeNode(Location loc, AssignableNode value, double addAmount, boolean postfix) { public ChangeNode(Location loc, AssignableNode assignable, Node value, Operation op) {
super(loc); super(loc);
this.assignable = assignable;
this.value = value; this.value = value;
this.addAmount = addAmount; this.op = op;
this.postfix = postfix;
} }
public static ParseRes<ChangeNode> parsePrefixIncrease(Source src, int i) { public static ParseRes<ChangeNode> parsePrefixIncrease(Source src, int i) {
@ -44,7 +42,7 @@ public class ChangeNode extends Node {
if (!res.isSuccess()) return res.chainError(src.loc(i + n), "Expected assignable value after prefix operator."); if (!res.isSuccess()) return res.chainError(src.loc(i + n), "Expected assignable value after prefix operator.");
else if (!(res.result instanceof AssignableNode)) return ParseRes.error(src.loc(i + n), "Expected assignable value after prefix operator."); else if (!(res.result instanceof AssignableNode)) return ParseRes.error(src.loc(i + n), "Expected assignable value after prefix operator.");
return ParseRes.res(new ChangeNode(loc, (AssignableNode)res.result, 1, false), n + res.n); return ParseRes.res(new ChangeNode(loc, (AssignableNode)res.result, new NumberNode(loc, -1), Operation.SUBTRACT), n + res.n);
} }
public static ParseRes<ChangeNode> parsePrefixDecrease(Source src, int i) { public static ParseRes<ChangeNode> parsePrefixDecrease(Source src, int i) {
var n = Parsing.skipEmpty(src, i); var n = Parsing.skipEmpty(src, i);
@ -57,31 +55,6 @@ public class ChangeNode extends Node {
if (!res.isSuccess()) return res.chainError(src.loc(i + n), "Expected assignable value after prefix operator."); if (!res.isSuccess()) return res.chainError(src.loc(i + n), "Expected assignable value after prefix operator.");
else if (!(res.result instanceof AssignableNode)) return ParseRes.error(src.loc(i + n), "Expected assignable value after prefix operator."); else if (!(res.result instanceof AssignableNode)) return ParseRes.error(src.loc(i + n), "Expected assignable value after prefix operator.");
return ParseRes.res(new ChangeNode(loc, (AssignableNode)res.result, -1, false), n + res.n); return ParseRes.res(new ChangeNode(loc, (AssignableNode)res.result, new NumberNode(loc, 1), Operation.SUBTRACT), n + res.n);
}
public static ParseRes<ChangeNode> parsePostfixIncrease(Source src, int i, Node prev, int precedence) {
if (precedence > 15) return ParseRes.failed();
var n = Parsing.skipEmpty(src, i);
var loc = src.loc(i + n);
if (!src.is(i + n, "++")) return ParseRes.failed();
if (!(prev instanceof AssignableNode)) return ParseRes.error(src.loc(i + n), "Expected assignable value before suffix operator.");
n += 2;
return ParseRes.res(new ChangeNode(loc, (AssignableNode)prev, 1, true), n);
}
public static ParseRes<ChangeNode> parsePostfixDecrease(Source src, int i, Node prev, int precedence) {
if (precedence > 15) return ParseRes.failed();
var n = Parsing.skipEmpty(src, i);
var loc = src.loc(i + n);
if (!src.is(i + n, "--")) return ParseRes.failed();
if (!(prev instanceof AssignableNode)) return ParseRes.error(src.loc(i + n), "Expected assignable value before suffix operator.");
n += 2;
return ParseRes.res(new ChangeNode(loc, (AssignableNode)prev, -1, true), n);
} }
} }

View File

@ -1,74 +0,0 @@
package me.topchetoeu.jscript.compilation.values.operations;
import me.topchetoeu.jscript.common.Instruction;
import me.topchetoeu.jscript.common.Operation;
import me.topchetoeu.jscript.common.Instruction.BreakpointType;
import me.topchetoeu.jscript.common.parsing.Location;
import me.topchetoeu.jscript.compilation.CompileResult;
import me.topchetoeu.jscript.compilation.Node;
import me.topchetoeu.jscript.compilation.values.constants.NumberNode;
import me.topchetoeu.jscript.compilation.values.constants.StringNode;
public class IndexAssignNode extends Node {
public final Node object;
public final Node index;
public final Node value;
public final Operation operation;
@Override public void compile(CompileResult target, boolean pollute) {
if (operation != null) {
object.compile(target, true);
if (index instanceof NumberNode num && (int)num.value == num.value) {
target.add(Instruction.loadMember((int)num.value));
value.compile(target, true);
target.add(Instruction.operation(operation));
target.add(Instruction.storeMember((int)num.value, pollute));
}
else if (index instanceof StringNode str) {
target.add(Instruction.loadMember(str.value));
value.compile(target, true);
target.add(Instruction.operation(operation));
target.add(Instruction.storeMember(str.value, pollute));
}
else {
index.compile(target, true);
target.add(Instruction.dup(2));
target.add(Instruction.loadMember());
value.compile(target, true);
target.add(Instruction.operation(operation));
target.add(Instruction.storeMember(pollute));
}
target.setLocationAndDebug(loc(), BreakpointType.STEP_IN);
}
else {
object.compile(target, true);
if (index instanceof NumberNode num && (int)num.value == num.value) {
value.compile(target, true);
target.add(Instruction.storeMember((int)num.value, pollute));
}
else if (index instanceof StringNode str) {
value.compile(target, true);
target.add(Instruction.storeMember(str.value, pollute));
}
else {
index.compile(target, true);
value.compile(target, true);
target.add(Instruction.storeMember(pollute));
}
target.setLocationAndDebug(loc(), BreakpointType.STEP_IN);;
}
}
public IndexAssignNode(Location loc, Node object, Node index, Node value, Operation operation) {
super(loc);
this.object = object;
this.index = index;
this.value = value;
this.operation = operation;
}
}

View File

@ -1,7 +1,6 @@
package me.topchetoeu.jscript.compilation.values.operations; package me.topchetoeu.jscript.compilation.values.operations;
import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Instruction;
import me.topchetoeu.jscript.common.Operation;
import me.topchetoeu.jscript.common.Instruction.BreakpointType; import me.topchetoeu.jscript.common.Instruction.BreakpointType;
import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.jscript.common.parsing.Location;
import me.topchetoeu.jscript.common.parsing.ParseRes; import me.topchetoeu.jscript.common.parsing.ParseRes;
@ -18,9 +17,46 @@ public class IndexNode extends Node implements AssignableNode {
public final Node object; public final Node object;
public final Node index; public final Node index;
@Override public Node toAssign(Node val, Operation operation) { @Override public void compileBeforeAssign(CompileResult target, boolean op) {
return new IndexAssignNode(loc(), object, index, val, operation); object.compile(target, true);
if (index instanceof NumberNode num && (int)num.value == num.value) {
if (op) {
target.add(Instruction.dup());
target.add(Instruction.loadMember((int)num.value));
}
}
else if (index instanceof StringNode str) {
if (op) {
target.add(Instruction.dup());
target.add(Instruction.loadMember(str.value));
}
}
else {
index.compile(target, true);
if (op) {
target.add(Instruction.dup(1, 1));
target.add(Instruction.dup(1, 1));
target.add(Instruction.loadMember());
}
}
} }
@Override public void compileAfterAssign(CompileResult target, boolean op, boolean pollute) {
if (index instanceof NumberNode num && (int)num.value == num.value) {
target.add(Instruction.storeMember((int)num.value, pollute));
}
else if (index instanceof StringNode str) {
target.add(Instruction.storeMember(str.value, pollute));
}
else {
target.add(Instruction.storeMember(pollute));
}
}
// @Override public Node toAssign(Node val, Operation operation) {
// return new IndexAssignNode(loc(), object, index, val, operation);
// }
public void compile(CompileResult target, boolean dupObj, boolean pollute) { public void compile(CompileResult target, boolean dupObj, boolean pollute) {
object.compile(target, true); object.compile(target, true);
if (dupObj) target.add(Instruction.dup()); if (dupObj) target.add(Instruction.dup());

View File

@ -58,7 +58,9 @@ public class OperationNode extends Node {
var other = JavaScript.parseExpression(src, i, precedence); var other = JavaScript.parseExpression(src, i, precedence);
if (!other.isSuccess()) return other.chainError(src.loc(i + other.n), String.format("Expected a value after '%s'", token)); if (!other.isSuccess()) return other.chainError(src.loc(i + other.n), String.format("Expected a value after '%s'", token));
return ParseRes.res(((AssignableNode)prev).toAssign(other.result, operation), other.n);
if (operation == null) return ParseRes.res(new AssignNode(loc, ((AssignableNode)prev), other.result), other.n);
else return ParseRes.res(new ChangeNode(loc, ((AssignableNode)prev), other.result, operation), other.n);
} }
public AssignmentOperatorFactory(String token, int precedence, Operation operation) { public AssignmentOperatorFactory(String token, int precedence, Operation operation) {

View File

@ -0,0 +1,52 @@
package me.topchetoeu.jscript.compilation.values.operations;
import me.topchetoeu.jscript.common.Instruction;
import me.topchetoeu.jscript.common.Operation;
import me.topchetoeu.jscript.common.parsing.Location;
import me.topchetoeu.jscript.common.parsing.ParseRes;
import me.topchetoeu.jscript.common.parsing.Parsing;
import me.topchetoeu.jscript.common.parsing.Source;
import me.topchetoeu.jscript.compilation.AssignableNode;
import me.topchetoeu.jscript.compilation.CompileResult;
import me.topchetoeu.jscript.compilation.Node;
import me.topchetoeu.jscript.compilation.values.constants.NumberNode;
public class PostfixNode extends ChangeNode {
@Override public void compile(CompileResult target, boolean pollute) {
super.compile(target, pollute);
if (pollute) {
value.compile(target, true);
target.add(Instruction.operation(Operation.ADD));
}
}
public PostfixNode(Location loc, AssignableNode value, double addAmount) {
super(loc, value, new NumberNode(loc, -addAmount), Operation.SUBTRACT);
}
public static ParseRes<ChangeNode> parsePostfixIncrease(Source src, int i, Node prev, int precedence) {
if (precedence > 15) return ParseRes.failed();
var n = Parsing.skipEmpty(src, i);
var loc = src.loc(i + n);
if (!src.is(i + n, "++")) return ParseRes.failed();
if (!(prev instanceof AssignableNode)) return ParseRes.error(src.loc(i + n), "Expected assignable value before suffix operator.");
n += 2;
return ParseRes.res(new PostfixNode(loc, (AssignableNode)prev, 1), n);
}
public static ParseRes<ChangeNode> parsePostfixDecrease(Source src, int i, Node prev, int precedence) {
if (precedence > 15) return ParseRes.failed();
var n = Parsing.skipEmpty(src, i);
var loc = src.loc(i + n);
if (!src.is(i + n, "--")) return ParseRes.failed();
if (!(prev instanceof AssignableNode)) return ParseRes.error(src.loc(i + n), "Expected assignable value before suffix operator.");
n += 2;
return ParseRes.res(new PostfixNode(loc, (AssignableNode)prev, -1), n);
}
}

View File

@ -41,10 +41,8 @@ public final class Engine implements EventLoop {
try { try {
((Task<Object>)task).notifier.complete(task.runnable.get()); ((Task<Object>)task).notifier.complete(task.runnable.get());
} }
catch (RuntimeException e) { catch (InterruptException e) { throw e; }
if (e instanceof InterruptException) throw e; catch (RuntimeException e) { task.notifier.completeExceptionally(e); }
task.notifier.completeExceptionally(e);
}
} }
catch (InterruptedException | InterruptException e) { catch (InterruptedException | InterruptException e) {
for (var msg : tasks) msg.notifier.cancel(false); for (var msg : tasks) msg.notifier.cancel(false);

View File

@ -229,12 +229,21 @@ public class SimpleRepl {
if (((ArgumentsValue)args.get(0)).frame.isNew) return new StringValue("new"); if (((ArgumentsValue)args.get(0)).frame.isNew) return new StringValue("new");
else return new StringValue("call"); else return new StringValue("call");
})); }));
res.defineOwnMember(env, "invoke", new NativeFunction(args -> { res.defineOwnMember(env, "invoke", new NativeFunction(args -> {
var func = (FunctionValue)args.get(0); var func = (FunctionValue)args.get(0);
var self = args.get(1); var self = args.get(1);
var funcArgs = (ArrayValue)args.get(2); var funcArgs = (ArrayValue)args.get(2);
var name = args.get(3).toString(env).value;
return func.call(env, self, funcArgs.toArray()); return func.invoke(env, name, self, funcArgs.toArray());
}));
res.defineOwnMember(env, "construct", new NativeFunction(args -> {
var func = (FunctionValue)args.get(0);
var funcArgs = (ArrayValue)args.get(1);
var name = args.get(2).toString(env).value;
return func.construct(env, name, funcArgs.toArray());
})); }));
return res; return res;
@ -264,7 +273,7 @@ public class SimpleRepl {
var self = args.get(1); var self = args.get(1);
var funcArgs = (ArrayValue)args.get(2); var funcArgs = (ArrayValue)args.get(2);
return func.call(env, self, funcArgs.toArray()); return func.invoke(env, self, funcArgs.toArray());
})); }));
return res; return res;
@ -303,6 +312,12 @@ public class SimpleRepl {
case "object": case "object":
args.env.add(Value.OBJECT_PROTO, obj); args.env.add(Value.OBJECT_PROTO, obj);
break; break;
case "function":
args.env.add(Value.FUNCTION_PROTO, obj);
break;
case "array":
args.env.add(Value.ARRAY_PROTO, obj);
break;
} }
return Value.UNDEFINED; return Value.UNDEFINED;

View File

@ -13,12 +13,12 @@ public interface Member {
public final boolean enumerable; public final boolean enumerable;
@Override public Value get(Environment env, Value self) { @Override public Value get(Environment env, Value self) {
if (getter != null) return getter.call(env, self); if (getter != null) return getter.call(env, false, "", self);
else return Value.UNDEFINED; else return Value.UNDEFINED;
} }
@Override public boolean set(Environment env, Value val, Value self) { @Override public boolean set(Environment env, Value val, Value self) {
if (setter == null) return false; if (setter == null) return false;
setter.call(env, self, val); setter.call(env, false, "", self, val);
return true; return true;
} }

View File

@ -1,7 +1,5 @@
package me.topchetoeu.jscript.runtime.values.primitives; package me.topchetoeu.jscript.runtime.values.primitives;
import java.util.Set;
import me.topchetoeu.jscript.common.environment.Environment; import me.topchetoeu.jscript.common.environment.Environment;
import me.topchetoeu.jscript.runtime.exceptions.EngineException; import me.topchetoeu.jscript.runtime.exceptions.EngineException;
import me.topchetoeu.jscript.runtime.values.KeyCache; import me.topchetoeu.jscript.runtime.values.KeyCache;
@ -24,12 +22,6 @@ public final class VoidValue extends PrimitiveValue {
@Override public Member getOwnMember(Environment env, KeyCache key) { @Override public Member getOwnMember(Environment env, KeyCache key) {
throw EngineException.ofError(String.format("Cannot read properties of %s (reading '%s')", name, key.toString(env))); throw EngineException.ofError(String.format("Cannot read properties of %s (reading '%s')", name, key.toString(env)));
} }
@Override public Set<String> getOwnMembers(Environment env, boolean onlyEnumerable) {
throw EngineException.ofError(String.format("Cannot read properties of %s (listing all members)", name));
}
@Override public Set<SymbolValue> getOwnSymbolMembers(Environment env, boolean onlyEnumerable) {
throw EngineException.ofError(String.format("Cannot read properties of %s (listing all symbol members)", name));
}
public VoidValue(String name, StringValue type) { public VoidValue(String name, StringValue type) {
this.name = name; this.name = name;

View File

@ -29,6 +29,7 @@ const invokeType = primordials.function.invokeType;
const setConstructable = primordials.function.setConstructable; const setConstructable = primordials.function.setConstructable;
const setCallable = primordials.function.setCallable; const setCallable = primordials.function.setCallable;
const invoke = primordials.function.invoke; const invoke = primordials.function.invoke;
const construct = primordials.function.construct;
const json = primordials.json; const json = primordials.json;
@ -305,9 +306,7 @@ defineField(Function.prototype, "valueOf", true, false, true, function() {
target.Function = Function; target.Function = Function;
let spread_obj; setIntrinsic("spread_obj", target.spread_obj = (target, obj) => {
setIntrinsic("spread_obj", spread_obj = (target, obj) => {
if (obj === null || obj === undefined) return; if (obj === null || obj === undefined) return;
const members = getOwnMembers(obj, true); const members = getOwnMembers(obj, true);
const symbols = getOwnSymbolMembers(obj, true); const symbols = getOwnSymbolMembers(obj, true);
@ -322,11 +321,16 @@ setIntrinsic("spread_obj", spread_obj = (target, obj) => {
target[member] = obj[member]; target[member] = obj[member];
} }
}); });
setIntrinsic("apply", target.spread_call = (func, self, args) => {
target.spread_obj = spread_obj; return invoke(func, self, args);
});
setIntrinsic("apply", target.spread_new = (func, args) => {
return invoke(func, null, args);
});
setGlobalPrototype("string", String.prototype); setGlobalPrototype("string", String.prototype);
setGlobalPrototype("number", Number.prototype); setGlobalPrototype("number", Number.prototype);
setGlobalPrototype("boolean", Boolean.prototype); setGlobalPrototype("boolean", Boolean.prototype);
setGlobalPrototype("symbol", Symbol.prototype); setGlobalPrototype("symbol", Symbol.prototype);
setGlobalPrototype("object", Object.prototype); setGlobalPrototype("object", Object.prototype);
setGlobalPrototype("function", Function.prototype);