From 71f735b8127bbdb79b739d4d968543b74d286de0 Mon Sep 17 00:00:00 2001 From: TopchetoEU <36534413+TopchetoEU@users.noreply.github.com> Date: Thu, 4 Jan 2024 13:58:04 +0200 Subject: [PATCH] fix: some more libs fixes --- src/me/topchetoeu/jscript/lib/BooleanLib.java | 6 + src/me/topchetoeu/jscript/lib/DateLib.java | 4 + src/me/topchetoeu/jscript/lib/ErrorLib.java | 3 +- .../topchetoeu/jscript/lib/FilesystemLib.java | 34 +- src/me/topchetoeu/jscript/lib/JSONLib.java | 2 +- src/me/topchetoeu/jscript/lib/MapLib.java | 6 +- src/me/topchetoeu/jscript/lib/NumberLib.java | 12 +- src/me/topchetoeu/jscript/lib/ObjectLib.java | 47 +- src/me/topchetoeu/jscript/lib/PromiseLib.java | 404 +++++++++--------- .../topchetoeu/jscript/lib/RangeErrorLib.java | 7 +- src/me/topchetoeu/jscript/lib/SetLib.java | 6 +- src/me/topchetoeu/jscript/lib/StringLib.java | 36 +- src/me/topchetoeu/jscript/lib/SymbolLib.java | 5 +- .../jscript/lib/SyntaxErrorLib.java | 7 +- .../topchetoeu/jscript/lib/TypeErrorLib.java | 7 +- 15 files changed, 310 insertions(+), 276 deletions(-) diff --git a/src/me/topchetoeu/jscript/lib/BooleanLib.java b/src/me/topchetoeu/jscript/lib/BooleanLib.java index 0a77408..15b58fd 100644 --- a/src/me/topchetoeu/jscript/lib/BooleanLib.java +++ b/src/me/topchetoeu/jscript/lib/BooleanLib.java @@ -1,6 +1,7 @@ package me.topchetoeu.jscript.lib; import me.topchetoeu.jscript.engine.values.ObjectValue; +import me.topchetoeu.jscript.engine.values.Values; import me.topchetoeu.jscript.interop.Arguments; import me.topchetoeu.jscript.interop.Expose; import me.topchetoeu.jscript.interop.ExposeConstructor; @@ -13,6 +14,10 @@ public class BooleanLib { public final boolean value; + @Override public String toString() { + return value + ""; + } + public BooleanLib(boolean val) { this.value = val; } @@ -26,6 +31,7 @@ public class BooleanLib { return args.self(Boolean.class) ? "true" : "false"; } @Expose public static boolean __valueOf(Arguments args) { + if (Values.isWrapper(args.self, BooleanLib.class)) return Values.wrapper(args.self, BooleanLib.class).value; return args.self(Boolean.class); } } diff --git a/src/me/topchetoeu/jscript/lib/DateLib.java b/src/me/topchetoeu/jscript/lib/DateLib.java index 599c19e..9acc8a2 100644 --- a/src/me/topchetoeu/jscript/lib/DateLib.java +++ b/src/me/topchetoeu/jscript/lib/DateLib.java @@ -238,6 +238,10 @@ public class DateLib { return normal.getTime().toString(); } + @Override public String toString() { + return __toString(); + } + public DateLib(long timestamp) { normal = Calendar.getInstance(); utc = Calendar.getInstance(); diff --git a/src/me/topchetoeu/jscript/lib/ErrorLib.java b/src/me/topchetoeu/jscript/lib/ErrorLib.java index 3d9479a..c21e8c2 100644 --- a/src/me/topchetoeu/jscript/lib/ErrorLib.java +++ b/src/me/topchetoeu/jscript/lib/ErrorLib.java @@ -8,6 +8,7 @@ import me.topchetoeu.jscript.exceptions.ConvertException; import me.topchetoeu.jscript.interop.WrapperName; import me.topchetoeu.jscript.interop.Arguments; import me.topchetoeu.jscript.interop.Expose; +import me.topchetoeu.jscript.interop.ExposeConstructor; import me.topchetoeu.jscript.interop.ExposeField; @WrapperName("Error") @@ -36,7 +37,7 @@ public class ErrorLib { else return "[Invalid error]"; } - @Expose public static ObjectValue __constructor(Arguments args) { + @ExposeConstructor public static ObjectValue __constructor(Arguments args) { var target = new ObjectValue(); var message = args.getString(0, ""); diff --git a/src/me/topchetoeu/jscript/lib/FilesystemLib.java b/src/me/topchetoeu/jscript/lib/FilesystemLib.java index aac8370..59f7b03 100644 --- a/src/me/topchetoeu/jscript/lib/FilesystemLib.java +++ b/src/me/topchetoeu/jscript/lib/FilesystemLib.java @@ -18,13 +18,17 @@ import me.topchetoeu.jscript.filesystem.FilesystemException.FSCode; import me.topchetoeu.jscript.interop.Arguments; import me.topchetoeu.jscript.interop.Expose; import me.topchetoeu.jscript.interop.ExposeField; +import me.topchetoeu.jscript.interop.ExposeTarget; import me.topchetoeu.jscript.interop.WrapperName; @WrapperName("Filesystem") public class FilesystemLib { - @ExposeField public static final int __SEEK_SET = 0; - @ExposeField public static final int __SEEK_CUR = 1; - @ExposeField public static final int __SEEK_END = 2; + @ExposeField(target = ExposeTarget.STATIC) + public static final int __SEEK_SET = 0; + @ExposeField(target = ExposeTarget.STATIC) + public static final int __SEEK_CUR = 1; + @ExposeField(target = ExposeTarget.STATIC) + public static final int __SEEK_END = 2; private static Filesystem fs(Context ctx) { var fs = Filesystem.get(ctx); @@ -32,11 +36,13 @@ public class FilesystemLib { throw EngineException.ofError("Current environment doesn't have a file system."); } - @Expose public static String __normalize(Arguments args) { + @Expose(target = ExposeTarget.STATIC) + public static String __normalize(Arguments args) { return fs(args.ctx).normalize(args.convert(String.class)); } - @Expose public static PromiseLib __open(Arguments args) { + @Expose(target = ExposeTarget.STATIC) + public static PromiseLib __open(Arguments args) { return PromiseLib.await(args.ctx, () -> { var fs = fs(args.ctx); var path = fs.normalize(args.getString(0)); @@ -53,7 +59,8 @@ public class FilesystemLib { catch (FilesystemException e) { throw e.toEngineException(); } }); } - @Expose public static ObjectValue __ls(Arguments args) { + @Expose(target = ExposeTarget.STATIC) + public static ObjectValue __ls(Arguments args) { return Values.toJSAsyncIterator(args.ctx, new Iterator<>() { private boolean failed, done; @@ -108,7 +115,8 @@ public class FilesystemLib { } }); } - @Expose public static PromiseLib __mkdir(Arguments args) throws IOException { + @Expose(target = ExposeTarget.STATIC) + public static PromiseLib __mkdir(Arguments args) throws IOException { return PromiseLib.await(args.ctx, () -> { try { fs(args.ctx).create(args.getString(0), EntryType.FOLDER); @@ -118,7 +126,8 @@ public class FilesystemLib { }); } - @Expose public static PromiseLib __mkfile(Arguments args) throws IOException { + @Expose(target = ExposeTarget.STATIC) + public static PromiseLib __mkfile(Arguments args) throws IOException { return PromiseLib.await(args.ctx, () -> { try { fs(args.ctx).create(args.getString(0), EntryType.FILE); @@ -127,7 +136,8 @@ public class FilesystemLib { catch (FilesystemException e) { throw e.toEngineException(); } }); } - @Expose public static PromiseLib __rm(Arguments args) throws IOException { + @Expose(target = ExposeTarget.STATIC) + public static PromiseLib __rm(Arguments args) throws IOException { return PromiseLib.await(args.ctx, () -> { try { var fs = fs(args.ctx); @@ -157,7 +167,8 @@ public class FilesystemLib { catch (FilesystemException e) { throw e.toEngineException(); } }); } - @Expose public static PromiseLib __stat(Arguments args) throws IOException { + @Expose(target = ExposeTarget.STATIC) + public static PromiseLib __stat(Arguments args) throws IOException { return PromiseLib.await(args.ctx, () -> { try { var fs = fs(args.ctx); @@ -172,7 +183,8 @@ public class FilesystemLib { catch (FilesystemException e) { throw e.toEngineException(); } }); } - @Expose public static PromiseLib __exists(Arguments args) throws IOException { + @Expose(target = ExposeTarget.STATIC) + public static PromiseLib __exists(Arguments args) throws IOException { return PromiseLib.await(args.ctx, () -> { try { fs(args.ctx).stat(args.getString(0)); return true; } catch (FilesystemException e) { return false; } diff --git a/src/me/topchetoeu/jscript/lib/JSONLib.java b/src/me/topchetoeu/jscript/lib/JSONLib.java index 3f025e1..1cd0118 100644 --- a/src/me/topchetoeu/jscript/lib/JSONLib.java +++ b/src/me/topchetoeu/jscript/lib/JSONLib.java @@ -19,6 +19,6 @@ public class JSONLib { } @Expose(target = ExposeTarget.STATIC) public static String __stringify(Arguments args) { - return me.topchetoeu.jscript.json.JSON.stringify(JSON.fromJs(args.ctx, args.get(0))); + return JSON.stringify(JSON.fromJs(args.ctx, args.get(0))); } } diff --git a/src/me/topchetoeu/jscript/lib/MapLib.java b/src/me/topchetoeu/jscript/lib/MapLib.java index dd52eea..2452102 100644 --- a/src/me/topchetoeu/jscript/lib/MapLib.java +++ b/src/me/topchetoeu/jscript/lib/MapLib.java @@ -37,7 +37,7 @@ public class MapLib { } @Expose public ObjectValue __entries(Arguments args) { - return ArrayValue.of(args.ctx, map + return Values.toJSIterator(args.ctx, map .entrySet() .stream() .map(v -> new ArrayValue(args.ctx, v.getKey(), v.getValue())) @@ -45,10 +45,10 @@ public class MapLib { ); } @Expose public ObjectValue __keys(Arguments args) { - return ArrayValue.of(args.ctx, map.keySet()); + return Values.toJSIterator(args.ctx, map.keySet()); } @Expose public ObjectValue __values(Arguments args) { - return ArrayValue.of(args.ctx, map.values()); + return Values.toJSIterator(args.ctx, map.values()); } @Expose public Object __get(Arguments args) { diff --git a/src/me/topchetoeu/jscript/lib/NumberLib.java b/src/me/topchetoeu/jscript/lib/NumberLib.java index 5777fed..d312e82 100644 --- a/src/me/topchetoeu/jscript/lib/NumberLib.java +++ b/src/me/topchetoeu/jscript/lib/NumberLib.java @@ -31,6 +31,12 @@ public class NumberLib { public final double value; + @Override public String toString() { return value + ""; } + + public NumberLib(double val) { + this.value = val; + } + @Expose(target = ExposeTarget.STATIC) public static boolean __isFinite(Arguments args) { return Double.isFinite(args.getDouble(0)); } @Expose(target = ExposeTarget.STATIC) @@ -59,11 +65,7 @@ public class NumberLib { return Values.toString(args.ctx, args.getDouble(0)); } @Expose public static double __valueOf(Arguments args) { - if (args.self instanceof NumberLib) return args.self(NumberLib.class).value; + if (Values.isWrapper(args.self, NumberLib.class)) return Values.wrapper(args.self, NumberLib.class).value; else return Values.toNumber(args.ctx, args.self); } - - public NumberLib(double val) { - this.value = val; - } } diff --git a/src/me/topchetoeu/jscript/lib/ObjectLib.java b/src/me/topchetoeu/jscript/lib/ObjectLib.java index ad14a7f..5aefe2f 100644 --- a/src/me/topchetoeu/jscript/lib/ObjectLib.java +++ b/src/me/topchetoeu/jscript/lib/ObjectLib.java @@ -80,8 +80,8 @@ public class ObjectLib { var obj = args.convert(0, ObjectValue.class); var attrib = args.convert(1, ObjectValue.class); - for (var key : Values.getMembers(null, obj, false, false)) { - obj.defineProperty(args.ctx, key, attrib.getMember(args.ctx, key)); + for (var key : Values.getMembers(null, attrib, false, false)) { + __defineProperty(new Arguments(args.ctx, null, obj, key, attrib.getMember(args.ctx, key))); } return obj; @@ -89,7 +89,7 @@ public class ObjectLib { @Expose(target = ExposeTarget.STATIC) public static ArrayValue __keys(Arguments args) { - var obj = args.convert(0, ObjectValue.class); + var obj = args.get(0); var all = args.getBoolean(1); var res = new ArrayValue(); @@ -102,7 +102,7 @@ public class ObjectLib { @Expose(target = ExposeTarget.STATIC) public static ArrayValue __entries(Arguments args) { var res = new ArrayValue(); - var obj = args.convert(0, ObjectValue.class); + var obj = args.get(0); var all = args.getBoolean(1); for (var key : Values.getMembers(args.ctx, obj, true, false)) { @@ -114,11 +114,11 @@ public class ObjectLib { @Expose(target = ExposeTarget.STATIC) public static ArrayValue __values(Arguments args) { var res = new ArrayValue(); - var obj = args.convert(0, ObjectValue.class); + var obj = args.get(0); var all = args.getBoolean(1); for (var key : Values.getMembers(args.ctx, obj, true, false)) { - if (all || key instanceof String) res.set(args.ctx, res.size(), Values.getMember(args.ctx, obj, key)); + if (all || !(key instanceof Symbol)) res.set(args.ctx, res.size(), Values.getMember(args.ctx, obj, key)); } return res; @@ -139,9 +139,9 @@ public class ObjectLib { } @Expose(target = ExposeTarget.STATIC) - public static ArrayValue __getOwnPropertyNames(Arguments args) { + public static ArrayValue __getOwnPropertyNames(Arguments args) { var res = new ArrayValue(); - var obj = args.convert(0, ObjectValue.class); + var obj = args.get(0); var all = args.getBoolean(1); for (var key : Values.getMembers(args.ctx, obj, true, true)) { @@ -152,7 +152,7 @@ public class ObjectLib { } @Expose(target = ExposeTarget.STATIC) public static ArrayValue __getOwnPropertySymbols(Arguments args) { - var obj = args.convert(0, ObjectValue.class); + var obj = args.get(0); var res = new ArrayValue(); for (var key : Values.getMembers(args.ctx, obj, true, true)) { @@ -208,17 +208,20 @@ public class ObjectLib { @Expose(target = ExposeTarget.STATIC) public static boolean __isExtensible(Arguments args) { var obj = args.get(0); - return obj instanceof ObjectValue && ((ObjectValue)obj).extensible(); + if (!(obj instanceof ObjectValue)) return false; + return ((ObjectValue)obj).extensible(); } @Expose(target = ExposeTarget.STATIC) public static boolean __isSealed(Arguments args) { var obj = args.get(0); - if (obj instanceof ObjectValue && ((ObjectValue)obj).extensible()) { - var _obj = (ObjectValue)obj; - for (var key : _obj.keys(true)) { - if (_obj.memberConfigurable(key)) return false; - } + if (!(obj instanceof ObjectValue)) return true; + var _obj = (ObjectValue)obj; + + if (_obj.extensible()) return false; + + for (var key : _obj.keys(true)) { + if (_obj.memberConfigurable(key)) return false; } return true; @@ -227,12 +230,14 @@ public class ObjectLib { public static boolean __isFrozen(Arguments args) { var obj = args.get(0); - if (obj instanceof ObjectValue && ((ObjectValue)obj).extensible()) { - var _obj = (ObjectValue)obj; - for (var key : _obj.keys(true)) { - if (_obj.memberConfigurable(key)) return false; - if (_obj.memberWritable(key)) return false; - } + if (!(obj instanceof ObjectValue)) return true; + var _obj = (ObjectValue)obj; + + if (_obj.extensible()) return false; + + for (var key : _obj.keys(true)) { + if (_obj.memberConfigurable(key)) return false; + if (_obj.memberWritable(key)) return false; } return true; diff --git a/src/me/topchetoeu/jscript/lib/PromiseLib.java b/src/me/topchetoeu/jscript/lib/PromiseLib.java index e54bdd3..f9055a4 100644 --- a/src/me/topchetoeu/jscript/lib/PromiseLib.java +++ b/src/me/topchetoeu/jscript/lib/PromiseLib.java @@ -41,207 +41,6 @@ public class PromiseLib { private static final int STATE_FULFILLED = 1; private static final int STATE_REJECTED = 2; - @Expose(value = "resolve", target = ExposeTarget.STATIC) - public static PromiseLib __ofResolved(Arguments args) { - return ofResolved(args.ctx, args.get(0)); - } - @Expose(value = "reject", target = ExposeTarget.STATIC) - public static PromiseLib __ofRejected(Arguments args) { - return ofRejected(args.ctx, new EngineException(args.get(0)).setCtx(args.ctx)); - } - - @Expose(target = ExposeTarget.STATIC) - private static PromiseLib __any(Arguments args) { - if (!(args.get(0) instanceof ArrayValue)) throw EngineException.ofType("Expected argument for any to be an array."); - var promises = args.convert(0, ArrayValue.class); - - if (promises.size() == 0) return ofRejected(args.ctx, EngineException.ofError("No promises passed to 'Promise.any'.").setCtx(args.ctx)); - var n = new int[] { promises.size() }; - var res = new PromiseLib(); - var errors = new ArrayValue(); - - for (var i = 0; i < promises.size(); i++) { - var index = i; - var val = promises.get(i); - if (res.state != STATE_PENDING) break; - - handle(args.ctx, val, new Handle() { - public void onFulfil(Object val) { res.fulfill(args.ctx, val); } - public void onReject(EngineException err) { - errors.set(args.ctx, index, err.value); - n[0]--; - if (n[0] <= 0) res.reject(args.ctx, new EngineException(errors).setCtx(args.ctx)); - } - }); - } - - return res; - } - @Expose(target = ExposeTarget.STATIC) - private static PromiseLib __race(Arguments args) { - if (!(args.get(0) instanceof ArrayValue)) throw EngineException.ofType("Expected argument for any to be an array."); - var promises = args.convert(0, ArrayValue.class); - var res = new PromiseLib(); - - for (var i = 0; i < promises.size(); i++) { - var val = promises.get(i); - if (res.state != STATE_PENDING) break; - - handle(args.ctx, val, new Handle() { - @Override public void onFulfil(Object val) { res.fulfill(args.ctx, val); } - @Override public void onReject(EngineException err) { res.reject(args.ctx, err); } - }); - } - - return res; - } - @Expose(target = ExposeTarget.STATIC) - private static PromiseLib __all(Arguments args) { - if (!(args.get(0) instanceof ArrayValue)) throw EngineException.ofType("Expected argument for any to be an array."); - var promises = args.convert(0, ArrayValue.class); - var n = new int[] { promises.size() }; - var res = new PromiseLib(); - var result = new ArrayValue(); - - for (var i = 0; i < promises.size(); i++) { - if (res.state != STATE_PENDING) break; - - var index = i; - var val = promises.get(i); - - handle(args.ctx, val, new Handle() { - @Override public void onFulfil(Object val) { - result.set(args.ctx, index, val); - n[0]--; - if (n[0] <= 0) res.fulfill(args.ctx, result); - } - @Override public void onReject(EngineException err) { - res.reject(args.ctx, err); - } - }); - } - - if (n[0] <= 0) res.fulfill(args.ctx, result); - - return res; - } - @Expose(target = ExposeTarget.STATIC) - private static PromiseLib __allSettled(Arguments args) { - if (!(args.get(0) instanceof ArrayValue)) throw EngineException.ofType("Expected argument for any to be an array."); - var promises = args.convert(0, ArrayValue.class); - var n = new int[] { promises.size() }; - var res = new PromiseLib(); - var result = new ArrayValue(); - - for (var i = 0; i < promises.size(); i++) { - if (res.state != STATE_PENDING) break; - - var index = i; - - handle(args.ctx, promises.get(i), new Handle() { - @Override public void onFulfil(Object val) { - var desc = new ObjectValue(); - desc.defineProperty(args.ctx, "status", "fulfilled"); - desc.defineProperty(args.ctx, "value", val); - - result.set(args.ctx, index, desc); - - n[0]--; - if (n[0] <= 0) res.fulfill(args.ctx, res); - } - @Override public void onReject(EngineException err) { - var desc = new ObjectValue(); - desc.defineProperty(args.ctx, "status", "reject"); - desc.defineProperty(args.ctx, "value", err.value); - - result.set(args.ctx, index, desc); - - n[0]--; - if (n[0] <= 0) res.fulfill(args.ctx, res); - } - }); - } - - if (n[0] <= 0) res.fulfill(args.ctx, result); - - return res; - } - - @Expose - private static Object __then(Arguments args) { - var onFulfill = args.get(0) instanceof FunctionValue ? args.convert(0, FunctionValue.class) : null; - var onReject = args.get(1) instanceof FunctionValue ? args.convert(1, FunctionValue.class) : null; - - var res = new PromiseLib(); - - handle(args.ctx, args.self, new Handle() { - @Override public void onFulfil(Object val) { - try { res.fulfill(args.ctx, onFulfill.call(args.ctx, null, val)); } - catch (EngineException e) { res.reject(args.ctx, e); } - } - @Override public void onReject(EngineException err) { - try { res.fulfill(args.ctx, onReject.call(args.ctx, null, err.value)); } - catch (EngineException e) { res.reject(args.ctx, e); } - } - }.defer(args.ctx.engine)); - - return res; - } - @Expose - private static Object __catch(Arguments args) { - return __then(new Arguments(args.ctx, args.self, null, args.get(0))); - } - @Expose - private static Object __finally(Arguments args) { - var func = args.get(0) instanceof FunctionValue ? args.convert(0, FunctionValue.class) : null; - - var res = new PromiseLib(); - - handle(args.ctx, args.self, new Handle() { - @Override public void onFulfil(Object val) { - try { - func.call(args.ctx); - res.fulfill(args.ctx, val); - } - catch (EngineException e) { res.reject(args.ctx, e); } - } - @Override public void onReject(EngineException err) { - try { - func.call(args.ctx); - res.reject(args.ctx, err); - } - catch (EngineException e) { res.reject(args.ctx, e); } - } - }.defer(args.ctx.engine)); - - return res; - } - - @ExposeConstructor - private static PromiseLib __constructor(Arguments args) { - var func = args.convert(0, FunctionValue.class); - var res = new PromiseLib(); - - try { - func.call( - args.ctx, null, - new NativeFunction(null, _args -> { - res.fulfill(_args.ctx, _args.get(0)); - return null; - }), - new NativeFunction(null, _args -> { - res.reject(_args.ctx, new EngineException(_args.get(0)).setCtx(_args.ctx)); - return null; - }) - ); - } - catch (EngineException e) { - res.reject(args.ctx, e); - } - - return res; - } - private List handles = new ArrayList<>(); private int state = STATE_PENDING; @@ -262,7 +61,7 @@ public class PromiseLib { } if (state == STATE_REJECTED && !handled) { - Values.printError(new EngineException(val).setCtx(ctx.environment, ctx.engine), "(in promise)"); + Values.printError(((EngineException)val).setCtx(ctx.environment, ctx.engine), "(in promise)"); } handles = null; @@ -383,4 +182,205 @@ public class PromiseLib { res.reject(ctx, value); return res; } + + @Expose(value = "resolve", target = ExposeTarget.STATIC) + public static PromiseLib __ofResolved(Arguments args) { + return ofResolved(args.ctx, args.get(0)); + } + @Expose(value = "reject", target = ExposeTarget.STATIC) + public static PromiseLib __ofRejected(Arguments args) { + return ofRejected(args.ctx, new EngineException(args.get(0)).setCtx(args.ctx)); + } + + @Expose(target = ExposeTarget.STATIC) + public static PromiseLib __any(Arguments args) { + if (!(args.get(0) instanceof ArrayValue)) throw EngineException.ofType("Expected argument for any to be an array."); + var promises = args.convert(0, ArrayValue.class); + + if (promises.size() == 0) return ofRejected(args.ctx, EngineException.ofError("No promises passed to 'Promise.any'.").setCtx(args.ctx)); + var n = new int[] { promises.size() }; + var res = new PromiseLib(); + var errors = new ArrayValue(); + + for (var i = 0; i < promises.size(); i++) { + var index = i; + var val = promises.get(i); + if (res.state != STATE_PENDING) break; + + handle(args.ctx, val, new Handle() { + public void onFulfil(Object val) { res.fulfill(args.ctx, val); } + public void onReject(EngineException err) { + errors.set(args.ctx, index, err.value); + n[0]--; + if (n[0] <= 0) res.reject(args.ctx, new EngineException(errors).setCtx(args.ctx)); + } + }); + } + + return res; + } + @Expose(target = ExposeTarget.STATIC) + public static PromiseLib __race(Arguments args) { + if (!(args.get(0) instanceof ArrayValue)) throw EngineException.ofType("Expected argument for any to be an array."); + var promises = args.convert(0, ArrayValue.class); + var res = new PromiseLib(); + + for (var i = 0; i < promises.size(); i++) { + var val = promises.get(i); + if (res.state != STATE_PENDING) break; + + handle(args.ctx, val, new Handle() { + @Override public void onFulfil(Object val) { res.fulfill(args.ctx, val); } + @Override public void onReject(EngineException err) { res.reject(args.ctx, err); } + }); + } + + return res; + } + @Expose(target = ExposeTarget.STATIC) + public static PromiseLib __all(Arguments args) { + if (!(args.get(0) instanceof ArrayValue)) throw EngineException.ofType("Expected argument for any to be an array."); + var promises = args.convert(0, ArrayValue.class); + var n = new int[] { promises.size() }; + var res = new PromiseLib(); + var result = new ArrayValue(); + + for (var i = 0; i < promises.size(); i++) { + if (res.state != STATE_PENDING) break; + + var index = i; + var val = promises.get(i); + + handle(args.ctx, val, new Handle() { + @Override public void onFulfil(Object val) { + result.set(args.ctx, index, val); + n[0]--; + if (n[0] <= 0) res.fulfill(args.ctx, result); + } + @Override public void onReject(EngineException err) { + res.reject(args.ctx, err); + } + }); + } + + if (n[0] <= 0) res.fulfill(args.ctx, result); + + return res; + } + @Expose(target = ExposeTarget.STATIC) + public static PromiseLib __allSettled(Arguments args) { + if (!(args.get(0) instanceof ArrayValue)) throw EngineException.ofType("Expected argument for any to be an array."); + var promises = args.convert(0, ArrayValue.class); + var n = new int[] { promises.size() }; + var res = new PromiseLib(); + var result = new ArrayValue(); + + for (var i = 0; i < promises.size(); i++) { + if (res.state != STATE_PENDING) break; + + var index = i; + + handle(args.ctx, promises.get(i), new Handle() { + @Override public void onFulfil(Object val) { + var desc = new ObjectValue(); + desc.defineProperty(args.ctx, "status", "fulfilled"); + desc.defineProperty(args.ctx, "value", val); + + result.set(args.ctx, index, desc); + + n[0]--; + if (n[0] <= 0) res.fulfill(args.ctx, res); + } + @Override public void onReject(EngineException err) { + var desc = new ObjectValue(); + desc.defineProperty(args.ctx, "status", "reject"); + desc.defineProperty(args.ctx, "value", err.value); + + result.set(args.ctx, index, desc); + + n[0]--; + if (n[0] <= 0) res.fulfill(args.ctx, res); + } + }); + } + + if (n[0] <= 0) res.fulfill(args.ctx, result); + + return res; + } + + @Expose + public static Object __then(Arguments args) { + var onFulfill = args.get(0) instanceof FunctionValue ? args.convert(0, FunctionValue.class) : null; + var onReject = args.get(1) instanceof FunctionValue ? args.convert(1, FunctionValue.class) : null; + + var res = new PromiseLib(); + + handle(args.ctx, args.self, new Handle() { + @Override public void onFulfil(Object val) { + try { res.fulfill(args.ctx, onFulfill.call(args.ctx, null, val)); } + catch (EngineException e) { res.reject(args.ctx, e); } + } + @Override public void onReject(EngineException err) { + try { res.fulfill(args.ctx, onReject.call(args.ctx, null, err.value)); } + catch (EngineException e) { res.reject(args.ctx, e); } + } + }.defer(args.ctx.engine)); + + return res; + } + @Expose + public static Object __catch(Arguments args) { + return __then(new Arguments(args.ctx, args.self, null, args.get(0))); + } + @Expose + public static Object __finally(Arguments args) { + var func = args.get(0) instanceof FunctionValue ? args.convert(0, FunctionValue.class) : null; + + var res = new PromiseLib(); + + handle(args.ctx, args.self, new Handle() { + @Override public void onFulfil(Object val) { + try { + func.call(args.ctx); + res.fulfill(args.ctx, val); + } + catch (EngineException e) { res.reject(args.ctx, e); } + } + @Override public void onReject(EngineException err) { + try { + func.call(args.ctx); + res.reject(args.ctx, err); + } + catch (EngineException e) { res.reject(args.ctx, e); } + } + }.defer(args.ctx.engine)); + + return res; + } + + @ExposeConstructor + public static PromiseLib __constructor(Arguments args) { + var func = args.convert(0, FunctionValue.class); + var res = new PromiseLib(); + + try { + func.call( + args.ctx, null, + new NativeFunction(null, _args -> { + res.fulfill(_args.ctx, _args.get(0)); + return null; + }), + new NativeFunction(null, _args -> { + res.reject(_args.ctx, new EngineException(_args.get(0)).setCtx(_args.ctx)); + return null; + }) + ); + } + catch (EngineException e) { + res.reject(args.ctx, e); + } + + return res; + } } diff --git a/src/me/topchetoeu/jscript/lib/RangeErrorLib.java b/src/me/topchetoeu/jscript/lib/RangeErrorLib.java index 86b10ad..906c826 100644 --- a/src/me/topchetoeu/jscript/lib/RangeErrorLib.java +++ b/src/me/topchetoeu/jscript/lib/RangeErrorLib.java @@ -6,15 +6,12 @@ import me.topchetoeu.jscript.interop.WrapperName; import me.topchetoeu.jscript.interop.Arguments; import me.topchetoeu.jscript.interop.ExposeConstructor; import me.topchetoeu.jscript.interop.ExposeField; -import me.topchetoeu.jscript.interop.ExposeTarget; @WrapperName("RangeError") public class RangeErrorLib extends ErrorLib { - @ExposeField(target = ExposeTarget.STATIC) - public static final String __name = "RangeError"; + @ExposeField public static final String __name = "RangeError"; - @ExposeConstructor - public static ObjectValue constructor(Arguments args) { + @ExposeConstructor public static ObjectValue constructor(Arguments args) { var target = ErrorLib.__constructor(args); target.setPrototype(PlaceholderProto.RANGE_ERROR); return target; diff --git a/src/me/topchetoeu/jscript/lib/SetLib.java b/src/me/topchetoeu/jscript/lib/SetLib.java index bda9149..eade541 100644 --- a/src/me/topchetoeu/jscript/lib/SetLib.java +++ b/src/me/topchetoeu/jscript/lib/SetLib.java @@ -24,13 +24,13 @@ public class SetLib { } @Expose public ObjectValue __entries(Arguments args) { - return ArrayValue.of(args.ctx, set.stream().map(v -> new ArrayValue(args.ctx, v, v)).collect(Collectors.toList())); + return Values.toJSIterator(args.ctx, set.stream().map(v -> new ArrayValue(args.ctx, v, v)).collect(Collectors.toList())); } @Expose public ObjectValue __keys(Arguments args) { - return ArrayValue.of(args.ctx, set); + return Values.toJSIterator(args.ctx, set); } @Expose public ObjectValue __values(Arguments args) { - return ArrayValue.of(args.ctx, set); + return Values.toJSIterator(args.ctx, set); } @Expose public Object __add(Arguments args) { diff --git a/src/me/topchetoeu/jscript/lib/StringLib.java b/src/me/topchetoeu/jscript/lib/StringLib.java index c377a38..65311b3 100644 --- a/src/me/topchetoeu/jscript/lib/StringLib.java +++ b/src/me/topchetoeu/jscript/lib/StringLib.java @@ -21,9 +21,15 @@ import me.topchetoeu.jscript.interop.WrapperName; public class StringLib { public final String value; + @Override public String toString() { return value; } + + public StringLib(String val) { + this.value = val; + } + private static String passThis(Arguments args, String funcName) { var val = args.self; - if (val instanceof StringLib) return ((StringLib)val).value; + if (Values.isWrapper(val, StringLib.class)) return Values.wrapper(val, StringLib.class).value; else if (val instanceof String) return (String)val; else throw EngineException.ofType(String.format("'%s' may only be called upon object and primitve strings.", funcName)); } @@ -43,16 +49,22 @@ public class StringLib { @Expose public static String __substring(Arguments args) { var val = passThis(args, "substring"); - var start = normalizeI(args.getInt(0), val.length(), true); - var end = normalizeI(args.getInt(1, val.length()), val.length(), true); + var start = Math.max(0, Math.min(val.length(), args.getInt(0))); + var end = Math.max(0, Math.min(val.length(), args.getInt(1, val.length()))); + + if (end < start) { + var tmp = end; + end = start; + start = tmp; + } return val.substring(start, end); } @Expose public static String __substr(Arguments args) { var val = passThis(args, "substr"); var start = normalizeI(args.getInt(0), val.length(), true); - int len = normalizeI(args.getInt(0), val.length() - start, true); - return val.substring(start, start + len); + int end = normalizeI(args.getInt(1, val.length() - start) + start, val.length(), true); + return val.substring(start, end); } @Expose public static String __toLowerCase(Arguments args) { @@ -206,6 +218,7 @@ public class StringLib { var pattern = Pattern.quote(Values.toString(args.ctx, term)); if (lim == null) parts = val.split(pattern); + else if ((double)lim < 1) return new ArrayValue(); else if (sensible) parts = val.split(pattern, (int)(double)lim); else { var limit = (int)(double)lim; @@ -232,8 +245,11 @@ public class StringLib { } @Expose public static String __slice(Arguments args) { - passThis(args, "slice"); - return __substring(args); + var self = passThis(args, "slice"); + var start = normalizeI(args.getInt(0), self.length(), false); + var end = normalizeI(args.getInt(1, self.length()), self.length(), false); + + return __substring(new Arguments(args.ctx, self, start, end)); } @Expose public static String __concat(Arguments args) { @@ -254,7 +270,7 @@ public class StringLib { } @ExposeConstructor public static Object __constructor(Arguments args) { - var val = args.getString(0); + var val = args.getString(0, ""); if (args.self instanceof ObjectValue) return new StringLib(val); else return val; } @@ -272,8 +288,4 @@ public class StringLib { for (var i = 0; i < val.length; i++) arr[i] = (char)val[i]; return new String(arr); } - - public StringLib(String val) { - this.value = val; - } } diff --git a/src/me/topchetoeu/jscript/lib/SymbolLib.java b/src/me/topchetoeu/jscript/lib/SymbolLib.java index 7a56ca2..d182108 100644 --- a/src/me/topchetoeu/jscript/lib/SymbolLib.java +++ b/src/me/topchetoeu/jscript/lib/SymbolLib.java @@ -5,6 +5,7 @@ import java.util.Map; import me.topchetoeu.jscript.engine.values.ObjectValue; import me.topchetoeu.jscript.engine.values.Symbol; +import me.topchetoeu.jscript.engine.values.Values; import me.topchetoeu.jscript.exceptions.EngineException; import me.topchetoeu.jscript.interop.Arguments; import me.topchetoeu.jscript.interop.Expose; @@ -40,7 +41,7 @@ public class SymbolLib { private static Symbol passThis(Arguments args, String funcName) { var val = args.self; - if (val instanceof SymbolLib) return ((SymbolLib)val).value; + if (Values.isWrapper(val, SymbolLib.class)) return Values.wrapper(val, SymbolLib.class).value; else if (val instanceof Symbol) return (Symbol)val; else throw EngineException.ofType(String.format("'%s' may only be called upon object and primitve symbols.", funcName)); } @@ -75,6 +76,6 @@ public class SymbolLib { } @Expose(target = ExposeTarget.STATIC) public static String __keyFor(Arguments args) { - return passThis(args.slice(-1), "keyFor").value; + return passThis(new Arguments(args.ctx, args.get(0)), "keyFor").value; } } diff --git a/src/me/topchetoeu/jscript/lib/SyntaxErrorLib.java b/src/me/topchetoeu/jscript/lib/SyntaxErrorLib.java index b457510..2ca77ee 100644 --- a/src/me/topchetoeu/jscript/lib/SyntaxErrorLib.java +++ b/src/me/topchetoeu/jscript/lib/SyntaxErrorLib.java @@ -6,15 +6,12 @@ import me.topchetoeu.jscript.interop.WrapperName; import me.topchetoeu.jscript.interop.Arguments; import me.topchetoeu.jscript.interop.ExposeConstructor; import me.topchetoeu.jscript.interop.ExposeField; -import me.topchetoeu.jscript.interop.ExposeTarget; @WrapperName("SyntaxError") public class SyntaxErrorLib extends ErrorLib { - @ExposeField(target = ExposeTarget.STATIC) - public static final String __name = "SyntaxError"; + @ExposeField public static final String __name = "SyntaxError"; - @ExposeConstructor - public static ObjectValue __constructor(Arguments args) { + @ExposeConstructor public static ObjectValue __constructor(Arguments args) { var target = ErrorLib.__constructor(args); target.setPrototype(PlaceholderProto.SYNTAX_ERROR); return target; diff --git a/src/me/topchetoeu/jscript/lib/TypeErrorLib.java b/src/me/topchetoeu/jscript/lib/TypeErrorLib.java index 0fb1c17..d8fd623 100644 --- a/src/me/topchetoeu/jscript/lib/TypeErrorLib.java +++ b/src/me/topchetoeu/jscript/lib/TypeErrorLib.java @@ -6,15 +6,12 @@ import me.topchetoeu.jscript.interop.WrapperName; import me.topchetoeu.jscript.interop.Arguments; import me.topchetoeu.jscript.interop.ExposeConstructor; import me.topchetoeu.jscript.interop.ExposeField; -import me.topchetoeu.jscript.interop.ExposeTarget; @WrapperName("TypeError") public class TypeErrorLib extends ErrorLib { - @ExposeField(target = ExposeTarget.STATIC) - public static final String __name = "TypeError"; + @ExposeField public static final String __name = "TypeError"; - @ExposeConstructor - public static ObjectValue __constructor(Arguments args) { + @ExposeConstructor public static ObjectValue __constructor(Arguments args) { var target = ErrorLib.__constructor(args); target.setPrototype(PlaceholderProto.TYPE_ERROR); return target;