Skip to content

Commit

Permalink
implements Promise.allSettled()
Browse files Browse the repository at this point in the history
resolves mozilla#1061
  • Loading branch information
Robert Gaggl committed Nov 21, 2021
1 parent cb8d5f0 commit dbcc9f6
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 106 deletions.
58 changes: 49 additions & 9 deletions src/org/mozilla/javascript/NativePromise.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ public static void init(Context cx, Scriptable scope, boolean sealed) {
scope, "reject", 1, NativePromise::reject, DONTENUM, DONTENUM | READONLY);
constructor.defineConstructorMethod(
scope, "all", 1, NativePromise::all, DONTENUM, DONTENUM | READONLY);
constructor.defineConstructorMethod(
scope, "allSettled", 1, NativePromise::allSettled, DONTENUM, DONTENUM | READONLY);
constructor.defineConstructorMethod(
scope, "race", 1, NativePromise::race, DONTENUM, DONTENUM | READONLY);

Expand Down Expand Up @@ -160,8 +162,7 @@ private static Object reject(Context cx, Scriptable scope, Scriptable thisObj, O
return cap.promise;
}

// Promise.all
private static Object all(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
private static Object doAll(Context cx, Scriptable scope, Scriptable thisObj, Object[] args, boolean failFast) {
Capability cap = new Capability(cx, scope, thisObj);
Object arg = (args.length > 0 ? args[0] : Undefined.instance);

Expand All @@ -180,7 +181,7 @@ private static Object all(Context cx, Scriptable scope, Scriptable thisObj, Obje

IteratorLikeIterable.Itr iterator = iterable.iterator();
try {
PromiseAllResolver resolver = new PromiseAllResolver(iterator, thisObj, cap);
PromiseAllResolver resolver = new PromiseAllResolver(iterator, thisObj, cap, failFast);
try {
return resolver.resolve(cx, scope);
} finally {
Expand All @@ -198,6 +199,16 @@ private static Object all(Context cx, Scriptable scope, Scriptable thisObj, Obje
}
}

// Promise.all
private static Object all(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
return doAll(cx, scope, thisObj, args, true);
}

// Promise.allSettled
private static Object allSettled(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
return doAll(cx, scope, thisObj, args, false);
}

// Promise.race
private static Object race(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
Capability cap = new Capability(cx, scope, thisObj);
Expand Down Expand Up @@ -691,11 +702,13 @@ private static class PromiseAllResolver {
IteratorLikeIterable.Itr iterator;
Scriptable thisObj;
Capability capability;
boolean failFast;

PromiseAllResolver(IteratorLikeIterable.Itr iter, Scriptable thisObj, Capability cap) {
PromiseAllResolver(IteratorLikeIterable.Itr iter, Scriptable thisObj, Capability cap, boolean failFast) {
this.iterator = iter;
this.thisObj = thisObj;
this.capability = cap;
this.failFast = failFast;
}

Object resolve(Context topCx, Scriptable topScope) {
Expand Down Expand Up @@ -745,13 +758,40 @@ Object resolve(Context topCx, Scriptable topScope) {
new LambdaFunction(
topScope,
1,
(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) ->
eltResolver.resolve(
(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) -> {
Object value = (args.length > 0 ? args[0] : Undefined.instance);
if (!failFast) {
Scriptable elementResult = cx.newObject(scope);
elementResult.put("status", elementResult, "fulfilled");
elementResult.put("value", elementResult, value);
value = elementResult;
}
return eltResolver.resolve(
cx,
scope,
(args.length > 0 ? args[0] : Undefined.instance),
this));
value,
this);
});
resolveFunc.setStandardPropertyAttributes(DONTENUM | READONLY);

Callable rejectFunc = capability.reject;
if (!failFast) {
LambdaFunction resolveSettledRejection = new LambdaFunction(
topScope,
1,
(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) -> {
Scriptable result = cx.newObject(scope);
result.put("status", result, " rejected");
result.put("reason", result, (args.length > 0 ? args[0] : Undefined.instance));
return eltResolver.resolve(
cx,
scope,
result,
this);
});
resolveSettledRejection.setStandardPropertyAttributes(DONTENUM | READONLY);
rejectFunc = resolveSettledRejection;
}
remainingElements++;

// Call "then" on the promise with the resolution func
Expand All @@ -761,7 +801,7 @@ Object resolve(Context topCx, Scriptable topScope) {
topCx,
topScope,
ScriptRuntime.lastStoredScriptable(topCx),
new Object[] {resolveFunc, capability.reject});
new Object[] {resolveFunc, rejectFunc});
index++;
}
}
Expand Down
97 changes: 0 additions & 97 deletions testsrc/test262.properties
Original file line number Diff line number Diff line change
Expand Up @@ -979,103 +979,6 @@ built-ins/parseInt 3/60 (5.0%)
S15.1.2.2_A9.2.js

built-ins/Promise 444/599 (74.12%)
allSettled/call-resolve-element.js
allSettled/call-resolve-element-after-return.js
allSettled/call-resolve-element-items.js
allSettled/capability-executor-called-twice.js
allSettled/capability-executor-not-callable.js
allSettled/capability-resolve-throws-no-close.js
allSettled/capability-resolve-throws-reject.js {unsupported: [async]}
allSettled/ctx-ctor.js {unsupported: [class]}
allSettled/ctx-ctor-throws.js
allSettled/does-not-invoke-array-setters.js {unsupported: [async]}
allSettled/invoke-resolve.js
allSettled/invoke-resolve-error-close.js
allSettled/invoke-resolve-error-reject.js {unsupported: [async]}
allSettled/invoke-resolve-get-error.js {unsupported: [async]}
allSettled/invoke-resolve-get-error-reject.js {unsupported: [async]}
allSettled/invoke-resolve-get-once-multiple-calls.js
allSettled/invoke-resolve-get-once-no-calls.js
allSettled/invoke-resolve-on-promises-every-iteration-of-custom.js {unsupported: [class, async]}
allSettled/invoke-resolve-on-promises-every-iteration-of-promise.js {unsupported: [async]}
allSettled/invoke-resolve-on-values-every-iteration-of-promise.js {unsupported: [async]}
allSettled/invoke-resolve-return.js
allSettled/invoke-then.js
allSettled/invoke-then-error-close.js
allSettled/invoke-then-error-reject.js {unsupported: [async]}
allSettled/invoke-then-get-error-close.js
allSettled/invoke-then-get-error-reject.js {unsupported: [async]}
allSettled/is-function.js
allSettled/iter-arg-is-false-reject.js {unsupported: [async]}
allSettled/iter-arg-is-null-reject.js {unsupported: [async]}
allSettled/iter-arg-is-number-reject.js {unsupported: [async]}
allSettled/iter-arg-is-poisoned.js {unsupported: [async]}
allSettled/iter-arg-is-string-resolve.js {unsupported: [async]}
allSettled/iter-arg-is-symbol-reject.js {unsupported: [async]}
allSettled/iter-arg-is-true-reject.js {unsupported: [async]}
allSettled/iter-arg-is-undefined-reject.js {unsupported: [async]}
allSettled/iter-assigned-false-reject.js {unsupported: [async]}
allSettled/iter-assigned-null-reject.js {unsupported: [async]}
allSettled/iter-assigned-number-reject.js {unsupported: [async]}
allSettled/iter-assigned-string-reject.js {unsupported: [async]}
allSettled/iter-assigned-symbol-reject.js {unsupported: [async]}
allSettled/iter-assigned-true-reject.js {unsupported: [async]}
allSettled/iter-assigned-undefined-reject.js {unsupported: [async]}
allSettled/iter-next-err-reject.js {unsupported: [async]}
allSettled/iter-next-val-err-no-close.js
allSettled/iter-next-val-err-reject.js {unsupported: [async]}
allSettled/iter-returns-false-reject.js {unsupported: [async]}
allSettled/iter-returns-null-reject.js {unsupported: [async]}
allSettled/iter-returns-number-reject.js {unsupported: [async]}
allSettled/iter-returns-string-reject.js {unsupported: [async]}
allSettled/iter-returns-symbol-reject.js {unsupported: [async]}
allSettled/iter-returns-true-reject.js {unsupported: [async]}
allSettled/iter-returns-undefined-reject.js {unsupported: [async]}
allSettled/iter-step-err-no-close.js
allSettled/iter-step-err-reject.js {unsupported: [async]}
allSettled/length.js
allSettled/name.js
allSettled/new-reject-function.js
allSettled/new-resolve-function.js
allSettled/prop-desc.js
allSettled/reject-deferred.js {unsupported: [async]}
allSettled/reject-element-function-extensible.js
allSettled/reject-element-function-length.js
allSettled/reject-element-function-multiple-calls.js
allSettled/reject-element-function-name.js
allSettled/reject-element-function-nonconstructor.js
allSettled/reject-element-function-prototype.js
allSettled/reject-ignored-deferred.js {unsupported: [async]}
allSettled/reject-ignored-immed.js {unsupported: [async]}
allSettled/reject-immed.js {unsupported: [async]}
allSettled/resolve-before-loop-exit.js
allSettled/resolve-before-loop-exit-from-same.js
allSettled/resolve-element-function-extensible.js
allSettled/resolve-element-function-length.js
allSettled/resolve-element-function-name.js
allSettled/resolve-element-function-nonconstructor.js
allSettled/resolve-element-function-prototype.js
allSettled/resolve-from-same-thenable.js
allSettled/resolve-ignores-late-rejection.js {unsupported: [async]}
allSettled/resolve-ignores-late-rejection-deferred.js {unsupported: [async]}
allSettled/resolve-non-callable.js {unsupported: [async]}
allSettled/resolve-non-thenable.js {unsupported: [async]}
allSettled/resolve-not-callable-reject-with-typeerror.js {unsupported: [async]}
allSettled/resolve-poisoned-then.js {unsupported: [async]}
allSettled/resolve-thenable.js {unsupported: [async]}
allSettled/resolved-all-fulfilled.js {unsupported: [async]}
allSettled/resolved-all-mixed.js {unsupported: [async]}
allSettled/resolved-all-rejected.js {unsupported: [async]}
allSettled/resolved-immed.js {unsupported: [async]}
allSettled/resolved-sequence.js {unsupported: [async]}
allSettled/resolved-sequence-extra-ticks.js {unsupported: [async]}
allSettled/resolved-sequence-mixed.js {unsupported: [async]}
allSettled/resolved-sequence-with-rejections.js {unsupported: [async]}
allSettled/resolved-then-catch-finally.js {unsupported: [async]}
allSettled/resolves-empty-array.js {unsupported: [async]}
allSettled/resolves-to-array.js {unsupported: [async]}
allSettled/returns-promise.js
allSettled/species-get-error.js {unsupported: [Symbol.species]}
all/capability-resolve-throws-reject.js {unsupported: [async]}
all/ctx-ctor.js {unsupported: [class]}
all/does-not-invoke-array-setters.js {unsupported: [async]}
Expand Down

0 comments on commit dbcc9f6

Please sign in to comment.