Implement Promise.allSettled
authordino@apple.com <dino@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 29 May 2019 21:28:09 +0000 (21:28 +0000)
committerdino@apple.com <dino@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 29 May 2019 21:28:09 +0000 (21:28 +0000)
https://bugs.webkit.org/show_bug.cgi?id=197600
<rdar://problem/50483885>

Reviewed by Keith Miller.

JSTests:

Start testing Promise.allSettled. We pass most of the tests.
The ones that fail are similar to the Promise.all tests we already fail.

* test262/config.yaml: Remove Promise.allSettled from skipped tests.
* test262/expectations.yaml: Add new expectations for allSettled tests.

Source/JavaScriptCore:

Implement Promise.allSettled
https://github.com/tc39/proposal-promise-allSettled/

Shipping in Firefox since version 68.
Shipping in V8 since https://chromium.googlesource.com/v8/v8.git/+/1f6d27e8df819b448712dface6ad367fb8de426b

* builtins/PromiseConstructor.js:
(allSettled.newResolveRejectElements.resolveElement):
(allSettled.newResolveRejectElements.rejectElement):
(allSettled.newResolveRejectElements):
(allSettled): Added.
* runtime/JSPromiseConstructor.cpp: Add ref to allSettled.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@245869 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JSTests/ChangeLog
JSTests/test262/config.yaml
JSTests/test262/expectations.yaml
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/builtins/PromiseConstructor.js
Source/JavaScriptCore/runtime/JSPromiseConstructor.cpp

index 23cc8b4..c2f72e8 100644 (file)
@@ -1,3 +1,17 @@
+2019-05-28  Dean Jackson  <dino@apple.com>
+
+        Implement Promise.allSettled
+        https://bugs.webkit.org/show_bug.cgi?id=197600
+        <rdar://problem/50483885>
+
+        Reviewed by Keith Miller.
+
+        Start testing Promise.allSettled. We pass most of the tests.
+        The ones that fail are similar to the Promise.all tests we already fail.
+
+        * test262/config.yaml: Remove Promise.allSettled from skipped tests.
+        * test262/expectations.yaml: Add new expectations for allSettled tests.
+
 2019-05-28  Michael Saboff  <msaboff@apple.com>
 
         [YARR] Properly handle RegExp's that require large ParenContext space
index 85ccab5..df1bbc7 100644 (file)
@@ -31,8 +31,6 @@ skip:
     - Intl.NumberFormat-unified
     - Intl.RelativeTimeFormat
     - Intl.Segmenter
-    # https://bugs.webkit.org/show_bug.cgi?id=196332
-    - Promise.allSettled
   files:
     - test/built-ins/Array/prototype/reverse/length-exceeding-integer-limit-with-object.js
     - test/built-ins/Array/prototype/unshift/length-near-integer-limit.js
index 9cbe35d..0d9d46f 100644 (file)
@@ -1086,9 +1086,27 @@ test/built-ins/Promise/all/invoke-resolve-get-error-close.js:
 test/built-ins/Promise/all/invoke-resolve-get-once-multiple-calls.js:
   default: 'Test262Error: Got `resolve` only once for each iterated value Expected SameValue(«4», Â«1») to be true'
   strict mode: 'Test262Error: Got `resolve` only once for each iterated value Expected SameValue(«4», Â«1») to be true'
+test/built-ins/Promise/all/invoke-resolve-get-once-no-calls.js:
+  default: 'Test262Error: Got `resolve` only once for each iterated value Expected SameValue(«0», Â«1») to be true'
+  strict mode: 'Test262Error: Got `resolve` only once for each iterated value Expected SameValue(«0», Â«1») to be true'
 test/built-ins/Promise/all/resolve-element-function-nonconstructor.js:
   default: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'
   strict mode: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'
+test/built-ins/Promise/allSettled/invoke-resolve-get-error-close.js:
+  default: 'Test262Error: Expected SameValue(«1», Â«0») to be true'
+  strict mode: 'Test262Error: Expected SameValue(«1», Â«0») to be true'
+test/built-ins/Promise/allSettled/invoke-resolve-get-once-multiple-calls.js:
+  default: 'Test262Error: Got `resolve` only once for each iterated value Expected SameValue(«4», Â«1») to be true'
+  strict mode: 'Test262Error: Got `resolve` only once for each iterated value Expected SameValue(«4», Â«1») to be true'
+test/built-ins/Promise/allSettled/invoke-resolve-get-once-no-calls.js:
+  default: 'Test262Error: Got `resolve` only once for each iterated value Expected SameValue(«0», Â«1») to be true'
+  strict mode: 'Test262Error: Got `resolve` only once for each iterated value Expected SameValue(«0», Â«1») to be true'
+test/built-ins/Promise/allSettled/reject-element-function-nonconstructor.js:
+  default: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'
+  strict mode: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'
+test/built-ins/Promise/allSettled/resolve-element-function-nonconstructor.js:
+  default: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'
+  strict mode: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'
 test/built-ins/Promise/proto-from-ctor-realm.js:
   default: 'Test262Error: Expected SameValue(«[object Promise]», Â«[object Promise]») to be true'
   strict mode: 'Test262Error: Expected SameValue(«[object Promise]», Â«[object Promise]») to be true'
