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 26 matching lines...) Expand all Loading... |
37 var ObjectHasOwnProperty; | 37 var ObjectHasOwnProperty; |
38 | 38 |
39 utils.Import(function(from) { | 39 utils.Import(function(from) { |
40 ObjectHasOwnProperty = from.ObjectHasOwnProperty; | 40 ObjectHasOwnProperty = from.ObjectHasOwnProperty; |
41 SpeciesConstructor = from.SpeciesConstructor; | 41 SpeciesConstructor = from.SpeciesConstructor; |
42 }); | 42 }); |
43 | 43 |
44 // ------------------------------------------------------------------- | 44 // ------------------------------------------------------------------- |
45 | 45 |
46 // [[PromiseState]] values: | 46 // [[PromiseState]] values: |
47 // These values should be kept in sync with PromiseStatus in globals.h | |
48 const kPending = 0; | 47 const kPending = 0; |
49 const kFulfilled = +1; | 48 const kFulfilled = +1; |
50 const kRejected = +2; | 49 const kRejected = -1; |
51 | 50 |
52 // ES#sec-createresolvingfunctions | 51 // ES#sec-createresolvingfunctions |
53 // CreateResolvingFunctions ( promise ) | 52 // CreateResolvingFunctions ( promise ) |
54 function CreateResolvingFunctions(promise, debugEvent) { | 53 function CreateResolvingFunctions(promise, debugEvent) { |
55 var alreadyResolved = false; | 54 var alreadyResolved = false; |
56 | 55 |
57 // ES#sec-promise-resolve-functions | 56 // ES#sec-promise-resolve-functions |
58 // Promise Resolve Functions | 57 // Promise Resolve Functions |
59 var resolve = value => { | 58 var resolve = value => { |
60 if (alreadyResolved === true) return; | 59 if (alreadyResolved === true) return; |
61 alreadyResolved = true; | 60 alreadyResolved = true; |
62 ResolvePromise(promise, value); | 61 ResolvePromise(promise, value); |
63 }; | 62 }; |
64 | 63 |
65 // ES#sec-promise-reject-functions | 64 // ES#sec-promise-reject-functions |
66 // Promise Reject Functions | 65 // Promise Reject Functions |
67 var reject = reason => { | 66 var reject = reason => { |
68 if (alreadyResolved === true) return; | 67 if (alreadyResolved === true) return; |
69 alreadyResolved = true; | 68 alreadyResolved = true; |
70 %PromiseReject(promise, reason, debugEvent); | 69 RejectPromise(promise, reason, debugEvent); |
71 PromiseSet(promise, kRejected, reason); | |
72 }; | 70 }; |
73 | 71 |
74 return { | 72 return { |
75 __proto__: null, | 73 __proto__: null, |
76 resolve: resolve, | 74 resolve: resolve, |
77 reject: reject | 75 reject: reject |
78 }; | 76 }; |
79 } | 77 } |
80 | 78 |
81 | 79 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 if (IS_UNDEFINED(deferred.resolve)) { | 150 if (IS_UNDEFINED(deferred.resolve)) { |
153 ResolvePromise(deferred.promise, result); | 151 ResolvePromise(deferred.promise, result); |
154 } else { | 152 } else { |
155 %_Call(deferred.resolve, UNDEFINED, result); | 153 %_Call(deferred.resolve, UNDEFINED, result); |
156 } | 154 } |
157 } %catch (exception) { // Natives syntax to mark this catch block. | 155 } %catch (exception) { // Natives syntax to mark this catch block. |
158 try { | 156 try { |
159 if (IS_UNDEFINED(deferred.reject)) { | 157 if (IS_UNDEFINED(deferred.reject)) { |
160 // Pass false for debugEvent so .then chaining does not trigger | 158 // Pass false for debugEvent so .then chaining does not trigger |
161 // redundant ExceptionEvents. | 159 // redundant ExceptionEvents. |
162 %PromiseReject(deferred.promise, exception, false); | 160 RejectPromise(deferred.promise, exception, false); |
163 PromiseSet(deferred.promise, kRejected, exception); | |
164 } else { | 161 } else { |
165 %_Call(deferred.reject, UNDEFINED, exception); | 162 %_Call(deferred.reject, UNDEFINED, exception); |
166 } | 163 } |
167 } catch (e) { } | 164 } catch (e) { } |
168 } finally { | 165 } finally { |
169 if (debug_is_active) %DebugPopPromise(); | 166 if (debug_is_active) %DebugPopPromise(); |
170 } | 167 } |
171 } | 168 } |
172 | 169 |
173 function PromiseDebugGetInfo(deferreds, status) { | 170 function PromiseDebugGetInfo(deferreds, status) { |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
239 } | 236 } |
240 | 237 |
241 function PromiseCreate() { | 238 function PromiseCreate() { |
242 return PromiseInit(new GlobalPromise(promiseRawSymbol)); | 239 return PromiseInit(new GlobalPromise(promiseRawSymbol)); |
243 } | 240 } |
244 | 241 |
245 // ES#sec-promise-resolve-functions | 242 // ES#sec-promise-resolve-functions |
246 // Promise Resolve Functions, steps 6-13 | 243 // Promise Resolve Functions, steps 6-13 |
247 function ResolvePromise(promise, resolution) { | 244 function ResolvePromise(promise, resolution) { |
248 if (resolution === promise) { | 245 if (resolution === promise) { |
249 var exception = %make_type_error(kPromiseCyclic, resolution); | 246 return RejectPromise(promise, |
250 %PromiseReject(promise, exception, true); | 247 %make_type_error(kPromiseCyclic, resolution), |
251 PromiseSet(promise, kRejected, exception); | 248 true); |
252 return; | |
253 } | 249 } |
254 if (IS_RECEIVER(resolution)) { | 250 if (IS_RECEIVER(resolution)) { |
255 // 25.4.1.3.2 steps 8-12 | 251 // 25.4.1.3.2 steps 8-12 |
256 try { | 252 try { |
257 var then = resolution.then; | 253 var then = resolution.then; |
258 } catch (e) { | 254 } catch (e) { |
259 %PromiseReject(promise, e, true); | 255 return RejectPromise(promise, e, true); |
260 PromiseSet(promise, kRejected, e); | |
261 return; | |
262 } | 256 } |
263 | 257 |
264 // Resolution is a native promise and if it's already resolved or | 258 // Resolution is a native promise and if it's already resolved or |
265 // rejected, shortcircuit the resolution procedure by directly | 259 // rejected, shortcircuit the resolution procedure by directly |
266 // reusing the value from the promise. | 260 // reusing the value from the promise. |
267 if (IsPromise(resolution) && then === PromiseThen) { | 261 if (IsPromise(resolution) && then === PromiseThen) { |
268 var thenableState = GET_PRIVATE(resolution, promiseStateSymbol); | 262 var thenableState = GET_PRIVATE(resolution, promiseStateSymbol); |
269 if (thenableState === kFulfilled) { | 263 if (thenableState === kFulfilled) { |
270 // This goes inside the if-else to save one symbol lookup in | 264 // This goes inside the if-else to save one symbol lookup in |
271 // the slow path. | 265 // the slow path. |
272 var thenableValue = GET_PRIVATE(resolution, promiseResultSymbol); | 266 var thenableValue = GET_PRIVATE(resolution, promiseResultSymbol); |
273 %PromiseFulfill(promise, kFulfilled, thenableValue, | 267 %PromiseFulfill(promise, kFulfilled, thenableValue, |
274 promiseFulfillReactionsSymbol); | 268 promiseFulfillReactionsSymbol); |
275 PromiseSet(promise, kFulfilled, thenableValue); | 269 PromiseSet(promise, kFulfilled, thenableValue); |
276 SET_PRIVATE(promise, promiseHasHandlerSymbol, true); | 270 SET_PRIVATE(promise, promiseHasHandlerSymbol, true); |
277 return; | 271 return; |
278 } else if (thenableState === kRejected) { | 272 } else if (thenableState === kRejected) { |
279 var thenableValue = GET_PRIVATE(resolution, promiseResultSymbol); | 273 var thenableValue = GET_PRIVATE(resolution, promiseResultSymbol); |
280 if (!HAS_DEFINED_PRIVATE(resolution, promiseHasHandlerSymbol)) { | 274 if (!HAS_DEFINED_PRIVATE(resolution, promiseHasHandlerSymbol)) { |
281 // Promise has already been rejected, but had no handler. | 275 // Promise has already been rejected, but had no handler. |
282 // Revoke previously triggered reject event. | 276 // Revoke previously triggered reject event. |
283 %PromiseRevokeReject(resolution); | 277 %PromiseRevokeReject(resolution); |
284 } | 278 } |
285 // Don't cause a debug event as this case is forwarding a rejection | 279 // Don't cause a debug event as this case is forwarding a rejection |
286 %PromiseReject(promise, thenableValue, false); | 280 RejectPromise(promise, thenableValue, false); |
287 PromiseSet(promise, kRejected, thenableValue); | |
288 SET_PRIVATE(resolution, promiseHasHandlerSymbol, true); | 281 SET_PRIVATE(resolution, promiseHasHandlerSymbol, true); |
289 return; | 282 return; |
290 } | 283 } |
291 } | 284 } |
292 | 285 |
293 if (IS_CALLABLE(then)) { | 286 if (IS_CALLABLE(then)) { |
294 var callbacks = CreateResolvingFunctions(promise, false); | 287 var callbacks = CreateResolvingFunctions(promise, false); |
295 if (DEBUG_IS_ACTIVE && IsPromise(resolution)) { | 288 if (DEBUG_IS_ACTIVE && IsPromise(resolution)) { |
296 // Mark the dependency of the new promise on the resolution | 289 // Mark the dependency of the new promise on the resolution |
297 SET_PRIVATE(resolution, promiseHandledBySymbol, promise); | 290 SET_PRIVATE(resolution, promiseHandledBySymbol, promise); |
298 } | 291 } |
299 %EnqueuePromiseResolveThenableJob( | 292 %EnqueuePromiseResolveThenableJob( |
300 resolution, then, callbacks.resolve, callbacks.reject); | 293 resolution, then, callbacks.resolve, callbacks.reject); |
301 return; | 294 return; |
302 } | 295 } |
303 } | 296 } |
304 %PromiseFulfill(promise, kFulfilled, resolution, | 297 %PromiseFulfill(promise, kFulfilled, resolution, |
305 promiseFulfillReactionsSymbol); | 298 promiseFulfillReactionsSymbol); |
306 PromiseSet(promise, kFulfilled, resolution); | 299 PromiseSet(promise, kFulfilled, resolution); |
307 } | 300 } |
308 | 301 |
309 // Only used by async-await.js | 302 // ES#sec-rejectpromise |
310 function RejectPromise(promise, reason) { | 303 // RejectPromise ( promise, reason ) |
311 %PromiseReject(promise, reason, false); | 304 function RejectPromise(promise, reason, debugEvent) { |
| 305 // Call runtime for callbacks to the debugger or for unhandled reject. |
| 306 // The debugEvent parameter sets whether a debug ExceptionEvent should |
| 307 // be triggered. It should be set to false when forwarding a rejection |
| 308 // rather than creating a new one. |
| 309 // This check is redundant with checks in the runtime, but it may help |
| 310 // avoid unnecessary runtime calls. |
| 311 if ((debugEvent && DEBUG_IS_ACTIVE) || |
| 312 !HAS_DEFINED_PRIVATE(promise, promiseHasHandlerSymbol)) { |
| 313 %PromiseRejectEvent(promise, reason, debugEvent); |
| 314 } |
| 315 %PromiseFulfill(promise, kRejected, reason, promiseRejectReactionsSymbol) |
312 PromiseSet(promise, kRejected, reason); | 316 PromiseSet(promise, kRejected, reason); |
313 } | 317 } |
314 | 318 |
315 // Export to bindings | 319 // Export to bindings |
316 function DoRejectPromise(promise, reason) { | 320 function DoRejectPromise(promise, reason) { |
317 %PromiseReject(promise, reason, true); | 321 return RejectPromise(promise, reason, true); |
318 PromiseSet(promise, kRejected, reason); | |
319 } | 322 } |
320 | 323 |
321 // ES#sec-newpromisecapability | 324 // ES#sec-newpromisecapability |
322 // NewPromiseCapability ( C ) | 325 // NewPromiseCapability ( C ) |
323 function NewPromiseCapability(C, debugEvent) { | 326 function NewPromiseCapability(C, debugEvent) { |
324 if (C === GlobalPromise) { | 327 if (C === GlobalPromise) { |
325 // Optimized case, avoid extra closure. | 328 // Optimized case, avoid extra closure. |
326 var promise = PromiseCreate(); | 329 var promise = PromiseCreate(); |
327 var callbacks = CreateResolvingFunctions(promise, debugEvent); | 330 var callbacks = CreateResolvingFunctions(promise, debugEvent); |
328 return { | 331 return { |
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
664 to.PromiseThen = PromiseThen; | 667 to.PromiseThen = PromiseThen; |
665 | 668 |
666 to.GlobalPromise = GlobalPromise; | 669 to.GlobalPromise = GlobalPromise; |
667 to.NewPromiseCapability = NewPromiseCapability; | 670 to.NewPromiseCapability = NewPromiseCapability; |
668 to.PerformPromiseThen = PerformPromiseThen; | 671 to.PerformPromiseThen = PerformPromiseThen; |
669 to.ResolvePromise = ResolvePromise; | 672 to.ResolvePromise = ResolvePromise; |
670 to.RejectPromise = RejectPromise; | 673 to.RejectPromise = RejectPromise; |
671 }); | 674 }); |
672 | 675 |
673 }) | 676 }) |
OLD | NEW |