1/* 2 * Copyright (C) 2013 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "JSPromiseConstructor.h" 28 29#if ENABLE(PROMISES) 30 31#include "Error.h" 32#include "JSCJSValueInlines.h" 33#include "JSCellInlines.h" 34#include "JSPromise.h" 35#include "JSPromiseDeferred.h" 36#include "JSPromiseFunctions.h" 37#include "JSPromisePrototype.h" 38#include "Lookup.h" 39#include "NumberObject.h" 40#include "StructureInlines.h" 41 42namespace JSC { 43 44STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSPromiseConstructor); 45 46static EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncCast(ExecState*); 47static EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncResolve(ExecState*); 48static EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncReject(ExecState*); 49static EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncRace(ExecState*); 50static EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncAll(ExecState*); 51} 52 53#include "JSPromiseConstructor.lut.h" 54 55namespace JSC { 56 57const ClassInfo JSPromiseConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::promiseConstructorTable, CREATE_METHOD_TABLE(JSPromiseConstructor) }; 58 59/* Source for JSPromiseConstructor.lut.h 60@begin promiseConstructorTable 61 cast JSPromiseConstructorFuncCast DontEnum|Function 1 62 resolve JSPromiseConstructorFuncResolve DontEnum|Function 1 63 reject JSPromiseConstructorFuncReject DontEnum|Function 1 64 race JSPromiseConstructorFuncRace DontEnum|Function 1 65 all JSPromiseConstructorFuncAll DontEnum|Function 1 66@end 67*/ 68 69JSPromiseConstructor* JSPromiseConstructor::create(VM& vm, Structure* structure, JSPromisePrototype* promisePrototype) 70{ 71 JSPromiseConstructor* constructor = new (NotNull, allocateCell<JSPromiseConstructor>(vm.heap)) JSPromiseConstructor(vm, structure); 72 constructor->finishCreation(vm, promisePrototype); 73 return constructor; 74} 75 76Structure* JSPromiseConstructor::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) 77{ 78 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); 79} 80 81JSPromiseConstructor::JSPromiseConstructor(VM& vm, Structure* structure) 82 : InternalFunction(vm, structure) 83{ 84} 85 86void JSPromiseConstructor::finishCreation(VM& vm, JSPromisePrototype* promisePrototype) 87{ 88 Base::finishCreation(vm, "Promise"); 89 putDirectWithoutTransition(vm, vm.propertyNames->prototype, promisePrototype, DontEnum | DontDelete | ReadOnly); 90 putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontEnum | DontDelete); 91} 92 93static EncodedJSValue JSC_HOST_CALL constructPromise(ExecState* exec) 94{ 95 // NOTE: We ignore steps 1-4 as they only matter if you support subclassing, which we do not yet. 96 // 1. Let promise be the this value. 97 // 2. If Type(promise) is not Object, then throw a TypeError exception. 98 // 3. If promise does not have a [[PromiseStatus]] internal slot, then throw a TypeError exception. 99 // 4. If promise's [[PromiseStatus]] internal slot is not undefined, then throw a TypeError exception. 100 101 JSValue resolver = exec->argument(0); 102 103 // 5. IsCallable(resolver) is false, then throw a TypeError exception 104 CallData callData; 105 CallType callType = getCallData(resolver, callData); 106 if (callType == CallTypeNone) 107 return JSValue::encode(throwTypeError(exec, ASCIILiteral("Promise constructor takes a function argument"))); 108 109 VM& vm = exec->vm(); 110 JSGlobalObject* globalObject = exec->callee()->globalObject(); 111 112 JSPromise* promise = JSPromise::create(vm, globalObject, jsCast<JSPromiseConstructor*>(exec->callee())); 113 114 // NOTE: Steps 6-8 are handled by JSPromise::create(). 115 // 6. Set promise's [[PromiseStatus]] internal slot to "unresolved". 116 // 7. Set promise's [[ResolveReactions]] internal slot to a new empty List. 117 // 8. Set promise's [[RejectReactions]] internal slot to a new empty List. 118 119 // 9. Let 'resolve' be a new built-in function object as defined in Resolve Promise Functions. 120 JSFunction* resolve = createResolvePromiseFunction(vm, globalObject); 121 122 // 10. Set the [[Promise]] internal slot of 'resolve' to 'promise'. 123 resolve->putDirect(vm, vm.propertyNames->promisePrivateName, promise); 124 125 // 11. Let 'reject' be a new built-in function object as defined in Reject Promise Functions 126 JSFunction* reject = createRejectPromiseFunction(vm, globalObject); 127 128 // 12. Set the [[Promise]] internal slot of 'reject' to 'promise'. 129 reject->putDirect(vm, vm.propertyNames->promisePrivateName, promise); 130 131 // 13. Let 'result' be the result of calling the [[Call]] internal method of resolver with 132 // undefined as thisArgument and a List containing resolve and reject as argumentsList. 133 MarkedArgumentBuffer arguments; 134 arguments.append(resolve); 135 arguments.append(reject); 136 call(exec, resolver, callType, callData, jsUndefined(), arguments); 137 138 // 14. If result is an abrupt completion, call PromiseReject(promise, result.[[value]]). 139 if (exec->hadException()) { 140 JSValue exception = exec->exception(); 141 exec->clearException(); 142 143 promise->reject(vm, exception); 144 } 145 146 // 15. Return promise. 147 return JSValue::encode(promise); 148} 149 150ConstructType JSPromiseConstructor::getConstructData(JSCell*, ConstructData& constructData) 151{ 152 constructData.native.function = constructPromise; 153 return ConstructTypeHost; 154} 155 156CallType JSPromiseConstructor::getCallData(JSCell*, CallData& callData) 157{ 158 callData.native.function = constructPromise; 159 return CallTypeHost; 160} 161 162bool JSPromiseConstructor::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot) 163{ 164 return getStaticFunctionSlot<InternalFunction>(exec, ExecState::promiseConstructorTable(exec->vm()), jsCast<JSPromiseConstructor*>(object), propertyName, slot); 165} 166 167EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncCast(ExecState* exec) 168{ 169 // -- Promise.cast(x) -- 170 JSValue x = exec->argument(0); 171 172 // 1. Let 'C' be the this value. 173 JSValue C = exec->thisValue(); 174 175 // 2. If IsPromise(x) is true, 176 JSPromise* promise = jsDynamicCast<JSPromise*>(x); 177 if (promise) { 178 // i. Let 'constructor' be the value of x's [[PromiseConstructor]] internal slot. 179 JSValue constructor = promise->constructor(); 180 // ii. If SameValue(constructor, C) is true, return x. 181 if (sameValue(exec, constructor, C)) 182 return JSValue::encode(x); 183 } 184 185 // 3. Let 'deferred' be the result of calling GetDeferred(C). 186 JSValue deferredValue = createJSPromiseDeferredFromConstructor(exec, C); 187 188 // 4. ReturnIfAbrupt(deferred). 189 if (exec->hadException()) 190 return JSValue::encode(jsUndefined()); 191 192 JSPromiseDeferred* deferred = jsCast<JSPromiseDeferred*>(deferredValue); 193 194 // 5. Let 'resolveResult' be the result of calling the [[Call]] internal method 195 // of deferred.[[Resolve]] with undefined as thisArgument and a List containing x 196 // as argumentsList. 197 performDeferredResolve(exec, deferred, x); 198 199 // 6. ReturnIfAbrupt(resolveResult). 200 if (exec->hadException()) 201 return JSValue::encode(jsUndefined()); 202 203 // 7. Return deferred.[[Promise]]. 204 return JSValue::encode(deferred->promise()); 205} 206 207EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncResolve(ExecState* exec) 208{ 209 // -- Promise.resolve(x) -- 210 JSValue x = exec->argument(0); 211 212 // 1. Let 'C' be the this value. 213 JSValue C = exec->thisValue(); 214 215 // 2. Let 'deferred' be the result of calling GetDeferred(C). 216 JSValue deferredValue = createJSPromiseDeferredFromConstructor(exec, C); 217 218 // 3. ReturnIfAbrupt(deferred). 219 if (exec->hadException()) 220 return JSValue::encode(jsUndefined()); 221 222 JSPromiseDeferred* deferred = jsCast<JSPromiseDeferred*>(deferredValue); 223 224 // 4. Let 'resolveResult' be the result of calling the [[Call]] internal method 225 // of deferred.[[Resolve]] with undefined as thisArgument and a List containing x 226 // as argumentsList. 227 performDeferredResolve(exec, deferred, x); 228 229 // 5. ReturnIfAbrupt(resolveResult). 230 if (exec->hadException()) 231 return JSValue::encode(jsUndefined()); 232 233 // 6. Return deferred.[[Promise]]. 234 return JSValue::encode(deferred->promise()); 235} 236 237EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncReject(ExecState* exec) 238{ 239 // -- Promise.reject(x) -- 240 JSValue r = exec->argument(0); 241 242 // 1. Let 'C' be the this value. 243 JSValue C = exec->thisValue(); 244 245 // 2. Let 'deferred' be the result of calling GetDeferred(C). 246 JSValue deferredValue = createJSPromiseDeferredFromConstructor(exec, C); 247 248 // 3. ReturnIfAbrupt(deferred). 249 if (exec->hadException()) 250 return JSValue::encode(jsUndefined()); 251 252 JSPromiseDeferred* deferred = jsCast<JSPromiseDeferred*>(deferredValue); 253 254 // 4. Let 'rejectResult' be the result of calling the [[Call]] internal method 255 // of deferred.[[Reject]] with undefined as thisArgument and a List containing r 256 // as argumentsList. 257 performDeferredReject(exec, deferred, r); 258 259 // 5. ReturnIfAbrupt(resolveResult). 260 if (exec->hadException()) 261 return JSValue::encode(jsUndefined()); 262 263 // 6. Return deferred.[[Promise]]. 264 return JSValue::encode(deferred->promise()); 265} 266 267EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncRace(ExecState* exec) 268{ 269 // -- Promise.race(iterable) -- 270 JSValue iterable = exec->argument(0); 271 VM& vm = exec->vm(); 272 273 // 1. Let 'C' be the this value. 274 JSValue C = exec->thisValue(); 275 276 // 2. Let 'deferred' be the result of calling GetDeferred(C). 277 JSValue deferredValue = createJSPromiseDeferredFromConstructor(exec, C); 278 279 // 3. ReturnIfAbrupt(deferred). 280 if (exec->hadException()) 281 return JSValue::encode(jsUndefined()); 282 283 JSPromiseDeferred* deferred = jsCast<JSPromiseDeferred*>(deferredValue); 284 285 // 4. Let 'iterator' be the result of calling GetIterator(iterable). 286 JSValue iteratorFunction = iterable.get(exec, vm.propertyNames->iteratorPrivateName); 287 if (exec->hadException()) 288 return JSValue::encode(abruptRejection(exec, deferred)); 289 290 CallData iteratorFunctionCallData; 291 CallType iteratorFunctionCallType = getCallData(iteratorFunction, iteratorFunctionCallData); 292 if (iteratorFunctionCallType == CallTypeNone) { 293 throwTypeError(exec); 294 return JSValue::encode(abruptRejection(exec, deferred)); 295 } 296 297 ArgList iteratorFunctionArguments; 298 JSValue iterator = call(exec, iteratorFunction, iteratorFunctionCallType, iteratorFunctionCallData, iterable, iteratorFunctionArguments); 299 300 // 5. RejectIfAbrupt(iterator, deferred). 301 if (exec->hadException()) 302 return JSValue::encode(abruptRejection(exec, deferred)); 303 304 // 6. Repeat 305 do { 306 // i. Let 'next' be the result of calling IteratorStep(iterator). 307 JSValue nextFunction = iterator.get(exec, exec->vm().propertyNames->iteratorNextPrivateName); 308 if (exec->hadException()) 309 return JSValue::encode(abruptRejection(exec, deferred)); 310 311 CallData nextFunctionCallData; 312 CallType nextFunctionCallType = getCallData(nextFunction, nextFunctionCallData); 313 if (nextFunctionCallType == CallTypeNone) { 314 throwTypeError(exec); 315 return JSValue::encode(abruptRejection(exec, deferred)); 316 } 317 318 MarkedArgumentBuffer nextFunctionArguments; 319 nextFunctionArguments.append(jsUndefined()); 320 JSValue next = call(exec, nextFunction, nextFunctionCallType, nextFunctionCallData, iterator, nextFunctionArguments); 321 322 // ii. RejectIfAbrupt(next, deferred). 323 if (exec->hadException()) 324 return JSValue::encode(abruptRejection(exec, deferred)); 325 326 // iii. If 'next' is false, return deferred.[[Promise]]. 327 // Note: We implement this as an iterationTerminator 328 if (next == vm.iterationTerminator.get()) 329 return JSValue::encode(deferred->promise()); 330 331 // iv. Let 'nextValue' be the result of calling IteratorValue(next). 332 // v. RejectIfAbrupt(nextValue, deferred). 333 // Note: 'next' is already the value, so there is nothing to do here. 334 335 // vi. Let 'nextPromise' be the result of calling Invoke(C, "cast", (nextValue)). 336 JSValue castFunction = C.get(exec, vm.propertyNames->cast); 337 if (exec->hadException()) 338 return JSValue::encode(abruptRejection(exec, deferred)); 339 340 CallData castFunctionCallData; 341 CallType castFunctionCallType = getCallData(castFunction, castFunctionCallData); 342 if (castFunctionCallType == CallTypeNone) { 343 throwTypeError(exec); 344 return JSValue::encode(abruptRejection(exec, deferred)); 345 } 346 347 MarkedArgumentBuffer castFunctionArguments; 348 castFunctionArguments.append(next); 349 JSValue nextPromise = call(exec, castFunction, castFunctionCallType, castFunctionCallData, C, castFunctionArguments); 350 351 // vii. RejectIfAbrupt(nextPromise, deferred). 352 if (exec->hadException()) 353 return JSValue::encode(abruptRejection(exec, deferred)); 354 355 // viii. Let 'result' be the result of calling Invoke(nextPromise, "then", (deferred.[[Resolve]], deferred.[[Reject]])). 356 JSValue thenFunction = nextPromise.get(exec, vm.propertyNames->then); 357 if (exec->hadException()) 358 return JSValue::encode(abruptRejection(exec, deferred)); 359 360 CallData thenFunctionCallData; 361 CallType thenFunctionCallType = getCallData(thenFunction, thenFunctionCallData); 362 if (thenFunctionCallType == CallTypeNone) { 363 throwTypeError(exec); 364 return JSValue::encode(abruptRejection(exec, deferred)); 365 } 366 367 MarkedArgumentBuffer thenFunctionArguments; 368 thenFunctionArguments.append(deferred->resolve()); 369 thenFunctionArguments.append(deferred->reject()); 370 371 call(exec, thenFunction, thenFunctionCallType, thenFunctionCallData, nextPromise, thenFunctionArguments); 372 373 // ix. RejectIfAbrupt(result, deferred). 374 if (exec->hadException()) 375 return JSValue::encode(abruptRejection(exec, deferred)); 376 } while (true); 377} 378 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 540JSPromise* constructPromise(ExecState* exec, JSGlobalObject* globalObject, JSFunction* resolver) 541{ 542 JSPromiseConstructor* promiseConstructor = globalObject->promiseConstructor(); 543 544 ConstructData constructData; 545 ConstructType constructType = getConstructData(promiseConstructor, constructData); 546 ASSERT(constructType != ConstructTypeNone); 547 548 MarkedArgumentBuffer arguments; 549 arguments.append(resolver); 550 551 return jsCast<JSPromise*>(construct(exec, promiseConstructor, constructType, constructData, arguments)); 552} 553 554} // namespace JSC 555 556#endif // ENABLE(PROMISES) 557