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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
44 // ES#sec-createresolvingfunctions | 44 // ES#sec-createresolvingfunctions |
45 // CreateResolvingFunctions ( promise ) | 45 // CreateResolvingFunctions ( promise ) |
46 function CreateResolvingFunctions(promise) { | 46 function CreateResolvingFunctions(promise) { |
47 var alreadyResolved = false; | 47 var alreadyResolved = false; |
48 | 48 |
49 // ES#sec-promise-resolve-functions | 49 // ES#sec-promise-resolve-functions |
50 // Promise Resolve Functions | 50 // Promise Resolve Functions |
51 var resolve = value => { | 51 var resolve = value => { |
52 if (alreadyResolved === true) return; | 52 if (alreadyResolved === true) return; |
53 alreadyResolved = true; | 53 alreadyResolved = true; |
54 FulfillPromise(promise, value); | 54 ResolvePromise(promise, value); |
55 }; | 55 }; |
56 | 56 |
57 // ES#sec-promise-reject-functions | 57 // ES#sec-promise-reject-functions |
58 // Promise Reject Functions | 58 // Promise Reject Functions |
59 var reject = reason => { | 59 var reject = reason => { |
60 if (alreadyResolved === true) return; | 60 if (alreadyResolved === true) return; |
61 alreadyResolved = true; | 61 alreadyResolved = true; |
62 RejectPromise(promise, reason); | 62 RejectPromise(promise, reason); |
63 }; | 63 }; |
64 | 64 |
65 return { | 65 return { |
66 __proto__: null, | 66 __proto__: null, |
67 resolve: resolve, | 67 resolve: resolve, |
68 reject: reject | 68 reject: reject |
69 }; | 69 }; |
70 } | 70 } |
71 | 71 |
72 | 72 |
73 // ES#sec-promise-executor | 73 // ES#sec-promise-executor |
74 // Promise ( executor ) | 74 // Promise ( executor ) |
75 var GlobalPromise = function Promise(resolver) { | 75 var GlobalPromise = function Promise(executor) { |
76 if (resolver === promiseRawSymbol) { | 76 if (executor === promiseRawSymbol) { |
77 return %_NewObject(GlobalPromise, new.target); | 77 return %_NewObject(GlobalPromise, new.target); |
78 } | 78 } |
79 if (IS_UNDEFINED(new.target)) throw MakeTypeError(kNotAPromise, this); | 79 if (IS_UNDEFINED(new.target)) throw MakeTypeError(kNotAPromise, this); |
80 if (!IS_CALLABLE(resolver)) { | 80 if (!IS_CALLABLE(executor)) { |
81 throw MakeTypeError(kResolverNotAFunction, resolver); | 81 throw MakeTypeError(kResolverNotAFunction, executor); |
82 } | 82 } |
83 | 83 |
84 var promise = PromiseInit(%_NewObject(GlobalPromise, new.target)); | 84 var promise = PromiseInit(%_NewObject(GlobalPromise, new.target)); |
85 var callbacks = CreateResolvingFunctions(promise); | 85 var callbacks = CreateResolvingFunctions(promise); |
86 var debug_is_active = DEBUG_IS_ACTIVE; | 86 var debug_is_active = DEBUG_IS_ACTIVE; |
87 try { | 87 try { |
88 if (debug_is_active) %DebugPushPromise(promise, Promise); | 88 if (debug_is_active) %DebugPushPromise(promise, Promise); |
89 resolver(callbacks.resolve, callbacks.reject); | 89 executor(callbacks.resolve, callbacks.reject); |
90 } catch (e) { | 90 } catch (e) { |
91 %_Call(callbacks.reject, UNDEFINED, e); | 91 %_Call(callbacks.reject, UNDEFINED, e); |
92 } finally { | 92 } finally { |
93 if (debug_is_active) %DebugPopPromise(); | 93 if (debug_is_active) %DebugPopPromise(); |
94 } | 94 } |
95 | 95 |
96 return promise; | 96 return promise; |
97 } | 97 } |
98 | 98 |
99 // Core functionality. | 99 // Core functionality. |
(...skipping 11 matching lines...) Expand all Loading... | |
111 // If debug is active, notify about the newly created promise first. | 111 // If debug is active, notify about the newly created promise first. |
112 if (DEBUG_IS_ACTIVE) PromiseSet(promise, kPending, UNDEFINED); | 112 if (DEBUG_IS_ACTIVE) PromiseSet(promise, kPending, UNDEFINED); |
113 return PromiseSet(promise, status, value); | 113 return PromiseSet(promise, status, value); |
114 } | 114 } |
115 | 115 |
116 function PromiseInit(promise) { | 116 function PromiseInit(promise) { |
117 return PromiseSet( | 117 return PromiseSet( |
118 promise, kPending, UNDEFINED, new InternalArray, new InternalArray) | 118 promise, kPending, UNDEFINED, new InternalArray, new InternalArray) |
119 } | 119 } |
120 | 120 |
121 function PromiseDone(promise, status, value, promiseQueue) { | 121 function FulfillPromise(promise, status, value, promiseQueue) { |
Dan Ehrenberg
2016/05/27 08:22:58
I'm not a big fan of this name change. This is a f
| |
122 if (GET_PRIVATE(promise, promiseStateSymbol) === kPending) { | 122 if (GET_PRIVATE(promise, promiseStateSymbol) === kPending) { |
123 var tasks = GET_PRIVATE(promise, promiseQueue); | 123 var tasks = GET_PRIVATE(promise, promiseQueue); |
124 if (tasks.length) PromiseEnqueue(value, tasks, status); | 124 if (tasks.length) PromiseEnqueue(value, tasks, status); |
125 PromiseSet(promise, status, value); | 125 PromiseSet(promise, status, value); |
126 } | 126 } |
127 } | 127 } |
128 | 128 |
129 function PromiseHandle(value, handler, deferred) { | 129 function PromiseHandle(value, handler, deferred) { |
130 var debug_is_active = DEBUG_IS_ACTIVE; | 130 var debug_is_active = DEBUG_IS_ACTIVE; |
131 try { | 131 try { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
171 | 171 |
172 // ES#sec-ispromise IsPromise ( x ) | 172 // ES#sec-ispromise IsPromise ( x ) |
173 function IsPromise(x) { | 173 function IsPromise(x) { |
174 return IS_RECEIVER(x) && HAS_DEFINED_PRIVATE(x, promiseStateSymbol); | 174 return IS_RECEIVER(x) && HAS_DEFINED_PRIVATE(x, promiseStateSymbol); |
175 } | 175 } |
176 | 176 |
177 function PromiseCreate() { | 177 function PromiseCreate() { |
178 return new GlobalPromise(PromiseNopResolver) | 178 return new GlobalPromise(PromiseNopResolver) |
179 } | 179 } |
180 | 180 |
181 // ES#sec-fulfillpromise | 181 // ES#sec-promise-resolve-functions |
182 // FulfillPromise ( promise, value) | 182 // Promise Resolve Functions, steps 6-13 |
Dan Ehrenberg
2016/05/27 08:22:58
As your comment says, the contents of this functio
| |
183 function FulfillPromise(promise, x) { | 183 function ResolvePromise(promise, resolution) { |
184 if (x === promise) { | 184 if (resolution === promise) { |
185 return RejectPromise(promise, MakeTypeError(kPromiseCyclic, x)); | 185 return RejectPromise(promise, MakeTypeError(kPromiseCyclic, resolution)); |
186 } | 186 } |
187 if (IS_RECEIVER(x)) { | 187 if (IS_RECEIVER(resolution)) { |
188 // 25.4.1.3.2 steps 8-12 | 188 // 25.4.1.3.2 steps 8-12 |
189 try { | 189 try { |
190 var then = x.then; | 190 var then = resolution.then; |
191 } catch (e) { | 191 } catch (e) { |
192 return RejectPromise(promise, e); | 192 return RejectPromise(promise, e); |
193 } | 193 } |
194 if (IS_CALLABLE(then)) { | 194 if (IS_CALLABLE(then)) { |
195 // PromiseResolveThenableJob | 195 // PromiseResolveThenableJob |
196 var id, name, instrumenting = DEBUG_IS_ACTIVE; | 196 var id, name, instrumenting = DEBUG_IS_ACTIVE; |
197 %EnqueueMicrotask(function() { | 197 %EnqueueMicrotask(function() { |
198 if (instrumenting) { | 198 if (instrumenting) { |
199 %DebugAsyncTaskEvent({ type: "willHandle", id: id, name: name }); | 199 %DebugAsyncTaskEvent({ type: "willHandle", id: id, name: name }); |
200 } | 200 } |
201 var callbacks = CreateResolvingFunctions(promise); | 201 var callbacks = CreateResolvingFunctions(promise); |
202 try { | 202 try { |
203 %_Call(then, x, callbacks.resolve, callbacks.reject); | 203 %_Call(then, resolution, callbacks.resolve, callbacks.reject); |
204 } catch (e) { | 204 } catch (e) { |
205 %_Call(callbacks.reject, UNDEFINED, e); | 205 %_Call(callbacks.reject, UNDEFINED, e); |
206 } | 206 } |
207 if (instrumenting) { | 207 if (instrumenting) { |
208 %DebugAsyncTaskEvent({ type: "didHandle", id: id, name: name }); | 208 %DebugAsyncTaskEvent({ type: "didHandle", id: id, name: name }); |
209 } | 209 } |
210 }); | 210 }); |
211 if (instrumenting) { | 211 if (instrumenting) { |
212 id = ++lastMicrotaskId; | 212 id = ++lastMicrotaskId; |
213 name = "PromseResolveThenableJob"; | 213 name = "PromseResolveThenableJob"; |
214 %DebugAsyncTaskEvent({ type: "enqueue", id: id, name: name }); | 214 %DebugAsyncTaskEvent({ type: "enqueue", id: id, name: name }); |
215 } | 215 } |
216 return; | 216 return; |
217 } | 217 } |
218 } | 218 } |
219 PromiseDone(promise, kFulfilled, x, promiseFulfillReactionsSymbol); | 219 FulfillPromise(promise, kFulfilled, resolution, promiseFulfillReactionsSymbol) ; |
220 } | 220 } |
221 | 221 |
222 // ES#sec-rejectpromise | 222 // ES#sec-rejectpromise |
223 // RejectPromise ( promise, reason ) | 223 // RejectPromise ( promise, reason ) |
224 function RejectPromise(promise, r) { | 224 function RejectPromise(promise, reason) { |
225 // Check promise status to confirm that this reject has an effect. | 225 // Check promise status to confirm that this reject has an effect. |
226 // Call runtime for callbacks to the debugger or for unhandled reject. | 226 // Call runtime for callbacks to the debugger or for unhandled reject. |
227 if (GET_PRIVATE(promise, promiseStateSymbol) === kPending) { | 227 if (GET_PRIVATE(promise, promiseStateSymbol) === kPending) { |
228 var debug_is_active = DEBUG_IS_ACTIVE; | 228 var debug_is_active = DEBUG_IS_ACTIVE; |
229 if (debug_is_active || | 229 if (debug_is_active || |
230 !HAS_DEFINED_PRIVATE(promise, promiseHasHandlerSymbol)) { | 230 !HAS_DEFINED_PRIVATE(promise, promiseHasHandlerSymbol)) { |
231 %PromiseRejectEvent(promise, r, debug_is_active); | 231 %PromiseRejectEvent(promise, reason, debug_is_active); |
232 } | 232 } |
233 } | 233 } |
234 PromiseDone(promise, kRejected, r, promiseRejectReactionsSymbol) | 234 FulfillPromise(promise, kRejected, reason, promiseRejectReactionsSymbol) |
235 } | 235 } |
236 | 236 |
237 // ES#sec-newpromisecapability | 237 // ES#sec-newpromisecapability |
238 // NewPromiseCapability ( C ) | 238 // NewPromiseCapability ( C ) |
239 function NewPromiseCapability(C) { | 239 function NewPromiseCapability(C) { |
240 if (C === GlobalPromise) { | 240 if (C === GlobalPromise) { |
241 // Optimized case, avoid extra closure. | 241 // Optimized case, avoid extra closure. |
242 var promise = PromiseInit(new GlobalPromise(promiseRawSymbol)); | 242 var promise = PromiseInit(new GlobalPromise(promiseRawSymbol)); |
243 var callbacks = CreateResolvingFunctions(promise); | 243 var callbacks = CreateResolvingFunctions(promise); |
244 return { | 244 return { |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
489 "then", PromiseThen, | 489 "then", PromiseThen, |
490 "catch", PromiseCatch | 490 "catch", PromiseCatch |
491 ]); | 491 ]); |
492 | 492 |
493 %InstallToContext([ | 493 %InstallToContext([ |
494 "promise_catch", PromiseCatch, | 494 "promise_catch", PromiseCatch, |
495 "promise_chain", PromiseChain, | 495 "promise_chain", PromiseChain, |
496 "promise_create", PromiseCreate, | 496 "promise_create", PromiseCreate, |
497 "promise_has_user_defined_reject_handler", PromiseHasUserDefinedRejectHandler, | 497 "promise_has_user_defined_reject_handler", PromiseHasUserDefinedRejectHandler, |
498 "promise_reject", RejectPromise, | 498 "promise_reject", RejectPromise, |
499 "promise_resolve", FulfillPromise, | 499 "promise_resolve", ResolvePromise, |
500 "promise_then", PromiseThen, | 500 "promise_then", PromiseThen, |
501 "promise_create_rejected", PromiseCreateRejected, | 501 "promise_create_rejected", PromiseCreateRejected, |
502 "promise_create_resolved", PromiseCreateResolved | 502 "promise_create_resolved", PromiseCreateResolved |
503 ]); | 503 ]); |
504 | 504 |
505 // This allows extras to create promises quickly without building extra | 505 // This allows extras to create promises quickly without building extra |
506 // resolve/reject closures, and allows them to later resolve and reject any | 506 // resolve/reject closures, and allows them to later resolve and reject any |
507 // promise without having to hold on to those closures forever. | 507 // promise without having to hold on to those closures forever. |
508 utils.InstallFunctions(extrasUtils, 0, [ | 508 utils.InstallFunctions(extrasUtils, 0, [ |
509 "createPromise", PromiseCreate, | 509 "createPromise", PromiseCreate, |
510 "resolvePromise", FulfillPromise, | 510 "resolvePromise", ResolvePromise, |
511 "rejectPromise", RejectPromise | 511 "rejectPromise", RejectPromise |
512 ]); | 512 ]); |
513 | 513 |
514 // TODO(v8:4567): Allow experimental natives to remove function prototype | 514 // TODO(v8:4567): Allow experimental natives to remove function prototype |
515 [PromiseChain, PromiseDefer, PromiseAccept].forEach( | 515 [PromiseChain, PromiseDefer, PromiseAccept].forEach( |
516 fn => %FunctionRemovePrototype(fn)); | 516 fn => %FunctionRemovePrototype(fn)); |
517 | 517 |
518 utils.Export(function(to) { | 518 utils.Export(function(to) { |
519 to.PromiseChain = PromiseChain; | 519 to.PromiseChain = PromiseChain; |
520 to.PromiseDefer = PromiseDefer; | 520 to.PromiseDefer = PromiseDefer; |
521 to.PromiseAccept = PromiseAccept; | 521 to.PromiseAccept = PromiseAccept; |
522 | 522 |
523 to.PromiseCreateRejected = PromiseCreateRejected; | 523 to.PromiseCreateRejected = PromiseCreateRejected; |
524 to.PromiseCreateResolved = PromiseCreateResolved; | 524 to.PromiseCreateResolved = PromiseCreateResolved; |
525 to.PromiseThen = PromiseThen; | 525 to.PromiseThen = PromiseThen; |
526 }); | 526 }); |
527 | 527 |
528 }) | 528 }) |
OLD | NEW |