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

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

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