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 |
11 // ------------------------------------------------------------------- | 11 // ------------------------------------------------------------------- |
12 // Imports | 12 // Imports |
13 | 13 |
14 var InternalArray = utils.InternalArray; | 14 var InternalArray = utils.InternalArray; |
15 var promiseAsyncStackIDSymbol = | 15 var promiseAsyncStackIDSymbol = |
16 utils.ImportNow("promise_async_stack_id_symbol"); | 16 utils.ImportNow("promise_async_stack_id_symbol"); |
17 var promiseHandledBySymbol = | 17 var promiseHandledBySymbol = |
18 utils.ImportNow("promise_handled_by_symbol"); | 18 utils.ImportNow("promise_handled_by_symbol"); |
19 var promiseForwardingHandlerSymbol = | 19 var promiseForwardingHandlerSymbol = |
20 utils.ImportNow("promise_forwarding_handler_symbol"); | 20 utils.ImportNow("promise_forwarding_handler_symbol"); |
21 var promiseHasHandlerSymbol = | 21 var promiseHasHandlerSymbol = |
22 utils.ImportNow("promise_has_handler_symbol"); | 22 utils.ImportNow("promise_has_handler_symbol"); |
23 var promiseRejectReactionsSymbol = | |
24 utils.ImportNow("promise_reject_reactions_symbol"); | |
25 var promiseFulfillReactionsSymbol = | |
26 utils.ImportNow("promise_fulfill_reactions_symbol"); | |
27 var promiseDeferredReactionSymbol = | |
28 utils.ImportNow("promise_deferred_reaction_symbol"); | |
29 var promiseHandledHintSymbol = | 23 var promiseHandledHintSymbol = |
30 utils.ImportNow("promise_handled_hint_symbol"); | 24 utils.ImportNow("promise_handled_hint_symbol"); |
31 var promiseRawSymbol = utils.ImportNow("promise_raw_symbol"); | 25 var promiseRawSymbol = utils.ImportNow("promise_raw_symbol"); |
32 var promiseStateSymbol = utils.ImportNow("promise_state_symbol"); | 26 var promiseStateSymbol = utils.ImportNow("promise_state_symbol"); |
33 var promiseResultSymbol = utils.ImportNow("promise_result_symbol"); | 27 var promiseResultSymbol = utils.ImportNow("promise_result_symbol"); |
34 var SpeciesConstructor; | 28 var SpeciesConstructor; |
35 var speciesSymbol = utils.ImportNow("species_symbol"); | 29 var speciesSymbol = utils.ImportNow("species_symbol"); |
36 var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol"); | 30 var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol"); |
37 var ObjectHasOwnProperty; | 31 var ObjectHasOwnProperty; |
38 var GlobalPromise = global.Promise; | 32 var GlobalPromise = global.Promise; |
| 33 var PromiseThen = GlobalPromise.prototype.then; |
39 | 34 |
40 utils.Import(function(from) { | 35 utils.Import(function(from) { |
41 ObjectHasOwnProperty = from.ObjectHasOwnProperty; | 36 ObjectHasOwnProperty = from.ObjectHasOwnProperty; |
42 SpeciesConstructor = from.SpeciesConstructor; | 37 SpeciesConstructor = from.SpeciesConstructor; |
43 }); | 38 }); |
44 | 39 |
45 // ------------------------------------------------------------------- | 40 // ------------------------------------------------------------------- |
46 | 41 |
47 // Core functionality. | 42 // Core functionality. |
48 | 43 |
49 function PromiseSet(promise, status, value) { | |
50 SET_PRIVATE(promise, promiseStateSymbol, status); | |
51 SET_PRIVATE(promise, promiseResultSymbol, value); | |
52 | |
53 // There are 3 possible states for the resolve, reject symbols when we add | |
54 // a new callback -- | |
55 // 1) UNDEFINED -- This is the zero state where there is no callback | |
56 // registered. When we see this state, we directly attach the callbacks to | |
57 // the symbol. | |
58 // 2) !IS_ARRAY -- There is a single callback directly attached to the | |
59 // symbols. We need to create a new array to store additional callbacks. | |
60 // 3) IS_ARRAY -- There are multiple callbacks already registered, | |
61 // therefore we can just push the new callback to the existing array. | |
62 SET_PRIVATE(promise, promiseFulfillReactionsSymbol, UNDEFINED); | |
63 SET_PRIVATE(promise, promiseRejectReactionsSymbol, UNDEFINED); | |
64 | |
65 // This symbol is used only when one deferred needs to be attached. When more | |
66 // than one deferred need to be attached the promise, we attach them directly | |
67 // to the promiseFulfillReactionsSymbol and promiseRejectReactionsSymbol and | |
68 // reset this back to UNDEFINED. | |
69 SET_PRIVATE(promise, promiseDeferredReactionSymbol, UNDEFINED); | |
70 | |
71 return promise; | |
72 } | |
73 | |
74 function PromiseCreateAndSet(status, value) { | |
75 var promise = %promise_internal_constructor(); | |
76 // If debug is active, notify about the newly created promise first. | |
77 if (DEBUG_IS_ACTIVE) PromiseSet(promise, kPending, UNDEFINED); | |
78 return PromiseSet(promise, status, value); | |
79 } | |
80 | |
81 function PromiseInit(promise) { | |
82 return PromiseSet(promise, kPending, UNDEFINED); | |
83 } | |
84 | |
85 function PromiseHandle(value, handler, deferred) { | 44 function PromiseHandle(value, handler, deferred) { |
86 var debug_is_active = DEBUG_IS_ACTIVE; | 45 var debug_is_active = DEBUG_IS_ACTIVE; |
87 try { | 46 try { |
88 if (debug_is_active) %DebugPushPromise(deferred.promise); | 47 if (debug_is_active) %DebugPushPromise(deferred.promise); |
89 var result = handler(value); | 48 var result = handler(value); |
90 if (IS_UNDEFINED(deferred.resolve)) { | 49 if (IS_UNDEFINED(deferred.resolve)) { |
91 ResolvePromise(deferred.promise, result); | 50 ResolvePromise(deferred.promise, result); |
92 } else { | 51 } else { |
93 %_Call(deferred.resolve, UNDEFINED, result); | 52 %_Call(deferred.resolve, UNDEFINED, result); |
94 } | 53 } |
95 } %catch (exception) { // Natives syntax to mark this catch block. | 54 } %catch (exception) { // Natives syntax to mark this catch block. |
96 try { | 55 try { |
97 if (IS_UNDEFINED(deferred.reject)) { | 56 if (IS_UNDEFINED(deferred.reject)) { |
98 // Pass false for debugEvent so .then chaining or throwaway promises | 57 // Pass false for debugEvent so .then chaining or throwaway promises |
99 // in async functions do not trigger redundant ExceptionEvents. | 58 // in async functions do not trigger redundant ExceptionEvents. |
100 %PromiseReject(deferred.promise, exception, false); | 59 %PromiseReject(deferred.promise, exception, false); |
101 PromiseSet(deferred.promise, kRejected, exception); | |
102 } else { | 60 } else { |
103 %_Call(deferred.reject, UNDEFINED, exception); | 61 %_Call(deferred.reject, UNDEFINED, exception); |
104 } | 62 } |
105 } catch (e) { } | 63 } catch (e) { } |
106 } finally { | 64 } finally { |
107 if (debug_is_active) %DebugPopPromise(); | 65 if (debug_is_active) %DebugPopPromise(); |
108 } | 66 } |
109 } | 67 } |
110 | 68 |
111 function PromiseDebugGetInfo(deferreds, status) { | 69 function PromiseDebugGetInfo(deferreds, status) { |
(...skipping 15 matching lines...) Expand all Loading... |
127 name = "async function"; | 85 name = "async function"; |
128 } else { | 86 } else { |
129 id = %DebugNextMicrotaskId(); | 87 id = %DebugNextMicrotaskId(); |
130 name = status === kFulfilled ? "Promise.resolve" : "Promise.reject"; | 88 name = status === kFulfilled ? "Promise.resolve" : "Promise.reject"; |
131 %DebugAsyncTaskEvent("enqueue", id, name); | 89 %DebugAsyncTaskEvent("enqueue", id, name); |
132 } | 90 } |
133 } | 91 } |
134 return [id, name]; | 92 return [id, name]; |
135 } | 93 } |
136 | 94 |
137 function PromiseAttachCallbacks(promise, deferred, onResolve, onReject) { | |
138 var maybeResolveCallbacks = | |
139 GET_PRIVATE(promise, promiseFulfillReactionsSymbol); | |
140 if (IS_UNDEFINED(maybeResolveCallbacks)) { | |
141 SET_PRIVATE(promise, promiseFulfillReactionsSymbol, onResolve); | |
142 SET_PRIVATE(promise, promiseRejectReactionsSymbol, onReject); | |
143 SET_PRIVATE(promise, promiseDeferredReactionSymbol, deferred); | |
144 } else if (!IS_ARRAY(maybeResolveCallbacks)) { | |
145 var resolveCallbacks = new InternalArray(); | |
146 var rejectCallbacks = new InternalArray(); | |
147 var existingDeferred = GET_PRIVATE(promise, promiseDeferredReactionSymbol); | |
148 | |
149 resolveCallbacks.push( | |
150 maybeResolveCallbacks, existingDeferred, onResolve, deferred); | |
151 rejectCallbacks.push(GET_PRIVATE(promise, promiseRejectReactionsSymbol), | |
152 existingDeferred, | |
153 onReject, | |
154 deferred); | |
155 | |
156 SET_PRIVATE(promise, promiseFulfillReactionsSymbol, resolveCallbacks); | |
157 SET_PRIVATE(promise, promiseRejectReactionsSymbol, rejectCallbacks); | |
158 SET_PRIVATE(promise, promiseDeferredReactionSymbol, UNDEFINED); | |
159 } else { | |
160 maybeResolveCallbacks.push(onResolve, deferred); | |
161 GET_PRIVATE(promise, promiseRejectReactionsSymbol).push(onReject, deferred); | |
162 } | |
163 } | |
164 | |
165 function PromiseIdResolveHandler(x) { return x; } | 95 function PromiseIdResolveHandler(x) { return x; } |
166 function PromiseIdRejectHandler(r) { %_ReThrow(r); } | 96 function PromiseIdRejectHandler(r) { %_ReThrow(r); } |
167 SET_PRIVATE(PromiseIdRejectHandler, promiseForwardingHandlerSymbol, true); | 97 SET_PRIVATE(PromiseIdRejectHandler, promiseForwardingHandlerSymbol, true); |
168 | 98 |
169 // ------------------------------------------------------------------- | 99 // ------------------------------------------------------------------- |
170 // Define exported functions. | 100 // Define exported functions. |
171 | 101 |
172 // For bootstrapper. | 102 // For bootstrapper. |
173 | 103 |
| 104 // This is used by utils and v8-extras. |
174 function PromiseCreate() { | 105 function PromiseCreate() { |
175 return PromiseInit(%promise_internal_constructor()); | 106 return %promise_internal_constructor(); |
176 } | 107 } |
177 | 108 |
178 // ES#sec-promise-resolve-functions | 109 // ES#sec-promise-resolve-functions |
179 // Promise Resolve Functions, steps 6-13 | 110 // Promise Resolve Functions, steps 6-13 |
180 function ResolvePromise(promise, resolution) { | 111 function ResolvePromise(promise, resolution) { |
181 if (resolution === promise) { | 112 if (resolution === promise) { |
182 var exception = %make_type_error(kPromiseCyclic, resolution); | 113 var exception = %make_type_error(kPromiseCyclic, resolution); |
183 %PromiseReject(promise, exception, true); | 114 %PromiseReject(promise, exception, true); |
184 PromiseSet(promise, kRejected, exception); | |
185 return; | 115 return; |
186 } | 116 } |
187 if (IS_RECEIVER(resolution)) { | 117 if (IS_RECEIVER(resolution)) { |
188 // 25.4.1.3.2 steps 8-12 | 118 // 25.4.1.3.2 steps 8-12 |
189 try { | 119 try { |
190 var then = resolution.then; | 120 var then = resolution.then; |
191 } catch (e) { | 121 } catch (e) { |
192 %PromiseReject(promise, e, true); | 122 %PromiseReject(promise, e, true); |
193 PromiseSet(promise, kRejected, e); | |
194 return; | 123 return; |
195 } | 124 } |
196 | 125 |
197 // Resolution is a native promise and if it's already resolved or | 126 // Resolution is a native promise and if it's already resolved or |
198 // rejected, shortcircuit the resolution procedure by directly | 127 // rejected, shortcircuit the resolution procedure by directly |
199 // reusing the value from the promise. | 128 // reusing the value from the promise. |
200 if (%is_promise(resolution) && then === PromiseThen) { | 129 if (%is_promise(resolution) && then === PromiseThen) { |
201 var thenableState = GET_PRIVATE(resolution, promiseStateSymbol); | 130 var thenableState = %PromiseStatus(resolution); |
202 if (thenableState === kFulfilled) { | 131 if (thenableState === kFulfilled) { |
203 // This goes inside the if-else to save one symbol lookup in | 132 // This goes inside the if-else to save one symbol lookup in |
204 // the slow path. | 133 // the slow path. |
205 var thenableValue = GET_PRIVATE(resolution, promiseResultSymbol); | 134 var thenableValue = %PromiseResult(resolution); |
206 %PromiseFulfill(promise, kFulfilled, thenableValue, | 135 %PromiseFulfill(promise, kFulfilled, thenableValue); |
207 promiseFulfillReactionsSymbol); | |
208 PromiseSet(promise, kFulfilled, thenableValue); | |
209 SET_PRIVATE(promise, promiseHasHandlerSymbol, true); | 136 SET_PRIVATE(promise, promiseHasHandlerSymbol, true); |
210 return; | 137 return; |
211 } else if (thenableState === kRejected) { | 138 } else if (thenableState === kRejected) { |
212 var thenableValue = GET_PRIVATE(resolution, promiseResultSymbol); | 139 var thenableValue = %PromiseResult(resolution); |
213 if (!HAS_DEFINED_PRIVATE(resolution, promiseHasHandlerSymbol)) { | 140 if (!HAS_DEFINED_PRIVATE(resolution, promiseHasHandlerSymbol)) { |
214 // Promise has already been rejected, but had no handler. | 141 // Promise has already been rejected, but had no handler. |
215 // Revoke previously triggered reject event. | 142 // Revoke previously triggered reject event. |
216 %PromiseRevokeReject(resolution); | 143 %PromiseRevokeReject(resolution); |
217 } | 144 } |
218 // Don't cause a debug event as this case is forwarding a rejection | 145 // Don't cause a debug event as this case is forwarding a rejection |
219 %PromiseReject(promise, thenableValue, false); | 146 %PromiseReject(promise, thenableValue, false); |
220 PromiseSet(promise, kRejected, thenableValue); | |
221 SET_PRIVATE(resolution, promiseHasHandlerSymbol, true); | 147 SET_PRIVATE(resolution, promiseHasHandlerSymbol, true); |
222 return; | 148 return; |
223 } | 149 } |
224 } | 150 } |
225 | 151 |
226 if (IS_CALLABLE(then)) { | 152 if (IS_CALLABLE(then)) { |
227 if (DEBUG_IS_ACTIVE && %is_promise(resolution)) { | 153 if (DEBUG_IS_ACTIVE && %is_promise(resolution)) { |
228 // Mark the dependency of the new promise on the resolution | 154 // Mark the dependency of the new promise on the resolution |
229 SET_PRIVATE(resolution, promiseHandledBySymbol, promise); | 155 SET_PRIVATE(resolution, promiseHandledBySymbol, promise); |
230 } | 156 } |
231 %EnqueuePromiseResolveThenableJob(promise, resolution, then); | 157 %EnqueuePromiseResolveThenableJob(promise, resolution, then); |
232 return; | 158 return; |
233 } | 159 } |
234 } | 160 } |
235 %PromiseFulfill(promise, kFulfilled, resolution, | 161 %PromiseFulfill(promise, kFulfilled, resolution); |
236 promiseFulfillReactionsSymbol); | |
237 PromiseSet(promise, kFulfilled, resolution); | |
238 } | 162 } |
239 | 163 |
240 // Only used by async-await.js | 164 // Only used by async-await.js |
241 function RejectPromise(promise, reason, debugEvent) { | 165 function RejectPromise(promise, reason, debugEvent) { |
242 %PromiseReject(promise, reason, debugEvent); | 166 %PromiseReject(promise, reason, debugEvent); |
243 PromiseSet(promise, kRejected, reason); | |
244 } | 167 } |
245 | 168 |
246 // Export to bindings | 169 // Export to bindings |
247 function DoRejectPromise(promise, reason) { | 170 function DoRejectPromise(promise, reason) { |
248 %PromiseReject(promise, reason, true); | 171 %PromiseReject(promise, reason, true); |
249 PromiseSet(promise, kRejected, reason); | |
250 } | 172 } |
251 | 173 |
252 // The resultCapability.promise is only ever fulfilled internally, | 174 // The resultCapability.promise is only ever fulfilled internally, |
253 // so we don't need the closures to protect against accidentally | 175 // so we don't need the closures to protect against accidentally |
254 // calling them multiple times. | 176 // calling them multiple times. |
255 function CreateInternalPromiseCapability() { | 177 function CreateInternalPromiseCapability() { |
256 return { | 178 return { |
257 promise: PromiseCreate(), | 179 promise: %promise_internal_constructor(), |
258 resolve: UNDEFINED, | 180 resolve: UNDEFINED, |
259 reject: UNDEFINED | 181 reject: UNDEFINED |
260 }; | 182 }; |
261 } | 183 } |
262 | 184 |
263 // ES#sec-newpromisecapability | 185 // ES#sec-newpromisecapability |
264 // NewPromiseCapability ( C ) | 186 // NewPromiseCapability ( C ) |
265 function NewPromiseCapability(C, debugEvent) { | 187 function NewPromiseCapability(C, debugEvent) { |
266 if (C === GlobalPromise) { | 188 if (C === GlobalPromise) { |
267 // Optimized case, avoid extra closure. | 189 // Optimized case, avoid extra closure. |
268 var promise = PromiseCreate(); | 190 var promise = %promise_internal_constructor(); |
269 // TODO(gsathya): Remove container for callbacks when this is | 191 // TODO(gsathya): Remove container for callbacks when this is |
270 // moved to CPP/TF. | 192 // moved to CPP/TF. |
271 var callbacks = %create_resolving_functions(promise, debugEvent); | 193 var callbacks = %create_resolving_functions(promise, debugEvent); |
272 return { | 194 return { |
273 promise: promise, | 195 promise: promise, |
274 resolve: callbacks[kResolveCallback], | 196 resolve: callbacks[kResolveCallback], |
275 reject: callbacks[kRejectCallback] | 197 reject: callbacks[kRejectCallback] |
276 }; | 198 }; |
277 } | 199 } |
278 | 200 |
(...skipping 12 matching lines...) Expand all Loading... |
291 } | 213 } |
292 | 214 |
293 // ES#sec-promise.reject | 215 // ES#sec-promise.reject |
294 // Promise.reject ( x ) | 216 // Promise.reject ( x ) |
295 function PromiseReject(r) { | 217 function PromiseReject(r) { |
296 if (!IS_RECEIVER(this)) { | 218 if (!IS_RECEIVER(this)) { |
297 throw %make_type_error(kCalledOnNonObject, PromiseResolve); | 219 throw %make_type_error(kCalledOnNonObject, PromiseResolve); |
298 } | 220 } |
299 if (this === GlobalPromise) { | 221 if (this === GlobalPromise) { |
300 // Optimized case, avoid extra closure. | 222 // Optimized case, avoid extra closure. |
301 var promise = PromiseCreateAndSet(kRejected, r); | 223 var promise = %promise_create_and_set(kRejected, r); |
302 // Trigger debug events if the debugger is on, as Promise.reject is | 224 // Trigger debug events if the debugger is on, as Promise.reject is |
303 // equivalent to throwing an exception directly. | 225 // equivalent to throwing an exception directly. |
304 %PromiseRejectEventFromStack(promise, r); | 226 %PromiseRejectEventFromStack(promise, r); |
305 return promise; | 227 return promise; |
306 } else { | 228 } else { |
307 var promiseCapability = NewPromiseCapability(this, true); | 229 var promiseCapability = NewPromiseCapability(this, true); |
308 %_Call(promiseCapability.reject, UNDEFINED, r); | 230 %_Call(promiseCapability.reject, UNDEFINED, r); |
309 return promiseCapability.promise; | 231 return promiseCapability.promise; |
310 } | 232 } |
311 } | 233 } |
312 | 234 |
313 function PerformPromiseThen(promise, onResolve, onReject, resultCapability) { | |
314 if (!IS_CALLABLE(onResolve)) onResolve = PromiseIdResolveHandler; | |
315 if (!IS_CALLABLE(onReject)) onReject = PromiseIdRejectHandler; | |
316 | |
317 var status = GET_PRIVATE(promise, promiseStateSymbol); | |
318 switch (status) { | |
319 case kPending: | |
320 PromiseAttachCallbacks(promise, resultCapability, onResolve, onReject); | |
321 break; | |
322 case kFulfilled: | |
323 %EnqueuePromiseReactionJob(GET_PRIVATE(promise, promiseResultSymbol), | |
324 onResolve, resultCapability, kFulfilled); | |
325 break; | |
326 case kRejected: | |
327 if (!HAS_DEFINED_PRIVATE(promise, promiseHasHandlerSymbol)) { | |
328 // Promise has already been rejected, but had no handler. | |
329 // Revoke previously triggered reject event. | |
330 %PromiseRevokeReject(promise); | |
331 } | |
332 %EnqueuePromiseReactionJob(GET_PRIVATE(promise, promiseResultSymbol), | |
333 onReject, resultCapability, kRejected); | |
334 break; | |
335 } | |
336 | |
337 // Mark this promise as having handler. | |
338 SET_PRIVATE(promise, promiseHasHandlerSymbol, true); | |
339 return resultCapability.promise; | |
340 } | |
341 | |
342 // ES#sec-promise.prototype.then | |
343 // Promise.prototype.then ( onFulfilled, onRejected ) | |
344 // Multi-unwrapped chaining with thenable coercion. | |
345 function PromiseThen(onResolve, onReject) { | |
346 if (!%is_promise(this)) { | |
347 throw %make_type_error(kNotAPromise, this); | |
348 } | |
349 | |
350 var constructor = SpeciesConstructor(this, GlobalPromise); | |
351 var resultCapability; | |
352 if (constructor === GlobalPromise) { | |
353 resultCapability = CreateInternalPromiseCapability(); | |
354 } else { | |
355 // Pass false for debugEvent so .then chaining does not trigger | |
356 // redundant ExceptionEvents. | |
357 resultCapability = NewPromiseCapability(constructor, false); | |
358 } | |
359 return PerformPromiseThen(this, onResolve, onReject, resultCapability); | |
360 } | |
361 | |
362 // ES#sec-promise.prototype.catch | 235 // ES#sec-promise.prototype.catch |
363 // Promise.prototype.catch ( onRejected ) | 236 // Promise.prototype.catch ( onRejected ) |
364 function PromiseCatch(onReject) { | 237 function PromiseCatch(onReject) { |
365 return this.then(UNDEFINED, onReject); | 238 return this.then(UNDEFINED, onReject); |
366 } | 239 } |
367 | 240 |
368 // Combinators. | 241 // Combinators. |
369 | 242 |
370 // ES#sec-promise.resolve | 243 // ES#sec-promise.resolve |
371 // Promise.resolve ( x ) | 244 // Promise.resolve ( x ) |
372 function PromiseResolve(x) { | 245 function PromiseResolve(x) { |
373 if (!IS_RECEIVER(this)) { | 246 if (!IS_RECEIVER(this)) { |
374 throw %make_type_error(kCalledOnNonObject, PromiseResolve); | 247 throw %make_type_error(kCalledOnNonObject, PromiseResolve); |
375 } | 248 } |
376 if (%is_promise(x) && x.constructor === this) return x; | 249 if (%is_promise(x) && x.constructor === this) return x; |
377 | 250 |
378 // Avoid creating resolving functions. | 251 // Avoid creating resolving functions. |
379 if (this === GlobalPromise) { | 252 if (this === GlobalPromise) { |
380 var promise = PromiseCreate(); | 253 var promise = %promise_internal_constructor(); |
381 ResolvePromise(promise, x); | 254 ResolvePromise(promise, x); |
382 return promise; | 255 return promise; |
383 } | 256 } |
384 | 257 |
385 // debugEvent is not so meaningful here as it will be resolved | 258 // debugEvent is not so meaningful here as it will be resolved |
386 var promiseCapability = NewPromiseCapability(this, true); | 259 var promiseCapability = NewPromiseCapability(this, true); |
387 %_Call(promiseCapability.resolve, UNDEFINED, x); | 260 %_Call(promiseCapability.resolve, UNDEFINED, x); |
388 return promiseCapability.promise; | 261 return promiseCapability.promise; |
389 } | 262 } |
390 | 263 |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
513 // with another Promise, or an intermediate, hidden, throwaway Promise | 386 // with another Promise, or an intermediate, hidden, throwaway Promise |
514 // within async/await), then recurse on the outer Promise. | 387 // within async/await), then recurse on the outer Promise. |
515 // In this case, the dependency is one possible way that the Promise | 388 // In this case, the dependency is one possible way that the Promise |
516 // could be resolved, so it does not subsume the other following cases. | 389 // could be resolved, so it does not subsume the other following cases. |
517 var outerPromise = GET_PRIVATE(promise, promiseHandledBySymbol); | 390 var outerPromise = GET_PRIVATE(promise, promiseHandledBySymbol); |
518 if (outerPromise && | 391 if (outerPromise && |
519 PromiseHasUserDefinedRejectHandlerRecursive(outerPromise)) { | 392 PromiseHasUserDefinedRejectHandlerRecursive(outerPromise)) { |
520 return true; | 393 return true; |
521 } | 394 } |
522 | 395 |
523 var queue = GET_PRIVATE(promise, promiseRejectReactionsSymbol); | 396 if (!%is_promise(promise)) return false; |
524 var deferred = GET_PRIVATE(promise, promiseDeferredReactionSymbol); | 397 |
| 398 var queue = %PromiseRejectReactions(promise); |
| 399 var deferred = %PromiseDeferred(promise); |
525 | 400 |
526 if (IS_UNDEFINED(queue)) return false; | 401 if (IS_UNDEFINED(queue)) return false; |
527 | 402 |
528 if (!IS_ARRAY(queue)) { | 403 if (!IS_ARRAY(queue)) { |
529 return PromiseHasUserDefinedRejectHandlerCheck(queue, deferred); | 404 return PromiseHasUserDefinedRejectHandlerCheck(queue, deferred); |
530 } | 405 } |
531 | 406 |
532 for (var i = 0; i < queue.length; i += 2) { | 407 for (var i = 0; i < queue.length; i++) { |
533 if (PromiseHasUserDefinedRejectHandlerCheck(queue[i], queue[i + 1])) { | 408 if (PromiseHasUserDefinedRejectHandlerCheck(queue[i], deferred[i])) { |
534 return true; | 409 return true; |
535 } | 410 } |
536 } | 411 } |
537 return false; | 412 return false; |
538 } | 413 } |
539 | 414 |
540 // Return whether the promise will be handled by a user-defined reject | 415 // Return whether the promise will be handled by a user-defined reject |
541 // handler somewhere down the promise chain. For this, we do a depth-first | 416 // handler somewhere down the promise chain. For this, we do a depth-first |
542 // search for a reject handler that's not the default PromiseIdRejectHandler. | 417 // search for a reject handler that's not the default PromiseIdRejectHandler. |
543 // This function also traverses dependencies of one Promise on another, | 418 // This function also traverses dependencies of one Promise on another, |
(...skipping 17 matching lines...) Expand all Loading... |
561 utils.InstallFunctions(GlobalPromise, DONT_ENUM, [ | 436 utils.InstallFunctions(GlobalPromise, DONT_ENUM, [ |
562 "reject", PromiseReject, | 437 "reject", PromiseReject, |
563 "all", PromiseAll, | 438 "all", PromiseAll, |
564 "race", PromiseRace, | 439 "race", PromiseRace, |
565 "resolve", PromiseResolve | 440 "resolve", PromiseResolve |
566 ]); | 441 ]); |
567 | 442 |
568 utils.InstallGetter(GlobalPromise, speciesSymbol, PromiseSpecies); | 443 utils.InstallGetter(GlobalPromise, speciesSymbol, PromiseSpecies); |
569 | 444 |
570 utils.InstallFunctions(GlobalPromise.prototype, DONT_ENUM, [ | 445 utils.InstallFunctions(GlobalPromise.prototype, DONT_ENUM, [ |
571 "then", PromiseThen, | |
572 "catch", PromiseCatch | 446 "catch", PromiseCatch |
573 ]); | 447 ]); |
574 | 448 |
575 %InstallToContext([ | 449 %InstallToContext([ |
576 "promise_catch", PromiseCatch, | 450 "promise_catch", PromiseCatch, |
577 "promise_create", PromiseCreate, | 451 "promise_create", PromiseCreate, |
578 "promise_has_user_defined_reject_handler", PromiseHasUserDefinedRejectHandler, | 452 "promise_has_user_defined_reject_handler", PromiseHasUserDefinedRejectHandler, |
579 "promise_reject", DoRejectPromise, | 453 "promise_reject", DoRejectPromise, |
580 // TODO(gsathya): Remove this once we update the promise builtin. | 454 // TODO(gsathya): Remove this once we update the promise builtin. |
581 "promise_internal_reject", RejectPromise, | 455 "promise_internal_reject", RejectPromise, |
582 "promise_resolve", ResolvePromise, | 456 "promise_resolve", ResolvePromise, |
583 "promise_then", PromiseThen, | 457 "promise_then", PromiseThen, |
584 "promise_handle", PromiseHandle, | 458 "promise_handle", PromiseHandle, |
585 "promise_debug_get_info", PromiseDebugGetInfo | 459 "promise_debug_get_info", PromiseDebugGetInfo, |
| 460 "new_promise_capability", NewPromiseCapability, |
| 461 "internal_promise_capability", CreateInternalPromiseCapability, |
| 462 "promise_id_resolve_handler", PromiseIdResolveHandler, |
| 463 "promise_id_reject_handler", PromiseIdRejectHandler |
586 ]); | 464 ]); |
587 | 465 |
588 // This allows extras to create promises quickly without building extra | 466 // This allows extras to create promises quickly without building extra |
589 // resolve/reject closures, and allows them to later resolve and reject any | 467 // resolve/reject closures, and allows them to later resolve and reject any |
590 // promise without having to hold on to those closures forever. | 468 // promise without having to hold on to those closures forever. |
591 utils.InstallFunctions(extrasUtils, 0, [ | 469 utils.InstallFunctions(extrasUtils, 0, [ |
592 "createPromise", PromiseCreate, | 470 "createPromise", PromiseCreate, |
593 "resolvePromise", ResolvePromise, | 471 "resolvePromise", ResolvePromise, |
594 "rejectPromise", DoRejectPromise, | 472 "rejectPromise", DoRejectPromise, |
595 "markPromiseAsHandled", MarkPromiseAsHandled | 473 "markPromiseAsHandled", MarkPromiseAsHandled |
596 ]); | 474 ]); |
597 | 475 |
598 utils.Export(function(to) { | 476 utils.Export(function(to) { |
599 to.PromiseCreate = PromiseCreate; | 477 to.PromiseCreate = PromiseCreate; |
600 to.PromiseThen = PromiseThen; | 478 to.PromiseThen = PromiseThen; |
601 | 479 |
602 to.CreateInternalPromiseCapability = CreateInternalPromiseCapability; | 480 to.CreateInternalPromiseCapability = CreateInternalPromiseCapability; |
603 to.PerformPromiseThen = PerformPromiseThen; | |
604 to.ResolvePromise = ResolvePromise; | 481 to.ResolvePromise = ResolvePromise; |
605 to.RejectPromise = RejectPromise; | 482 to.RejectPromise = RejectPromise; |
606 }); | 483 }); |
607 | 484 |
608 }) | 485 }) |
OLD | NEW |