Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(784)

Side by Side Diff: src/js/promise.js

Issue 2554943002: Reland Create JSPromise (patchset #16 id:300001 of https://codereview.chromium.org/2536463002/ )" (Closed)
Patch Set: fix test Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/js/async-await.js ('k') | src/objects.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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 })
OLDNEW
« no previous file with comments | « src/js/async-await.js ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698