fix: gd damn it

This commit is contained in:
TopchetoEU 2024-11-24 12:47:15 +02:00
parent 41bb27e4dd
commit 61c5df5003
Signed by: topchetoeu
GPG Key ID: 6531B8583E5F6ED4
4 changed files with 443 additions and 480 deletions

4
.gitignore vendored
View File

@ -1,6 +1,6 @@
* *
!/src !/src/
!/src/**/* !/src/**/*
!/doc !/doc
@ -22,3 +22,5 @@
!/gradle !/gradle
!/gradle/wrapper !/gradle/wrapper
!/gradle/wrapper/gradle-wrapper.properties !/gradle/wrapper/gradle-wrapper.properties
!/

View File

@ -80,7 +80,7 @@ public class IfNode extends Node {
var a = JavaScript.parseExpression(src, i + n, 2); var a = JavaScript.parseExpression(src, i + n, 2);
if (!a.isSuccess()) return a.chainError(src.loc(i + n), "Expected a value after the ternary operator."); if (!a.isSuccess()) return a.chainError(src.loc(i + n), "Expected a value after the ternary operator.");
n += a.n; n += a.n;
n += Parsing.skipEmpty(src, i); n += Parsing.skipEmpty(src, i + n);
if (!src.is(i + n, ":")) return ParseRes.failed(); if (!src.is(i + n, ":")) return ParseRes.failed();
n++; n++;

View File

@ -10,6 +10,7 @@ import me.topchetoeu.jscript.common.Metadata;
import me.topchetoeu.jscript.common.Reading; import me.topchetoeu.jscript.common.Reading;
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.json.JSON; import me.topchetoeu.jscript.common.json.JSON;
import me.topchetoeu.jscript.common.parsing.Filename; import me.topchetoeu.jscript.common.parsing.Filename;
import me.topchetoeu.jscript.runtime.debug.DebugContext; import me.topchetoeu.jscript.runtime.debug.DebugContext;
@ -252,21 +253,17 @@ public class SimpleRepl {
res.defineOwnMember(env, "parse", new NativeFunction(args -> { res.defineOwnMember(env, "parse", new NativeFunction(args -> {
return JSONConverter.toJs(JSON.parse(null, args.get(0).toString(env))); return JSONConverter.toJs(JSON.parse(null, args.get(0).toString(env)));
})); }));
res.defineOwnMember(env, "invokeType", new NativeFunction(args -> {
if (((ArgumentsValue)args.get(0)).frame.isNew) return StringValue.of("new");
else return StringValue.of("call");
}));
res.defineOwnMember(env, "invoke", new NativeFunction(args -> {
var func = (FunctionValue)args.get(0);
var self = args.get(1);
var funcArgs = (ArrayValue)args.get(2);
return func.apply(env, self, funcArgs.toArray());
}));
return res; return res;
} }
private static void setProto(Environment env, Environment target, Key<ObjectValue> key, ObjectValue repo, String name) {
var val = repo.getMember(env, name);
if (val instanceof ObjectValue obj) {
target.add(key, obj);
}
}
private static ObjectValue primordials(Environment env) { private static ObjectValue primordials(Environment env) {
var res = new ObjectValue(); var res = new ObjectValue();
res.setPrototype(null, null); res.setPrototype(null, null);
@ -280,45 +277,20 @@ public class SimpleRepl {
int[] i = new int[1]; int[] i = new int[1];
res.defineOwnMember(env, "setGlobalPrototype", new NativeFunction(args -> { res.defineOwnMember(env, "setGlobalPrototypes", new NativeFunction(args -> {
var type = args.get(0).toString(env);
var obj = (ObjectValue)args.get(1); var obj = (ObjectValue)args.get(1);
switch (type) { setProto(args.env, env, Value.OBJECT_PROTO, obj, "object");
case "object": setProto(args.env, env, Value.FUNCTION_PROTO, obj, "function");
args.env.add(Value.OBJECT_PROTO, obj); setProto(args.env, env, Value.ARRAY_PROTO, obj, "array");
break; setProto(args.env, env, Value.BOOL_PROTO, obj, "boolean");
case "function": setProto(args.env, env, Value.NUMBER_PROTO, obj, "number");
args.env.add(Value.FUNCTION_PROTO, obj); setProto(args.env, env, Value.STRING_PROTO, obj, "string");
break; setProto(args.env, env, Value.SYMBOL_PROTO, obj, "symbol");
case "array": setProto(args.env, env, Value.ERROR_PROTO, obj, "error");
args.env.add(Value.ARRAY_PROTO, obj); setProto(args.env, env, Value.SYNTAX_ERR_PROTO, obj, "syntax");
break; setProto(args.env, env, Value.TYPE_ERR_PROTO, obj, "type");
case "boolean": setProto(args.env, env, Value.RANGE_ERR_PROTO, obj, "range");
args.env.add(Value.BOOL_PROTO, obj);
break;
case "number":
args.env.add(Value.NUMBER_PROTO, obj);
break;
case "string":
args.env.add(Value.STRING_PROTO, obj);
break;
case "symbol":
args.env.add(Value.SYMBOL_PROTO, obj);
break;
case "error":
args.env.add(Value.ERROR_PROTO, obj);
break;
case "syntax":
args.env.add(Value.SYNTAX_ERR_PROTO, obj);
break;
case "type":
args.env.add(Value.TYPE_ERR_PROTO, obj);
break;
case "range":
args.env.add(Value.RANGE_ERR_PROTO, obj);
break;
}
return Value.UNDEFINED; return Value.UNDEFINED;
})); }));

View File

@ -1,265 +1,251 @@
const target = arguments[0]; return;
const primordials = arguments[1]; (function main() {
var __extends = (this && this.__extends) || (function () {
const symbol = primordials.symbol || (() => { var extendStatics = function (d, b) {
const repo = {}; extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var target = arguments[0];
var primordials = arguments[1];
var symbol = primordials.symbol || (function () {
var repo = {};
return { return {
makeSymbol: (name) => { name }, makeSymbol: function (name) { return { name: name }; },
getSymbol(name) { getSymbol: function (name) {
if (name in repo) return repo[name]; if (name in repo) return repo[name];
else return repo[name] = { name }; else return repo[name] = { name: name };
}, },
getSymbolKey(symbol) { getSymbolKey: function (symbol) {
if (symbol.name in repo && repo[symbol.name] === symbol) return symbol.name; if (symbol.name in repo && repo[symbol.name] === symbol) return symbol.name;
else return undefined; else return undefined;
}, },
getSymbolDescription: ({ name }) => name, getSymbolDescription: function (symbol) {
return symbol.name;
}
}; };
}); });
var number = primordials.number || {
const number = primordials.number || { parseInt: function () { throw new Error("parseInt not supported"); },
parseInt() { throw new Error("parseInt not supported"); }, parseFloat: function () { throw new Error("parseFloat not supported"); },
parseFloat() { throw new Error("parseFloat not supported"); }, isNaN: function (val) { return val !== val; },
isNaN: (val) => val !== val,
NaN: 0 / 0, NaN: 0 / 0,
Infinity: 1 / 0, Infinity: 1 / 0,
}; };
var string = primordials.string;
var object = primordials.object || {
defineProperty: function () { throw new Error("Define property not polyfillable"); },
defineField: function (obj, key, a, b, c, value) { obj[key] = value; },
getOwnMember: function () { throw new Error("Get own member not polyfillable"); },
getOwnSymbolMember: function () { throw new Error("Get own symbol member not polyfillable"); },
getOwnMembers: function () { throw new Error("Get own members not polyfillable"); },
getOwnSymbolMembers: function () { throw new Error("Get own symbol members not polyfillable"); },
getPrototype: function () { throw new Error("Get prototype not polyfillable"); },
setPrototype: function () { throw new Error("Set prototype not polyfillable"); },
};
var func = primordials.function || {
invokeType: function (args, self) {
if (typeof self === "object") return "new";
else return "call";
},
setConstructable: function () { throw new Error("Set constructable not polyfillable"); },
setCallable: function () { throw new Error("Set callable not polyfillable"); },
invoke: function () { throw new Error("Invoke not polyfillable"); },
construct: function () { throw new Error("Construct not polyfillable"); },
};
var json = primordials.json || {
stringify: function (val) { throw new Error("JSON stringify not polyfillable"); },
parse: function (val) { throw new Error("JSON parse not polyfillable"); },
}
const string = primordials.string; var setGlobalPrototypes = primordials.setGlobalPrototype;
var compile = primordials.compile;
const object = primordials.object || { var setIntrinsic = primordials.setIntrinsic;
defineProperty() { throw new Error("Define property not polyfillable"); }, var valueKey = symbol.makeSymbol("Primitive.value");
defineField(obj, key, a, b, c, value) { obj[key] = value; }, var undefined = void 0;
getOwnMember() { throw new Error("Get own member not polyfillable"); }, target.undefined = undefined;
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;
const setCallable = primordials.function.setCallable;
const invoke = primordials.function.invoke;
const construct = primordials.function.construct;
const json = primordials.json;
const setGlobalPrototype = primordials.setGlobalPrototype;
const compile = primordials.compile;
const setIntrinsic = primordials.setIntrinsic;
const valueKey = symbol.makeSymbol("Primitive.value");
const undefined = ({}).definitelyDefined;
target.undefined = undefined;
const unwrapThis = (self, type, constr, name, arg = "this", defaultVal) => {
if (typeof self === type) return self;
if (self instanceof constr && valueKey in self) self = self[valueKey];
if (typeof self === type) return self;
if (defaultVal !== undefined) return defaultVal;
function unwrapThis(self, type, constr, name, arg, defaultVal) {
if (arg === void 0) { arg = "this"; }
if (typeof self === type)
return self;
if (self instanceof constr && valueKey in self)
self = self[valueKey];
if (typeof self === type)
return self;
if (defaultVal !== undefined)
return defaultVal;
throw new TypeError(name + " requires that '" + arg + "' be a " + constr.name); throw new TypeError(name + " requires that '" + arg + "' be a " + constr.name);
}
const wrapIndex = (i, len) => {};
class Symbol {
get description() {
return symbol.getSymbolDescriptor(unwrapThis(this, "symbol", Symbol, "Symbol.prototype.description"));
} }
toString() { function wrapIndex(i, len) { }
return "Symbol(" + unwrapThis(this, "symbol", Symbol, "Symbol.prototype.toString").description + ")"; var Symbol = /** @class */ (function () {
} function Symbol(name) {
valueOf() { if (name === undefined) name = "";
return unwrapThis(this, "symbol", Symbol, "Symbol.prototype.valueOf");
}
constructor(name = "") {
return symbol.makeSymbol(name); return symbol.makeSymbol(name);
} }
Symbol.prototype.toString = function () {
static for(name) { return "Symbol(" + unwrapThis(this, "symbol", Symbol, "Symbol.prototype.toString").description + ")";
};
Symbol.prototype.valueOf = function () {
return unwrapThis(this, "symbol", Symbol, "Symbol.prototype.valueOf");
};
Symbol.for = function (name) {
return symbol.getSymbol(name + ""); return symbol.getSymbol(name + "");
} };
static keyFor(value) { Symbol.keyFor = function (value) {
return symbol.getSymbolKey(unwrapThis(value, "symbol", Symbol, "Symbol.keyFor")); return symbol.getSymbolKey(unwrapThis(value, "symbol", Symbol, "Symbol.keyFor"));
} };
} return Symbol;
}());
;
object.defineProperty(Symbol.prototype, "desc", false, true, function () {
return symbol.getSymbolDescriptor(unwrapThis(this, "symbol", Symbol, "Symbol.prototype.description"));
});
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"));
func.setConstructable(Symbol, false);
setCallable(Symbol, true); function Number(value) {
setConstructable(Symbol, false); if (func.invokeType(arguments, this) === "call") {
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;
class Number {
toString() {
return "" + unwrapThis(this, "number", Number, "Number.prototype.toString");
}
valueOf() {
return unwrapThis(this, "number", Number, "Number.prototype.toString");
}
constructor(value) {
if (invokeType(arguments) === "call") {
if (arguments.length === 0) return 0; if (arguments.length === 0) return 0;
else return +value; else return +value;
} }
this[valueKey] = target.Number(value); this[valueKey] = target.Number(value);
} }
Number.prototype.toString = function () {
static isFinite(value) { return "" + unwrapThis(this, "number", Number, "Number.prototype.toString");
};
Number.prototype.valueOf = function () {
return unwrapThis(this, "number", Number, "Number.prototype.toString");
};
Number.isFinite = function (value) {
value = unwrapThis(value, "number", Number, "Number.isFinite", "value", undefined); value = unwrapThis(value, "number", Number, "Number.isFinite", "value", undefined);
if (value === undefined || value !== value)
if (value === undefined || value !== value) return false; return false;
if (value === Infinity || value === -Infinity) return false; if (value === Infinity || value === -Infinity)
return false;
return true; return true;
} };
static isInteger(value) { Number.isInteger = function (value) {
value = unwrapThis(value, "number", Number, "Number.isInteger", "value", undefined); value = unwrapThis(value, "number", Number, "Number.isInteger", "value", undefined);
if (value === undefined) return false; if (value === undefined)
return false;
return number.parseInt(value) === value; return number.parseInt(value) === value;
} };
static isNaN(value) { Number.isNaN = function (value) {
return number.isNaN(value); return number.isNaN(value);
} };
static isSafeInteger(value) { Number.isSafeInteger = function (value) {
value = unwrapThis(value, "number", Number, "Number.isSafeInteger", "value", undefined); value = unwrapThis(value, "number", Number, "Number.isSafeInteger", "value", undefined);
if (value === undefined || number.parseInt(value) !== value) return false; if (value === undefined || number.parseInt(value) !== value)
return false;
return value >= -9007199254740991 && value <= 9007199254740991; return value >= -9007199254740991 && value <= 9007199254740991;
} };
static parseFloat(value) { Number.parseFloat = function (value) {
value = 0 + value; value = 0 + value;
return number.parseFloat(value); return number.parseFloat(value);
} };
static parseInt(value, radix) { Number.parseInt = function (value, radix) {
value = 0 + value; value = 0 + value;
radix = +radix; radix = +radix;
if (number.isNaN(radix)) radix = 10; if (number.isNaN(radix))
radix = 10;
return number.parseInt(value, radix); return number.parseInt(value, radix);
} };
}
object.defineField(Number, "EPSILON", false, false, false, 2.220446049250313e-16); object.defineField(Number, "EPSILON", false, false, false, 2.220446049250313e-16);
object.defineField(Number, "MIN_SAFE_INTEGER", false, false, false, -9007199254740991); object.defineField(Number, "MIN_SAFE_INTEGER", false, false, false, -9007199254740991);
object.defineField(Number, "MAX_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, "POSITIVE_INFINITY", false, false, false, +number.Infinity);
object.defineField(Number, "NEGATIVE_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, "NaN", false, false, false, number.NaN);
object.defineField(Number, "MAX_VALUE", false, false, false, 1.7976931348623157e+308); object.defineField(Number, "MAX_VALUE", false, false, false, 1.7976931348623157e+308);
object.defineField(Number, "MIN_VALUE", false, false, false, 5e-324); object.defineField(Number, "MIN_VALUE", false, false, false, 5e-324);
func.setCallable(Number, true);
target.Number = Number;
target.parseInt = Number.parseInt;
target.parseFloat = Number.parseFloat;
target.NaN = Number.NaN;
target.Infinity = Number.POSITIVE_INFINITY;
setCallable(Number, true); function String(value) {
target.Number = Number; if (func.invokeType(arguments, this) === "call") {
target.parseInt = Number.parseInt; if (arguments.length === 0)
target.parseFloat = Number.parseFloat; return "";
target.NaN = Number.NaN; else
target.Infinity = Number.POSITIVE_INFINITY; return value + "";
class String {
at(index) {
throw "Not implemented :/";
return unwrapThis(this, "string", String, "String.prototype.at")[index];
} }
toString() {
return unwrapThis(this, "string", String, "String.prototype.toString");
}
valueOf() {
return unwrapThis(this, "string", String, "String.prototype.valueOf");
}
constructor(value) {
if (invokeType(arguments) === "call") {
if (arguments.length === 0) return "";
else return value + "";
}
this[valueKey] = String(value); this[valueKey] = String(value);
} }
String.prototype.at = function (index) {
static fromCharCode() { throw "Not implemented :/";
const res = []; return unwrapThis(this, "string", String, "String.prototype.at")[index];
};
String.prototype.toString = function () {
return unwrapThis(this, "string", String, "String.prototype.toString");
};
String.prototype.valueOf = function () {
return unwrapThis(this, "string", String, "String.prototype.valueOf");
};
String.fromCharCode = function () {
var res = [];
res[arguments.length] = 0; res[arguments.length] = 0;
for (var i = 0; i < arguments.length; i++) {
for (let i = 0; i < arguments.length; i++) {
res[i] = string.fromCharCode(+arguments[i]); res[i] = string.fromCharCode(+arguments[i]);
} }
return string.stringBuild(res); return string.stringBuild(res);
} };
static fromCodePoint() { String.fromCodePoint = function () {
const res = []; var res = [];
res[arguments.length] = 0; res[arguments.length] = 0;
for (let i = 0; i < arguments.length; i++) { for (var i = 0; i < arguments.length; i++) {
res[i] = string.fromCodePoint(+arguments[i]); res[i] = string.fromCodePoint(+arguments[i]);
} }
return string.stringBuild(res); return string.stringBuild(res);
} };
} func.setCallable(String, true);
target.String = String;
setCallable(String, true); function Boolean(value) {
target.String = String; if (func.invokeType(arguments, this) === "call") {
class Boolean {
toString() {
return "" + unwrapThis(this, "boolean", Boolean, "Boolean.prototype.toString");
}
valueOf() {
return unwrapThis(this, "boolean", Boolean, "Boolean.prototype.valueOf");
}
constructor(value) {
if (invokeType(arguments) === "call") {
if (arguments.length === 0) return false; if (arguments.length === 0) return false;
else return !!value; else return !!value;
} }
this[valueKey] = Boolean(value); this[valueKey] = Boolean(value);
} }
} Boolean.prototype.toString = function () {
return "" + unwrapThis(this, "boolean", Boolean, "Boolean.prototype.toString");
};
Boolean.prototype.valueOf = function () {
return unwrapThis(this, "boolean", Boolean, "Boolean.prototype.valueOf");
};
func.setCallable(Boolean, true);
target.Boolean = Boolean;
setCallable(Boolean, true); function Object(value) {
target.Boolean = Boolean;
class Object {
toString() {
if (this !== null && this !== undefined && (Symbol.toStringTag in this)) return "[object " + this[Symbol.toStringTag] + "]";
else if (typeof this === "number" || this instanceof Number) return "[object Number]";
else if (typeof this === "symbol" || this instanceof Symbol) return "[object Symbol]";
else if (typeof this === "string" || this instanceof String) return "[object String]";
else if (typeof this === "boolean" || this instanceof Boolean) return "[object Boolean]";
else if (typeof this === "function") return "[object Function]";
else return "[object Object]";
}
valueOf() {
return this;
}
constructor(value) {
if (typeof value === 'object' && value !== null) return value; if (typeof value === 'object' && value !== null) return value;
if (typeof value === 'string') return new String(value); if (typeof value === 'string') return new String(value);
if (typeof value === 'number') return new Number(value); if (typeof value === 'number') return new Number(value);
if (typeof value === 'boolean') return new Boolean(value); if (typeof value === 'boolean') return new Boolean(value);
if (typeof value === 'symbol') { if (typeof value === 'symbol') {
const res = {}; var res = {};
setPrototype(res, Symbol.prototype); setPrototype(res, Symbol.prototype);
res[valueKey] = value; res[valueKey] = value;
return res; return res;
@ -268,24 +254,31 @@ class Object {
return {}; return {};
// // TODO: use new.target.prototype as proto // // TODO: use new.target.prototype as proto
// if (target == null || typeof target !== 'object') target = {}; // if (target == null || typeof target !== 'object') target = {};
// return target; // return target;
} }
Object.prototype.toString = function () {
static defineProperty(obj, key, desc) { if (this !== null && this !== undefined && (Symbol.toStringTag in this)) return "[object " + this[Symbol.toStringTag] + "]";
else if (typeof this === "number" || this instanceof Number) return "[object Number]";
else if (typeof this === "symbol" || this instanceof Symbol) return "[object Symbol]";
else if (typeof this === "string" || this instanceof String) return "[object String]";
else if (typeof this === "boolean" || this instanceof Boolean) return "[object Boolean]";
else if (typeof this === "function") return "[object Function]";
else return "[object Object]";
};
Object.prototype.valueOf = function () {
return this;
};
Object.defineProperty = function (obj, key, desc) {
if (typeof obj !== "object" || obj === null) throw new TypeError("Object.defineProperty called on non-object"); if (typeof obj !== "object" || obj === null) throw new TypeError("Object.defineProperty called on non-object");
if (typeof desc !== "object" || desc === null) throw new TypeError("Property description must be an object: " + desc); if (typeof desc !== "object" || desc === null) throw new TypeError("Property description must be an object: " + desc);
if ("get" in desc || "set" in desc) { if ("get" in desc || "set" in desc) {
let get = desc.get, set = desc.set; var get = desc.get, set = desc.set;
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);
if ("value" in desc || "writable" in desc) { if ("value" in desc || "writable" in desc) {
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 (!object.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);
} }
@ -295,135 +288,131 @@ class Object {
} }
return obj; return obj;
} };
} func.setCallable(Object, true);
object.setPrototype(Object.prototype, null);
target.Object = Object;
setCallable(Object, true); function Function() {
object.setPrototype(Object.prototype, null); var parts = ["(function annonymous("];
target.Object = Object; for (var i = 0; i < arguments.length - 1; i++) {
if (i > 0)
class Function { parts[parts.length] = ",";
toString() {
if (this.name !== "") return "function " + this.name + "(...) { ... }";
else return "function (...) { ... }";
}
constructor() {
const parts = ["(function annonymous("];
for (let i = 0; i < arguments.length - 1; i++) {
if (i > 0) parts[parts.length] = ",";
parts[parts.length] = arguments[i]; parts[parts.length] = arguments[i];
} }
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})";
var res = compile(string.stringBuild(parts))();
const res = compile(string.stringBuild(parts))();
return res; return res;
} }
Function.prototype.toString = function () {
if (this.name !== "")
return "function " + this.name + "(...) { ... }";
else
return "function (...) { ... }";
};
Function.compile = function (src, opts) {
if (src === void 0) src = "";
if (opts === void 0) opts = {};
if (opts.globals === void 0) opts.globals = [];
if (opts.wrap === void 0) opts.wrap = false;
static compile(src = "", { globals = [], wrap = false } = {}) { var globals = opts.globals;
const parts = []; var wrap = opts.wrap;
var parts = [];
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] = "let {"; parts[parts.length] = "let {";
for (var 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] = "} = arguments[0];"; parts[parts.length] = "} = arguments[0];";
} }
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(string.stringBuild(parts)); var res = compile(string.stringBuild(parts));
return res; return res;
} };
} func.setCallable(Function, true);
target.Function = Function;
setCallable(Function, true); function Array(len) {
target.Function = Function;
class Array {
constructor(len) {
if (arguments.length === 1 && typeof len === "number") { if (arguments.length === 1 && typeof len === "number") {
const res = []; var res = [];
res.length = len; res.length = len;
return res; return res;
} }
// TODO: Implement spreading // TODO: Implement spreading
else throw new Error("Spreading not implemented"); else throw new Error("Spreading not implemented");
} }
} func.setCallable(Array, true);
target.Array = Array;
setCallable(Array, true); function Error(msg) {
target.Array = Array; if (msg === void 0) { msg = ""; }
if (func.invokeType(arguments, this) === "call")
class Error { return new Error(msg);
toString() {
let res = this.name || "Error";
const msg = this.message;
if (msg) res += ": " + msg;
return res;
}
constructor (msg = "") {
if (invokeType(arguments) === "call") return new Error(msg);
this.message = msg + ""; this.message = msg + "";
} }
} Error.prototype.toString = function () {
var res = this.name || "Error";
var msg = this.message;
if (msg)
res += ": " + msg;
return res;
};
object.defineField(Error.prototype, "name", true, false, true, "Error");
object.defineField(Error.prototype, "message", true, false, true, "");
func.setCallable(Error, true);
target.Error = Error;
object.defineField(Error.prototype, "name", true, false, true, "Error"); __extends(SyntaxError, Error);
object.defineField(Error.prototype, "message", true, false, true, ""); function SyntaxError(msg) {
setCallable(Error, true); if (func.invokeType(arguments, this) === "call")
target.Error = Error; return new SyntaxError(msg);
return _super.call(this, msg) || this;
class SyntaxError extends Error {
constructor (msg) {
if (invokeType(arguments) === "call") return new SyntaxError(msg);
super(msg);
} }
} object.defineField(SyntaxError.prototype, "name", true, false, true, "SyntaxError");
func.setCallable(SyntaxError, true);
target.SyntaxError = SyntaxError;
object.defineField(SyntaxError.prototype, "name", true, false, true, "SyntaxError"); __extends(TypeError, Error);
setCallable(SyntaxError, true); function TypeError(msg) {
target.SyntaxError = SyntaxError; if (func.invokeType(arguments, this) === "call")
return new TypeError(msg);
class TypeError extends Error { return _super.call(this, msg) || this;
constructor (msg) {
if (invokeType(arguments) === "call") return new TypeError(msg);
super(msg);
} }
} object.defineField(TypeError.prototype, "name", true, false, true, "TypeError");
func.setCallable(TypeError, true);
target.TypeError = TypeError;
object.defineField(TypeError.prototype, "name", true, false, true, "TypeError"); __extends(RangeError, Error);
setCallable(TypeError, true); function RangeError(msg) {
target.TypeError = TypeError; if (func.invokeType(arguments, this) === "call")
return new RangeError(msg);
class RangeError extends Error { return _super.call(this, msg) || this;
constructor (msg) {
if (invokeType(arguments) === "call") return new RangeError(msg);
super(msg);
} }
} object.defineField(RangeError.prototype, "name", true, false, true, "RangeError");
func.setCallable(RangeError, true);
target.RangeError = RangeError;
object.defineField(RangeError.prototype, "name", true, false, true, "RangeError"); target.uint8 = primordials.uint8;
setCallable(RangeError, true);
target.RangeError = RangeError;
setGlobalPrototype("string", String.prototype); setGlobalPrototypes({
setGlobalPrototype("number", Number.prototype); string: String.prototype,
setGlobalPrototype("boolean", Boolean.prototype); number: Number.prototype,
setGlobalPrototype("symbol", Symbol.prototype); boolean: Boolean.prototype,
setGlobalPrototype("object", Object.prototype); symbol: Symbol.prototype,
setGlobalPrototype("array", Array.prototype); object: Object.prototype,
setGlobalPrototype("function", Function.prototype); array: Array.prototype,
setGlobalPrototype("error", Error.prototype); function: Function.prototype,
setGlobalPrototype("syntax", SyntaxError.prototype); error: Error.prototype,
syntax: SyntaxError.prototype,
range: RangeError.prototype,
type: TypeError.prototype,
});
})(arguments[0], arguments[1]);