From 8dee4353d4948fa0ada3efa7d50060ce8cfc55e8 Mon Sep 17 00:00:00 2001 From: TopchetoEU <36534413+TopchetoEU@users.noreply.github.com> Date: Fri, 20 Sep 2024 11:37:42 +0300 Subject: [PATCH] feat: implement non-enumerable members in classes --- .../jscript/common/Instruction.java | 8 +- .../jscript/compilation/ClassNode.java | 25 ++-- .../jscript/compilation/FunctionNode.java | 6 +- .../jscript/compilation/JavaScript.java | 8 ++ .../members/AssignShorthandNode.java | 9 +- .../compilation/members/FieldMemberNode.java | 11 +- .../jscript/compilation/members/Member.java | 10 ++ .../compilation/members/MethodMemberNode.java | 7 +- .../members/PropertyMemberNode.java | 8 +- .../compilation/values/ObjectNode.java | 11 +- .../jscript/compilation/values/SuperNode.java | 17 +++ .../compilation/values/VariableNode.java | 6 +- .../jscript/runtime/InstructionRunner.java | 7 +- src/main/resources/lib/index.js | 129 ++++++++---------- 14 files changed, 151 insertions(+), 111 deletions(-) create mode 100644 src/main/java/me/topchetoeu/jscript/compilation/members/Member.java create mode 100644 src/main/java/me/topchetoeu/jscript/compilation/values/SuperNode.java diff --git a/src/main/java/me/topchetoeu/jscript/common/Instruction.java b/src/main/java/me/topchetoeu/jscript/common/Instruction.java index fa441f5..f4884ae 100644 --- a/src/main/java/me/topchetoeu/jscript/common/Instruction.java +++ b/src/main/java/me/topchetoeu/jscript/common/Instruction.java @@ -454,11 +454,11 @@ public class Instruction { return new Instruction(Type.KEYS, own, onlyEnumerable); } - public static Instruction defProp(boolean setter) { - return new Instruction(Type.DEF_PROP, setter); + public static Instruction defProp(boolean setter, boolean enumerable) { + return new Instruction(Type.DEF_PROP, setter, enumerable); } - public static Instruction defField() { - return new Instruction(Type.DEF_FIELD); + public static Instruction defField(boolean enumerable) { + return new Instruction(Type.DEF_FIELD, enumerable); } public static Instruction operation(Operation op) { diff --git a/src/main/java/me/topchetoeu/jscript/compilation/ClassNode.java b/src/main/java/me/topchetoeu/jscript/compilation/ClassNode.java index 9b2ba98..898009a 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/ClassNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/ClassNode.java @@ -11,19 +11,20 @@ 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.members.FieldMemberNode; +import me.topchetoeu.jscript.compilation.members.Member; import me.topchetoeu.jscript.compilation.members.MethodMemberNode; import me.topchetoeu.jscript.compilation.members.PropertyMemberNode; public abstract class ClassNode extends FunctionNode { public static final class ClassBody { - public final List staticMembers; + public final List staticMembers; public final List protoFields; - public final List protoMembers; + public final List protoMembers; public final Parameters constructorParameters; public final CompoundNode constructorBody; public ClassBody( - List staticMembers, List protoFields, List protoMembers, + List staticMembers, List protoFields, List protoMembers, Parameters constructorParameters, CompoundNode constructorBody ) { this.staticMembers = staticMembers; @@ -34,13 +35,15 @@ public abstract class ClassNode extends FunctionNode { } } + // public static final Key + public final ClassBody body; public final String name; @Override public String name() { return name; } public void compileStatic(CompileResult target) { - for (var member : body.staticMembers) member.compile(target, true); + for (var member : body.staticMembers) member.compile(target, true, false); } public void compilePrototype(CompileResult target) { if (body.protoMembers.size() > 0) { @@ -48,17 +51,17 @@ public abstract class ClassNode extends FunctionNode { target.add(Instruction.loadMember("prototype")); for (var i = 0; i < body.protoMembers.size() - 1; i++) { - body.protoMembers.get(i).compile(target, true); + body.protoMembers.get(i).compile(target, true, false); } - body.protoMembers.get(body.protoMembers.size() - 1).compile(target, false); + body.protoMembers.get(body.protoMembers.size() - 1).compile(target, false, false); } } @Override protected void compilePreBody(CompileResult target) { for (var member : body.protoFields) { target.add(Instruction.loadThis()); - member.compile(target, false); + member.compile(target, false, false); } } @@ -76,7 +79,7 @@ public abstract class ClassNode extends FunctionNode { this.body = body; } - public static ParseRes parseMember(Source src, int i) { + public static ParseRes parseMember(Source src, int i) { return ParseRes.first(src, i, PropertyMemberNode::parse, FieldMemberNode::parseClass, @@ -93,8 +96,8 @@ public abstract class ClassNode extends FunctionNode { n += Parsing.skipEmpty(src, i + n); var fields = new LinkedList(); - var members = new LinkedList(); - var statics = new LinkedList(); + var members = new LinkedList(); + var statics = new LinkedList(); var params = new Parameters(new ArrayList<>()); var body = new CompoundNode(loc, false); @@ -106,7 +109,7 @@ public abstract class ClassNode extends FunctionNode { } while (true) { - ParseRes prop = parseMember(src, i + n); + ParseRes prop = parseMember(src, i + n); if (prop.isSuccess()) { n += prop.n; diff --git a/src/main/java/me/topchetoeu/jscript/compilation/FunctionNode.java b/src/main/java/me/topchetoeu/jscript/compilation/FunctionNode.java index 270ea0d..730cf1f 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/FunctionNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/FunctionNode.java @@ -27,10 +27,6 @@ public abstract class FunctionNode extends Node { public final CompileResult compileBody(Environment env, FunctionScope scope, boolean lastReturn, String _name, String selfName) { var name = this.name() != null ? this.name() : _name; - env = env.child() - .remove(LabelContext.BREAK_CTX) - .remove(LabelContext.CONTINUE_CTX); - return new CompileResult(env, scope, params.params.size(), target -> { compilePreBody(target); @@ -68,7 +64,7 @@ public abstract class FunctionNode extends Node { }); } public final CompileResult compileBody(CompileResult parent, String name, String selfName) { - return compileBody(parent.env, new FunctionScope(parent.scope), false, name, selfName); + return compileBody(parent.env.get(JavaScript.COMPILE_ROOT).child(), new FunctionScope(parent.scope), false, name, selfName); } public abstract void compile(CompileResult target, boolean pollute, String name, BreakpointType bp); diff --git a/src/main/java/me/topchetoeu/jscript/compilation/JavaScript.java b/src/main/java/me/topchetoeu/jscript/compilation/JavaScript.java index cc0441d..d9ddbc9 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/JavaScript.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/JavaScript.java @@ -7,6 +7,7 @@ import java.util.Set; import me.topchetoeu.jscript.common.SyntaxException; import me.topchetoeu.jscript.common.environment.Environment; +import me.topchetoeu.jscript.common.environment.Key; import me.topchetoeu.jscript.common.parsing.Filename; import me.topchetoeu.jscript.common.parsing.ParseRes; import me.topchetoeu.jscript.common.parsing.Parsing; @@ -31,6 +32,7 @@ import me.topchetoeu.jscript.compilation.values.ArrayNode; import me.topchetoeu.jscript.compilation.values.ClassValueNode; import me.topchetoeu.jscript.compilation.values.ObjectNode; import me.topchetoeu.jscript.compilation.values.RegexNode; +import me.topchetoeu.jscript.compilation.values.SuperNode; import me.topchetoeu.jscript.compilation.values.ThisNode; import me.topchetoeu.jscript.compilation.values.VariableNode; import me.topchetoeu.jscript.compilation.values.constants.BoolNode; @@ -59,6 +61,8 @@ public final class JavaScript { } } + public static final Key COMPILE_ROOT = Key.of(); + static final Set reserved = new HashSet<>(Arrays.asList( "true", "false", "void", "null", "this", "if", "else", "try", "catch", "finally", "for", "do", "while", "switch", "case", "default", "new", @@ -120,6 +124,7 @@ public final class JavaScript { if (id.result.equals("false")) return ParseRes.res(new BoolNode(loc, false), n); if (id.result.equals("null")) return ParseRes.res(new NullNode(loc), n); if (id.result.equals("this")) return ParseRes.res(new ThisNode(loc), n); + if (id.result.equals("super")) return ParseRes.res(new SuperNode(loc), n); if (id.result.equals("arguments")) return ParseRes.res(new ArgumentsNode(loc), n); return ParseRes.failed(); @@ -264,6 +269,9 @@ public final class JavaScript { } public static CompileResult compile(Environment env, Node ...statements) { + env = env.child(); + env.add(COMPILE_ROOT, env); + var func = new FunctionValueNode(null, null, new Parameters(Arrays.asList()), new CompoundNode(null, true, statements), null); var res = func.compileBody(env, new FunctionScope(true), true, null, null); res.buildTask.run(); diff --git a/src/main/java/me/topchetoeu/jscript/compilation/members/AssignShorthandNode.java b/src/main/java/me/topchetoeu/jscript/compilation/members/AssignShorthandNode.java index 5fc491c..116f787 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/members/AssignShorthandNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/members/AssignShorthandNode.java @@ -13,17 +13,20 @@ import me.topchetoeu.jscript.compilation.values.VariableNode; import me.topchetoeu.jscript.compilation.values.constants.StringNode; import me.topchetoeu.jscript.compilation.values.operations.AssignNode; -public class AssignShorthandNode extends Node { +public class AssignShorthandNode implements Member { + public final Location loc; public final Node key; public final AssignTarget target; public final Node value; - @Override public void compile(CompileResult target, boolean pollute) { + @Override public Location loc() { return loc; } + + @Override public void compile(CompileResult target, boolean pollute, boolean enumerable) { throw new SyntaxException(loc(), "Unexpected assign shorthand in non-destructor context"); } public AssignShorthandNode(Location loc, Node key, AssignTarget target, Node value) { - super(loc); + this.loc = loc; this.key = key; this.target = target; this.value = value; diff --git a/src/main/java/me/topchetoeu/jscript/compilation/members/FieldMemberNode.java b/src/main/java/me/topchetoeu/jscript/compilation/members/FieldMemberNode.java index 9706722..4402693 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/members/FieldMemberNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/members/FieldMemberNode.java @@ -12,22 +12,25 @@ import me.topchetoeu.jscript.compilation.values.ObjectNode; import me.topchetoeu.jscript.compilation.values.VariableNode; import me.topchetoeu.jscript.compilation.values.constants.StringNode; -public class FieldMemberNode extends Node { +public class FieldMemberNode implements Member { + public final Location loc; public final Node key; public final Node value; - @Override public void compile(CompileResult target, boolean pollute) { + @Override public Location loc() { return loc; } + + @Override public void compile(CompileResult target, boolean pollute, boolean enumerable) { if (pollute) target.add(Instruction.dup()); key.compile(target, true); if (value == null) target.add(Instruction.pushUndefined()); else value.compile(target, true); - target.add(Instruction.defField()); + target.add(Instruction.defField(enumerable)); } public FieldMemberNode(Location loc, Node key, Node value) { - super(loc); + this.loc = loc; this.key = key; this.value = value; } diff --git a/src/main/java/me/topchetoeu/jscript/compilation/members/Member.java b/src/main/java/me/topchetoeu/jscript/compilation/members/Member.java new file mode 100644 index 0000000..505071a --- /dev/null +++ b/src/main/java/me/topchetoeu/jscript/compilation/members/Member.java @@ -0,0 +1,10 @@ +package me.topchetoeu.jscript.compilation.members; + +import me.topchetoeu.jscript.common.parsing.Location; +import me.topchetoeu.jscript.compilation.CompileResult; + +public interface Member { + Location loc(); + + void compile(CompileResult target, boolean pollute, boolean enumerable); +} diff --git a/src/main/java/me/topchetoeu/jscript/compilation/members/MethodMemberNode.java b/src/main/java/me/topchetoeu/jscript/compilation/members/MethodMemberNode.java index 8636c3d..d100366 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/members/MethodMemberNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/members/MethodMemberNode.java @@ -14,7 +14,7 @@ import me.topchetoeu.jscript.compilation.Parameters; import me.topchetoeu.jscript.compilation.values.ObjectNode; import me.topchetoeu.jscript.compilation.values.constants.StringNode; -public class MethodMemberNode extends FunctionNode { +public class MethodMemberNode extends FunctionNode implements Member { public final Node key; @Override public String name() { @@ -28,8 +28,11 @@ public class MethodMemberNode extends FunctionNode { var id = target.addChild(compileBody(target, name, null)); target.add(_i -> Instruction.loadFunc(id, true, false, false, name, captures(id, target))); + } - target.add(Instruction.defField()); + @Override public void compile(CompileResult target, boolean pollute, boolean enumerable) { + compile(target, pollute); + target.add(Instruction.defField(enumerable)); } public MethodMemberNode(Location loc, Location end, Node key, Parameters params, CompoundNode body) { diff --git a/src/main/java/me/topchetoeu/jscript/compilation/members/PropertyMemberNode.java b/src/main/java/me/topchetoeu/jscript/compilation/members/PropertyMemberNode.java index 6e49e62..ff7d748 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/members/PropertyMemberNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/members/PropertyMemberNode.java @@ -17,7 +17,7 @@ import me.topchetoeu.jscript.compilation.patterns.Pattern; import me.topchetoeu.jscript.compilation.values.ObjectNode; import me.topchetoeu.jscript.compilation.values.constants.StringNode; -public class PropertyMemberNode extends FunctionNode { +public class PropertyMemberNode extends FunctionNode implements Member{ public final Node key; public final Pattern argument; @@ -38,8 +38,12 @@ public class PropertyMemberNode extends FunctionNode { var id = target.addChild(compileBody(target, name, null)); target.add(_i -> Instruction.loadFunc(id, true, false, false, name, captures(id, target))); + } - target.add(Instruction.defProp(isSetter())); + + @Override public void compile(CompileResult target, boolean pollute, boolean enumerable) { + compile(target, pollute); + target.add(Instruction.defProp(isSetter(), enumerable)); } public PropertyMemberNode(Location loc, Location end, Node key, Pattern argument, CompoundNode body) { diff --git a/src/main/java/me/topchetoeu/jscript/compilation/values/ObjectNode.java b/src/main/java/me/topchetoeu/jscript/compilation/values/ObjectNode.java index eee8f17..b694117 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/values/ObjectNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/values/ObjectNode.java @@ -14,6 +14,7 @@ import me.topchetoeu.jscript.compilation.JavaScript; import me.topchetoeu.jscript.compilation.Node; import me.topchetoeu.jscript.compilation.members.AssignShorthandNode; import me.topchetoeu.jscript.compilation.members.FieldMemberNode; +import me.topchetoeu.jscript.compilation.members.Member; import me.topchetoeu.jscript.compilation.members.MethodMemberNode; import me.topchetoeu.jscript.compilation.members.PropertyMemberNode; import me.topchetoeu.jscript.compilation.patterns.AssignTarget; @@ -23,7 +24,7 @@ import me.topchetoeu.jscript.compilation.values.constants.NumberNode; import me.topchetoeu.jscript.compilation.values.constants.StringNode; public class ObjectNode extends Node implements AssignTargetLike { - public final List members; + public final List members; // TODO: Implement spreading into object @@ -64,7 +65,7 @@ public class ObjectNode extends Node implements AssignTargetLike { @Override public void compile(CompileResult target, boolean pollute) { target.add(Instruction.loadObj()); - for (var el : members) el.compile(target, true); + for (var el : members) el.compile(target, true, true); } @Override public AssignTarget toAssignTarget() { @@ -82,7 +83,7 @@ public class ObjectNode extends Node implements AssignTargetLike { return new ObjectPattern(loc(), newMembers); } - public ObjectNode(Location loc, List map) { + public ObjectNode(Location loc, List map) { super(loc); this.members = map; } @@ -126,7 +127,7 @@ public class ObjectNode extends Node implements AssignTargetLike { n++; n += Parsing.skipEmpty(src, i + n); - var members = new LinkedList(); + var members = new LinkedList(); if (src.is(i + n, "}")) { n++; @@ -134,7 +135,7 @@ public class ObjectNode extends Node implements AssignTargetLike { } while (true) { - ParseRes prop = ParseRes.first(src, i + n, + ParseRes prop = ParseRes.first(src, i + n, MethodMemberNode::parse, PropertyMemberNode::parse, FieldMemberNode::parseObject, diff --git a/src/main/java/me/topchetoeu/jscript/compilation/values/SuperNode.java b/src/main/java/me/topchetoeu/jscript/compilation/values/SuperNode.java new file mode 100644 index 0000000..b7284fb --- /dev/null +++ b/src/main/java/me/topchetoeu/jscript/compilation/values/SuperNode.java @@ -0,0 +1,17 @@ +package me.topchetoeu.jscript.compilation.values; + +import me.topchetoeu.jscript.common.SyntaxException; +import me.topchetoeu.jscript.common.parsing.Location; +import me.topchetoeu.jscript.compilation.CompileResult; +import me.topchetoeu.jscript.compilation.Node; + + +public class SuperNode extends Node { + @Override public void compile(CompileResult target, boolean pollute) { + throw new SyntaxException(loc(), "Unexpected 'super' reference here"); + } + + public SuperNode(Location loc) { + super(loc); + } +} diff --git a/src/main/java/me/topchetoeu/jscript/compilation/values/VariableNode.java b/src/main/java/me/topchetoeu/jscript/compilation/values/VariableNode.java index ae32c9c..c4e90e4 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/values/VariableNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/values/VariableNode.java @@ -45,6 +45,8 @@ public class VariableNode extends Node implements Pattern, ChangeTarget { if (i == null) return Instruction.globDef(name); else return Instruction.nop(); }); + + target.setLocation(loc()); } @Override public void destruct(CompileResult target, DeclarationType decl, boolean shouldDeclare) { @@ -57,10 +59,12 @@ public class VariableNode extends Node implements Pattern, ChangeTarget { var v = target.scope.define(decl, name, loc()); target.add(_i -> v.index().toInit()); } + + target.setLocation(loc()); } @Override public void compile(CompileResult target, boolean pollute) { - target.add(toGet(target, loc(), name, true, false)); + target.add(toGet(target, loc(), name, true, false)).setLocation(loc()); } public static IntFunction toGet(CompileResult target, Location loc, String name, boolean keep, boolean forceGet) { diff --git a/src/main/java/me/topchetoeu/jscript/runtime/InstructionRunner.java b/src/main/java/me/topchetoeu/jscript/runtime/InstructionRunner.java index a019369..8bdc6dd 100644 --- a/src/main/java/me/topchetoeu/jscript/runtime/InstructionRunner.java +++ b/src/main/java/me/topchetoeu/jscript/runtime/InstructionRunner.java @@ -7,6 +7,7 @@ import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Operation; import me.topchetoeu.jscript.common.environment.Environment; import me.topchetoeu.jscript.runtime.exceptions.EngineException; +import me.topchetoeu.jscript.runtime.values.Member.FieldMember; import me.topchetoeu.jscript.runtime.values.Member.PropertyMember; import me.topchetoeu.jscript.runtime.values.Value; import me.topchetoeu.jscript.runtime.values.functions.CodeFunction; @@ -68,8 +69,8 @@ public class InstructionRunner { else if (val instanceof FunctionValue func) accessor = func; else throw EngineException.ofType("Getter must be a function or undefined."); - if ((boolean)instr.get(0)) obj.defineOwnMember(env, key, new PropertyMember(obj, null, accessor, true, true)); - else obj.defineOwnMember(env, key, new PropertyMember(obj, accessor, null, true, true)); + if ((boolean)instr.get(0)) obj.defineOwnMember(env, key, new PropertyMember(obj, null, accessor, true, instr.get(1))); + else obj.defineOwnMember(env, key, new PropertyMember(obj, accessor, null, true, instr.get(1))); frame.codePtr++; return null; @@ -79,7 +80,7 @@ public class InstructionRunner { var key = frame.pop(); var obj = frame.pop(); - obj.defineOwnMember(env, key, val); + obj.defineOwnMember(env, key, FieldMember.of(obj, val, true, instr.get(0), true)); frame.codePtr++; return null; diff --git a/src/main/resources/lib/index.js b/src/main/resources/lib/index.js index b7711eb..e2f8af6 100644 --- a/src/main/resources/lib/index.js +++ b/src/main/resources/lib/index.js @@ -1,5 +1,3 @@ -// return; - const target = arguments[0]; const primordials = arguments[1]; @@ -20,28 +18,26 @@ const symbol = primordials.symbol || (() => { }; }); -const number = primordials.number || (() => { - return { - parseInt() { throw new Error("parseInt not supported"); }, - parseFloat() { throw new Error("parseFloat not supported"); }, - isNaN: (val) => val !== val, - NaN: 0 / 0, - Infinity: 1 / 0, - }; -}); +const number = primordials.number || { + parseInt() { throw new Error("parseInt not supported"); }, + parseFloat() { throw new Error("parseFloat not supported"); }, + isNaN: (val) => val !== val, + NaN: 0 / 0, + Infinity: 1 / 0, +}; -const fromCharCode = primordials.string.fromCharCode; -const fromCodePoint = primordials.string.fromCodePoint; -const stringBuild = primordials.string.stringBuild; +const string = primordials.string; -const defineProperty = primordials.object.defineProperty; -const defineField = primordials.object.defineField; -const getOwnMember = primordials.object.getMember; -const getOwnSymbolMember = primordials.object.getOwnSymbolMember; -const getOwnMembers = primordials.object.getOwnMembers; -const getOwnSymbolMembers = primordials.object.getOwnSymbolMembers; -const getPrototype = primordials.object.getPrototype; -const setPrototype = primordials.object.setPrototype; +const object = primordials.object || { + defineProperty() { throw new Error("Define property not polyfillable"); }, + defineField(obj, key, a, b, c, value) { obj[key] = value; }, + getOwnMember() { throw new Error("Get own member not polyfillable"); }, + getOwnSymbolMember() { throw new Error("Get own symbol member not polyfillable"); }, + getOwnMembers() { throw new Error("Get own members not polyfillable"); }, + getOwnSymbolMembers() { throw new Error("Get own symbol members not polyfillable"); }, + getPrototype() { throw new Error("Get prototype not polyfillable"); }, + setPrototype() { throw new Error("Set prototype not polyfillable"); }, +} const invokeType = primordials.function.invokeType; const setConstructable = primordials.function.setConstructable; @@ -97,14 +93,14 @@ class Symbol { setCallable(Symbol, true); setConstructable(Symbol, false); -defineField(Symbol, "asyncIterator", false, false, false, Symbol("Symbol.asyncIterator")); -defineField(Symbol, "iterator", false, false, false, Symbol("Symbol.iterator")); -defineField(Symbol, "match", false, false, false, Symbol("Symbol.match")); -defineField(Symbol, "matchAll", false, false, false, Symbol("Symbol.matchAll")); -defineField(Symbol, "replace", false, false, false, Symbol("Symbol.replace")); -defineField(Symbol, "search", false, false, false, Symbol("Symbol.search")); -defineField(Symbol, "split", false, false, false, Symbol("Symbol.split")); -defineField(Symbol, "toStringTag", false, false, false, Symbol("Symbol.toStringTag")); +object.defineField(Symbol, "asyncIterator", false, false, false, Symbol("Symbol.asyncIterator")); +object.defineField(Symbol, "iterator", false, false, false, Symbol("Symbol.iterator")); +object.defineField(Symbol, "match", false, false, false, Symbol("Symbol.match")); +object.defineField(Symbol, "matchAll", false, false, false, Symbol("Symbol.matchAll")); +object.defineField(Symbol, "replace", false, false, false, Symbol("Symbol.replace")); +object.defineField(Symbol, "search", false, false, false, Symbol("Symbol.search")); +object.defineField(Symbol, "split", false, false, false, Symbol("Symbol.split")); +object.defineField(Symbol, "toStringTag", false, false, false, Symbol("Symbol.toStringTag")); Symbol(); target.Symbol = Symbol; @@ -160,14 +156,14 @@ class Number { } } -defineField(Number, "EPSILON", false, false, false, 2.220446049250313e-16); -defineField(Number, "MIN_SAFE_INTEGER", false, false, false, -9007199254740991); -defineField(Number, "MAX_SAFE_INTEGER", false, false, false, 9007199254740991); -defineField(Number, "POSITIVE_INFINITY", false, false, false, +number.Infinity); -defineField(Number, "NEGATIVE_INFINITY", false, false, false, -number.Infinity); -defineField(Number, "NaN", false, false, false, number.NaN); -defineField(Number, "MAX_VALUE", false, false, false, 1.7976931348623157e+308); -defineField(Number, "MIN_VALUE", false, false, false, 5e-324); +object.defineField(Number, "EPSILON", false, false, false, 2.220446049250313e-16); +object.defineField(Number, "MIN_SAFE_INTEGER", false, false, false, -9007199254740991); +object.defineField(Number, "MAX_SAFE_INTEGER", false, false, false, 9007199254740991); +object.defineField(Number, "POSITIVE_INFINITY", false, false, false, +number.Infinity); +object.defineField(Number, "NEGATIVE_INFINITY", false, false, false, -number.Infinity); +object.defineField(Number, "NaN", false, false, false, number.NaN); +object.defineField(Number, "MAX_VALUE", false, false, false, 1.7976931348623157e+308); +object.defineField(Number, "MIN_VALUE", false, false, false, 5e-324); setCallable(Number, true); target.Number = Number; @@ -202,20 +198,20 @@ class String { res[arguments.length] = 0; for (let i = 0; i < arguments.length; i++) { - res[i] = fromCharCode(+arguments[i]); + res[i] = string.fromCharCode(+arguments[i]); } - return stringBuild(res); + return string.stringBuild(res); } static fromCodePoint() { const res = []; res[arguments.length] = 0; for (let i = 0; i < arguments.length; i++) { - res[i] = fromCodePoint(+arguments[i]); + res[i] = string.fromCodePoint(+arguments[i]); } - return stringBuild(res); + return string.stringBuild(res); } } @@ -290,8 +286,6 @@ class Object { if ("get" in desc || "set" in desc) { let get = desc.get, set = desc.set; - print(typeof get); - if (get !== undefined && typeof get !== "function") throw new TypeError("Getter must be a function: " + get); if (set !== undefined && typeof set !== "function") throw new TypeError("Setter must be a function: " + set); @@ -299,11 +293,11 @@ class Object { throw new TypeError("Invalid property descriptor. Cannot both specify accessors and a value or writable attribute"); } - if (!defineProperty(obj, key, desc.enumerable, desc.configurable, get, set)) { + if (!object.defineProperty(obj, key, desc.enumerable, desc.configurable, get, set)) { throw new TypeError("Cannot redefine property: " + key); } } - else if (!defineField(obj, key, desc.writable, desc.enumerable, desc.configurable, desc.value)) { + else if (!object.defineField(obj, key, desc.writable, desc.enumerable, desc.configurable, desc.value)) { throw new TypeError("Cannot redefine property: " + key); } @@ -312,7 +306,7 @@ class Object { } setCallable(Object, true); -setPrototype(Object.prototype, null); +object.setPrototype(Object.prototype, null); target.Object = Object; class Function { @@ -322,7 +316,7 @@ class Function { } constructor() { - const parts = ["return function annonymous("]; + const parts = ["(function annonymous("]; for (let i = 0; i < arguments.length - 1; i++) { if (i > 0) parts[parts.length] = ","; @@ -330,9 +324,9 @@ class Function { } parts[parts.length] = "){\n"; parts[parts.length] = String(arguments[arguments.length - 1]); - parts[parts.length] = "\n}"; + parts[parts.length] = "\n})"; - const res = compile(stringBuild(parts))(); + const res = compile(string.stringBuild(parts))(); return res; } @@ -341,27 +335,20 @@ class Function { if (wrap) parts[parts.length] = "return (function() {\n"; if (globals.length > 0) { - parts[parts.length] = "var "; + parts[parts.length] = "let {"; for (let i = 0; i < globals.length; i++) { if (i > 0) parts[parts.length] = ","; parts[parts.length] = globals[i]; } - parts[parts.length] = ";((g=arguments[0])=>{"; - - for (let i = 0; i < globals.length; i++) { - const name = globals[i]; - parts[parts.length] = name + "=g[" + json.stringify(name) + "];"; - } - - parts[parts.length] = "})()\n"; + parts[parts.length] = "} = arguments[0];"; } parts[parts.length] = src; if (wrap) parts[parts.length] = "\n})(arguments[0])"; - const res = compile(stringBuild(parts)); + const res = compile(string.stringBuild(parts)); return res; } } @@ -400,8 +387,8 @@ class Error { } } -defineField(Error.prototype, "name", true, false, true, "Error"); -defineField(Error.prototype, "message", true, false, true, ""); +object.defineField(Error.prototype, "name", true, false, true, "Error"); +object.defineField(Error.prototype, "message", true, false, true, ""); setCallable(Error, true); target.Error = Error; @@ -412,9 +399,9 @@ class SyntaxError { } } -defineField(SyntaxError.prototype, "name", true, false, true, "SyntaxError"); -setPrototype(SyntaxError, Error); -setPrototype(SyntaxError.prototype, Error.prototype); +object.defineField(SyntaxError.prototype, "name", true, false, true, "SyntaxError"); +object.setPrototype(SyntaxError, Error); +object.setPrototype(SyntaxError.prototype, Error.prototype); setCallable(SyntaxError, true); target.SyntaxError = SyntaxError; @@ -425,9 +412,9 @@ class TypeError { } } -defineField(TypeError.prototype, "name", true, false, true, "TypeError"); -setPrototype(TypeError, Error); -setPrototype(TypeError.prototype, Error.prototype); +object.defineField(TypeError.prototype, "name", true, false, true, "TypeError"); +object.setPrototype(TypeError, Error); +object.setPrototype(TypeError.prototype, Error.prototype); setCallable(TypeError, true); target.TypeError = TypeError; @@ -438,9 +425,9 @@ class RangeError { } } -defineField(RangeError.prototype, "name", true, false, true, "RangeError"); -setPrototype(RangeError, Error); -setPrototype(RangeError.prototype, Error.prototype); +object.defineField(RangeError.prototype, "name", true, false, true, "RangeError"); +object.setPrototype(RangeError, Error); +object.setPrototype(RangeError.prototype, Error.prototype); setCallable(RangeError, true); target.RangeError = RangeError;