| 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 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 } | 139 } |
| 140 | 140 |
| 141 function PromiseInit(promise) { | 141 function PromiseInit(promise) { |
| 142 return PromiseSet(promise, kPending, UNDEFINED); | 142 return PromiseSet(promise, kPending, UNDEFINED); |
| 143 } | 143 } |
| 144 | 144 |
| 145 function FulfillPromise(promise, status, value, promiseQueue) { | 145 function FulfillPromise(promise, status, value, promiseQueue) { |
| 146 var tasks = GET_PRIVATE(promise, promiseQueue); | 146 var tasks = GET_PRIVATE(promise, promiseQueue); |
| 147 if (!IS_UNDEFINED(tasks)) { | 147 if (!IS_UNDEFINED(tasks)) { |
| 148 var deferred = GET_PRIVATE(promise, promiseDeferredReactionSymbol); | 148 var deferred = GET_PRIVATE(promise, promiseDeferredReactionSymbol); |
| 149 PromiseEnqueue(value, tasks, deferred, status); | 149 %EnqueuePromiseReactionJob(value, tasks, deferred, status); |
| 150 } | 150 } |
| 151 PromiseSet(promise, status, value); | 151 PromiseSet(promise, status, value); |
| 152 } | 152 } |
| 153 | 153 |
| 154 function PromiseHandle(value, handler, deferred) { | 154 function PromiseHandle(value, handler, deferred) { |
| 155 var debug_is_active = DEBUG_IS_ACTIVE; | 155 var debug_is_active = DEBUG_IS_ACTIVE; |
| 156 try { | 156 try { |
| 157 if (debug_is_active) %DebugPushPromise(deferred.promise); | 157 if (debug_is_active) %DebugPushPromise(deferred.promise); |
| 158 var result = handler(value); | 158 var result = handler(value); |
| 159 if (IS_UNDEFINED(deferred.resolve)) { | 159 if (IS_UNDEFINED(deferred.resolve)) { |
| 160 ResolvePromise(deferred.promise, result); | 160 ResolvePromise(deferred.promise, result); |
| 161 } else { | 161 } else { |
| 162 %_Call(deferred.resolve, UNDEFINED, result); | 162 %_Call(deferred.resolve, UNDEFINED, result); |
| 163 } | 163 } |
| 164 } %catch (exception) { // Natives syntax to mark this catch block. | 164 } %catch (exception) { // Natives syntax to mark this catch block. |
| 165 try { | 165 try { |
| 166 if (IS_UNDEFINED(deferred.reject)) { | 166 if (IS_UNDEFINED(deferred.reject)) { |
| 167 // Pass false for debugEvent so .then chaining does not trigger | 167 // Pass false for debugEvent so .then chaining does not trigger |
| 168 // redundant ExceptionEvents. | 168 // redundant ExceptionEvents. |
| 169 RejectPromise(deferred.promise, exception, false); | 169 RejectPromise(deferred.promise, exception, false); |
| 170 } else { | 170 } else { |
| 171 %_Call(deferred.reject, UNDEFINED, exception); | 171 %_Call(deferred.reject, UNDEFINED, exception); |
| 172 } | 172 } |
| 173 } catch (e) { } | 173 } catch (e) { } |
| 174 } finally { | 174 } finally { |
| 175 if (debug_is_active) %DebugPopPromise(); | 175 if (debug_is_active) %DebugPopPromise(); |
| 176 } | 176 } |
| 177 } | 177 } |
| 178 | 178 |
| 179 function PromiseEnqueue(value, tasks, deferreds, status) { | 179 function PromiseDebugGetInfo(deferreds, status) { |
| 180 var id, name, instrumenting = DEBUG_IS_ACTIVE; | 180 var id, name, instrumenting = DEBUG_IS_ACTIVE; |
| 181 | 181 |
| 182 if (instrumenting) { | 182 if (instrumenting) { |
| 183 // In an async function, reuse the existing stack related to the outer | 183 // In an async function, reuse the existing stack related to the outer |
| 184 // Promise. Otherwise, e.g. in a direct call to then, save a new stack. | 184 // Promise. Otherwise, e.g. in a direct call to then, save a new stack. |
| 185 // Promises with multiple reactions with one or more of them being async | 185 // Promises with multiple reactions with one or more of them being async |
| 186 // functions will not get a good stack trace, as async functions require | 186 // functions will not get a good stack trace, as async functions require |
| 187 // different stacks from direct Promise use, but we save and restore a | 187 // different stacks from direct Promise use, but we save and restore a |
| 188 // stack once for all reactions. TODO(littledan): Improve this case. | 188 // stack once for all reactions. TODO(littledan): Improve this case. |
| 189 if (!IS_UNDEFINED(deferreds) && | 189 if (!IS_UNDEFINED(deferreds) && |
| 190 HAS_PRIVATE(deferreds.promise, promiseHandledBySymbol) && | 190 HAS_PRIVATE(deferreds.promise, promiseHandledBySymbol) && |
| 191 HAS_PRIVATE(GET_PRIVATE(deferreds.promise, promiseHandledBySymbol), | 191 HAS_PRIVATE(GET_PRIVATE(deferreds.promise, promiseHandledBySymbol), |
| 192 promiseAsyncStackIDSymbol)) { | 192 promiseAsyncStackIDSymbol)) { |
| 193 id = GET_PRIVATE(GET_PRIVATE(deferreds.promise, promiseHandledBySymbol), | 193 id = GET_PRIVATE(GET_PRIVATE(deferreds.promise, promiseHandledBySymbol), |
| 194 promiseAsyncStackIDSymbol); | 194 promiseAsyncStackIDSymbol); |
| 195 name = "async function"; | 195 name = "async function"; |
| 196 } else { | 196 } else { |
| 197 id = %DebugNextMicrotaskId(); | 197 id = %DebugNextMicrotaskId(); |
| 198 name = status === kFulfilled ? "Promise.resolve" : "Promise.reject"; | 198 name = status === kFulfilled ? "Promise.resolve" : "Promise.reject"; |
| 199 %DebugAsyncTaskEvent("enqueue", id, name); | 199 %DebugAsyncTaskEvent("enqueue", id, name); |
| 200 } | 200 } |
| 201 } | 201 } |
| 202 %EnqueuePromiseReactionJob(value, tasks, deferreds, id, name); | 202 return [id, name]; |
| 203 } | 203 } |
| 204 | 204 |
| 205 function PromiseAttachCallbacks(promise, deferred, onResolve, onReject) { | 205 function PromiseAttachCallbacks(promise, deferred, onResolve, onReject) { |
| 206 var maybeResolveCallbacks = | 206 var maybeResolveCallbacks = |
| 207 GET_PRIVATE(promise, promiseFulfillReactionsSymbol); | 207 GET_PRIVATE(promise, promiseFulfillReactionsSymbol); |
| 208 if (IS_UNDEFINED(maybeResolveCallbacks)) { | 208 if (IS_UNDEFINED(maybeResolveCallbacks)) { |
| 209 SET_PRIVATE(promise, promiseFulfillReactionsSymbol, onResolve); | 209 SET_PRIVATE(promise, promiseFulfillReactionsSymbol, onResolve); |
| 210 SET_PRIVATE(promise, promiseRejectReactionsSymbol, onReject); | 210 SET_PRIVATE(promise, promiseRejectReactionsSymbol, onReject); |
| 211 SET_PRIVATE(promise, promiseDeferredReactionSymbol, deferred); | 211 SET_PRIVATE(promise, promiseDeferredReactionSymbol, deferred); |
| 212 } else if (!IS_ARRAY(maybeResolveCallbacks)) { | 212 } else if (!IS_ARRAY(maybeResolveCallbacks)) { |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 381 function PerformPromiseThen(promise, onResolve, onReject, resultCapability) { | 381 function PerformPromiseThen(promise, onResolve, onReject, resultCapability) { |
| 382 if (!IS_CALLABLE(onResolve)) onResolve = PromiseIdResolveHandler; | 382 if (!IS_CALLABLE(onResolve)) onResolve = PromiseIdResolveHandler; |
| 383 if (!IS_CALLABLE(onReject)) onReject = PromiseIdRejectHandler; | 383 if (!IS_CALLABLE(onReject)) onReject = PromiseIdRejectHandler; |
| 384 | 384 |
| 385 var status = GET_PRIVATE(promise, promiseStateSymbol); | 385 var status = GET_PRIVATE(promise, promiseStateSymbol); |
| 386 switch (status) { | 386 switch (status) { |
| 387 case kPending: | 387 case kPending: |
| 388 PromiseAttachCallbacks(promise, resultCapability, onResolve, onReject); | 388 PromiseAttachCallbacks(promise, resultCapability, onResolve, onReject); |
| 389 break; | 389 break; |
| 390 case kFulfilled: | 390 case kFulfilled: |
| 391 PromiseEnqueue(GET_PRIVATE(promise, promiseResultSymbol), | 391 %EnqueuePromiseReactionJob(GET_PRIVATE(promise, promiseResultSymbol), |
| 392 onResolve, resultCapability, kFulfilled); | 392 onResolve, resultCapability, kFulfilled); |
| 393 break; | 393 break; |
| 394 case kRejected: | 394 case kRejected: |
| 395 if (!HAS_DEFINED_PRIVATE(promise, promiseHasHandlerSymbol)) { | 395 if (!HAS_DEFINED_PRIVATE(promise, promiseHasHandlerSymbol)) { |
| 396 // Promise has already been rejected, but had no handler. | 396 // Promise has already been rejected, but had no handler. |
| 397 // Revoke previously triggered reject event. | 397 // Revoke previously triggered reject event. |
| 398 %PromiseRevokeReject(promise); | 398 %PromiseRevokeReject(promise); |
| 399 } | 399 } |
| 400 PromiseEnqueue(GET_PRIVATE(promise, promiseResultSymbol), | 400 %EnqueuePromiseReactionJob(GET_PRIVATE(promise, promiseResultSymbol), |
| 401 onReject, resultCapability, kRejected); | 401 onReject, resultCapability, kRejected); |
| 402 break; | 402 break; |
| 403 } | 403 } |
| 404 | 404 |
| 405 // Mark this promise as having handler. | 405 // Mark this promise as having handler. |
| 406 SET_PRIVATE(promise, promiseHasHandlerSymbol, true); | 406 SET_PRIVATE(promise, promiseHasHandlerSymbol, true); |
| 407 return resultCapability.promise; | 407 return resultCapability.promise; |
| 408 } | 408 } |
| 409 | 409 |
| 410 // ES#sec-promise.prototype.then | 410 // ES#sec-promise.prototype.then |
| 411 // Promise.prototype.then ( onFulfilled, onRejected ) | 411 // Promise.prototype.then ( onFulfilled, onRejected ) |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 650 "catch", PromiseCatch | 650 "catch", PromiseCatch |
| 651 ]); | 651 ]); |
| 652 | 652 |
| 653 %InstallToContext([ | 653 %InstallToContext([ |
| 654 "promise_catch", PromiseCatch, | 654 "promise_catch", PromiseCatch, |
| 655 "promise_create", PromiseCreate, | 655 "promise_create", PromiseCreate, |
| 656 "promise_has_user_defined_reject_handler", PromiseHasUserDefinedRejectHandler, | 656 "promise_has_user_defined_reject_handler", PromiseHasUserDefinedRejectHandler, |
| 657 "promise_reject", DoRejectPromise, | 657 "promise_reject", DoRejectPromise, |
| 658 "promise_resolve", ResolvePromise, | 658 "promise_resolve", ResolvePromise, |
| 659 "promise_then", PromiseThen, | 659 "promise_then", PromiseThen, |
| 660 "promise_handle", PromiseHandle | 660 "promise_handle", PromiseHandle, |
| 661 "promise_debug_get_info", PromiseDebugGetInfo |
| 661 ]); | 662 ]); |
| 662 | 663 |
| 663 // This allows extras to create promises quickly without building extra | 664 // This allows extras to create promises quickly without building extra |
| 664 // resolve/reject closures, and allows them to later resolve and reject any | 665 // resolve/reject closures, and allows them to later resolve and reject any |
| 665 // promise without having to hold on to those closures forever. | 666 // promise without having to hold on to those closures forever. |
| 666 utils.InstallFunctions(extrasUtils, 0, [ | 667 utils.InstallFunctions(extrasUtils, 0, [ |
| 667 "createPromise", PromiseCreate, | 668 "createPromise", PromiseCreate, |
| 668 "resolvePromise", ResolvePromise, | 669 "resolvePromise", ResolvePromise, |
| 669 "rejectPromise", DoRejectPromise | 670 "rejectPromise", DoRejectPromise |
| 670 ]); | 671 ]); |
| 671 | 672 |
| 672 utils.Export(function(to) { | 673 utils.Export(function(to) { |
| 673 to.IsPromise = IsPromise; | 674 to.IsPromise = IsPromise; |
| 674 to.PromiseCreate = PromiseCreate; | 675 to.PromiseCreate = PromiseCreate; |
| 675 to.PromiseThen = PromiseThen; | 676 to.PromiseThen = PromiseThen; |
| 676 | 677 |
| 677 to.GlobalPromise = GlobalPromise; | 678 to.GlobalPromise = GlobalPromise; |
| 678 to.NewPromiseCapability = NewPromiseCapability; | 679 to.NewPromiseCapability = NewPromiseCapability; |
| 679 to.PerformPromiseThen = PerformPromiseThen; | 680 to.PerformPromiseThen = PerformPromiseThen; |
| 680 to.ResolvePromise = ResolvePromise; | 681 to.ResolvePromise = ResolvePromise; |
| 681 to.RejectPromise = RejectPromise; | 682 to.RejectPromise = RejectPromise; |
| 682 }); | 683 }); |
| 683 | 684 |
| 684 }) | 685 }) |
| OLD | NEW |