feat: implement non-enumerable members in classes

This commit is contained in:
TopchetoEU 2024-09-20 11:37:42 +03:00
parent 59e6f34a01
commit 8dee4353d4
Signed by: topchetoeu
GPG Key ID: 6531B8583E5F6ED4
14 changed files with 151 additions and 111 deletions

View File

@ -454,11 +454,11 @@ public class Instruction {
return new Instruction(Type.KEYS, own, onlyEnumerable); return new Instruction(Type.KEYS, own, onlyEnumerable);
} }
public static Instruction defProp(boolean setter) { public static Instruction defProp(boolean setter, boolean enumerable) {
return new Instruction(Type.DEF_PROP, setter); return new Instruction(Type.DEF_PROP, setter, enumerable);
} }
public static Instruction defField() { public static Instruction defField(boolean enumerable) {
return new Instruction(Type.DEF_FIELD); return new Instruction(Type.DEF_FIELD, enumerable);
} }
public static Instruction operation(Operation op) { public static Instruction operation(Operation op) {

View File

@ -11,19 +11,20 @@ import me.topchetoeu.jscript.common.parsing.ParseRes;
import me.topchetoeu.jscript.common.parsing.Parsing; import me.topchetoeu.jscript.common.parsing.Parsing;
import me.topchetoeu.jscript.common.parsing.Source; import me.topchetoeu.jscript.common.parsing.Source;
import me.topchetoeu.jscript.compilation.members.FieldMemberNode; 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.MethodMemberNode;
import me.topchetoeu.jscript.compilation.members.PropertyMemberNode; import me.topchetoeu.jscript.compilation.members.PropertyMemberNode;
public abstract class ClassNode extends FunctionNode { public abstract class ClassNode extends FunctionNode {
public static final class ClassBody { public static final class ClassBody {
public final List<Node> staticMembers; public final List<Member> staticMembers;
public final List<FieldMemberNode> protoFields; public final List<FieldMemberNode> protoFields;
public final List<Node> protoMembers; public final List<Member> protoMembers;
public final Parameters constructorParameters; public final Parameters constructorParameters;
public final CompoundNode constructorBody; public final CompoundNode constructorBody;
public ClassBody( public ClassBody(
List<Node> staticMembers, List<FieldMemberNode> protoFields, List<Node> protoMembers, List<Member> staticMembers, List<FieldMemberNode> protoFields, List<Member> protoMembers,
Parameters constructorParameters, CompoundNode constructorBody Parameters constructorParameters, CompoundNode constructorBody
) { ) {
this.staticMembers = staticMembers; this.staticMembers = staticMembers;
@ -34,13 +35,15 @@ public abstract class ClassNode extends FunctionNode {
} }
} }
// public static final Key<Void>
public final ClassBody body; public final ClassBody body;
public final String name; public final String name;
@Override public String name() { return name; } @Override public String name() { return name; }
public void compileStatic(CompileResult target) { 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) { public void compilePrototype(CompileResult target) {
if (body.protoMembers.size() > 0) { if (body.protoMembers.size() > 0) {
@ -48,17 +51,17 @@ public abstract class ClassNode extends FunctionNode {
target.add(Instruction.loadMember("prototype")); target.add(Instruction.loadMember("prototype"));
for (var i = 0; i < body.protoMembers.size() - 1; i++) { 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) { @Override protected void compilePreBody(CompileResult target) {
for (var member : body.protoFields) { for (var member : body.protoFields) {
target.add(Instruction.loadThis()); 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; this.body = body;
} }
public static ParseRes<Node> parseMember(Source src, int i) { public static ParseRes<Member> parseMember(Source src, int i) {
return ParseRes.first(src, i, return ParseRes.first(src, i,
PropertyMemberNode::parse, PropertyMemberNode::parse,
FieldMemberNode::parseClass, FieldMemberNode::parseClass,
@ -93,8 +96,8 @@ public abstract class ClassNode extends FunctionNode {
n += Parsing.skipEmpty(src, i + n); n += Parsing.skipEmpty(src, i + n);
var fields = new LinkedList<FieldMemberNode>(); var fields = new LinkedList<FieldMemberNode>();
var members = new LinkedList<Node>(); var members = new LinkedList<Member>();
var statics = new LinkedList<Node>(); var statics = new LinkedList<Member>();
var params = new Parameters(new ArrayList<>()); var params = new Parameters(new ArrayList<>());
var body = new CompoundNode(loc, false); var body = new CompoundNode(loc, false);
@ -106,7 +109,7 @@ public abstract class ClassNode extends FunctionNode {
} }
while (true) { while (true) {
ParseRes<Node> prop = parseMember(src, i + n); ParseRes<Member> prop = parseMember(src, i + n);
if (prop.isSuccess()) { if (prop.isSuccess()) {
n += prop.n; n += prop.n;

View File

@ -27,10 +27,6 @@ public abstract class FunctionNode extends Node {
public final CompileResult compileBody(Environment env, FunctionScope scope, boolean lastReturn, String _name, String selfName) { public final CompileResult compileBody(Environment env, FunctionScope scope, boolean lastReturn, String _name, String selfName) {
var name = this.name() != null ? this.name() : _name; 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 -> { return new CompileResult(env, scope, params.params.size(), target -> {
compilePreBody(target); compilePreBody(target);
@ -68,7 +64,7 @@ public abstract class FunctionNode extends Node {
}); });
} }
public final CompileResult compileBody(CompileResult parent, String name, String selfName) { 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); public abstract void compile(CompileResult target, boolean pollute, String name, BreakpointType bp);

View File

@ -7,6 +7,7 @@ import java.util.Set;
import me.topchetoeu.jscript.common.SyntaxException; import me.topchetoeu.jscript.common.SyntaxException;
import me.topchetoeu.jscript.common.environment.Environment; 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.Filename;
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;
@ -31,6 +32,7 @@ import me.topchetoeu.jscript.compilation.values.ArrayNode;
import me.topchetoeu.jscript.compilation.values.ClassValueNode; import me.topchetoeu.jscript.compilation.values.ClassValueNode;
import me.topchetoeu.jscript.compilation.values.ObjectNode; import me.topchetoeu.jscript.compilation.values.ObjectNode;
import me.topchetoeu.jscript.compilation.values.RegexNode; 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.ThisNode;
import me.topchetoeu.jscript.compilation.values.VariableNode; import me.topchetoeu.jscript.compilation.values.VariableNode;
import me.topchetoeu.jscript.compilation.values.constants.BoolNode; import me.topchetoeu.jscript.compilation.values.constants.BoolNode;
@ -59,6 +61,8 @@ public final class JavaScript {
} }
} }
public static final Key<Environment> COMPILE_ROOT = Key.of();
static final Set<String> reserved = new HashSet<>(Arrays.asList( static final Set<String> reserved = new HashSet<>(Arrays.asList(
"true", "false", "void", "null", "this", "if", "else", "try", "catch", "true", "false", "void", "null", "this", "if", "else", "try", "catch",
"finally", "for", "do", "while", "switch", "case", "default", "new", "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("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("null")) return ParseRes.res(new NullNode(loc), n);
if (id.result.equals("this")) return ParseRes.res(new ThisNode(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); if (id.result.equals("arguments")) return ParseRes.res(new ArgumentsNode(loc), n);
return ParseRes.failed(); return ParseRes.failed();
@ -264,6 +269,9 @@ public final class JavaScript {
} }
public static CompileResult compile(Environment env, Node ...statements) { 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 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); var res = func.compileBody(env, new FunctionScope(true), true, null, null);
res.buildTask.run(); res.buildTask.run();

View File

@ -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.constants.StringNode;
import me.topchetoeu.jscript.compilation.values.operations.AssignNode; 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 Node key;
public final AssignTarget target; public final AssignTarget target;
public final Node value; 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"); throw new SyntaxException(loc(), "Unexpected assign shorthand in non-destructor context");
} }
public AssignShorthandNode(Location loc, Node key, AssignTarget target, Node value) { public AssignShorthandNode(Location loc, Node key, AssignTarget target, Node value) {
super(loc); this.loc = loc;
this.key = key; this.key = key;
this.target = target; this.target = target;
this.value = value; this.value = value;

View File

@ -12,22 +12,25 @@ import me.topchetoeu.jscript.compilation.values.ObjectNode;
import me.topchetoeu.jscript.compilation.values.VariableNode; import me.topchetoeu.jscript.compilation.values.VariableNode;
import me.topchetoeu.jscript.compilation.values.constants.StringNode; 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 key;
public final Node value; 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()); if (pollute) target.add(Instruction.dup());
key.compile(target, true); key.compile(target, true);
if (value == null) target.add(Instruction.pushUndefined()); if (value == null) target.add(Instruction.pushUndefined());
else value.compile(target, true); else value.compile(target, true);
target.add(Instruction.defField()); target.add(Instruction.defField(enumerable));
} }
public FieldMemberNode(Location loc, Node key, Node value) { public FieldMemberNode(Location loc, Node key, Node value) {
super(loc); this.loc = loc;
this.key = key; this.key = key;
this.value = value; this.value = value;
} }

View File

@ -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);
}

View File

@ -14,7 +14,7 @@ import me.topchetoeu.jscript.compilation.Parameters;
import me.topchetoeu.jscript.compilation.values.ObjectNode; import me.topchetoeu.jscript.compilation.values.ObjectNode;
import me.topchetoeu.jscript.compilation.values.constants.StringNode; import me.topchetoeu.jscript.compilation.values.constants.StringNode;
public class MethodMemberNode extends FunctionNode { public class MethodMemberNode extends FunctionNode implements Member {
public final Node key; public final Node key;
@Override public String name() { @Override public String name() {
@ -28,8 +28,11 @@ public class MethodMemberNode extends FunctionNode {
var id = target.addChild(compileBody(target, name, null)); var id = target.addChild(compileBody(target, name, null));
target.add(_i -> Instruction.loadFunc(id, true, false, false, name, captures(id, target))); 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) { public MethodMemberNode(Location loc, Location end, Node key, Parameters params, CompoundNode body) {

View File

@ -17,7 +17,7 @@ import me.topchetoeu.jscript.compilation.patterns.Pattern;
import me.topchetoeu.jscript.compilation.values.ObjectNode; import me.topchetoeu.jscript.compilation.values.ObjectNode;
import me.topchetoeu.jscript.compilation.values.constants.StringNode; 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 Node key;
public final Pattern argument; public final Pattern argument;
@ -38,8 +38,12 @@ public class PropertyMemberNode extends FunctionNode {
var id = target.addChild(compileBody(target, name, null)); var id = target.addChild(compileBody(target, name, null));
target.add(_i -> Instruction.loadFunc(id, true, false, false, name, captures(id, target))); 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) { public PropertyMemberNode(Location loc, Location end, Node key, Pattern argument, CompoundNode body) {

View File

@ -14,6 +14,7 @@ import me.topchetoeu.jscript.compilation.JavaScript;
import me.topchetoeu.jscript.compilation.Node; import me.topchetoeu.jscript.compilation.Node;
import me.topchetoeu.jscript.compilation.members.AssignShorthandNode; import me.topchetoeu.jscript.compilation.members.AssignShorthandNode;
import me.topchetoeu.jscript.compilation.members.FieldMemberNode; 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.MethodMemberNode;
import me.topchetoeu.jscript.compilation.members.PropertyMemberNode; import me.topchetoeu.jscript.compilation.members.PropertyMemberNode;
import me.topchetoeu.jscript.compilation.patterns.AssignTarget; 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; import me.topchetoeu.jscript.compilation.values.constants.StringNode;
public class ObjectNode extends Node implements AssignTargetLike { public class ObjectNode extends Node implements AssignTargetLike {
public final List<Node> members; public final List<Member> members;
// TODO: Implement spreading into object // TODO: Implement spreading into object
@ -64,7 +65,7 @@ public class ObjectNode extends Node implements AssignTargetLike {
@Override public void compile(CompileResult target, boolean pollute) { @Override public void compile(CompileResult target, boolean pollute) {
target.add(Instruction.loadObj()); 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() { @Override public AssignTarget toAssignTarget() {
@ -82,7 +83,7 @@ public class ObjectNode extends Node implements AssignTargetLike {
return new ObjectPattern(loc(), newMembers); return new ObjectPattern(loc(), newMembers);
} }
public ObjectNode(Location loc, List<Node> map) { public ObjectNode(Location loc, List<Member> map) {
super(loc); super(loc);
this.members = map; this.members = map;
} }
@ -126,7 +127,7 @@ public class ObjectNode extends Node implements AssignTargetLike {
n++; n++;
n += Parsing.skipEmpty(src, i + n); n += Parsing.skipEmpty(src, i + n);
var members = new LinkedList<Node>(); var members = new LinkedList<Member>();
if (src.is(i + n, "}")) { if (src.is(i + n, "}")) {
n++; n++;
@ -134,7 +135,7 @@ public class ObjectNode extends Node implements AssignTargetLike {
} }
while (true) { while (true) {
ParseRes<Node> prop = ParseRes.first(src, i + n, ParseRes<Member> prop = ParseRes.first(src, i + n,
MethodMemberNode::parse, MethodMemberNode::parse,
PropertyMemberNode::parse, PropertyMemberNode::parse,
FieldMemberNode::parseObject, FieldMemberNode::parseObject,

View File

@ -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);
}
}

View File

@ -45,6 +45,8 @@ public class VariableNode extends Node implements Pattern, ChangeTarget {
if (i == null) return Instruction.globDef(name); if (i == null) return Instruction.globDef(name);
else return Instruction.nop(); else return Instruction.nop();
}); });
target.setLocation(loc());
} }
@Override public void destruct(CompileResult target, DeclarationType decl, boolean shouldDeclare) { @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()); var v = target.scope.define(decl, name, loc());
target.add(_i -> v.index().toInit()); target.add(_i -> v.index().toInit());
} }
target.setLocation(loc());
} }
@Override public void compile(CompileResult target, boolean pollute) { @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<Instruction> toGet(CompileResult target, Location loc, String name, boolean keep, boolean forceGet) { public static IntFunction<Instruction> toGet(CompileResult target, Location loc, String name, boolean keep, boolean forceGet) {

View File

@ -7,6 +7,7 @@ import me.topchetoeu.jscript.common.Instruction;
import me.topchetoeu.jscript.common.Operation; import me.topchetoeu.jscript.common.Operation;
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.Member.FieldMember;
import me.topchetoeu.jscript.runtime.values.Member.PropertyMember; import me.topchetoeu.jscript.runtime.values.Member.PropertyMember;
import me.topchetoeu.jscript.runtime.values.Value; import me.topchetoeu.jscript.runtime.values.Value;
import me.topchetoeu.jscript.runtime.values.functions.CodeFunction; import me.topchetoeu.jscript.runtime.values.functions.CodeFunction;
@ -68,8 +69,8 @@ public class InstructionRunner {
else if (val instanceof FunctionValue func) accessor = func; else if (val instanceof FunctionValue func) accessor = func;
else throw EngineException.ofType("Getter must be a function or undefined."); 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)); 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, true)); else obj.defineOwnMember(env, key, new PropertyMember(obj, accessor, null, true, instr.get(1)));
frame.codePtr++; frame.codePtr++;
return null; return null;
@ -79,7 +80,7 @@ public class InstructionRunner {
var key = frame.pop(); var key = frame.pop();
var obj = 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++; frame.codePtr++;
return null; return null;

View File

@ -1,5 +1,3 @@
// return;
const target = arguments[0]; const target = arguments[0];
const primordials = arguments[1]; const primordials = arguments[1];
@ -20,28 +18,26 @@ const symbol = primordials.symbol || (() => {
}; };
}); });
const number = primordials.number || (() => { const number = primordials.number || {
return { parseInt() { throw new Error("parseInt not supported"); },
parseInt() { throw new Error("parseInt not supported"); }, parseFloat() { throw new Error("parseFloat not supported"); },
parseFloat() { throw new Error("parseFloat not supported"); }, isNaN: (val) => val !== val,
isNaN: (val) => val !== val, NaN: 0 / 0,
NaN: 0 / 0, Infinity: 1 / 0,
Infinity: 1 / 0, };
};
});
const fromCharCode = primordials.string.fromCharCode; const string = primordials.string;
const fromCodePoint = primordials.string.fromCodePoint;
const stringBuild = primordials.string.stringBuild;
const defineProperty = primordials.object.defineProperty; const object = primordials.object || {
const defineField = primordials.object.defineField; defineProperty() { throw new Error("Define property not polyfillable"); },
const getOwnMember = primordials.object.getMember; defineField(obj, key, a, b, c, value) { obj[key] = value; },
const getOwnSymbolMember = primordials.object.getOwnSymbolMember; getOwnMember() { throw new Error("Get own member not polyfillable"); },
const getOwnMembers = primordials.object.getOwnMembers; getOwnSymbolMember() { throw new Error("Get own symbol member not polyfillable"); },
const getOwnSymbolMembers = primordials.object.getOwnSymbolMembers; getOwnMembers() { throw new Error("Get own members not polyfillable"); },
const getPrototype = primordials.object.getPrototype; getOwnSymbolMembers() { throw new Error("Get own symbol members not polyfillable"); },
const setPrototype = primordials.object.setPrototype; getPrototype() { throw new Error("Get prototype not polyfillable"); },
setPrototype() { throw new Error("Set prototype not polyfillable"); },
}
const invokeType = primordials.function.invokeType; const invokeType = primordials.function.invokeType;
const setConstructable = primordials.function.setConstructable; const setConstructable = primordials.function.setConstructable;
@ -97,14 +93,14 @@ class Symbol {
setCallable(Symbol, true); setCallable(Symbol, true);
setConstructable(Symbol, false); setConstructable(Symbol, false);
defineField(Symbol, "asyncIterator", false, false, false, Symbol("Symbol.asyncIterator")); object.defineField(Symbol, "asyncIterator", false, false, false, Symbol("Symbol.asyncIterator"));
defineField(Symbol, "iterator", false, false, false, Symbol("Symbol.iterator")); object.defineField(Symbol, "iterator", false, false, false, Symbol("Symbol.iterator"));
defineField(Symbol, "match", false, false, false, Symbol("Symbol.match")); object.defineField(Symbol, "match", false, false, false, Symbol("Symbol.match"));
defineField(Symbol, "matchAll", false, false, false, Symbol("Symbol.matchAll")); object.defineField(Symbol, "matchAll", false, false, false, Symbol("Symbol.matchAll"));
defineField(Symbol, "replace", false, false, false, Symbol("Symbol.replace")); object.defineField(Symbol, "replace", false, false, false, Symbol("Symbol.replace"));
defineField(Symbol, "search", false, false, false, Symbol("Symbol.search")); object.defineField(Symbol, "search", false, false, false, Symbol("Symbol.search"));
defineField(Symbol, "split", false, false, false, Symbol("Symbol.split")); object.defineField(Symbol, "split", false, false, false, Symbol("Symbol.split"));
defineField(Symbol, "toStringTag", false, false, false, Symbol("Symbol.toStringTag")); object.defineField(Symbol, "toStringTag", false, false, false, Symbol("Symbol.toStringTag"));
Symbol(); Symbol();
target.Symbol = Symbol; target.Symbol = Symbol;
@ -160,14 +156,14 @@ class Number {
} }
} }
defineField(Number, "EPSILON", false, false, false, 2.220446049250313e-16); object.defineField(Number, "EPSILON", false, false, false, 2.220446049250313e-16);
defineField(Number, "MIN_SAFE_INTEGER", false, false, false, -9007199254740991); object.defineField(Number, "MIN_SAFE_INTEGER", false, false, false, -9007199254740991);
defineField(Number, "MAX_SAFE_INTEGER", false, false, false, 9007199254740991); object.defineField(Number, "MAX_SAFE_INTEGER", false, false, false, 9007199254740991);
defineField(Number, "POSITIVE_INFINITY", false, false, false, +number.Infinity); object.defineField(Number, "POSITIVE_INFINITY", false, false, false, +number.Infinity);
defineField(Number, "NEGATIVE_INFINITY", false, false, false, -number.Infinity); object.defineField(Number, "NEGATIVE_INFINITY", false, false, false, -number.Infinity);
defineField(Number, "NaN", false, false, false, number.NaN); object.defineField(Number, "NaN", false, false, false, number.NaN);
defineField(Number, "MAX_VALUE", false, false, false, 1.7976931348623157e+308); object.defineField(Number, "MAX_VALUE", false, false, false, 1.7976931348623157e+308);
defineField(Number, "MIN_VALUE", false, false, false, 5e-324); object.defineField(Number, "MIN_VALUE", false, false, false, 5e-324);
setCallable(Number, true); setCallable(Number, true);
target.Number = Number; target.Number = Number;
@ -202,20 +198,20 @@ class String {
res[arguments.length] = 0; res[arguments.length] = 0;
for (let i = 0; i < arguments.length; i++) { 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() { static fromCodePoint() {
const res = []; const res = [];
res[arguments.length] = 0; res[arguments.length] = 0;
for (let i = 0; i < arguments.length; i++) { 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) { if ("get" in desc || "set" in desc) {
let get = desc.get, set = desc.set; 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 (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); 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"); 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); 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); throw new TypeError("Cannot redefine property: " + key);
} }
@ -312,7 +306,7 @@ class Object {
} }
setCallable(Object, true); setCallable(Object, true);
setPrototype(Object.prototype, null); object.setPrototype(Object.prototype, null);
target.Object = Object; target.Object = Object;
class Function { class Function {
@ -322,7 +316,7 @@ class Function {
} }
constructor() { constructor() {
const parts = ["return function annonymous("]; const parts = ["(function annonymous("];
for (let i = 0; i < arguments.length - 1; i++) { for (let i = 0; i < arguments.length - 1; i++) {
if (i > 0) parts[parts.length] = ","; if (i > 0) parts[parts.length] = ",";
@ -330,9 +324,9 @@ class Function {
} }
parts[parts.length] = "){\n"; parts[parts.length] = "){\n";
parts[parts.length] = String(arguments[arguments.length - 1]); 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; return res;
} }
@ -341,27 +335,20 @@ class Function {
if (wrap) parts[parts.length] = "return (function() {\n"; if (wrap) parts[parts.length] = "return (function() {\n";
if (globals.length > 0) { if (globals.length > 0) {
parts[parts.length] = "var "; parts[parts.length] = "let {";
for (let i = 0; i < globals.length; i++) { for (let i = 0; i < globals.length; i++) {
if (i > 0) parts[parts.length] = ","; if (i > 0) parts[parts.length] = ",";
parts[parts.length] = globals[i]; parts[parts.length] = globals[i];
} }
parts[parts.length] = ";((g=arguments[0])=>{"; parts[parts.length] = "} = 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] = src; parts[parts.length] = src;
if (wrap) parts[parts.length] = "\n})(arguments[0])"; if (wrap) parts[parts.length] = "\n})(arguments[0])";
const res = compile(stringBuild(parts)); const res = compile(string.stringBuild(parts));
return res; return res;
} }
} }
@ -400,8 +387,8 @@ class Error {
} }
} }
defineField(Error.prototype, "name", true, false, true, "Error"); object.defineField(Error.prototype, "name", true, false, true, "Error");
defineField(Error.prototype, "message", true, false, true, ""); object.defineField(Error.prototype, "message", true, false, true, "");
setCallable(Error, true); setCallable(Error, true);
target.Error = Error; target.Error = Error;
@ -412,9 +399,9 @@ class SyntaxError {
} }
} }
defineField(SyntaxError.prototype, "name", true, false, true, "SyntaxError"); object.defineField(SyntaxError.prototype, "name", true, false, true, "SyntaxError");
setPrototype(SyntaxError, Error); object.setPrototype(SyntaxError, Error);
setPrototype(SyntaxError.prototype, Error.prototype); object.setPrototype(SyntaxError.prototype, Error.prototype);
setCallable(SyntaxError, true); setCallable(SyntaxError, true);
target.SyntaxError = SyntaxError; target.SyntaxError = SyntaxError;
@ -425,9 +412,9 @@ class TypeError {
} }
} }
defineField(TypeError.prototype, "name", true, false, true, "TypeError"); object.defineField(TypeError.prototype, "name", true, false, true, "TypeError");
setPrototype(TypeError, Error); object.setPrototype(TypeError, Error);
setPrototype(TypeError.prototype, Error.prototype); object.setPrototype(TypeError.prototype, Error.prototype);
setCallable(TypeError, true); setCallable(TypeError, true);
target.TypeError = TypeError; target.TypeError = TypeError;
@ -438,9 +425,9 @@ class RangeError {
} }
} }
defineField(RangeError.prototype, "name", true, false, true, "RangeError"); object.defineField(RangeError.prototype, "name", true, false, true, "RangeError");
setPrototype(RangeError, Error); object.setPrototype(RangeError, Error);
setPrototype(RangeError.prototype, Error.prototype); object.setPrototype(RangeError.prototype, Error.prototype);
setCallable(RangeError, true); setCallable(RangeError, true);
target.RangeError = RangeError; target.RangeError = RangeError;