From bd0890219668788f0ced95d2694ebf616ba47bab Mon Sep 17 00:00:00 2001 From: TopchetoEU <36534413+TopchetoEU@users.noreply.github.com> Date: Wed, 27 Sep 2023 10:26:55 +0300 Subject: [PATCH] fix: revert back to old error protocol --- .../jscript/engine/Environment.java | 2 +- .../jscript/engine/MessageContext.java | 2 +- .../jscript/engine/frame/Runners.java | 18 ++++---- .../jscript/engine/scope/GlobalScope.java | 6 +-- .../jscript/engine/scope/LocalScope.java | 3 +- .../jscript/engine/values/ObjectValue.java | 20 ++++++++ .../jscript/engine/values/Values.java | 10 ++-- .../jscript/exceptions/EngineException.java | 46 ++++++++----------- .../interop/NativeWrapperProvider.java | 2 +- .../jscript/interop/OverloadFunction.java | 16 +++---- .../polyfills/AsyncFunctionPolyfill.java | 2 +- .../polyfills/AsyncGeneratorPolyfill.java | 2 +- .../jscript/polyfills/ErrorPolyfill.java | 45 +++++++++--------- .../jscript/polyfills/FunctionPolyfill.java | 4 +- .../jscript/polyfills/GeneratorPolyfill.java | 2 +- src/me/topchetoeu/jscript/polyfills/JSON.java | 2 +- .../jscript/polyfills/ObjectPolyfill.java | 10 ++-- .../jscript/polyfills/PromisePolyfill.java | 10 ++-- .../jscript/polyfills/StringPolyfill.java | 10 ++-- .../jscript/polyfills/SymbolPolyfill.java | 4 +- 20 files changed, 116 insertions(+), 100 deletions(-) diff --git a/src/me/topchetoeu/jscript/engine/Environment.java b/src/me/topchetoeu/jscript/engine/Environment.java index 5340774..a146cba 100644 --- a/src/me/topchetoeu/jscript/engine/Environment.java +++ b/src/me/topchetoeu/jscript/engine/Environment.java @@ -22,7 +22,7 @@ public class Environment { @Native public FunctionValue compile; @Native public FunctionValue regexConstructor = new NativeFunction("RegExp", (ctx, thisArg, args) -> { - throw EngineException.ofError(ctx, "Regular expressions not supported."); + throw EngineException.ofError("Regular expressions not supported."); }); @Native public ObjectValue proto(String name) { return prototypes.get(name); diff --git a/src/me/topchetoeu/jscript/engine/MessageContext.java b/src/me/topchetoeu/jscript/engine/MessageContext.java index 9125018..febc7f0 100644 --- a/src/me/topchetoeu/jscript/engine/MessageContext.java +++ b/src/me/topchetoeu/jscript/engine/MessageContext.java @@ -17,7 +17,7 @@ public class MessageContext { public MessageContext pushFrame(Context ctx, CodeFrame frame) throws InterruptedException { this.frames.add(frame); - if (this.frames.size() > maxStackFrames) throw EngineException.ofRange(ctx, "Stack overflow!"); + if (this.frames.size() > maxStackFrames) throw EngineException.ofRange("Stack overflow!"); return this; } public boolean popFrame(CodeFrame frame) { diff --git a/src/me/topchetoeu/jscript/engine/frame/Runners.java b/src/me/topchetoeu/jscript/engine/frame/Runners.java index 3032da1..09f3f18 100644 --- a/src/me/topchetoeu/jscript/engine/frame/Runners.java +++ b/src/me/topchetoeu/jscript/engine/frame/Runners.java @@ -27,7 +27,7 @@ public class Runners { throw new EngineException(frame.pop()); } public static Object execThrowSyntax(Context ctx, Instruction instr, CodeFrame frame) throws InterruptedException { - throw EngineException.ofSyntax(ctx, (String)instr.get(0)); + throw EngineException.ofSyntax((String)instr.get(0)); } private static Object call(Context ctx, Object func, Object thisArg, Object ...args) throws InterruptedException { @@ -77,9 +77,9 @@ public class Runners { var name = frame.pop(); var obj = frame.pop(); - if (getter != null && !Values.isFunction(getter)) throw EngineException.ofType(ctx, "Getter must be a function or undefined."); - if (setter != null && !Values.isFunction(setter)) throw EngineException.ofType(ctx, "Setter must be a function or undefined."); - if (!Values.isObject(obj)) throw EngineException.ofType(ctx, "Property apply target must be an object."); + if (getter != null && !Values.isFunction(getter)) throw EngineException.ofType("Getter must be a function or undefined."); + if (setter != null && !Values.isFunction(setter)) throw EngineException.ofType("Setter must be a function or undefined."); + if (!Values.isObject(obj)) throw EngineException.ofType("Property apply target must be an object."); Values.object(obj).defineProperty(ctx, name, Values.function(getter), Values.function(setter), false, false); frame.push(ctx, obj); @@ -214,7 +214,7 @@ public class Runners { frame.push(ctx, Values.getMember(ctx, obj, key)); } catch (IllegalArgumentException e) { - throw EngineException.ofType(ctx, e.getMessage()); + throw EngineException.ofType(e.getMessage()); } frame.codePtr++; return NO_RETURN; @@ -239,7 +239,7 @@ public class Runners { var key = frame.pop(); var obj = frame.pop(); - if (!Values.setMember(ctx, obj, key, val)) throw EngineException.ofSyntax(ctx, "Can't set member '" + key + "'."); + if (!Values.setMember(ctx, obj, key, val)) throw EngineException.ofSyntax("Can't set member '" + key + "'."); if ((boolean)instr.get(0)) frame.push(ctx, val); frame.codePtr++; return NO_RETURN; @@ -311,7 +311,7 @@ public class Runners { if (instr.is(0, "dbg_names")) { var names = new String[instr.params.length - 1]; for (var i = 0; i < instr.params.length - 1; i++) { - if (!(instr.params[i + 1] instanceof String)) throw EngineException.ofSyntax(ctx, "NOP dbg_names instruction must specify only string parameters."); + if (!(instr.params[i + 1] instanceof String)) throw EngineException.ofSyntax("NOP dbg_names instruction must specify only string parameters."); names[i] = (String)instr.params[i + 1]; } frame.scope.setNames(names); @@ -325,7 +325,7 @@ public class Runners { var key = frame.pop(); var val = frame.pop(); - if (!Values.deleteMember(ctx, val, key)) throw EngineException.ofSyntax(ctx, "Can't delete member '" + key + "'."); + if (!Values.deleteMember(ctx, val, key)) throw EngineException.ofSyntax("Can't delete member '" + key + "'."); frame.push(ctx, true); frame.codePtr++; return NO_RETURN; @@ -383,7 +383,7 @@ public class Runners { case OPERATION: return execOperation(ctx, instr, frame); - default: throw EngineException.ofSyntax(ctx, "Invalid instruction " + instr.type.name() + "."); + default: throw EngineException.ofSyntax("Invalid instruction " + instr.type.name() + "."); } } } diff --git a/src/me/topchetoeu/jscript/engine/scope/GlobalScope.java b/src/me/topchetoeu/jscript/engine/scope/GlobalScope.java index d505532..e447f2a 100644 --- a/src/me/topchetoeu/jscript/engine/scope/GlobalScope.java +++ b/src/me/topchetoeu/jscript/engine/scope/GlobalScope.java @@ -60,12 +60,12 @@ public class GlobalScope implements ScopeRecord { } public Object get(Context ctx, String name) throws InterruptedException { - if (!obj.hasMember(ctx, name, false)) throw EngineException.ofSyntax(ctx, "The variable '" + name + "' doesn't exist."); + if (!obj.hasMember(ctx, name, false)) throw EngineException.ofSyntax("The variable '" + name + "' doesn't exist."); else return obj.getMember(ctx, name); } public void set(Context ctx, String name, Object val) throws InterruptedException { - if (!obj.hasMember(ctx, name, false)) throw EngineException.ofSyntax(ctx, "The variable '" + name + "' doesn't exist."); - if (!obj.setMember(ctx, name, val, false)) throw EngineException.ofSyntax(ctx, "The global '" + name + "' is readonly."); + if (!obj.hasMember(ctx, name, false)) throw EngineException.ofSyntax("The variable '" + name + "' doesn't exist."); + if (!obj.setMember(ctx, name, val, false)) throw EngineException.ofSyntax("The global '" + name + "' is readonly."); } public Set keys() { diff --git a/src/me/topchetoeu/jscript/engine/scope/LocalScope.java b/src/me/topchetoeu/jscript/engine/scope/LocalScope.java index 3232f47..4ec8991 100644 --- a/src/me/topchetoeu/jscript/engine/scope/LocalScope.java +++ b/src/me/topchetoeu/jscript/engine/scope/LocalScope.java @@ -9,7 +9,8 @@ public class LocalScope { public final ArrayList catchVars = new ArrayList<>(); public ValueVariable get(int i) { - if (i >= locals.length) return catchVars.get(i - locals.length); + if (i >= locals.length) + return catchVars.get(i - locals.length); if (i >= 0) return locals[i]; else return captures[~i]; } diff --git a/src/me/topchetoeu/jscript/engine/values/ObjectValue.java b/src/me/topchetoeu/jscript/engine/values/ObjectValue.java index 4eec36f..eae0dce 100644 --- a/src/me/topchetoeu/jscript/engine/values/ObjectValue.java +++ b/src/me/topchetoeu/jscript/engine/values/ObjectValue.java @@ -14,6 +14,10 @@ public class ObjectValue { OBJECT, ARRAY, FUNCTION, + ERROR, + SYNTAX_ERROR, + TYPE_ERROR, + RANGE_ERROR, } public static enum State { NORMAL, @@ -35,6 +39,10 @@ public class ObjectValue { private static final Object OBJ_PROTO = new Object(); private static final Object ARR_PROTO = new Object(); private static final Object FUNC_PROTO = new Object(); + private static final Object ERR_PROTO = new Object(); + private static final Object SYNTAX_ERR_PROTO = new Object(); + private static final Object TYPE_ERR_PROTO = new Object(); + private static final Object RANGE_ERR_PROTO = new Object(); protected Object prototype; @@ -142,6 +150,10 @@ public class ObjectValue { if (prototype == OBJ_PROTO) return ctx.env.proto("object"); if (prototype == ARR_PROTO) return ctx.env.proto("array"); if (prototype == FUNC_PROTO) return ctx.env.proto("function"); + if (prototype == ERR_PROTO) return ctx.env.proto("error"); + if (prototype == RANGE_ERR_PROTO) return ctx.env.proto("rangeErr"); + if (prototype == SYNTAX_ERR_PROTO) return ctx.env.proto("syntaxErr"); + if (prototype == TYPE_ERR_PROTO) return ctx.env.proto("typeErr"); } catch (NullPointerException e) { return null; @@ -164,6 +176,10 @@ public class ObjectValue { if (obj == ctx.env.proto("object")) prototype = OBJ_PROTO; else if (obj == ctx.env.proto("array")) prototype = ARR_PROTO; else if (obj == ctx.env.proto("function")) prototype = FUNC_PROTO; + else if (obj == ctx.env.proto("error")) prototype = ERR_PROTO; + else if (obj == ctx.env.proto("syntaxErr")) prototype = SYNTAX_ERR_PROTO; + else if (obj == ctx.env.proto("typeErr")) prototype = TYPE_ERR_PROTO; + else if (obj == ctx.env.proto("rangeErr")) prototype = RANGE_ERR_PROTO; else prototype = obj; } else prototype = obj; @@ -178,6 +194,10 @@ public class ObjectValue { case OBJECT: prototype = OBJ_PROTO; break; case FUNCTION: prototype = FUNC_PROTO; break; case ARRAY: prototype = ARR_PROTO; break; + case ERROR: prototype = ERR_PROTO; break; + case SYNTAX_ERROR: prototype = SYNTAX_ERR_PROTO; break; + case TYPE_ERROR: prototype = TYPE_ERR_PROTO; break; + case RANGE_ERROR: prototype = RANGE_ERR_PROTO; break; case NONE: prototype = null; break; } return true; diff --git a/src/me/topchetoeu/jscript/engine/values/Values.java b/src/me/topchetoeu/jscript/engine/values/Values.java index ab7a962..d909ede 100644 --- a/src/me/topchetoeu/jscript/engine/values/Values.java +++ b/src/me/topchetoeu/jscript/engine/values/Values.java @@ -75,7 +75,7 @@ public class Values { if (isPrimitive(res)) return res; } - throw EngineException.ofType(ctx, "Value couldn't be converted to a primitive."); + throw EngineException.ofType("Value couldn't be converted to a primitive."); } public static boolean isPrimitive(Object obj) { @@ -105,7 +105,7 @@ public class Values { } } - throw EngineException.ofType(ctx, "Value couldn't be converted to a primitive."); + throw EngineException.ofType("Value couldn't be converted to a primitive."); } public static boolean toBoolean(Object obj) { if (obj == NULL || obj == null) return false; @@ -284,8 +284,8 @@ public class Values { } public static boolean setMember(Context ctx, Object obj, Object key, Object val) throws InterruptedException { obj = normalize(ctx, obj); key = normalize(ctx, key); val = normalize(ctx, val); - if (obj == null) throw EngineException.ofType(ctx, "Tried to access member of undefined."); - if (obj == NULL) throw EngineException.ofType(ctx, "Tried to access member of null."); + if (obj == null) throw EngineException.ofType("Tried to access member of undefined."); + if (obj == NULL) throw EngineException.ofType("Tried to access member of null."); if (key.equals("__proto__")) return setPrototype(ctx, obj, val); if (isObject(obj)) return object(obj).setMember(ctx, key, val, false); @@ -373,7 +373,7 @@ public class Values { } public static Object call(Context ctx, Object func, Object thisArg, Object ...args) throws InterruptedException { - if (!isFunction(func)) throw EngineException.ofType(ctx, "Tried to call a non-function value."); + if (!isFunction(func)) throw EngineException.ofType("Tried to call a non-function value."); return function(func).call(ctx, thisArg, args); } public static Object callNew(Context ctx, Object func, Object ...args) throws InterruptedException { diff --git a/src/me/topchetoeu/jscript/exceptions/EngineException.java b/src/me/topchetoeu/jscript/exceptions/EngineException.java index 93471cc..fab5276 100644 --- a/src/me/topchetoeu/jscript/exceptions/EngineException.java +++ b/src/me/topchetoeu/jscript/exceptions/EngineException.java @@ -5,8 +5,9 @@ import java.util.List; import me.topchetoeu.jscript.Location; import me.topchetoeu.jscript.engine.Context; -import me.topchetoeu.jscript.engine.values.FunctionValue; +import me.topchetoeu.jscript.engine.values.ObjectValue; import me.topchetoeu.jscript.engine.values.Values; +import me.topchetoeu.jscript.engine.values.ObjectValue.PlaceholderProto; public class EngineException extends RuntimeException { public final Object value; @@ -48,20 +49,11 @@ public class EngineException extends RuntimeException { return ss.toString(); } - private static Object err(Context ctx, String type, String name, String msg) throws InterruptedException { - try { - var proto = ctx.env.proto(type); - var constr = Values.getMember(ctx, proto, "constructor"); - - if (constr instanceof FunctionValue) { - var res = Values.callNew(ctx, constr, msg); - if (name != null) Values.setMember(ctx, res, "name", name); - return res; - } - } - catch (IllegalArgumentException e) { } - - return name + ": " + msg; + private static Object err(String name, String msg, PlaceholderProto proto) { + var res = new ObjectValue(proto); + if (name != null) res.defineProperty(null, "name", name); + res.defineProperty(null, "message", msg); + return res; } public EngineException(Object error) { @@ -71,22 +63,22 @@ public class EngineException extends RuntimeException { this.cause = null; } - public static EngineException ofError(Context ctx, String name, String msg) throws InterruptedException { - return new EngineException(err(ctx, "error", name, msg)); + public static EngineException ofError(String name, String msg) { + return new EngineException(err(name, msg, PlaceholderProto.ERROR)); } - public static EngineException ofError(Context ctx, String msg) throws InterruptedException { - return new EngineException(err(ctx, "error", null, msg)); + public static EngineException ofError(String msg) { + return new EngineException(err(null, msg, PlaceholderProto.ERROR)); } - public static EngineException ofSyntax(Context ctx, SyntaxException e) throws InterruptedException { - return new EngineException(err(ctx, "syntaxErr", null, e.msg)).add(null, e.loc); + public static EngineException ofSyntax(SyntaxException e) { + return new EngineException(err(null, e.msg, PlaceholderProto.SYNTAX_ERROR)).add(null, e.loc); } - public static EngineException ofSyntax(Context ctx, String msg) throws InterruptedException { - return new EngineException(err(ctx, "syntaxErr", null, msg)); + public static EngineException ofSyntax(String msg) { + return new EngineException(err(null, msg, PlaceholderProto.SYNTAX_ERROR)); } - public static EngineException ofType(Context ctx, String msg) throws InterruptedException { - return new EngineException(err(ctx, "typeErr", null, msg)); + public static EngineException ofType(String msg) { + return new EngineException(err(null, msg, PlaceholderProto.TYPE_ERROR)); } - public static EngineException ofRange(Context ctx, String msg) throws InterruptedException { - return new EngineException(err(ctx, "rangeErr", null, msg)); + public static EngineException ofRange(String msg) { + return new EngineException(err(null, msg, PlaceholderProto.RANGE_ERROR)); } } diff --git a/src/me/topchetoeu/jscript/interop/NativeWrapperProvider.java b/src/me/topchetoeu/jscript/interop/NativeWrapperProvider.java index 3d6f1e9..0098016 100644 --- a/src/me/topchetoeu/jscript/interop/NativeWrapperProvider.java +++ b/src/me/topchetoeu/jscript/interop/NativeWrapperProvider.java @@ -142,7 +142,7 @@ public class NativeWrapperProvider implements WrappersProvider { } if (((OverloadFunction)func).overloads.size() == 0) { - func = new NativeFunction(clazz.getName(), (a, b, c) -> { throw EngineException.ofError(a, "This constructor is not invokable."); }); + func = new NativeFunction(clazz.getName(), (a, b, c) -> { throw EngineException.ofError("This constructor is not invokable."); }); } applyMethods(ctx, false, func, clazz); diff --git a/src/me/topchetoeu/jscript/interop/OverloadFunction.java b/src/me/topchetoeu/jscript/interop/OverloadFunction.java index daf68ee..bf0f20c 100644 --- a/src/me/topchetoeu/jscript/interop/OverloadFunction.java +++ b/src/me/topchetoeu/jscript/interop/OverloadFunction.java @@ -34,7 +34,7 @@ public class OverloadFunction extends FunctionValue { } catch (ConvertException e) { if (overloads.size() > 1) continue loop; - else throw EngineException.ofType(ctx, String.format("Argument %d can't be converted from %s to %s", i - start, e.source, e.target)); + else throw EngineException.ofType(String.format("Argument %d can't be converted from %s to %s", i - start, e.source, e.target)); } } @@ -49,7 +49,7 @@ public class OverloadFunction extends FunctionValue { } catch (ConvertException e) { if (overloads.size() > 1) continue loop; - else throw EngineException.ofType(ctx, String.format("Element in variadic argument can't be converted from %s to %s", e.source, e.target)); + else throw EngineException.ofType(String.format("Element in variadic argument can't be converted from %s to %s", e.source, e.target)); } } @@ -64,7 +64,7 @@ public class OverloadFunction extends FunctionValue { } catch (ConvertException e) { if (overloads.size() > 1) continue loop; - else throw EngineException.ofType(ctx, String.format("This argument can't be converted from %s to %s", e.source, e.target)); + else throw EngineException.ofType(String.format("This argument can't be converted from %s to %s", e.source, e.target)); } if (consumesEngine) newArgs[0] = ctx; @@ -77,7 +77,7 @@ public class OverloadFunction extends FunctionValue { return Values.normalize(ctx, overload.runner.run(ctx, _this, newArgs)); } catch (InstantiationException e) { - throw EngineException.ofError(ctx, "The class may not be instantiated."); + throw EngineException.ofError("The class may not be instantiated."); } catch (IllegalAccessException | IllegalArgumentException e) { continue; @@ -88,21 +88,21 @@ public class OverloadFunction extends FunctionValue { throw ((EngineException)e.getTargetException()).add(name, loc); } else if (e.getTargetException() instanceof NullPointerException) { - throw EngineException.ofType(ctx, "Unexpected value of 'undefined'.").add(name, loc); + throw EngineException.ofType("Unexpected value of 'undefined'.").add(name, loc); } else { - throw EngineException.ofError(ctx, e.getTargetException().getMessage()).add(name, loc); + throw EngineException.ofError(e.getTargetException().getMessage()).add(name, loc); } } catch (ReflectiveOperationException e) { - throw EngineException.ofError(ctx, e.getMessage()).add(name, new Location(0, 0, "")); + throw EngineException.ofError(e.getMessage()).add(name, new Location(0, 0, "")); } catch (Exception e) { throw e; } } - throw EngineException.ofType(ctx, "No overload found for native method."); + throw EngineException.ofType("No overload found for native method."); } public OverloadFunction add(Overload overload) { diff --git a/src/me/topchetoeu/jscript/polyfills/AsyncFunctionPolyfill.java b/src/me/topchetoeu/jscript/polyfills/AsyncFunctionPolyfill.java index 46c024b..3aad543 100644 --- a/src/me/topchetoeu/jscript/polyfills/AsyncFunctionPolyfill.java +++ b/src/me/topchetoeu/jscript/polyfills/AsyncFunctionPolyfill.java @@ -65,7 +65,7 @@ public class AsyncFunctionPolyfill extends FunctionValue { public Object call(Context ctx, Object thisArg, Object ...args) throws InterruptedException { var handler = new AsyncHelper(); var func = factory.call(ctx, thisArg, new NativeFunction("await", handler::await)); - if (!(func instanceof CodeFunction)) throw EngineException.ofType(ctx, "Return value of argument must be a js function."); + if (!(func instanceof CodeFunction)) throw EngineException.ofType("Return value of argument must be a js function."); handler.frame = new CodeFrame(ctx, thisArg, args, (CodeFunction)func); handler.next(ctx, Runners.NO_RETURN, Runners.NO_RETURN); return handler.promise; diff --git a/src/me/topchetoeu/jscript/polyfills/AsyncGeneratorPolyfill.java b/src/me/topchetoeu/jscript/polyfills/AsyncGeneratorPolyfill.java index acf3d07..801cc8b 100644 --- a/src/me/topchetoeu/jscript/polyfills/AsyncGeneratorPolyfill.java +++ b/src/me/topchetoeu/jscript/polyfills/AsyncGeneratorPolyfill.java @@ -122,7 +122,7 @@ public class AsyncGeneratorPolyfill extends FunctionValue { new NativeFunction("await", handler::await), new NativeFunction("yield", handler::yield) ); - if (!(func instanceof CodeFunction)) throw EngineException.ofType(ctx, "Return value of argument must be a js function."); + if (!(func instanceof CodeFunction)) throw EngineException.ofType("Return value of argument must be a js function."); handler.frame = new CodeFrame(ctx, thisArg, args, (CodeFunction)func); return handler; } diff --git a/src/me/topchetoeu/jscript/polyfills/ErrorPolyfill.java b/src/me/topchetoeu/jscript/polyfills/ErrorPolyfill.java index 6a530eb..540cd55 100644 --- a/src/me/topchetoeu/jscript/polyfills/ErrorPolyfill.java +++ b/src/me/topchetoeu/jscript/polyfills/ErrorPolyfill.java @@ -5,31 +5,31 @@ import me.topchetoeu.jscript.engine.values.ArrayValue; 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 ErrorPolyfill { public static class SyntaxErrorPolyfill extends ErrorPolyfill { - @Native public SyntaxErrorPolyfill(Context ctx, Object message) throws InterruptedException { - super(ctx, message); - this.name = "SyntaxError"; + @NativeConstructor(thisArg = true) public static ObjectValue constructor(Context ctx, Object thisArg, Object message) throws InterruptedException { + var target = ErrorPolyfill.constructor(ctx, thisArg, message); + target.defineProperty(ctx, "name", "SyntaxError"); + return target; } } public static class TypeErrorPolyfill extends ErrorPolyfill { - @Native public TypeErrorPolyfill(Context ctx, Object message) throws InterruptedException { - super(ctx, message); - this.name = "TypeError"; + @NativeConstructor(thisArg = true) public static ObjectValue constructor(Context ctx, Object thisArg, Object message) throws InterruptedException { + var target = ErrorPolyfill.constructor(ctx, thisArg, message); + target.defineProperty(ctx, "name", "TypeError"); + return target; } } public static class RangeErrorPolyfill extends ErrorPolyfill { - @Native public RangeErrorPolyfill(Context ctx, Object message) throws InterruptedException { - super(ctx, message); - this.name = "RangeError"; + @NativeConstructor(thisArg = true) public static ObjectValue constructor(Context ctx, Object thisArg, Object message) throws InterruptedException { + var target = ErrorPolyfill.constructor(ctx, thisArg, message); + target.defineProperty(ctx, "name", "RangeError"); + return target; } } - @Native public final ArrayValue stack; - @Native public String message; - @Native public String name = "Error"; - private static String toString(Context ctx, Object name, Object message, ArrayValue stack) throws InterruptedException { if (name == null) name = ""; else name = Values.toString(ctx, name).trim(); @@ -52,10 +52,7 @@ public class ErrorPolyfill { } @Native(thisArg = true) public static String toString(Context ctx, Object thisArg) throws InterruptedException { - if (thisArg instanceof ErrorPolyfill) { - return toString(ctx, ((ErrorPolyfill)thisArg).name, ((ErrorPolyfill)thisArg).message, ((ErrorPolyfill)thisArg).stack); - } - else if (thisArg instanceof ObjectValue) { + if (thisArg instanceof ObjectValue) { var stack = Values.getMember(ctx, thisArg, "stack"); if (!(stack instanceof ArrayValue)) stack = null; return toString(ctx, @@ -67,9 +64,15 @@ public class ErrorPolyfill { else return "[Invalid error]"; } - @Native public ErrorPolyfill(Context ctx, Object message) throws InterruptedException { - this.stack = new ArrayValue(ctx, ctx.message.stackTrace().toArray()); - if (message == null) this.message = ""; - else this.message = Values.toString(ctx, message); + @NativeConstructor(thisArg = true) public static ObjectValue constructor(Context ctx, Object thisArg, Object message) throws InterruptedException { + var target = new ObjectValue(); + if (thisArg instanceof ObjectValue) target = (ObjectValue)thisArg; + + target.defineProperty(ctx, "stack", new ArrayValue(ctx, ctx.message.stackTrace().toArray())); + target.defineProperty(ctx, "name", "Error"); + if (message == null) target.defineProperty(ctx, "message", ""); + else target.defineProperty(ctx, "message", Values.toString(ctx, message)); + + return target; } } diff --git a/src/me/topchetoeu/jscript/polyfills/FunctionPolyfill.java b/src/me/topchetoeu/jscript/polyfills/FunctionPolyfill.java index 9b6f00f..7fbdbc7 100644 --- a/src/me/topchetoeu/jscript/polyfills/FunctionPolyfill.java +++ b/src/me/topchetoeu/jscript/polyfills/FunctionPolyfill.java @@ -14,12 +14,12 @@ public class FunctionPolyfill { return func.call(ctx, thisArg, args.toArray()); } @Native(thisArg = true) public static Object call(Context ctx, FunctionValue func, Object thisArg, Object... args) throws InterruptedException { - if (!(func instanceof FunctionValue)) throw EngineException.ofError(ctx, "Expected this to be a function."); + if (!(func instanceof FunctionValue)) throw EngineException.ofError("Expected this to be a function."); return func.call(ctx, thisArg, args); } @Native(thisArg = true) public static FunctionValue bind(Context ctx, FunctionValue func, Object thisArg, Object... args) throws InterruptedException { - if (!(func instanceof FunctionValue)) throw EngineException.ofError(ctx, "Expected this to be a function."); + if (!(func instanceof FunctionValue)) throw EngineException.ofError("Expected this to be a function."); return new NativeFunction(func.name + " (bound)", (callCtx, _0, callArgs) -> { var resArgs = new Object[args.length + callArgs.length]; diff --git a/src/me/topchetoeu/jscript/polyfills/GeneratorPolyfill.java b/src/me/topchetoeu/jscript/polyfills/GeneratorPolyfill.java index ca3a35d..6da8d8f 100644 --- a/src/me/topchetoeu/jscript/polyfills/GeneratorPolyfill.java +++ b/src/me/topchetoeu/jscript/polyfills/GeneratorPolyfill.java @@ -89,7 +89,7 @@ public class GeneratorPolyfill extends FunctionValue { public Object call(Context ctx, Object thisArg, Object ...args) throws InterruptedException { var handler = new Generator(); var func = factory.call(ctx, thisArg, new NativeFunction("yield", handler::yield)); - if (!(func instanceof CodeFunction)) throw EngineException.ofType(ctx, "Return value of argument must be a js function."); + if (!(func instanceof CodeFunction)) throw EngineException.ofType("Return value of argument must be a js function."); handler.frame = new CodeFrame(ctx, thisArg, args, (CodeFunction)func); return handler; } diff --git a/src/me/topchetoeu/jscript/polyfills/JSON.java b/src/me/topchetoeu/jscript/polyfills/JSON.java index bcf7697..53873a5 100644 --- a/src/me/topchetoeu/jscript/polyfills/JSON.java +++ b/src/me/topchetoeu/jscript/polyfills/JSON.java @@ -75,7 +75,7 @@ public class JSON { return toJS(me.topchetoeu.jscript.json.JSON.parse("", val)); } catch (SyntaxException e) { - throw EngineException.ofSyntax(ctx, e.msg); + throw EngineException.ofSyntax(e.msg); } } @Native diff --git a/src/me/topchetoeu/jscript/polyfills/ObjectPolyfill.java b/src/me/topchetoeu/jscript/polyfills/ObjectPolyfill.java index 2ce6712..9875a74 100644 --- a/src/me/topchetoeu/jscript/polyfills/ObjectPolyfill.java +++ b/src/me/topchetoeu/jscript/polyfills/ObjectPolyfill.java @@ -33,27 +33,27 @@ public class ObjectPolyfill { var hasSet = attrib.hasMember(ctx, "set", false); if (hasVal) { - if (hasGet || hasSet) throw EngineException.ofType(ctx, "Cannot specify a value and accessors for a property."); + if (hasGet || hasSet) throw EngineException.ofType("Cannot specify a value and accessors for a property."); if (!obj.defineProperty( ctx, key, attrib.getMember(ctx, "value"), Values.toBoolean(attrib.getMember(ctx, "writable")), Values.toBoolean(attrib.getMember(ctx, "configurable")), Values.toBoolean(attrib.getMember(ctx, "enumerable")) - )) throw EngineException.ofType(ctx, "Can't define property '" + key + "'."); + )) throw EngineException.ofType("Can't define property '" + key + "'."); } else { var get = attrib.getMember(ctx, "get"); var set = attrib.getMember(ctx, "set"); - if (get != null && !(get instanceof FunctionValue)) throw EngineException.ofType(ctx, "Get accessor must be a function."); - if (set != null && !(set instanceof FunctionValue)) throw EngineException.ofType(ctx, "Set accessor must be a function."); + if (get != null && !(get instanceof FunctionValue)) throw EngineException.ofType("Get accessor must be a function."); + if (set != null && !(set instanceof FunctionValue)) throw EngineException.ofType("Set accessor must be a function."); if (!obj.defineProperty( ctx, key, (FunctionValue)get, (FunctionValue)set, Values.toBoolean(attrib.getMember(ctx, "configurable")), Values.toBoolean(attrib.getMember(ctx, "enumerable")) - )) throw EngineException.ofType(ctx, "Can't define property '" + key + "'."); + )) throw EngineException.ofType("Can't define property '" + key + "'."); } return obj; diff --git a/src/me/topchetoeu/jscript/polyfills/PromisePolyfill.java b/src/me/topchetoeu/jscript/polyfills/PromisePolyfill.java index dab4f57..41e977d 100644 --- a/src/me/topchetoeu/jscript/polyfills/PromisePolyfill.java +++ b/src/me/topchetoeu/jscript/polyfills/PromisePolyfill.java @@ -44,7 +44,7 @@ public class PromisePolyfill { } @Native public static PromisePolyfill any(Context ctx, Object _promises) throws InterruptedException { - if (!Values.isArray(_promises)) throw EngineException.ofType(ctx, "Expected argument for any to be an array."); + if (!Values.isArray(_promises)) throw EngineException.ofType("Expected argument for any to be an array."); var promises = Values.array(_promises); if (promises.size() == 0) return ofResolved(ctx, new ArrayValue()); var n = new int[] { promises.size() }; @@ -69,7 +69,7 @@ public class PromisePolyfill { return res; } @Native public static PromisePolyfill race(Context ctx, Object _promises) throws InterruptedException { - if (!Values.isArray(_promises)) throw EngineException.ofType(ctx, "Expected argument for any to be an array."); + if (!Values.isArray(_promises)) throw EngineException.ofType("Expected argument for any to be an array."); var promises = Values.array(_promises); if (promises.size() == 0) return ofResolved(ctx, new ArrayValue()); var res = new PromisePolyfill(); @@ -85,7 +85,7 @@ public class PromisePolyfill { return res; } @Native public static PromisePolyfill all(Context ctx, Object _promises) throws InterruptedException { - if (!Values.isArray(_promises)) throw EngineException.ofType(ctx, "Expected argument for any to be an array."); + if (!Values.isArray(_promises)) throw EngineException.ofType("Expected argument for any to be an array."); var promises = Values.array(_promises); if (promises.size() == 0) return ofResolved(ctx, new ArrayValue()); var n = new int[] { promises.size() }; @@ -112,7 +112,7 @@ public class PromisePolyfill { return res; } @Native public static PromisePolyfill allSettled(Context ctx, Object _promises) throws InterruptedException { - if (!Values.isArray(_promises)) throw EngineException.ofType(ctx, "Expected argument for any to be an array."); + if (!Values.isArray(_promises)) throw EngineException.ofType("Expected argument for any to be an array."); var promises = Values.array(_promises); if (promises.size() == 0) return ofResolved(ctx, new ArrayValue()); var n = new int[] { promises.size() }; @@ -314,7 +314,7 @@ public class PromisePolyfill { * NOT THREAD SAFE - must be called from the engine executor thread */ @Native public PromisePolyfill(Context ctx, FunctionValue func) throws InterruptedException { - if (!(func instanceof FunctionValue)) throw EngineException.ofType(ctx, "A function must be passed to the promise constructor."); + if (!(func instanceof FunctionValue)) throw EngineException.ofType("A function must be passed to the promise constructor."); try { func.call( ctx, null, diff --git a/src/me/topchetoeu/jscript/polyfills/StringPolyfill.java b/src/me/topchetoeu/jscript/polyfills/StringPolyfill.java index 51255d6..41093f5 100644 --- a/src/me/topchetoeu/jscript/polyfills/StringPolyfill.java +++ b/src/me/topchetoeu/jscript/polyfills/StringPolyfill.java @@ -21,7 +21,7 @@ public class StringPolyfill { private static String passThis(Context ctx, String funcName, Object val) throws InterruptedException { if (val instanceof StringPolyfill) return ((StringPolyfill)val).value; else if (val instanceof String) return (String)val; - else throw EngineException.ofType(ctx, String.format("'%s' may only be called upon object and primitve strings.", funcName)); + else throw EngineException.ofType(String.format("'%s' may only be called upon object and primitve strings.", funcName)); } private static int normalizeI(int i, int len, boolean clamp) { if (i < 0) i += len; @@ -137,9 +137,9 @@ public class StringPolyfill { var regex = Values.callNew(ctx, ctx.env.regexConstructor, Values.toString(ctx, term), ""); _match = Values.getMember(ctx, regex, ctx.env.symbol("Symbol.match")); if (_match instanceof FunctionValue) match = (FunctionValue)_match; - else throw EngineException.ofError(ctx, "Regular expressions don't support matching."); + else throw EngineException.ofError("Regular expressions don't support matching."); } - else throw EngineException.ofError(ctx, "Regular expressions not supported."); + else throw EngineException.ofError("Regular expressions not supported."); } catch (IllegalArgumentException e) { return new ArrayValue(ctx, ""); } @@ -162,9 +162,9 @@ public class StringPolyfill { var regex = Values.callNew(ctx, ctx.env.regexConstructor, Values.toString(ctx, term), "g"); var _match = Values.getMember(ctx, regex, ctx.env.symbol("Symbol.matchAll")); if (_match instanceof FunctionValue) match = (FunctionValue)_match; - else throw EngineException.ofError(ctx, "Regular expressions don't support matching."); + else throw EngineException.ofError("Regular expressions don't support matching."); } - else throw EngineException.ofError(ctx, "Regular expressions not supported."); + else throw EngineException.ofError("Regular expressions not supported."); return match.call(ctx, term, val); } diff --git a/src/me/topchetoeu/jscript/polyfills/SymbolPolyfill.java b/src/me/topchetoeu/jscript/polyfills/SymbolPolyfill.java index 67ad078..149b2be 100644 --- a/src/me/topchetoeu/jscript/polyfills/SymbolPolyfill.java +++ b/src/me/topchetoeu/jscript/polyfills/SymbolPolyfill.java @@ -30,11 +30,11 @@ public class SymbolPolyfill { private static Symbol passThis(Context ctx, String funcName, Object val) throws InterruptedException { if (val instanceof SymbolPolyfill) return ((SymbolPolyfill)val).value; else if (val instanceof Symbol) return (Symbol)val; - else throw EngineException.ofType(ctx, String.format("'%s' may only be called upon object and primitve symbols.", funcName)); + else throw EngineException.ofType(String.format("'%s' may only be called upon object and primitve symbols.", funcName)); } @NativeConstructor(thisArg = true) public static Object constructor(Context ctx, Object thisArg, Object val) throws InterruptedException { - if (thisArg instanceof ObjectValue) throw EngineException.ofType(ctx, "Symbol constructor may not be called with new."); + if (thisArg instanceof ObjectValue) throw EngineException.ofType("Symbol constructor may not be called with new."); if (val == null) return new Symbol(""); else return new Symbol(Values.toString(ctx, val)); }