index a14505d..119cd00 100644 (file)
@@ -1,3 +1,24 @@
+2019-05-28  Dean Jackson  <dino@apple.com>
+
+        Implement Promise.allSettled
+        https://bugs.webkit.org/show_bug.cgi?id=197600
+        <rdar://problem/50483885>
+
+        Reviewed by Keith Miller.
+
+        Implement Promise.allSettled
+        https://github.com/tc39/proposal-promise-allSettled/
+
+        Shipping in Firefox since version 68.
+        Shipping in V8 since https://chromium.googlesource.com/v8/v8.git/+/1f6d27e8df819b448712dface6ad367fb8de426b
+
+        * builtins/PromiseConstructor.js:
+        (allSettled.newResolveRejectElements.resolveElement):
+        (allSettled.newResolveRejectElements.rejectElement):
+        (allSettled.newResolveRejectElements):
+        (allSettled): Added.
+        * runtime/JSPromiseConstructor.cpp: Add ref to allSettled.
+
 2019-05-28  Michael Saboff  <msaboff@apple.com>
 
         [YARR] Properly handle RegExp's that require large ParenContext space
index b13d146..c667afd 100644 (file)
@@ -75,6 +75,86 @@ function all(iterable)
     return promiseCapability.@promise;
 }
 
+function allSettled(iterable)
+{
+    "use strict";
+
+    if (!@isObject(this))
+        @throwTypeError("|this| is not a object");
+
+    var promiseCapability = @newPromiseCapability(this);
+
+    var values = [];
+    var remainingElementsCount = 1;
+    var index = 0;
+
+    function newResolveRejectElements(index)
+    {
+        var alreadyCalled = false;
+
+        var resolveElement = function @resolve(x)
+        {
+            if (alreadyCalled)
+                return @undefined;
+            alreadyCalled = true;
+
+            var obj = {
+                status: "fulfilled",
+                value: x
+            };
+
+            @putByValDirect(values, index, obj);
+
+            --remainingElementsCount;
+            if (remainingElementsCount === 0)
+                return promiseCapability.@resolve.@call(@undefined, values);
+
+            return @undefined;
+        };
+
+        var rejectElement = function @reject(x)
+        {
+            if (alreadyCalled)
+                return @undefined;
+            alreadyCalled = true;
+
+            var obj = {
+                status: "rejected",
+                reason: x
+            };
+
+            @putByValDirect(values, index, obj);
+
+            --remainingElementsCount;
+            if (remainingElementsCount === 0)
+                return promiseCapability.@resolve.@call(@undefined, values);
+
+            return @undefined;
+        };
+
+        return [resolveElement, rejectElement];
+    }
+
+    try {
+        for (var value of iterable) {
+            @putByValDirect(values, index, @undefined);
+            var nextPromise = this.resolve(value);
+            var [resolveElement, rejectElement] = newResolveRejectElements(index);
+            ++remainingElementsCount;
+            nextPromise.then(resolveElement, rejectElement);
+            ++index;
+        }
+
+        --remainingElementsCount;
+        if (remainingElementsCount === 0)
+            promiseCapability.@resolve.@call(@undefined, values);
+    } catch (error) {
+        promiseCapability.@reject.@call(@undefined, error);
+    }
+
+    return promiseCapability.@promise;
+}
+
 function race(iterable)
 {
     "use strict";
index 74177c4..053fed2 100644 (file)
@@ -57,6 +57,7 @@ const ClassInfo JSPromiseConstructor::s_info = { "Function", &Base::s_info, &pro
   reject          JSBuiltin             DontEnum|Function 1
   race            JSBuiltin             DontEnum|Function 1
   all             JSBuiltin             DontEnum|Function 1
+  allSettled      JSBuiltin             DontEnum|Function 1
 @end
 */