]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/JSPromiseConstructor.cpp
JavaScriptCore-7600.1.4.9.tar.gz
[apple/javascriptcore.git] / runtime / JSPromiseConstructor.cpp
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
42 namespace JSC {
43
44 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSPromiseConstructor);
45
46 static EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncCast(ExecState*);
47 static EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncResolve(ExecState*);
48 static EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncReject(ExecState*);
49 static EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncRace(ExecState*);
50 static EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncAll(ExecState*);
51 }
52
53 #include "JSPromiseConstructor.lut.h"
54
55 namespace JSC {
56
57 const 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
69 JSPromiseConstructor* 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
76 Structure* JSPromiseConstructor::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
77 {
78 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
79 }
80
81 JSPromiseConstructor::JSPromiseConstructor(VM& vm, Structure* structure)
82 : InternalFunction(vm, structure)
83 {
84 }
85
86 void 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
93 static 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
150 ConstructType JSPromiseConstructor::getConstructData(JSCell*, ConstructData& constructData)
151 {
152 constructData.native.function = constructPromise;
153 return ConstructTypeHost;
154 }
155
156 CallType JSPromiseConstructor::getCallData(JSCell*, CallData& callData)
157 {
158 callData.native.function = constructPromise;
159 return CallTypeHost;
160 }
161
162 bool 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
167 EncodedJSValue 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
207 EncodedJSValue 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
237 EncodedJSValue 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
267 EncodedJSValue 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
379 EncodedJSValue 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
540 JSPromise* 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)