diff --git a/lib/core.ts b/lib/core.ts index c1485fe..a19dc25 100644 --- a/lib/core.ts +++ b/lib/core.ts @@ -9,6 +9,7 @@ interface Internals { function: FunctionConstructor; array: ArrayConstructor; promise: PromiseConstructor; + bool: BooleanConstructor; markSpecial(...funcs: Function[]): void; getEnv(func: Function): Environment | undefined; @@ -46,21 +47,22 @@ try { var Function = env.global.Function = internals.function; var Array = env.global.Array = internals.array; var Promise = env.global.Promise = internals.promise; + var Boolean = env.global.Boolean = internals.bool; env.setProto('object', Object.prototype); env.setProto('function', Function.prototype); env.setProto('array', Array.prototype); + env.setProto('bool', Boolean.prototype); + (Object.prototype as any).__proto__ = null; internals.getEnv(run)?.setProto('array', Array.prototype); - globalThis.log = (...args) => internals.apply(internals.log, internals, args); run('values/symbol'); run('values/errors'); run('values/string'); run('values/number'); - run('values/boolean'); run('map'); run('set'); run('regex'); diff --git a/lib/lib.d.ts b/lib/lib.d.ts index 4e83de2..5ce6aab 100644 --- a/lib/lib.d.ts +++ b/lib/lib.d.ts @@ -244,6 +244,7 @@ interface ArrayConstructor { } interface Boolean { + toString(): string; valueOf(): boolean; } interface BooleanConstructor { diff --git a/lib/tsconfig.json b/lib/tsconfig.json index 01d7996..497b3a9 100644 --- a/lib/tsconfig.json +++ b/lib/tsconfig.json @@ -7,7 +7,6 @@ "values/errors.ts", "values/string.ts", "values/number.ts", - "values/boolean.ts", "map.ts", "set.ts", "regex.ts", diff --git a/lib/values/boolean.ts b/lib/values/boolean.ts deleted file mode 100644 index c0d45a2..0000000 --- a/lib/values/boolean.ts +++ /dev/null @@ -1,12 +0,0 @@ -define("values/boolean", () => { - var Boolean = env.global.Boolean = function (this: Boolean | undefined, arg) { - var val; - if (arguments.length === 0) val = false; - else val = !!arg; - if (this === undefined || this === null) return val; - else (this as any).value = val; - } as BooleanConstructor; - - env.setProto('bool', Boolean.prototype); - setConstr(Boolean.prototype, Boolean); -}); diff --git a/src/me/topchetoeu/jscript/engine/values/Values.java b/src/me/topchetoeu/jscript/engine/values/Values.java index 03dffd9..8d892e3 100644 --- a/src/me/topchetoeu/jscript/engine/values/Values.java +++ b/src/me/topchetoeu/jscript/engine/values/Values.java @@ -377,14 +377,13 @@ public class Values { return function(func).call(ctx, thisArg, args); } public static Object callNew(Context ctx, Object func, Object ...args) throws InterruptedException { - if (func instanceof FunctionValue && ((FunctionValue)func).special) return ((FunctionValue)func).call(ctx, null, args); - var res = new ObjectValue(); var proto = Values.getMember(ctx, func, "prototype"); res.setPrototype(ctx, proto); - call(ctx, func, res, args); + var ret = call(ctx, func, res, args); + if (ret != null && func instanceof FunctionValue && ((FunctionValue)func).special) return ret; return res; } diff --git a/src/me/topchetoeu/jscript/polyfills/BooleanPolyfill.java b/src/me/topchetoeu/jscript/polyfills/BooleanPolyfill.java new file mode 100644 index 0000000..4d2c77e --- /dev/null +++ b/src/me/topchetoeu/jscript/polyfills/BooleanPolyfill.java @@ -0,0 +1,24 @@ +package me.topchetoeu.jscript.polyfills; + +import me.topchetoeu.jscript.engine.Context; +import me.topchetoeu.jscript.engine.values.ObjectValue; +import me.topchetoeu.jscript.engine.values.Values; +import me.topchetoeu.jscript.interop.Native; +import me.topchetoeu.jscript.interop.NativeConstructor; + +public class BooleanPolyfill { + @NativeConstructor(thisArg = true) public static Object constructor(Context ctx, Object thisArg, Object val) { + val = Values.toBoolean(val); + if (thisArg instanceof ObjectValue) { + ((ObjectValue)thisArg).defineProperty(ctx, "value", val); + return null; + } + else return val; + } + @Native(thisArg = true) public static String toString(Context ctx, Object thisArg) { + return Values.toBoolean(thisArg) ? "true" : "false"; + } + @Native(thisArg = true) public static boolean valueOf(Context ctx, Object thisArg) { + return Values.toBoolean(thisArg); + } +} diff --git a/src/me/topchetoeu/jscript/polyfills/Internals.java b/src/me/topchetoeu/jscript/polyfills/Internals.java index d09bb4b..9d3d8cd 100644 --- a/src/me/topchetoeu/jscript/polyfills/Internals.java +++ b/src/me/topchetoeu/jscript/polyfills/Internals.java @@ -14,10 +14,7 @@ import me.topchetoeu.jscript.interop.Native; public class Internals { public final Environment targetEnv; - @Native public final FunctionValue object; - @Native public final FunctionValue function; - @Native public final FunctionValue promise; - @Native public final FunctionValue array; + @Native public final FunctionValue object, function, promise, array, bool; @Native public void markSpecial(FunctionValue ...funcs) { for (var func : funcs) { @@ -160,5 +157,6 @@ public class Internals { this.function = targetEnv.wrappersProvider.getConstr(FunctionPolyfill.class); this.promise = targetEnv.wrappersProvider.getConstr(PromisePolyfill.class); this.array = targetEnv.wrappersProvider.getConstr(ArrayPolyfill.class); + this.bool = targetEnv.wrappersProvider.getConstr(BooleanPolyfill.class); } } diff --git a/src/me/topchetoeu/jscript/polyfills/ObjectPolyfill.java b/src/me/topchetoeu/jscript/polyfills/ObjectPolyfill.java index 0c15f92..66387ee 100644 --- a/src/me/topchetoeu/jscript/polyfills/ObjectPolyfill.java +++ b/src/me/topchetoeu/jscript/polyfills/ObjectPolyfill.java @@ -201,9 +201,9 @@ public class ObjectPolyfill { return ObjectPolyfill.hasOwn(ctx, thisArg, Values.convert(ctx, key, String.class)); } - @NativeConstructor public static Object constructor(Context ctx, Object arg) throws InterruptedException { + @NativeConstructor(thisArg = true) public static Object constructor(Context ctx, Object thisArg, Object arg) throws InterruptedException { if (arg == null || arg == Values.NULL) return new ObjectValue(); - else if (arg instanceof Boolean) return Values.callNew(ctx, ctx.env.global.get(ctx, "Boolean"), arg); + else if (arg instanceof Boolean) return BooleanPolyfill.constructor(ctx, thisArg, arg); else if (arg instanceof Number) return Values.callNew(ctx, ctx.env.global.get(ctx, "Number"), arg); else if (arg instanceof String) return Values.callNew(ctx, ctx.env.global.get(ctx, "String"), arg); else if (arg instanceof Symbol) return Values.callNew(ctx, ctx.env.global.get(ctx, "Symbol"), arg);