OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 (function(global, utils, extrasUtils) { | 5 (function(global, utils, extrasUtils) { |
6 | 6 |
7 "use strict"; | 7 "use strict"; |
8 | 8 |
9 %CheckIsBootstrapping(); | 9 %CheckIsBootstrapping(); |
10 | 10 |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 | 173 |
174 function PromiseIdResolveHandler(x) { return x; } | 174 function PromiseIdResolveHandler(x) { return x; } |
175 function PromiseIdRejectHandler(r) { %_ReThrow(r); } | 175 function PromiseIdRejectHandler(r) { %_ReThrow(r); } |
176 SET_PRIVATE(PromiseIdRejectHandler, promiseForwardingHandlerSymbol, true); | 176 SET_PRIVATE(PromiseIdRejectHandler, promiseForwardingHandlerSymbol, true); |
177 | 177 |
178 // ------------------------------------------------------------------- | 178 // ------------------------------------------------------------------- |
179 // Define exported functions. | 179 // Define exported functions. |
180 | 180 |
181 // For bootstrapper. | 181 // For bootstrapper. |
182 | 182 |
183 // Only used by utils | |
184 // ES#sec-ispromise IsPromise ( x ) | |
185 function IsPromise(x) { | |
186 return IS_RECEIVER(x) && HAS_DEFINED_PRIVATE(x, promiseStateSymbol); | |
187 } | |
188 | |
189 function PromiseCreate() { | 183 function PromiseCreate() { |
190 return PromiseInit(%promise_internal_constructor()); | 184 return PromiseInit(%promise_internal_constructor()); |
191 } | 185 } |
192 | 186 |
193 // ES#sec-promise-resolve-functions | 187 // ES#sec-promise-resolve-functions |
194 // Promise Resolve Functions, steps 6-13 | 188 // Promise Resolve Functions, steps 6-13 |
195 function ResolvePromise(promise, resolution) { | 189 function ResolvePromise(promise, resolution) { |
196 if (resolution === promise) { | 190 if (resolution === promise) { |
197 var exception = %make_type_error(kPromiseCyclic, resolution); | 191 var exception = %make_type_error(kPromiseCyclic, resolution); |
198 %PromiseReject(promise, exception, true); | 192 %PromiseReject(promise, exception, true); |
199 PromiseSet(promise, kRejected, exception); | 193 PromiseSet(promise, kRejected, exception); |
200 return; | 194 return; |
201 } | 195 } |
202 if (IS_RECEIVER(resolution)) { | 196 if (IS_RECEIVER(resolution)) { |
203 // 25.4.1.3.2 steps 8-12 | 197 // 25.4.1.3.2 steps 8-12 |
204 try { | 198 try { |
205 var then = resolution.then; | 199 var then = resolution.then; |
206 } catch (e) { | 200 } catch (e) { |
207 %PromiseReject(promise, e, true); | 201 %PromiseReject(promise, e, true); |
208 PromiseSet(promise, kRejected, e); | 202 PromiseSet(promise, kRejected, e); |
209 return; | 203 return; |
210 } | 204 } |
211 | 205 |
212 // Resolution is a native promise and if it's already resolved or | 206 // Resolution is a native promise and if it's already resolved or |
213 // rejected, shortcircuit the resolution procedure by directly | 207 // rejected, shortcircuit the resolution procedure by directly |
214 // reusing the value from the promise. | 208 // reusing the value from the promise. |
215 if (IsPromise(resolution) && then === PromiseThen) { | 209 if (%is_promise(resolution) && then === PromiseThen) { |
216 var thenableState = GET_PRIVATE(resolution, promiseStateSymbol); | 210 var thenableState = GET_PRIVATE(resolution, promiseStateSymbol); |
217 if (thenableState === kFulfilled) { | 211 if (thenableState === kFulfilled) { |
218 // This goes inside the if-else to save one symbol lookup in | 212 // This goes inside the if-else to save one symbol lookup in |
219 // the slow path. | 213 // the slow path. |
220 var thenableValue = GET_PRIVATE(resolution, promiseResultSymbol); | 214 var thenableValue = GET_PRIVATE(resolution, promiseResultSymbol); |
221 %PromiseFulfill(promise, kFulfilled, thenableValue, | 215 %PromiseFulfill(promise, kFulfilled, thenableValue, |
222 promiseFulfillReactionsSymbol); | 216 promiseFulfillReactionsSymbol); |
223 PromiseSet(promise, kFulfilled, thenableValue); | 217 PromiseSet(promise, kFulfilled, thenableValue); |
224 SET_PRIVATE(promise, promiseHasHandlerSymbol, true); | 218 SET_PRIVATE(promise, promiseHasHandlerSymbol, true); |
225 return; | 219 return; |
226 } else if (thenableState === kRejected) { | 220 } else if (thenableState === kRejected) { |
227 var thenableValue = GET_PRIVATE(resolution, promiseResultSymbol); | 221 var thenableValue = GET_PRIVATE(resolution, promiseResultSymbol); |
228 if (!HAS_DEFINED_PRIVATE(resolution, promiseHasHandlerSymbol)) { | 222 if (!HAS_DEFINED_PRIVATE(resolution, promiseHasHandlerSymbol)) { |
229 // Promise has already been rejected, but had no handler. | 223 // Promise has already been rejected, but had no handler. |
230 // Revoke previously triggered reject event. | 224 // Revoke previously triggered reject event. |
231 %PromiseRevokeReject(resolution); | 225 %PromiseRevokeReject(resolution); |
232 } | 226 } |
233 // Don't cause a debug event as this case is forwarding a rejection | 227 // Don't cause a debug event as this case is forwarding a rejection |
234 %PromiseReject(promise, thenableValue, false); | 228 %PromiseReject(promise, thenableValue, false); |
235 PromiseSet(promise, kRejected, thenableValue); | 229 PromiseSet(promise, kRejected, thenableValue); |
236 SET_PRIVATE(resolution, promiseHasHandlerSymbol, true); | 230 SET_PRIVATE(resolution, promiseHasHandlerSymbol, true); |
237 return; | 231 return; |
238 } | 232 } |
239 } | 233 } |
240 | 234 |
241 if (IS_CALLABLE(then)) { | 235 if (IS_CALLABLE(then)) { |
242 if (DEBUG_IS_ACTIVE && IsPromise(resolution)) { | 236 if (DEBUG_IS_ACTIVE && %is_promise(resolution)) { |
243 // Mark the dependency of the new promise on the resolution | 237 // Mark the dependency of the new promise on the resolution |
244 SET_PRIVATE(resolution, promiseHandledBySymbol, promise); | 238 SET_PRIVATE(resolution, promiseHandledBySymbol, promise); |
245 } | 239 } |
246 %EnqueuePromiseResolveThenableJob(promise, resolution, then); | 240 %EnqueuePromiseResolveThenableJob(promise, resolution, then); |
247 return; | 241 return; |
248 } | 242 } |
249 } | 243 } |
250 %PromiseFulfill(promise, kFulfilled, resolution, | 244 %PromiseFulfill(promise, kFulfilled, resolution, |
251 promiseFulfillReactionsSymbol); | 245 promiseFulfillReactionsSymbol); |
252 PromiseSet(promise, kFulfilled, resolution); | 246 PromiseSet(promise, kFulfilled, resolution); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 | 345 |
352 // Mark this promise as having handler. | 346 // Mark this promise as having handler. |
353 SET_PRIVATE(promise, promiseHasHandlerSymbol, true); | 347 SET_PRIVATE(promise, promiseHasHandlerSymbol, true); |
354 return resultCapability.promise; | 348 return resultCapability.promise; |
355 } | 349 } |
356 | 350 |
357 // ES#sec-promise.prototype.then | 351 // ES#sec-promise.prototype.then |
358 // Promise.prototype.then ( onFulfilled, onRejected ) | 352 // Promise.prototype.then ( onFulfilled, onRejected ) |
359 // Multi-unwrapped chaining with thenable coercion. | 353 // Multi-unwrapped chaining with thenable coercion. |
360 function PromiseThen(onResolve, onReject) { | 354 function PromiseThen(onResolve, onReject) { |
361 if (!IsPromise(this)) { | 355 if (!%is_promise(this)) { |
362 throw %make_type_error(kNotAPromise, this); | 356 throw %make_type_error(kNotAPromise, this); |
363 } | 357 } |
364 | 358 |
365 var constructor = SpeciesConstructor(this, GlobalPromise); | 359 var constructor = SpeciesConstructor(this, GlobalPromise); |
366 var resultCapability; | 360 var resultCapability; |
367 if (constructor === GlobalPromise) { | 361 if (constructor === GlobalPromise) { |
368 resultCapability = CreateInternalPromiseCapability(); | 362 resultCapability = CreateInternalPromiseCapability(); |
369 } else { | 363 } else { |
370 // Pass false for debugEvent so .then chaining does not trigger | 364 // Pass false for debugEvent so .then chaining does not trigger |
371 // redundant ExceptionEvents. | 365 // redundant ExceptionEvents. |
372 resultCapability = NewPromiseCapability(constructor, false); | 366 resultCapability = NewPromiseCapability(constructor, false); |
373 } | 367 } |
374 return PerformPromiseThen(this, onResolve, onReject, resultCapability); | 368 return PerformPromiseThen(this, onResolve, onReject, resultCapability); |
375 } | 369 } |
376 | 370 |
377 // ES#sec-promise.prototype.catch | 371 // ES#sec-promise.prototype.catch |
378 // Promise.prototype.catch ( onRejected ) | 372 // Promise.prototype.catch ( onRejected ) |
379 function PromiseCatch(onReject) { | 373 function PromiseCatch(onReject) { |
380 return this.then(UNDEFINED, onReject); | 374 return this.then(UNDEFINED, onReject); |
381 } | 375 } |
382 | 376 |
383 // Combinators. | 377 // Combinators. |
384 | 378 |
385 // ES#sec-promise.resolve | 379 // ES#sec-promise.resolve |
386 // Promise.resolve ( x ) | 380 // Promise.resolve ( x ) |
387 function PromiseResolve(x) { | 381 function PromiseResolve(x) { |
388 if (!IS_RECEIVER(this)) { | 382 if (!IS_RECEIVER(this)) { |
389 throw %make_type_error(kCalledOnNonObject, PromiseResolve); | 383 throw %make_type_error(kCalledOnNonObject, PromiseResolve); |
390 } | 384 } |
391 if (IsPromise(x) && x.constructor === this) return x; | 385 if (%is_promise(x) && x.constructor === this) return x; |
392 | 386 |
393 // Avoid creating resolving functions. | 387 // Avoid creating resolving functions. |
394 if (this === GlobalPromise) { | 388 if (this === GlobalPromise) { |
395 var promise = PromiseCreate(); | 389 var promise = PromiseCreate(); |
396 ResolvePromise(promise, x); | 390 ResolvePromise(promise, x); |
397 return promise; | 391 return promise; |
398 } | 392 } |
399 | 393 |
400 // debugEvent is not so meaningful here as it will be resolved | 394 // debugEvent is not so meaningful here as it will be resolved |
401 var promiseCapability = NewPromiseCapability(this, true); | 395 var promiseCapability = NewPromiseCapability(this, true); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
441 var i = 0; | 435 var i = 0; |
442 count = 1; | 436 count = 1; |
443 for (var value of iterable) { | 437 for (var value of iterable) { |
444 var nextPromise = this.resolve(value); | 438 var nextPromise = this.resolve(value); |
445 ++count; | 439 ++count; |
446 var throwawayPromise = nextPromise.then( | 440 var throwawayPromise = nextPromise.then( |
447 CreateResolveElementFunction(i, resolutions, deferred), | 441 CreateResolveElementFunction(i, resolutions, deferred), |
448 deferred.reject); | 442 deferred.reject); |
449 // For catch prediction, mark that rejections here are semantically | 443 // For catch prediction, mark that rejections here are semantically |
450 // handled by the combined Promise. | 444 // handled by the combined Promise. |
451 if (instrumenting && IsPromise(throwawayPromise)) { | 445 if (instrumenting && %is_promise(throwawayPromise)) { |
452 SET_PRIVATE(throwawayPromise, promiseHandledBySymbol, deferred.promise); | 446 SET_PRIVATE(throwawayPromise, promiseHandledBySymbol, deferred.promise); |
453 } | 447 } |
454 ++i; | 448 ++i; |
455 } | 449 } |
456 | 450 |
457 // 6.d | 451 // 6.d |
458 if (--count === 0) { | 452 if (--count === 0) { |
459 var valuesArray = []; | 453 var valuesArray = []; |
460 %MoveArrayContents(resolutions, valuesArray); | 454 %MoveArrayContents(resolutions, valuesArray); |
461 %_Call(deferred.resolve, UNDEFINED, valuesArray); | 455 %_Call(deferred.resolve, UNDEFINED, valuesArray); |
(...skipping 22 matching lines...) Expand all Loading... |
484 if (instrumenting) { | 478 if (instrumenting) { |
485 SET_PRIVATE(deferred.reject, promiseForwardingHandlerSymbol, true); | 479 SET_PRIVATE(deferred.reject, promiseForwardingHandlerSymbol, true); |
486 } | 480 } |
487 | 481 |
488 try { | 482 try { |
489 for (var value of iterable) { | 483 for (var value of iterable) { |
490 var throwawayPromise = this.resolve(value).then(deferred.resolve, | 484 var throwawayPromise = this.resolve(value).then(deferred.resolve, |
491 deferred.reject); | 485 deferred.reject); |
492 // For catch prediction, mark that rejections here are semantically | 486 // For catch prediction, mark that rejections here are semantically |
493 // handled by the combined Promise. | 487 // handled by the combined Promise. |
494 if (instrumenting && IsPromise(throwawayPromise)) { | 488 if (instrumenting && %is_promise(throwawayPromise)) { |
495 SET_PRIVATE(throwawayPromise, promiseHandledBySymbol, deferred.promise); | 489 SET_PRIVATE(throwawayPromise, promiseHandledBySymbol, deferred.promise); |
496 } | 490 } |
497 } | 491 } |
498 } catch (e) { | 492 } catch (e) { |
499 %_Call(deferred.reject, UNDEFINED, e); | 493 %_Call(deferred.reject, UNDEFINED, e); |
500 } | 494 } |
501 return deferred.promise; | 495 return deferred.promise; |
502 } | 496 } |
503 | 497 |
504 | 498 |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
604 // resolve/reject closures, and allows them to later resolve and reject any | 598 // resolve/reject closures, and allows them to later resolve and reject any |
605 // promise without having to hold on to those closures forever. | 599 // promise without having to hold on to those closures forever. |
606 utils.InstallFunctions(extrasUtils, 0, [ | 600 utils.InstallFunctions(extrasUtils, 0, [ |
607 "createPromise", PromiseCreate, | 601 "createPromise", PromiseCreate, |
608 "resolvePromise", ResolvePromise, | 602 "resolvePromise", ResolvePromise, |
609 "rejectPromise", DoRejectPromise, | 603 "rejectPromise", DoRejectPromise, |
610 "markPromiseAsHandled", MarkPromiseAsHandled | 604 "markPromiseAsHandled", MarkPromiseAsHandled |
611 ]); | 605 ]); |
612 | 606 |
613 utils.Export(function(to) { | 607 utils.Export(function(to) { |
614 to.IsPromise = IsPromise; | |
615 to.PromiseCreate = PromiseCreate; | 608 to.PromiseCreate = PromiseCreate; |
616 to.PromiseThen = PromiseThen; | 609 to.PromiseThen = PromiseThen; |
617 | 610 |
618 to.CreateInternalPromiseCapability = CreateInternalPromiseCapability; | 611 to.CreateInternalPromiseCapability = CreateInternalPromiseCapability; |
619 to.PerformPromiseThen = PerformPromiseThen; | 612 to.PerformPromiseThen = PerformPromiseThen; |
620 to.ResolvePromise = ResolvePromise; | 613 to.ResolvePromise = ResolvePromise; |
621 to.RejectPromise = RejectPromise; | 614 to.RejectPromise = RejectPromise; |
622 }); | 615 }); |
623 | 616 |
624 }) | 617 }) |
OLD | NEW |