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 |