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 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
162 } | 162 } |
163 PromiseSet(promise, status, value); | 163 PromiseSet(promise, status, value); |
164 } | 164 } |
165 } | 165 } |
166 | 166 |
167 function PromiseHandle(value, handler, deferred) { | 167 function PromiseHandle(value, handler, deferred) { |
168 var debug_is_active = DEBUG_IS_ACTIVE; | 168 var debug_is_active = DEBUG_IS_ACTIVE; |
169 try { | 169 try { |
170 if (debug_is_active) %DebugPushPromise(deferred.promise); | 170 if (debug_is_active) %DebugPushPromise(deferred.promise); |
171 var result = handler(value); | 171 var result = handler(value); |
172 deferred.resolve(result); | 172 if (deferred.resolve) { deferred.resolve(result); } |
173 else { ResolvePromise(deferred.promise, result); } | |
173 } %catch (exception) { // Natives syntax to mark this catch block. | 174 } %catch (exception) { // Natives syntax to mark this catch block. |
174 try { deferred.reject(exception); } catch (e) { } | 175 try { |
176 if (deferred.reject) { deferred.reject(exception); } | |
177 else { RejectPromise(deferred.promise, exception, false); } | |
178 } catch (e) { } | |
175 } finally { | 179 } finally { |
176 if (debug_is_active) %DebugPopPromise(); | 180 if (debug_is_active) %DebugPopPromise(); |
177 } | 181 } |
178 } | 182 } |
179 | 183 |
180 function PromiseEnqueue(value, tasks, deferreds, status) { | 184 function PromiseEnqueue(value, tasks, deferreds, status) { |
181 var id, name, instrumenting = DEBUG_IS_ACTIVE; | 185 var id, name, instrumenting = DEBUG_IS_ACTIVE; |
182 %EnqueueMicrotask(function() { | 186 %EnqueueMicrotask(function() { |
183 if (instrumenting) { | 187 if (instrumenting) { |
184 %DebugAsyncTaskEvent({ type: "willHandle", id: id, name: name }); | 188 %DebugAsyncTaskEvent({ type: "willHandle", id: id, name: name }); |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
362 | 366 |
363 // Export to bindings | 367 // Export to bindings |
364 function DoRejectPromise(promise, reason) { | 368 function DoRejectPromise(promise, reason) { |
365 return RejectPromise(promise, reason, true); | 369 return RejectPromise(promise, reason, true); |
366 } | 370 } |
367 | 371 |
368 // ES#sec-newpromisecapability | 372 // ES#sec-newpromisecapability |
369 // NewPromiseCapability ( C ) | 373 // NewPromiseCapability ( C ) |
370 function NewPromiseCapability(C, debugEvent) { | 374 function NewPromiseCapability(C, debugEvent) { |
371 if (C === GlobalPromise) { | 375 if (C === GlobalPromise) { |
372 // Optimized case, avoid extra closure. | |
373 var promise = PromiseCreate(); | |
374 var callbacks = CreateResolvingFunctions(promise, debugEvent); | |
375 return { | 376 return { |
376 promise: promise, | 377 promise: PromiseCreate(), |
377 resolve: callbacks.resolve, | 378 resolve: false, |
378 reject: callbacks.reject | 379 reject: false, |
379 }; | 380 }; |
380 } | 381 } |
381 | 382 |
382 var result = {promise: UNDEFINED, resolve: UNDEFINED, reject: UNDEFINED }; | 383 var result = {promise: UNDEFINED, resolve: UNDEFINED, reject: UNDEFINED }; |
383 result.promise = new C((resolve, reject) => { | 384 result.promise = new C((resolve, reject) => { |
384 if (!IS_UNDEFINED(result.resolve) || !IS_UNDEFINED(result.reject)) | 385 if (!IS_UNDEFINED(result.resolve) || !IS_UNDEFINED(result.reject)) |
385 throw %make_type_error(kPromiseExecutorAlreadyInvoked); | 386 throw %make_type_error(kPromiseExecutorAlreadyInvoked); |
386 result.resolve = resolve; | 387 result.resolve = resolve; |
387 result.reject = reject; | 388 result.reject = reject; |
388 }); | 389 }); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
467 // Combinators. | 468 // Combinators. |
468 | 469 |
469 // ES#sec-promise.resolve | 470 // ES#sec-promise.resolve |
470 // Promise.resolve ( x ) | 471 // Promise.resolve ( x ) |
471 function PromiseResolve(x) { | 472 function PromiseResolve(x) { |
472 if (!IS_RECEIVER(this)) { | 473 if (!IS_RECEIVER(this)) { |
473 throw %make_type_error(kCalledOnNonObject, PromiseResolve); | 474 throw %make_type_error(kCalledOnNonObject, PromiseResolve); |
474 } | 475 } |
475 if (IsPromise(x) && x.constructor === this) return x; | 476 if (IsPromise(x) && x.constructor === this) return x; |
476 | 477 |
477 // Avoid creating resolving functions. | 478 // debugEvent is not so meaningful here as it will be resolved |
479 var promiseCapability = NewPromiseCapability(this, true); | |
480 | |
478 if (this === GlobalPromise) { | 481 if (this === GlobalPromise) { |
479 var promise = PromiseCreate(); | 482 ResolvePromise(promiseCapability.promise, x); |
480 var resolveResult = ResolvePromise(promise, x); | 483 } else { |
481 return promise; | 484 %_Call(promiseCapability.resolve, UNDEFINED, x); |
482 } | 485 } |
483 | 486 |
484 // debugEvent is not so meaningful here as it will be resolved | |
485 var promiseCapability = NewPromiseCapability(this, true); | |
486 var resolveResult = %_Call(promiseCapability.resolve, UNDEFINED, x); | |
487 return promiseCapability.promise; | 487 return promiseCapability.promise; |
488 } | 488 } |
489 | 489 |
490 // ES#sec-promise.all | 490 // ES#sec-promise.all |
491 // Promise.all ( iterable ) | 491 // Promise.all ( iterable ) |
492 function PromiseAll(iterable) { | 492 function PromiseAll(iterable) { |
493 if (!IS_RECEIVER(this)) { | 493 if (!IS_RECEIVER(this)) { |
494 throw %make_type_error(kCalledOnNonObject, "Promise.all"); | 494 throw %make_type_error(kCalledOnNonObject, "Promise.all"); |
495 } | 495 } |
496 | 496 |
497 // false debugEvent so that forwarding the rejection through all does not | 497 // false debugEvent so that forwarding the rejection through all does not |
498 // trigger redundant ExceptionEvents | 498 // trigger redundant ExceptionEvents |
499 var deferred = NewPromiseCapability(this, false); | 499 var deferred = NewPromiseCapability(this, false); |
500 if (this === GlobalPromise) { | |
501 var callbacks = CreateResolvingFunctions(deferred.promise, false); | |
502 deferred.resolve = callbacks.resolve; | |
503 deferred.reject = callbacks.reject; | |
504 } | |
500 var resolutions = new InternalArray(); | 505 var resolutions = new InternalArray(); |
501 var count; | 506 var count; |
502 | 507 |
503 // For catch prediction, don't treat the .then calls as handling it; | 508 // For catch prediction, don't treat the .then calls as handling it; |
504 // instead, recurse outwards. | 509 // instead, recurse outwards. |
505 var instrumenting = DEBUG_IS_ACTIVE; | 510 var instrumenting = DEBUG_IS_ACTIVE; |
506 if (instrumenting) { | 511 if (instrumenting) { |
507 SET_PRIVATE(deferred.reject, promiseForwardingHandlerSymbol, true); | 512 SET_PRIVATE(deferred.reject, promiseForwardingHandlerSymbol, true); |
508 } | 513 } |
509 | 514 |
510 function CreateResolveElementFunction(index, values, promiseCapability) { | 515 function CreateResolveElementFunction(index, values, promiseCapability) { |
511 var alreadyCalled = false; | 516 var alreadyCalled = false; |
512 return (x) => { | 517 return function(x) { |
513 if (alreadyCalled === true) return; | 518 if (alreadyCalled === true) return; |
514 alreadyCalled = true; | 519 alreadyCalled = true; |
515 values[index] = x; | 520 values[index] = x; |
516 if (--count === 0) { | 521 if (--count === 0) { |
517 var valuesArray = []; | 522 var valuesArray = []; |
518 %MoveArrayContents(values, valuesArray); | 523 %MoveArrayContents(values, valuesArray); |
519 %_Call(promiseCapability.resolve, UNDEFINED, valuesArray); | 524 %_Call(promiseCapability.resolve, UNDEFINED, valuesArray); |
520 } | 525 } |
521 }; | 526 }; |
522 } | 527 } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
554 // ES#sec-promise.race | 559 // ES#sec-promise.race |
555 // Promise.race ( iterable ) | 560 // Promise.race ( iterable ) |
556 function PromiseRace(iterable) { | 561 function PromiseRace(iterable) { |
557 if (!IS_RECEIVER(this)) { | 562 if (!IS_RECEIVER(this)) { |
558 throw %make_type_error(kCalledOnNonObject, PromiseRace); | 563 throw %make_type_error(kCalledOnNonObject, PromiseRace); |
559 } | 564 } |
560 | 565 |
561 // false debugEvent so that forwarding the rejection through race does not | 566 // false debugEvent so that forwarding the rejection through race does not |
562 // trigger redundant ExceptionEvents | 567 // trigger redundant ExceptionEvents |
563 var deferred = NewPromiseCapability(this, false); | 568 var deferred = NewPromiseCapability(this, false); |
569 if (this === GlobalPromise) { | |
570 var callbacks = CreateResolvingFunctions(deferred.promise, false); | |
adamk
2016/10/05 20:18:09
Ah, I didn't realize some callers need the callbac
| |
571 deferred.resolve = callbacks.resolve; | |
572 deferred.reject = callbacks.reject; | |
573 } | |
564 | 574 |
565 // For catch prediction, don't treat the .then calls as handling it; | 575 // For catch prediction, don't treat the .then calls as handling it; |
566 // instead, recurse outwards. | 576 // instead, recurse outwards. |
567 var instrumenting = DEBUG_IS_ACTIVE; | 577 var instrumenting = DEBUG_IS_ACTIVE; |
568 if (instrumenting) { | 578 if (instrumenting) { |
569 SET_PRIVATE(deferred.reject, promiseForwardingHandlerSymbol, true); | 579 SET_PRIVATE(deferred.reject, promiseForwardingHandlerSymbol, true); |
570 } | 580 } |
571 | 581 |
572 try { | 582 try { |
573 for (var value of iterable) { | 583 for (var value of iterable) { |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
696 to.PromiseNextMicrotaskID = PromiseNextMicrotaskID; | 706 to.PromiseNextMicrotaskID = PromiseNextMicrotaskID; |
697 | 707 |
698 to.GlobalPromise = GlobalPromise; | 708 to.GlobalPromise = GlobalPromise; |
699 to.NewPromiseCapability = NewPromiseCapability; | 709 to.NewPromiseCapability = NewPromiseCapability; |
700 to.PerformPromiseThen = PerformPromiseThen; | 710 to.PerformPromiseThen = PerformPromiseThen; |
701 to.ResolvePromise = ResolvePromise; | 711 to.ResolvePromise = ResolvePromise; |
702 to.RejectPromise = RejectPromise; | 712 to.RejectPromise = RejectPromise; |
703 }); | 713 }); |
704 | 714 |
705 }) | 715 }) |
OLD | NEW |