Changeset 161365 in webkit


Ignore:
Timestamp:
Jan 6, 2014 1:00:03 PM (10 years ago)
Author:
weinig@apple.com
Message:

[JS] Implement Promise.all()
https://bugs.webkit.org/show_bug.cgi?id=126510

Reviewed by Gavin Barraclough.

Source/JavaScriptCore:

Add Promise.all() implementation and factor out performing resolves and rejects
on deferreds to share a bit of code. Also moves the abruptRejection helper to
JSPromiseDeferred so it can be used in JSPromiseFunctions.

  • runtime/CommonIdentifiers.h:
  • runtime/JSPromiseConstructor.cpp:

(JSC::JSPromiseConstructorFuncCast):
(JSC::JSPromiseConstructorFuncResolve):
(JSC::JSPromiseConstructorFuncReject):
(JSC::JSPromiseConstructorFuncAll):

  • runtime/JSPromiseDeferred.cpp:

(JSC::updateDeferredFromPotentialThenable):
(JSC::performDeferredResolve):
(JSC::performDeferredReject):
(JSC::abruptRejection):

  • runtime/JSPromiseDeferred.h:
  • runtime/JSPromiseFunctions.cpp:

(JSC::promiseAllCountdownFunction):
(JSC::createPromiseAllCountdownFunction):

  • runtime/JSPromiseFunctions.h:
  • runtime/JSPromiseReaction.cpp:

(JSC::ExecutePromiseReactionMicrotask::run):

LayoutTests:

Enabled and fix the existing Promise.all() test case.

  • Promise.all() and Promise.all({}) should reject by my reading of the spec.

Also removes the Promise.all() shim used by the crypto tests.

  • crypto/subtle/resources/common.js:
  • js/dom/Promise-static-all-expected.txt:
  • js/dom/Promise-static-all.html:
