| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 (function(global, utils, extrasUtils) { | 5 (function(global, utils, extrasUtils) { |
| 6 | 6 |
| 7 "use strict"; | 7 "use strict"; |
| 8 | 8 |
| 9 %CheckIsBootstrapping(); | 9 %CheckIsBootstrapping(); |
| 10 | 10 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 utils.ImportNow("promise_deferred_reaction_symbol"); | 28 utils.ImportNow("promise_deferred_reaction_symbol"); |
| 29 var promiseHandledHintSymbol = | 29 var promiseHandledHintSymbol = |
| 30 utils.ImportNow("promise_handled_hint_symbol"); | 30 utils.ImportNow("promise_handled_hint_symbol"); |
| 31 var promiseRawSymbol = utils.ImportNow("promise_raw_symbol"); | 31 var promiseRawSymbol = utils.ImportNow("promise_raw_symbol"); |
| 32 var promiseStateSymbol = utils.ImportNow("promise_state_symbol"); | 32 var promiseStateSymbol = utils.ImportNow("promise_state_symbol"); |
| 33 var promiseResultSymbol = utils.ImportNow("promise_result_symbol"); | 33 var promiseResultSymbol = utils.ImportNow("promise_result_symbol"); |
| 34 var SpeciesConstructor; | 34 var SpeciesConstructor; |
| 35 var speciesSymbol = utils.ImportNow("species_symbol"); | 35 var speciesSymbol = utils.ImportNow("species_symbol"); |
| 36 var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol"); | 36 var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol"); |
| 37 var ObjectHasOwnProperty; | 37 var ObjectHasOwnProperty; |
| 38 var GlobalPromise = global.Promise; |
| 38 | 39 |
| 39 utils.Import(function(from) { | 40 utils.Import(function(from) { |
| 40 ObjectHasOwnProperty = from.ObjectHasOwnProperty; | 41 ObjectHasOwnProperty = from.ObjectHasOwnProperty; |
| 41 SpeciesConstructor = from.SpeciesConstructor; | 42 SpeciesConstructor = from.SpeciesConstructor; |
| 42 }); | 43 }); |
| 43 | 44 |
| 44 // ------------------------------------------------------------------- | 45 // ------------------------------------------------------------------- |
| 45 | 46 |
| 46 // [[PromiseState]] values: | 47 // [[PromiseState]] values: |
| 47 // These values should be kept in sync with PromiseStatus in globals.h | 48 // These values should be kept in sync with PromiseStatus in globals.h |
| 48 const kPending = 0; | 49 const kPending = 0; |
| 49 const kFulfilled = +1; | 50 const kFulfilled = +1; |
| 50 const kRejected = +2; | 51 const kRejected = +2; |
| 51 | 52 |
| 52 const kResolveCallback = 0; | 53 const kResolveCallback = 0; |
| 53 const kRejectCallback = 1; | 54 const kRejectCallback = 1; |
| 54 | 55 |
| 55 // ES#sec-promise-executor | |
| 56 // Promise ( executor ) | |
| 57 var GlobalPromise = function Promise(executor) { | |
| 58 if (executor === promiseRawSymbol) { | |
| 59 return %_NewObject(GlobalPromise, new.target); | |
| 60 } | |
| 61 if (IS_UNDEFINED(new.target)) throw %make_type_error(kNotAPromise, this); | |
| 62 if (!IS_CALLABLE(executor)) { | |
| 63 throw %make_type_error(kResolverNotAFunction, executor); | |
| 64 } | |
| 65 | |
| 66 var promise = PromiseInit(%_NewObject(GlobalPromise, new.target)); | |
| 67 // Calling the reject function would be a new exception, so debugEvent = true | |
| 68 // TODO(gsathya): Remove container for callbacks when this is moved | |
| 69 // to CPP/TF. | |
| 70 var callbacks = %create_resolving_functions(promise, true); | |
| 71 var debug_is_active = DEBUG_IS_ACTIVE; | |
| 72 try { | |
| 73 if (debug_is_active) %DebugPushPromise(promise); | |
| 74 executor(callbacks[kResolveCallback], callbacks[kRejectCallback]); | |
| 75 } %catch (e) { // Natives syntax to mark this catch block. | |
| 76 %_Call(callbacks[kRejectCallback], UNDEFINED, e); | |
| 77 } finally { | |
| 78 if (debug_is_active) %DebugPopPromise(); | |
| 79 } | |
| 80 | |
| 81 return promise; | |
| 82 } | |
| 83 | |
| 84 // Core functionality. | 56 // Core functionality. |
| 85 | 57 |
| 86 function PromiseSet(promise, status, value) { | 58 function PromiseSet(promise, status, value) { |
| 87 SET_PRIVATE(promise, promiseStateSymbol, status); | 59 SET_PRIVATE(promise, promiseStateSymbol, status); |
| 88 SET_PRIVATE(promise, promiseResultSymbol, value); | 60 SET_PRIVATE(promise, promiseResultSymbol, value); |
| 89 | 61 |
| 90 // There are 3 possible states for the resolve, reject symbols when we add | 62 // There are 3 possible states for the resolve, reject symbols when we add |
| 91 // a new callback -- | 63 // a new callback -- |
| 92 // 1) UNDEFINED -- This is the zero state where there is no callback | 64 // 1) UNDEFINED -- This is the zero state where there is no callback |
| 93 // registered. When we see this state, we directly attach the callbacks to | 65 // registered. When we see this state, we directly attach the callbacks to |
| 94 // the symbol. | 66 // the symbol. |
| 95 // 2) !IS_ARRAY -- There is a single callback directly attached to the | 67 // 2) !IS_ARRAY -- There is a single callback directly attached to the |
| 96 // symbols. We need to create a new array to store additional callbacks. | 68 // symbols. We need to create a new array to store additional callbacks. |
| 97 // 3) IS_ARRAY -- There are multiple callbacks already registered, | 69 // 3) IS_ARRAY -- There are multiple callbacks already registered, |
| 98 // therefore we can just push the new callback to the existing array. | 70 // therefore we can just push the new callback to the existing array. |
| 99 SET_PRIVATE(promise, promiseFulfillReactionsSymbol, UNDEFINED); | 71 SET_PRIVATE(promise, promiseFulfillReactionsSymbol, UNDEFINED); |
| 100 SET_PRIVATE(promise, promiseRejectReactionsSymbol, UNDEFINED); | 72 SET_PRIVATE(promise, promiseRejectReactionsSymbol, UNDEFINED); |
| 101 | 73 |
| 102 // This symbol is used only when one deferred needs to be attached. When more | 74 // This symbol is used only when one deferred needs to be attached. When more |
| 103 // than one deferred need to be attached the promise, we attach them directly | 75 // than one deferred need to be attached the promise, we attach them directly |
| 104 // to the promiseFulfillReactionsSymbol and promiseRejectReactionsSymbol and | 76 // to the promiseFulfillReactionsSymbol and promiseRejectReactionsSymbol and |
| 105 // reset this back to UNDEFINED. | 77 // reset this back to UNDEFINED. |
| 106 SET_PRIVATE(promise, promiseDeferredReactionSymbol, UNDEFINED); | 78 SET_PRIVATE(promise, promiseDeferredReactionSymbol, UNDEFINED); |
| 107 | 79 |
| 108 return promise; | 80 return promise; |
| 109 } | 81 } |
| 110 | 82 |
| 111 function PromiseCreateAndSet(status, value) { | 83 function PromiseCreateAndSet(status, value) { |
| 112 var promise = new GlobalPromise(promiseRawSymbol); | 84 var promise = %promise_internal_constructor(); |
| 113 // If debug is active, notify about the newly created promise first. | 85 // If debug is active, notify about the newly created promise first. |
| 114 if (DEBUG_IS_ACTIVE) PromiseSet(promise, kPending, UNDEFINED); | 86 if (DEBUG_IS_ACTIVE) PromiseSet(promise, kPending, UNDEFINED); |
| 115 return PromiseSet(promise, status, value); | 87 return PromiseSet(promise, status, value); |
| 116 } | 88 } |
| 117 | 89 |
| 118 function PromiseInit(promise) { | 90 function PromiseInit(promise) { |
| 119 return PromiseSet(promise, kPending, UNDEFINED); | 91 return PromiseSet(promise, kPending, UNDEFINED); |
| 120 } | 92 } |
| 121 | 93 |
| 122 function PromiseHandle(value, handler, deferred) { | 94 function PromiseHandle(value, handler, deferred) { |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 | 173 |
| 202 function PromiseIdResolveHandler(x) { return x; } | 174 function PromiseIdResolveHandler(x) { return x; } |
| 203 function PromiseIdRejectHandler(r) { %_ReThrow(r); } | 175 function PromiseIdRejectHandler(r) { %_ReThrow(r); } |
| 204 SET_PRIVATE(PromiseIdRejectHandler, promiseForwardingHandlerSymbol, true); | 176 SET_PRIVATE(PromiseIdRejectHandler, promiseForwardingHandlerSymbol, true); |
| 205 | 177 |
| 206 // ------------------------------------------------------------------- | 178 // ------------------------------------------------------------------- |
| 207 // Define exported functions. | 179 // Define exported functions. |
| 208 | 180 |
| 209 // For bootstrapper. | 181 // For bootstrapper. |
| 210 | 182 |
| 183 // Only used by utils |
| 211 // ES#sec-ispromise IsPromise ( x ) | 184 // ES#sec-ispromise IsPromise ( x ) |
| 212 function IsPromise(x) { | 185 function IsPromise(x) { |
| 213 return IS_RECEIVER(x) && HAS_DEFINED_PRIVATE(x, promiseStateSymbol); | 186 return IS_RECEIVER(x) && HAS_DEFINED_PRIVATE(x, promiseStateSymbol); |
| 214 } | 187 } |
| 215 | 188 |
| 216 function PromiseCreate() { | 189 function PromiseCreate() { |
| 217 return PromiseInit(new GlobalPromise(promiseRawSymbol)); | 190 return PromiseInit(%promise_internal_constructor()); |
| 218 } | 191 } |
| 219 | 192 |
| 220 // ES#sec-promise-resolve-functions | 193 // ES#sec-promise-resolve-functions |
| 221 // Promise Resolve Functions, steps 6-13 | 194 // Promise Resolve Functions, steps 6-13 |
| 222 function ResolvePromise(promise, resolution) { | 195 function ResolvePromise(promise, resolution) { |
| 223 if (resolution === promise) { | 196 if (resolution === promise) { |
| 224 var exception = %make_type_error(kPromiseCyclic, resolution); | 197 var exception = %make_type_error(kPromiseCyclic, resolution); |
| 225 %PromiseReject(promise, exception, true); | 198 %PromiseReject(promise, exception, true); |
| 226 PromiseSet(promise, kRejected, exception); | 199 PromiseSet(promise, kRejected, exception); |
| 227 return; | 200 return; |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 | 351 |
| 379 // Mark this promise as having handler. | 352 // Mark this promise as having handler. |
| 380 SET_PRIVATE(promise, promiseHasHandlerSymbol, true); | 353 SET_PRIVATE(promise, promiseHasHandlerSymbol, true); |
| 381 return resultCapability.promise; | 354 return resultCapability.promise; |
| 382 } | 355 } |
| 383 | 356 |
| 384 // ES#sec-promise.prototype.then | 357 // ES#sec-promise.prototype.then |
| 385 // Promise.prototype.then ( onFulfilled, onRejected ) | 358 // Promise.prototype.then ( onFulfilled, onRejected ) |
| 386 // Multi-unwrapped chaining with thenable coercion. | 359 // Multi-unwrapped chaining with thenable coercion. |
| 387 function PromiseThen(onResolve, onReject) { | 360 function PromiseThen(onResolve, onReject) { |
| 388 var status = GET_PRIVATE(this, promiseStateSymbol); | 361 if (!IsPromise(this)) { |
| 389 if (IS_UNDEFINED(status)) { | |
| 390 throw %make_type_error(kNotAPromise, this); | 362 throw %make_type_error(kNotAPromise, this); |
| 391 } | 363 } |
| 392 | 364 |
| 393 var constructor = SpeciesConstructor(this, GlobalPromise); | 365 var constructor = SpeciesConstructor(this, GlobalPromise); |
| 394 var resultCapability; | 366 var resultCapability; |
| 395 if (constructor === GlobalPromise) { | 367 if (constructor === GlobalPromise) { |
| 396 resultCapability = CreateInternalPromiseCapability(); | 368 resultCapability = CreateInternalPromiseCapability(); |
| 397 } else { | 369 } else { |
| 398 // Pass false for debugEvent so .then chaining does not trigger | 370 // Pass false for debugEvent so .then chaining does not trigger |
| 399 // redundant ExceptionEvents. | 371 // redundant ExceptionEvents. |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 594 } | 566 } |
| 595 | 567 |
| 596 | 568 |
| 597 function PromiseSpecies() { | 569 function PromiseSpecies() { |
| 598 return this; | 570 return this; |
| 599 } | 571 } |
| 600 | 572 |
| 601 // ------------------------------------------------------------------- | 573 // ------------------------------------------------------------------- |
| 602 // Install exported functions. | 574 // Install exported functions. |
| 603 | 575 |
| 604 %AddNamedProperty(global, 'Promise', GlobalPromise, DONT_ENUM); | |
| 605 %AddNamedProperty(GlobalPromise.prototype, toStringTagSymbol, "Promise", | |
| 606 DONT_ENUM | READ_ONLY); | |
| 607 | |
| 608 utils.InstallFunctions(GlobalPromise, DONT_ENUM, [ | 576 utils.InstallFunctions(GlobalPromise, DONT_ENUM, [ |
| 609 "reject", PromiseReject, | 577 "reject", PromiseReject, |
| 610 "all", PromiseAll, | 578 "all", PromiseAll, |
| 611 "race", PromiseRace, | 579 "race", PromiseRace, |
| 612 "resolve", PromiseResolve | 580 "resolve", PromiseResolve |
| 613 ]); | 581 ]); |
| 614 | 582 |
| 615 utils.InstallGetter(GlobalPromise, speciesSymbol, PromiseSpecies); | 583 utils.InstallGetter(GlobalPromise, speciesSymbol, PromiseSpecies); |
| 616 | 584 |
| 617 utils.InstallFunctions(GlobalPromise.prototype, DONT_ENUM, [ | 585 utils.InstallFunctions(GlobalPromise.prototype, DONT_ENUM, [ |
| (...skipping 29 matching lines...) Expand all Loading... |
| 647 to.PromiseCreate = PromiseCreate; | 615 to.PromiseCreate = PromiseCreate; |
| 648 to.PromiseThen = PromiseThen; | 616 to.PromiseThen = PromiseThen; |
| 649 | 617 |
| 650 to.CreateInternalPromiseCapability = CreateInternalPromiseCapability; | 618 to.CreateInternalPromiseCapability = CreateInternalPromiseCapability; |
| 651 to.PerformPromiseThen = PerformPromiseThen; | 619 to.PerformPromiseThen = PerformPromiseThen; |
| 652 to.ResolvePromise = ResolvePromise; | 620 to.ResolvePromise = ResolvePromise; |
| 653 to.RejectPromise = RejectPromise; | 621 to.RejectPromise = RejectPromise; |
| 654 }); | 622 }); |
| 655 | 623 |
| 656 }) | 624 }) |
| OLD | NEW |