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 = | |
22 utils.ImportNow("promise_has_handler_symbol"); | |
23 var promiseHandledHintSymbol = | 21 var promiseHandledHintSymbol = |
24 utils.ImportNow("promise_handled_hint_symbol"); | 22 utils.ImportNow("promise_handled_hint_symbol"); |
25 var promiseRawSymbol = utils.ImportNow("promise_raw_symbol"); | 23 var promiseRawSymbol = utils.ImportNow("promise_raw_symbol"); |
26 var promiseStateSymbol = utils.ImportNow("promise_state_symbol"); | 24 var promiseStateSymbol = utils.ImportNow("promise_state_symbol"); |
27 var promiseResultSymbol = utils.ImportNow("promise_result_symbol"); | 25 var promiseResultSymbol = utils.ImportNow("promise_result_symbol"); |
28 var SpeciesConstructor; | 26 var SpeciesConstructor; |
29 var speciesSymbol = utils.ImportNow("species_symbol"); | 27 var speciesSymbol = utils.ImportNow("species_symbol"); |
30 var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol"); | 28 var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol"); |
31 var ObjectHasOwnProperty; | 29 var ObjectHasOwnProperty; |
32 var GlobalPromise = global.Promise; | 30 var GlobalPromise = global.Promise; |
33 var PromiseThen = GlobalPromise.prototype.then; | 31 var PromiseThen = GlobalPromise.prototype.then; |
34 | 32 |
35 utils.Import(function(from) { | 33 utils.Import(function(from) { |
36 ObjectHasOwnProperty = from.ObjectHasOwnProperty; | 34 ObjectHasOwnProperty = from.ObjectHasOwnProperty; |
37 SpeciesConstructor = from.SpeciesConstructor; | 35 SpeciesConstructor = from.SpeciesConstructor; |
38 }); | 36 }); |
39 | 37 |
40 // ------------------------------------------------------------------- | 38 // ------------------------------------------------------------------- |
41 | 39 |
42 // Core functionality. | 40 // Core functionality. |
43 | 41 |
44 function PromiseHandle(value, handler, deferred) { | 42 function PromiseHandle(value, handler, deferred) { |
45 var debug_is_active = DEBUG_IS_ACTIVE; | 43 var debug_is_active = DEBUG_IS_ACTIVE; |
46 try { | 44 try { |
47 if (debug_is_active) %DebugPushPromise(deferred.promise); | 45 if (debug_is_active) %DebugPushPromise(deferred.promise); |
48 var result = handler(value); | 46 var result = handler(value); |
49 if (IS_UNDEFINED(deferred.resolve)) { | 47 if (IS_UNDEFINED(deferred.resolve)) { |
50 ResolvePromise(deferred.promise, result); | 48 %promise_resolve(deferred.promise, result); |
51 } else { | 49 } else { |
52 %_Call(deferred.resolve, UNDEFINED, result); | 50 %_Call(deferred.resolve, UNDEFINED, result); |
53 } | 51 } |
54 } %catch (exception) { // Natives syntax to mark this catch block. | 52 } %catch (exception) { // Natives syntax to mark this catch block. |
55 try { | 53 try { |
56 if (IS_UNDEFINED(deferred.reject)) { | 54 if (IS_UNDEFINED(deferred.reject)) { |
57 // Pass false for debugEvent so .then chaining or throwaway promises | 55 // Pass false for debugEvent so .then chaining or throwaway promises |
58 // in async functions do not trigger redundant ExceptionEvents. | 56 // in async functions do not trigger redundant ExceptionEvents. |
59 %PromiseReject(deferred.promise, exception, false); | 57 %PromiseReject(deferred.promise, exception, false); |
60 } else { | 58 } else { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
99 // ------------------------------------------------------------------- | 97 // ------------------------------------------------------------------- |
100 // Define exported functions. | 98 // Define exported functions. |
101 | 99 |
102 // For bootstrapper. | 100 // For bootstrapper. |
103 | 101 |
104 // This is used by utils and v8-extras. | 102 // This is used by utils and v8-extras. |
105 function PromiseCreate() { | 103 function PromiseCreate() { |
106 return %promise_internal_constructor(); | 104 return %promise_internal_constructor(); |
107 } | 105 } |
108 | 106 |
109 // ES#sec-promise-resolve-functions | |
110 // Promise Resolve Functions, steps 6-13 | |
111 function ResolvePromise(promise, resolution) { | |
112 if (resolution === promise) { | |
113 var exception = %make_type_error(kPromiseCyclic, resolution); | |
114 %PromiseReject(promise, exception, true); | |
115 return; | |
116 } | |
117 if (IS_RECEIVER(resolution)) { | |
118 // 25.4.1.3.2 steps 8-12 | |
119 try { | |
120 var then = resolution.then; | |
121 } catch (e) { | |
122 %PromiseReject(promise, e, true); | |
123 return; | |
124 } | |
125 | |
126 // Resolution is a native promise and if it's already resolved or | |
127 // rejected, shortcircuit the resolution procedure by directly | |
128 // reusing the value from the promise. | |
129 if (%is_promise(resolution) && then === PromiseThen) { | |
130 var thenableState = %PromiseStatus(resolution); | |
131 if (thenableState === kFulfilled) { | |
132 // This goes inside the if-else to save one symbol lookup in | |
133 // the slow path. | |
134 var thenableValue = %PromiseResult(resolution); | |
135 %PromiseFulfill(promise, kFulfilled, thenableValue); | |
136 SET_PRIVATE(promise, promiseHasHandlerSymbol, true); | |
137 return; | |
138 } else if (thenableState === kRejected) { | |
139 var thenableValue = %PromiseResult(resolution); | |
140 if (!HAS_DEFINED_PRIVATE(resolution, promiseHasHandlerSymbol)) { | |
141 // Promise has already been rejected, but had no handler. | |
142 // Revoke previously triggered reject event. | |
143 %PromiseRevokeReject(resolution); | |
144 } | |
145 // Don't cause a debug event as this case is forwarding a rejection | |
146 %PromiseReject(promise, thenableValue, false); | |
147 SET_PRIVATE(resolution, promiseHasHandlerSymbol, true); | |
148 return; | |
149 } | |
150 } | |
151 | |
152 if (IS_CALLABLE(then)) { | |
153 if (DEBUG_IS_ACTIVE && %is_promise(resolution)) { | |
154 // Mark the dependency of the new promise on the resolution | |
155 SET_PRIVATE(resolution, promiseHandledBySymbol, promise); | |
156 } | |
157 %EnqueuePromiseResolveThenableJob(promise, resolution, then); | |
158 return; | |
159 } | |
160 } | |
161 %PromiseFulfill(promise, kFulfilled, resolution); | |
162 } | |
163 | |
164 // Only used by async-await.js | 107 // Only used by async-await.js |
165 function RejectPromise(promise, reason, debugEvent) { | 108 function RejectPromise(promise, reason, debugEvent) { |
166 %PromiseReject(promise, reason, debugEvent); | 109 %PromiseReject(promise, reason, debugEvent); |
167 } | 110 } |
168 | 111 |
169 // Export to bindings | 112 // Export to bindings |
170 function DoRejectPromise(promise, reason) { | 113 function DoRejectPromise(promise, reason) { |
171 %PromiseReject(promise, reason, true); | 114 %PromiseReject(promise, reason, true); |
172 } | 115 } |
173 | 116 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
244 // Promise.resolve ( x ) | 187 // Promise.resolve ( x ) |
245 function PromiseResolve(x) { | 188 function PromiseResolve(x) { |
246 if (!IS_RECEIVER(this)) { | 189 if (!IS_RECEIVER(this)) { |
247 throw %make_type_error(kCalledOnNonObject, PromiseResolve); | 190 throw %make_type_error(kCalledOnNonObject, PromiseResolve); |
248 } | 191 } |
249 if (%is_promise(x) && x.constructor === this) return x; | 192 if (%is_promise(x) && x.constructor === this) return x; |
250 | 193 |
251 // Avoid creating resolving functions. | 194 // Avoid creating resolving functions. |
252 if (this === GlobalPromise) { | 195 if (this === GlobalPromise) { |
253 var promise = %promise_internal_constructor(); | 196 var promise = %promise_internal_constructor(); |
254 ResolvePromise(promise, x); | 197 %promise_resolve(promise, x); |
255 return promise; | 198 return promise; |
256 } | 199 } |
257 | 200 |
258 // debugEvent is not so meaningful here as it will be resolved | 201 // debugEvent is not so meaningful here as it will be resolved |
259 var promiseCapability = NewPromiseCapability(this, true); | 202 var promiseCapability = NewPromiseCapability(this, true); |
260 %_Call(promiseCapability.resolve, UNDEFINED, x); | 203 %_Call(promiseCapability.resolve, UNDEFINED, x); |
261 return promiseCapability.promise; | 204 return promiseCapability.promise; |
262 } | 205 } |
263 | 206 |
264 // ES#sec-promise.all | 207 // ES#sec-promise.all |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
415 // Return whether the promise will be handled by a user-defined reject | 358 // 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 | 359 // 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. | 360 // search for a reject handler that's not the default PromiseIdRejectHandler. |
418 // This function also traverses dependencies of one Promise on another, | 361 // This function also traverses dependencies of one Promise on another, |
419 // set up through async/await and Promises resolved with Promises. | 362 // set up through async/await and Promises resolved with Promises. |
420 function PromiseHasUserDefinedRejectHandler() { | 363 function PromiseHasUserDefinedRejectHandler() { |
421 return PromiseHasUserDefinedRejectHandlerRecursive(this); | 364 return PromiseHasUserDefinedRejectHandlerRecursive(this); |
422 }; | 365 }; |
423 | 366 |
424 function MarkPromiseAsHandled(promise) { | 367 function MarkPromiseAsHandled(promise) { |
425 SET_PRIVATE(promise, promiseHasHandlerSymbol, true); | 368 %PromiseMarkAsHandled(promise); |
426 } | 369 } |
427 | 370 |
428 | 371 |
429 function PromiseSpecies() { | 372 function PromiseSpecies() { |
430 return this; | 373 return this; |
431 } | 374 } |
432 | 375 |
433 // ------------------------------------------------------------------- | 376 // ------------------------------------------------------------------- |
434 // Install exported functions. | 377 // Install exported functions. |
435 | 378 |
436 utils.InstallFunctions(GlobalPromise, DONT_ENUM, [ | 379 utils.InstallFunctions(GlobalPromise, DONT_ENUM, [ |
437 "reject", PromiseReject, | 380 "reject", PromiseReject, |
438 "all", PromiseAll, | 381 "all", PromiseAll, |
439 "race", PromiseRace, | 382 "race", PromiseRace, |
440 "resolve", PromiseResolve | 383 "resolve", PromiseResolve |
441 ]); | 384 ]); |
442 | 385 |
443 utils.InstallGetter(GlobalPromise, speciesSymbol, PromiseSpecies); | 386 utils.InstallGetter(GlobalPromise, speciesSymbol, PromiseSpecies); |
444 | 387 |
445 utils.InstallFunctions(GlobalPromise.prototype, DONT_ENUM, [ | 388 %SetCode(GlobalPromise.prototype.catch, PromiseCatch); |
446 "catch", PromiseCatch | |
447 ]); | |
448 | 389 |
449 %InstallToContext([ | 390 %InstallToContext([ |
450 "promise_catch", PromiseCatch, | 391 "promise_catch", PromiseCatch, |
jochen (gone - plz use gerrit)
2016/12/08 15:56:08
fyi, after the %SetCode above, we shouldn't use th
| |
451 "promise_create", PromiseCreate, | 392 "promise_create", PromiseCreate, |
452 "promise_has_user_defined_reject_handler", PromiseHasUserDefinedRejectHandler, | 393 "promise_has_user_defined_reject_handler", PromiseHasUserDefinedRejectHandler, |
453 "promise_reject", DoRejectPromise, | 394 "promise_reject", DoRejectPromise, |
454 // TODO(gsathya): Remove this once we update the promise builtin. | 395 // TODO(gsathya): Remove this once we update the promise builtin. |
455 "promise_internal_reject", RejectPromise, | 396 "promise_internal_reject", RejectPromise, |
456 "promise_resolve", ResolvePromise, | |
457 "promise_then", PromiseThen, | |
458 "promise_handle", PromiseHandle, | 397 "promise_handle", PromiseHandle, |
459 "promise_debug_get_info", PromiseDebugGetInfo, | 398 "promise_debug_get_info", PromiseDebugGetInfo, |
460 "new_promise_capability", NewPromiseCapability, | 399 "new_promise_capability", NewPromiseCapability, |
461 "internal_promise_capability", CreateInternalPromiseCapability, | 400 "internal_promise_capability", CreateInternalPromiseCapability, |
462 "promise_id_resolve_handler", PromiseIdResolveHandler, | 401 "promise_id_resolve_handler", PromiseIdResolveHandler, |
463 "promise_id_reject_handler", PromiseIdRejectHandler | 402 "promise_id_reject_handler", PromiseIdRejectHandler |
464 ]); | 403 ]); |
465 | 404 |
466 // This allows extras to create promises quickly without building extra | 405 // This allows extras to create promises quickly without building extra |
467 // resolve/reject closures, and allows them to later resolve and reject any | 406 // resolve/reject closures, and allows them to later resolve and reject any |
468 // promise without having to hold on to those closures forever. | 407 // promise without having to hold on to those closures forever. |
469 utils.InstallFunctions(extrasUtils, 0, [ | 408 utils.InstallFunctions(extrasUtils, 0, [ |
470 "createPromise", PromiseCreate, | 409 "createPromise", PromiseCreate, |
471 "resolvePromise", ResolvePromise, | |
472 "rejectPromise", DoRejectPromise, | 410 "rejectPromise", DoRejectPromise, |
473 "markPromiseAsHandled", MarkPromiseAsHandled | 411 "markPromiseAsHandled", MarkPromiseAsHandled |
474 ]); | 412 ]); |
475 | 413 |
476 utils.Export(function(to) { | 414 utils.Export(function(to) { |
477 to.PromiseCreate = PromiseCreate; | 415 to.PromiseCreate = PromiseCreate; |
478 to.PromiseThen = PromiseThen; | 416 to.PromiseThen = PromiseThen; |
479 | 417 |
480 to.CreateInternalPromiseCapability = CreateInternalPromiseCapability; | 418 to.CreateInternalPromiseCapability = CreateInternalPromiseCapability; |
481 to.ResolvePromise = ResolvePromise; | |
482 to.RejectPromise = RejectPromise; | 419 to.RejectPromise = RejectPromise; |
483 }); | 420 }); |
484 | 421 |
485 }) | 422 }) |
OLD | NEW |