Location:
trunk
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r161344 r161365  
     12014-01-05  Sam Weinig  <sam@webkit.org>
     2
     3        [JS] Implement Promise.all()
     4        https://bugs.webkit.org/show_bug.cgi?id=126510
     5
     6        Reviewed by Gavin Barraclough.
     7
     8        Enabled and fix the existing Promise.all() test case.
     9        - Promise.all() and Promise.all({}) should reject by my reading of the spec.
     10        Also removes the Promise.all() shim used by the crypto tests.
     11
     12        * crypto/subtle/resources/common.js:
     13        * js/dom/Promise-static-all-expected.txt:
     14        * js/dom/Promise-static-all.html:
     15
    1162014-01-06  Zan Dobersek  <zdobersek@igalia.com>
    217
  • trunk/LayoutTests/crypto/subtle/resources/common.js

    r161241 r161365  
    102102};
    103103
    104 if (!Promise.all) {
    105     // A very simple temporary implementation only for WebCrypto tests.
    106     Promise.all = function(promises) {
    107         var results = [];
    108         var resultCount = 0;
    109         var resolver;
    110         var rejector;
    111         function next(result) {
    112             results[resultCount++] = result;
    113             if (resultCount < promises.length)
    114                 promises[resultCount].then(next);
    115             else
    116                 resolver(results);
    117         }
    118         promises[0].then(next, function() { rejector(null) });
    119         return new Promise(function(resolve, reject) { resolver = resolve; rejector = reject; });
    120     }
    121 }
    122 
    123104if (!crypto.subtle)
    124105    crypto.subtle = crypto.webkitSubtle;
  • trunk/LayoutTests/js/dom/Promise-static-all-expected.txt

    r161241 r161365  
    33On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
    44
     5PASS result is undefined
     6PASS Promise.all() is rejected.
     7PASS Promise.all([p1, p2, p3]) is fulfilled.
     8PASS result.length is 3
     9PASS result[0] is "p1"
     10PASS result[1] is "p2"
     11PASS result[2] is "p3"
     12PASS Promise.all([p1, p6, p5]) is rejected.
     13PASS result is "p6"
     14PASS Promise.all([p9]) is fulfilled.
     15PASS result.length is 1
     16PASS result[0] is "p2"
     17PASS Promise.all([p9,,,]) is fulfilled.
     18PASS result.length is 3
     19PASS result[0] is "p2"
     20PASS result[1] is undefined
     21PASS result[2] is undefined
     22PASS Promise.all([p9,42]) is fulfilled.
     23PASS result.length is 2
     24PASS result[0] is "p2"
     25PASS result[1] is 42
     26PASS Promise.all({}) is rejected.
    527PASS successfullyParsed is true
    628
  • trunk/LayoutTests/js/dom/Promise-static-all.html

    r161241 r161365  
    1010description('Test Promise.all');
    1111
    12 /*
    1312window.jsTestIsAsync = true;
    1413result = undefined;
     
    3130
    3231Promise.all().then(function(result) {
    33   testPassed('Promise.all() is fulfilled.');
    34   window.result = result;
    35   shouldBe('result.length', '0');
     32  testFailed('Promise.all() is fulfilled.');
    3633}, function() {
    37   testFailed('Promise.all() is rejected.');
     34  testPassed('Promise.all() is rejected.');
    3835}).then(function() {
    3936  return Promise.all([p1, p2, p3]).then(function(result) {
     
    9188  // Not iterable object case.
    9289  return Promise.all({}).then(function(result) {
    93     testPassed('Promise.all({}) is fulfilled.');
    94     window.result = result;
    95     shouldBe('result.length', '0');
     90    testFailed('Promise.all({}) is fulfilled.');
    9691  }, function(result) {
    97     testFailed('Promise.all({}) is rejected.');
     92    testPassed('Promise.all({}) is rejected.');
    9893  });
    9994}).then(finishJSTest, finishJSTest);
    10095
    10196shouldBe('result', 'undefined');
    102 */
    10397
    10498</script>
  • trunk/Source/JavaScriptCore/ChangeLog

    r161364 r161365  
     12014-01-05  Sam Weinig  <sam@webkit.org>
     2
     3        [JS] Implement Promise.all()
     4        https://bugs.webkit.org/show_bug.cgi?id=126510
     5
     6        Reviewed by Gavin Barraclough.
     7
     8        Add Promise.all() implementation and factor out performing resolves and rejects
     9        on deferreds to share a bit of code. Also moves the abruptRejection helper to
     10        JSPromiseDeferred so it can be used in JSPromiseFunctions.
     11
     12        * runtime/CommonIdentifiers.h:
     13        * runtime/JSPromiseConstructor.cpp:
     14        (JSC::JSPromiseConstructorFuncCast):
     15        (JSC::JSPromiseConstructorFuncResolve):
     16        (JSC::JSPromiseConstructorFuncReject):
     17        (JSC::JSPromiseConstructorFuncAll):
     18        * runtime/JSPromiseDeferred.cpp:
     19        (JSC::updateDeferredFromPotentialThenable):
     20        (JSC::performDeferredResolve):
     21        (JSC::performDeferredReject):
     22        (JSC::abruptRejection):
     23        * runtime/JSPromiseDeferred.h:
     24        * runtime/JSPromiseFunctions.cpp:
     25        (JSC::promiseAllCountdownFunction):
     26        (JSC::createPromiseAllCountdownFunction):
     27        * runtime/JSPromiseFunctions.h:
     28        * runtime/JSPromiseReaction.cpp:
     29        (JSC::ExecutePromiseReactionMicrotask::run):
     30
    1312014-01-06  Filip Pizlo  <fpizlo@apple.com>
    232
  • trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h

    r161330 r161365  
    213213    macro(promise) \
    214214    macro(fulfillmentHandler) \
    215     macro(rejectionHandler)
     215    macro(rejectionHandler) \
     216    macro(index) \
     217    macro(values) \
     218    macro(deferred) \
     219    macro(countdownHolder)
    216220
    217221namespace JSC {
  • trunk/Source/JavaScriptCore/runtime/JSPromiseConstructor.cpp

    r161330 r161365  
    3737#include "JSPromisePrototype.h"
    3838#include "Lookup.h"
     39#include "NumberObject.h"
    3940#include "StructureInlines.h"
    4041
     
    4748static EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncReject(ExecState*);
    4849static EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncRace(ExecState*);
     50static EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncAll(ExecState*);
    4951}
    5052
     
    6163  reject          JSPromiseConstructorFuncReject              DontEnum|Function 1
    6264  race            JSPromiseConstructorFuncRace                DontEnum|Function 1
     65  all             JSPromiseConstructorFuncAll                 DontEnum|Function 1
    6366@end
    6467*/
     
    192195    //    of deferred.[[Resolve]] with undefined as thisArgument and a List containing x
    193196    //    as argumentsList.
    194    
    195     JSValue deferredResolve = deferred->resolve();
    196 
    197     CallData resolveCallData;
    198     CallType resolveCallType = getCallData(deferredResolve, resolveCallData);
    199     ASSERT(resolveCallType != CallTypeNone);
    200 
    201     MarkedArgumentBuffer arguments;
    202     arguments.append(x);
    203 
    204     call(exec, deferredResolve, resolveCallType, resolveCallData, jsUndefined(), arguments);
     197    performDeferredResolve(exec, deferred, x);
    205198
    206199    // 6. ReturnIfAbrupt(resolveResult).
     
    232225    //    of deferred.[[Resolve]] with undefined as thisArgument and a List containing x
    233226    //    as argumentsList.
    234 
    235     JSValue deferredResolve = deferred->resolve();
    236 
    237     CallData resolveCallData;
    238     CallType resolveCallType = getCallData(deferredResolve, resolveCallData);
    239     ASSERT(resolveCallType != CallTypeNone);
    240 
    241     MarkedArgumentBuffer arguments;
    242     arguments.append(x);
    243 
    244     call(exec, deferredResolve, resolveCallType, resolveCallData, jsUndefined(), arguments);
     227    performDeferredResolve(exec, deferred, x);
    245228   
    246229    // 5. ReturnIfAbrupt(resolveResult).
     
    272255    //    of deferred.[[Reject]] with undefined as thisArgument and a List containing r
    273256    //    as argumentsList.
    274 
    275     JSValue deferredReject = deferred->reject();
    276 
    277     CallData rejectCallData;
    278     CallType rejectCallType = getCallData(deferredReject, rejectCallData);
    279     ASSERT(rejectCallType != CallTypeNone);
    280 
    281     MarkedArgumentBuffer arguments;
    282     arguments.append(r);
    283 
    284     call(exec, deferredReject, rejectCallType, rejectCallData, jsUndefined(), arguments);
     257    performDeferredReject(exec, deferred, r);
    285258
    286259    // 5. ReturnIfAbrupt(resolveResult).
     
    290263    // 6. Return deferred.[[Promise]].
    291264    return JSValue::encode(deferred->promise());
    292 }
    293 
    294 static JSValue abruptRejection(ExecState* exec, JSPromiseDeferred* deferred)
    295 {
    296     ASSERT(exec->hadException());
    297     JSValue argument = exec->exception();
    298     exec->clearException();
    299 
    300     // i. Let 'rejectResult' be the result of calling the [[Call]] internal method
    301     // of deferred.[[Reject]] with undefined as thisArgument and a List containing
    302     // argument.[[value]] as argumentsList.
    303     JSValue deferredReject = deferred->reject();
    304 
    305     CallData rejectCallData;
    306     CallType rejectCallType = getCallData(deferredReject, rejectCallData);
    307     ASSERT(rejectCallType != CallTypeNone);
    308 
    309     MarkedArgumentBuffer arguments;
    310     arguments.append(argument);
    311 
    312     call(exec, deferredReject, rejectCallType, rejectCallData, jsUndefined(), arguments);
    313 
    314     // ii. ReturnIfAbrupt(rejectResult).
    315     if (exec->hadException())
    316         return jsUndefined();
    317 
    318     // iii. Return deferred.[[Promise]].
    319     return deferred->promise();
    320265}
    321266
     
    432377}
    433378
     379EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncAll(ExecState* exec)
     380{
     381    // -- Promise.all(iterable) --
     382
     383    JSValue iterable = exec->argument(0);
     384    VM& vm = exec->vm();
     385
     386    // 1. Let 'C' be the this value.
     387    JSValue C = exec->thisValue();
     388
     389    // 2. Let 'deferred' be the result of calling GetDeferred(C).
     390    JSValue deferredValue = createJSPromiseDeferredFromConstructor(exec, C);
     391
     392    // 3. ReturnIfAbrupt(deferred).
     393    if (exec->hadException())
     394        return JSValue::encode(jsUndefined());
     395
     396    // NOTE: A non-abrupt completion of createJSPromiseDeferredFromConstructor implies that
     397    // C and deferredValue are objects.
     398    JSObject* thisObject = asObject(C);
     399    JSPromiseDeferred* deferred = jsCast<JSPromiseDeferred*>(deferredValue);
     400
     401    // 4. Let 'iterator' be the result of calling GetIterator(iterable).
     402    JSValue iteratorFunction = iterable.get(exec, vm.propertyNames->iteratorPrivateName);
     403    if (exec->hadException())
     404        return JSValue::encode(abruptRejection(exec, deferred));
     405
     406    CallData iteratorFunctionCallData;
     407    CallType iteratorFunctionCallType = getCallData(iteratorFunction, iteratorFunctionCallData);
     408    if (iteratorFunctionCallType == CallTypeNone) {
     409        throwTypeError(exec);
     410        return JSValue::encode(abruptRejection(exec, deferred));
     411    }
     412
     413    ArgList iteratorFunctionArguments;
     414    JSValue iterator = call(exec, iteratorFunction, iteratorFunctionCallType, iteratorFunctionCallData, iterable, iteratorFunctionArguments);
     415
     416    // 5. RejectIfAbrupt(iterator, deferred).
     417    if (exec->hadException())
     418        return JSValue::encode(abruptRejection(exec, deferred));
     419
     420    // 6. Let 'values' be the result of calling ArrayCreate(0).
     421    JSArray* values = constructEmptyArray(exec, nullptr, thisObject->globalObject());
     422   
     423    // 7. Let 'countdownHolder' be Record { [[Countdown]]: 0 }.
     424    NumberObject* countdownHolder = constructNumber(exec, thisObject->globalObject(), JSValue(0));
     425   
     426    // 8. Let 'index' be 0.
     427    unsigned index = 0;
     428   
     429    // 9. Repeat.
     430    do {
     431        // i. Let 'next' be the result of calling IteratorStep(iterator).
     432        JSValue nextFunction = iterator.get(exec, exec->vm().propertyNames->iteratorNextPrivateName);
     433        if (exec->hadException())
     434            return JSValue::encode(abruptRejection(exec, deferred));
     435
     436        CallData nextFunctionCallData;
     437        CallType nextFunctionCallType = getCallData(nextFunction, nextFunctionCallData);
     438        if (nextFunctionCallType == CallTypeNone) {
     439            throwTypeError(exec);
     440            return JSValue::encode(abruptRejection(exec, deferred));
     441        }
     442
     443        MarkedArgumentBuffer nextFunctionArguments;
     444        nextFunctionArguments.append(jsUndefined());
     445        JSValue next = call(exec, nextFunction, nextFunctionCallType, nextFunctionCallData, iterator, nextFunctionArguments);
     446       
     447        // ii. RejectIfAbrupt(next, deferred).
     448        if (exec->hadException())
     449            return JSValue::encode(abruptRejection(exec, deferred));
     450
     451        // iii. If 'next' is false,
     452        // Note: We implement this as an iterationTerminator
     453        if (next == vm.iterationTerminator.get()) {
     454            // a. If 'index' is 0,
     455            if (!index) {
     456                // a. Let 'resolveResult' be the result of calling the [[Call]] internal method
     457                //    of deferred.[[Resolve]] with undefined as thisArgument and a List containing
     458                //    values as argumentsList.
     459                performDeferredResolve(exec, deferred, values);
     460
     461                // b. ReturnIfAbrupt(resolveResult).
     462                if (exec->hadException())
     463                    return JSValue::encode(jsUndefined());
     464            }
     465           
     466            // b. Return deferred.[[Promise]].
     467            return JSValue::encode(deferred->promise());
     468        }
     469       
     470        // iv. Let 'nextValue' be the result of calling IteratorValue(next).
     471        // v. RejectIfAbrupt(nextValue, deferred).
     472        // Note: 'next' is already the value, so there is nothing to do here.
     473
     474        // vi. Let 'nextPromise' be the result of calling Invoke(C, "cast", (nextValue)).
     475        JSValue castFunction = C.get(exec, vm.propertyNames->cast);
     476        if (exec->hadException())
     477            return JSValue::encode(abruptRejection(exec, deferred));
     478
     479        CallData castFunctionCallData;
     480        CallType castFunctionCallType = getCallData(castFunction, castFunctionCallData);
     481        if (castFunctionCallType == CallTypeNone) {
     482            throwTypeError(exec);
     483            return JSValue::encode(abruptRejection(exec, deferred));
     484        }
     485
     486        MarkedArgumentBuffer castFunctionArguments;
     487        castFunctionArguments.append(next);
     488        JSValue nextPromise = call(exec, castFunction, castFunctionCallType, castFunctionCallData, C, castFunctionArguments);
     489
     490        // vii. RejectIfAbrupt(nextPromise, deferred).
     491        if (exec->hadException())
     492            return JSValue::encode(abruptRejection(exec, deferred));
     493
     494        // viii. Let 'countdownFunction' be a new built-in function object as defined in Promise.all Countdown Functions.
     495        JSFunction* countdownFunction = createPromiseAllCountdownFunction(vm, thisObject->globalObject());
     496       
     497        // ix. Set the [[Index]] internal slot of 'countdownFunction' to 'index'.
     498        countdownFunction->putDirect(vm, vm.propertyNames->indexPrivateName, JSValue(index));
     499
     500        // x. Set the [[Values]] internal slot of 'countdownFunction' to 'values'.
     501        countdownFunction->putDirect(vm, vm.propertyNames->valuesPrivateName, values);
     502
     503        // xi. Set the [[Deferred]] internal slot of 'countdownFunction' to 'deferred'.
     504        countdownFunction->putDirect(vm, vm.propertyNames->deferredPrivateName, deferred);
     505
     506        // xii. Set the [[CountdownHolder]] internal slot of 'countdownFunction' to 'countdownHolder'.
     507        countdownFunction->putDirect(vm, vm.propertyNames->countdownHolderPrivateName, countdownHolder);
     508
     509        // xiii. Let 'result' be the result of calling Invoke(nextPromise, "then", (countdownFunction, deferred.[[Reject]])).
     510        JSValue thenFunction = nextPromise.get(exec, vm.propertyNames->then);
     511        if (exec->hadException())
     512            return JSValue::encode(abruptRejection(exec, deferred));
     513
     514        CallData thenFunctionCallData;
     515        CallType thenFunctionCallType = getCallData(thenFunction, thenFunctionCallData);
     516        if (thenFunctionCallType == CallTypeNone) {
     517            throwTypeError(exec);
     518            return JSValue::encode(abruptRejection(exec, deferred));
     519        }
     520
     521        MarkedArgumentBuffer thenFunctionArguments;
     522        thenFunctionArguments.append(countdownFunction);
     523        thenFunctionArguments.append(deferred->reject());
     524
     525        call(exec, thenFunction, thenFunctionCallType, thenFunctionCallData, nextPromise, thenFunctionArguments);
     526
     527        // xiv. RejectIfAbrupt(result, deferred).
     528        if (exec->hadException())
     529            return JSValue::encode(abruptRejection(exec, deferred));
     530
     531        // xv. Set index to index + 1.
     532        index++;
     533
     534        // xvi. Set countdownHolder.[[Countdown]] to countdownHolder.[[Countdown]] + 1.
     535        uint32_t newCountdownValue = countdownHolder->internalValue().asUInt32() + 1;
     536        countdownHolder->setInternalValue(vm, JSValue(newCountdownValue));
     537    } while (true);
     538}
     539
    434540JSPromise* constructPromise(ExecState* exec, JSGlobalObject* globalObject, JSFunction* resolver)
    435541{
  • trunk/Source/JavaScriptCore/runtime/JSPromiseDeferred.cpp

    r161241 r161365  
    153153        exec->clearException();
    154154
    155         JSValue deferredReject = deferred->reject();
    156 
    157         CallData rejectCallData;
    158         CallType rejectCallType = getCallData(deferredReject, rejectCallData);
    159         ASSERT(rejectCallType != CallTypeNone);
    160 
    161         MarkedArgumentBuffer rejectArguments;
    162         rejectArguments.append(exception);
    163 
    164         call(exec, deferredReject, rejectCallType, rejectCallData, jsUndefined(), rejectArguments);
     155        performDeferredReject(exec, deferred, exception);
    165156
    166157        // ii. ReturnIfAbrupt(rejectResult).
     
    197188        exec->clearException();
    198189
    199         JSValue deferredReject = deferred->reject();
    200 
    201         CallData rejectCallData;
    202         CallType rejectCallType = getCallData(deferredReject, rejectCallData);
    203         ASSERT(rejectCallType != CallTypeNone);
    204 
    205         MarkedArgumentBuffer rejectArguments;
    206         rejectArguments.append(exception);
    207 
    208         call(exec, deferredReject, rejectCallType, rejectCallData, jsUndefined(), rejectArguments);
     190        performDeferredReject(exec, deferred, exception);
    209191
    210192        // ii. ReturnIfAbrupt(rejectResult).
     
    215197}
    216198
     199void performDeferredResolve(ExecState* exec, JSPromiseDeferred* deferred, JSValue argument)
     200{
     201    JSValue deferredResolve = deferred->resolve();
     202
     203    CallData resolveCallData;
     204    CallType resolveCallType = getCallData(deferredResolve, resolveCallData);
     205    ASSERT(resolveCallType != CallTypeNone);
     206
     207    MarkedArgumentBuffer arguments;
     208    arguments.append(argument);
     209
     210    call(exec, deferredResolve, resolveCallType, resolveCallData, jsUndefined(), arguments);
     211}
     212
     213void performDeferredReject(ExecState* exec, JSPromiseDeferred* deferred, JSValue argument)
     214{
     215    JSValue deferredReject = deferred->reject();
     216
     217    CallData rejectCallData;
     218    CallType rejectCallType = getCallData(deferredReject, rejectCallData);
     219    ASSERT(rejectCallType != CallTypeNone);
     220
     221    MarkedArgumentBuffer arguments;
     222    arguments.append(argument);
     223
     224    call(exec, deferredReject, rejectCallType, rejectCallData, jsUndefined(), arguments);
     225}
     226
     227JSValue abruptRejection(ExecState* exec, JSPromiseDeferred* deferred)
     228{
     229    ASSERT(exec->hadException());
     230    JSValue argument = exec->exception();
     231    exec->clearException();
     232
     233    // i. Let 'rejectResult' be the result of calling the [[Call]] internal method
     234    // of deferred.[[Reject]] with undefined as thisArgument and a List containing
     235    // argument.[[value]] as argumentsList.
     236    performDeferredReject(exec, deferred, argument);
     237
     238    // ii. ReturnIfAbrupt(rejectResult).
     239    if (exec->hadException())
     240        return jsUndefined();
     241
     242    // iii. Return deferred.[[Promise]].
     243    return deferred->promise();
     244}
     245
    217246} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/JSPromiseDeferred.h

    r161241 r161365  
    7171ThenableStatus updateDeferredFromPotentialThenable(ExecState*, JSValue, JSPromiseDeferred*);
    7272
     73void performDeferredResolve(ExecState*, JSPromiseDeferred*, JSValue argument);
     74void performDeferredReject(ExecState*, JSPromiseDeferred*, JSValue argument);
     75
     76JSValue abruptRejection(ExecState*, JSPromiseDeferred*);
     77
    7378} // namespace JSC
    7479
  • trunk/Source/JavaScriptCore/runtime/JSPromiseFunctions.cpp

    r161241 r161365  
    3535#include "JSPromiseConstructor.h"
    3636#include "JSPromiseDeferred.h"
     37#include "NumberObject.h"
    3738
    3839namespace JSC {
     
    7071{
    7172    return JSFunction::create(vm, globalObject, 1, ASCIILiteral("IdentityFunction"), identifyFunction);
     73}
     74
     75// Promise.All Countdown Functions
     76
     77static EncodedJSValue JSC_HOST_CALL promiseAllCountdownFunction(ExecState* exec)
     78{
     79    JSValue x = exec->argument(0);
     80    VM& vm = exec->vm();
     81    JSObject* F = exec->callee();
     82
     83    // 1. Let 'index' be the value of F's [[Index]] internal slot.
     84    uint32_t index = F->get(exec, vm.propertyNames->indexPrivateName).asUInt32();
     85
     86    // 2. Let 'values' be the value of F's [[Values]] internal slot..
     87    JSArray* values = jsCast<JSArray*>(F->get(exec, vm.propertyNames->valuesPrivateName));
     88
     89    // 3. Let 'deferred' be the value of F's [[Deferred]] internal slot.
     90    JSPromiseDeferred* deferred = jsCast<JSPromiseDeferred*>(F->get(exec, vm.propertyNames->deferredPrivateName));
     91
     92    // 4. Let 'countdownHolder' be the value of F's [[CountdownHolder]] internal slot.
     93    NumberObject* countdownHolder = jsCast<NumberObject*>(F->get(exec, vm.propertyNames->countdownHolderPrivateName));
     94
     95    // 5. Let 'result' be the result of calling the [[DefineOwnProperty]] internal method
     96    //    of 'values' with arguments 'index' and Property Descriptor { [[Value]]: x,
     97    //    [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }.
     98    values->putDirectIndex(exec, index, x);
     99
     100    // 6. RejectIfAbrupt(result, deferred).
     101    if (exec->hadException())
     102        abruptRejection(exec, deferred);
     103
     104    // 7. Set countdownHolder.[[Countdown]] to countdownHolder.[[Countdown]] - 1.
     105    uint32_t newCountdownValue = countdownHolder->internalValue().asUInt32() - 1;
     106    countdownHolder->setInternalValue(vm, JSValue(newCountdownValue));
     107
     108    // 8. If countdownHolder.[[Countdown]] is 0,
     109    if (!newCountdownValue) {
     110        // i. Return the result of calling the [[Call]] internal method of deferred.[[Resolve]]
     111        //    with undefined as thisArgument and a List containing 'values' as argumentsList.
     112        performDeferredResolve(exec, deferred, values);
     113    }
     114
     115    // 9. Return.
     116    return JSValue::encode(jsUndefined());
     117}
     118
     119JSFunction* createPromiseAllCountdownFunction(VM& vm, JSGlobalObject* globalObject)
     120{
     121    return JSFunction::create(vm, globalObject, 1, ASCIILiteral("PromiseAllCountdownFunction"), promiseAllCountdownFunction);
    72122}
    73123
  • trunk/Source/JavaScriptCore/runtime/JSPromiseFunctions.h

    r161241 r161365  
    3535JSFunction* createDeferredConstructionFunction(VM&, JSGlobalObject*);
    3636JSFunction* createIdentifyFunction(VM&, JSGlobalObject*);
     37JSFunction* createPromiseAllCountdownFunction(VM&, JSGlobalObject*);
    3738JSFunction* createPromiseResolutionHandlerFunction(VM&, JSGlobalObject*);
    3839JSFunction* createRejectPromiseFunction(VM&, JSGlobalObject*);
  • trunk/Source/JavaScriptCore/runtime/JSPromiseReaction.cpp

    r161317 r161365  
    9090        exec->clearException();
    9191
    92         JSValue deferredReject = deferred->reject();
    93 
    94         CallData rejectCallData;
    95         CallType rejectCallType = getCallData(deferredReject, rejectCallData);
    96         ASSERT(rejectCallType != CallTypeNone);
    97 
    98         MarkedArgumentBuffer rejectArguments;
    99         rejectArguments.append(exception);
    100 
    101         call(exec, deferredReject, rejectCallType, rejectCallData, jsUndefined(), rejectArguments);
    102         // FIXME: Should we return the result somewhere?
     92        performDeferredReject(exec, deferred, exception);
    10393    }
    10494   
     
    110100        // i. Let 'selfResolutionError' be a newly-created TypeError object.
    111101        JSObject* selfResolutionError = createTypeError(exec, ASCIILiteral("Resolve a promise with itself"));
     102
    112103        // ii. Return the result of calling the [[Call]] internal method of deferred.[[Reject]] passing
    113104        //     undefined as thisArgument and a List containing selfResolutionError as argumentsList.
    114         JSValue deferredReject = deferred->reject();
    115 
    116         CallData rejectCallData;
    117         CallType rejectCallType = getCallData(deferredReject, rejectCallData);
    118         ASSERT(rejectCallType != CallTypeNone);
    119 
    120         MarkedArgumentBuffer rejectArguments;
    121         rejectArguments.append(selfResolutionError);
    122 
    123         call(exec, deferredReject, rejectCallType, rejectCallData, jsUndefined(), rejectArguments);
    124         // FIXME: Should we return the result somewhere?
     105        performDeferredReject(exec, deferred, selfResolutionError);
    125106    }
    126107
     
    136117        // i. Return the result of calling the [[Call]] internal method of deferred.[[Resolve]]
    137118        //    passing undefined as thisArgument and a List containing handlerResult as argumentsList.
    138 
    139         JSValue deferredResolve = deferred->resolve();
    140 
    141         CallData resolveCallData;
    142         CallType resolveCallType = getCallData(deferredResolve, resolveCallData);
    143         ASSERT(resolveCallType != CallTypeNone);
    144 
    145         MarkedArgumentBuffer arguments;
    146         arguments.append(handlerResult);
    147 
    148         call(exec, deferredResolve, resolveCallType, resolveCallData, jsUndefined(), arguments);
    149         // FIXME: Should we return the result somewhere?
     119        performDeferredResolve(exec, deferred, handlerResult);
    150120    }
    151121}
Note: See TracChangeset for help on using the changeset viewer.