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