| Index: src/js/promise.js
|
| diff --git a/src/js/promise.js b/src/js/promise.js
|
| index 25c8beaa9e0aef86dd966faa3af89d8e342c04a3..b78f68c4f71c367365a8a149803c3091a9e55f75 100644
|
| --- a/src/js/promise.js
|
| +++ b/src/js/promise.js
|
| @@ -20,12 +20,6 @@ var promiseForwardingHandlerSymbol =
|
| utils.ImportNow("promise_forwarding_handler_symbol");
|
| var promiseHasHandlerSymbol =
|
| utils.ImportNow("promise_has_handler_symbol");
|
| -var promiseRejectReactionsSymbol =
|
| - utils.ImportNow("promise_reject_reactions_symbol");
|
| -var promiseFulfillReactionsSymbol =
|
| - utils.ImportNow("promise_fulfill_reactions_symbol");
|
| -var promiseDeferredReactionSymbol =
|
| - utils.ImportNow("promise_deferred_reaction_symbol");
|
| var promiseHandledHintSymbol =
|
| utils.ImportNow("promise_handled_hint_symbol");
|
| var promiseRawSymbol = utils.ImportNow("promise_raw_symbol");
|
| @@ -36,6 +30,7 @@ var speciesSymbol = utils.ImportNow("species_symbol");
|
| var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
|
| var ObjectHasOwnProperty;
|
| var GlobalPromise = global.Promise;
|
| +var PromiseThen = GlobalPromise.prototype.then;
|
|
|
| utils.Import(function(from) {
|
| ObjectHasOwnProperty = from.ObjectHasOwnProperty;
|
| @@ -46,42 +41,6 @@ utils.Import(function(from) {
|
|
|
| // Core functionality.
|
|
|
| -function PromiseSet(promise, status, value) {
|
| - SET_PRIVATE(promise, promiseStateSymbol, status);
|
| - SET_PRIVATE(promise, promiseResultSymbol, value);
|
| -
|
| - // There are 3 possible states for the resolve, reject symbols when we add
|
| - // a new callback --
|
| - // 1) UNDEFINED -- This is the zero state where there is no callback
|
| - // registered. When we see this state, we directly attach the callbacks to
|
| - // the symbol.
|
| - // 2) !IS_ARRAY -- There is a single callback directly attached to the
|
| - // symbols. We need to create a new array to store additional callbacks.
|
| - // 3) IS_ARRAY -- There are multiple callbacks already registered,
|
| - // therefore we can just push the new callback to the existing array.
|
| - SET_PRIVATE(promise, promiseFulfillReactionsSymbol, UNDEFINED);
|
| - SET_PRIVATE(promise, promiseRejectReactionsSymbol, UNDEFINED);
|
| -
|
| - // This symbol is used only when one deferred needs to be attached. When more
|
| - // than one deferred need to be attached the promise, we attach them directly
|
| - // to the promiseFulfillReactionsSymbol and promiseRejectReactionsSymbol and
|
| - // reset this back to UNDEFINED.
|
| - SET_PRIVATE(promise, promiseDeferredReactionSymbol, UNDEFINED);
|
| -
|
| - return promise;
|
| -}
|
| -
|
| -function PromiseCreateAndSet(status, value) {
|
| - var promise = %promise_internal_constructor();
|
| - // If debug is active, notify about the newly created promise first.
|
| - if (DEBUG_IS_ACTIVE) PromiseSet(promise, kPending, UNDEFINED);
|
| - return PromiseSet(promise, status, value);
|
| -}
|
| -
|
| -function PromiseInit(promise) {
|
| - return PromiseSet(promise, kPending, UNDEFINED);
|
| -}
|
| -
|
| function PromiseHandle(value, handler, deferred) {
|
| var debug_is_active = DEBUG_IS_ACTIVE;
|
| try {
|
| @@ -98,7 +57,6 @@ function PromiseHandle(value, handler, deferred) {
|
| // Pass false for debugEvent so .then chaining or throwaway promises
|
| // in async functions do not trigger redundant ExceptionEvents.
|
| %PromiseReject(deferred.promise, exception, false);
|
| - PromiseSet(deferred.promise, kRejected, exception);
|
| } else {
|
| %_Call(deferred.reject, UNDEFINED, exception);
|
| }
|
| @@ -134,34 +92,6 @@ function PromiseDebugGetInfo(deferreds, status) {
|
| return [id, name];
|
| }
|
|
|
| -function PromiseAttachCallbacks(promise, deferred, onResolve, onReject) {
|
| - var maybeResolveCallbacks =
|
| - GET_PRIVATE(promise, promiseFulfillReactionsSymbol);
|
| - if (IS_UNDEFINED(maybeResolveCallbacks)) {
|
| - SET_PRIVATE(promise, promiseFulfillReactionsSymbol, onResolve);
|
| - SET_PRIVATE(promise, promiseRejectReactionsSymbol, onReject);
|
| - SET_PRIVATE(promise, promiseDeferredReactionSymbol, deferred);
|
| - } else if (!IS_ARRAY(maybeResolveCallbacks)) {
|
| - var resolveCallbacks = new InternalArray();
|
| - var rejectCallbacks = new InternalArray();
|
| - var existingDeferred = GET_PRIVATE(promise, promiseDeferredReactionSymbol);
|
| -
|
| - resolveCallbacks.push(
|
| - maybeResolveCallbacks, existingDeferred, onResolve, deferred);
|
| - rejectCallbacks.push(GET_PRIVATE(promise, promiseRejectReactionsSymbol),
|
| - existingDeferred,
|
| - onReject,
|
| - deferred);
|
| -
|
| - SET_PRIVATE(promise, promiseFulfillReactionsSymbol, resolveCallbacks);
|
| - SET_PRIVATE(promise, promiseRejectReactionsSymbol, rejectCallbacks);
|
| - SET_PRIVATE(promise, promiseDeferredReactionSymbol, UNDEFINED);
|
| - } else {
|
| - maybeResolveCallbacks.push(onResolve, deferred);
|
| - GET_PRIVATE(promise, promiseRejectReactionsSymbol).push(onReject, deferred);
|
| - }
|
| -}
|
| -
|
| function PromiseIdResolveHandler(x) { return x; }
|
| function PromiseIdRejectHandler(r) { %_ReThrow(r); }
|
| SET_PRIVATE(PromiseIdRejectHandler, promiseForwardingHandlerSymbol, true);
|
| @@ -171,8 +101,9 @@ SET_PRIVATE(PromiseIdRejectHandler, promiseForwardingHandlerSymbol, true);
|
|
|
| // For bootstrapper.
|
|
|
| +// This is used by utils and v8-extras.
|
| function PromiseCreate() {
|
| - return PromiseInit(%promise_internal_constructor());
|
| + return %promise_internal_constructor();
|
| }
|
|
|
| // ES#sec-promise-resolve-functions
|
| @@ -181,7 +112,6 @@ function ResolvePromise(promise, resolution) {
|
| if (resolution === promise) {
|
| var exception = %make_type_error(kPromiseCyclic, resolution);
|
| %PromiseReject(promise, exception, true);
|
| - PromiseSet(promise, kRejected, exception);
|
| return;
|
| }
|
| if (IS_RECEIVER(resolution)) {
|
| @@ -190,7 +120,6 @@ function ResolvePromise(promise, resolution) {
|
| var then = resolution.then;
|
| } catch (e) {
|
| %PromiseReject(promise, e, true);
|
| - PromiseSet(promise, kRejected, e);
|
| return;
|
| }
|
|
|
| @@ -198,18 +127,16 @@ function ResolvePromise(promise, resolution) {
|
| // rejected, shortcircuit the resolution procedure by directly
|
| // reusing the value from the promise.
|
| if (%is_promise(resolution) && then === PromiseThen) {
|
| - var thenableState = GET_PRIVATE(resolution, promiseStateSymbol);
|
| + var thenableState = %PromiseStatus(resolution);
|
| if (thenableState === kFulfilled) {
|
| // This goes inside the if-else to save one symbol lookup in
|
| // the slow path.
|
| - var thenableValue = GET_PRIVATE(resolution, promiseResultSymbol);
|
| - %PromiseFulfill(promise, kFulfilled, thenableValue,
|
| - promiseFulfillReactionsSymbol);
|
| - PromiseSet(promise, kFulfilled, thenableValue);
|
| + var thenableValue = %PromiseResult(resolution);
|
| + %PromiseFulfill(promise, kFulfilled, thenableValue);
|
| SET_PRIVATE(promise, promiseHasHandlerSymbol, true);
|
| return;
|
| } else if (thenableState === kRejected) {
|
| - var thenableValue = GET_PRIVATE(resolution, promiseResultSymbol);
|
| + var thenableValue = %PromiseResult(resolution);
|
| if (!HAS_DEFINED_PRIVATE(resolution, promiseHasHandlerSymbol)) {
|
| // Promise has already been rejected, but had no handler.
|
| // Revoke previously triggered reject event.
|
| @@ -217,7 +144,6 @@ function ResolvePromise(promise, resolution) {
|
| }
|
| // Don't cause a debug event as this case is forwarding a rejection
|
| %PromiseReject(promise, thenableValue, false);
|
| - PromiseSet(promise, kRejected, thenableValue);
|
| SET_PRIVATE(resolution, promiseHasHandlerSymbol, true);
|
| return;
|
| }
|
| @@ -232,21 +158,17 @@ function ResolvePromise(promise, resolution) {
|
| return;
|
| }
|
| }
|
| - %PromiseFulfill(promise, kFulfilled, resolution,
|
| - promiseFulfillReactionsSymbol);
|
| - PromiseSet(promise, kFulfilled, resolution);
|
| + %PromiseFulfill(promise, kFulfilled, resolution);
|
| }
|
|
|
| // Only used by async-await.js
|
| function RejectPromise(promise, reason, debugEvent) {
|
| %PromiseReject(promise, reason, debugEvent);
|
| - PromiseSet(promise, kRejected, reason);
|
| }
|
|
|
| // Export to bindings
|
| function DoRejectPromise(promise, reason) {
|
| %PromiseReject(promise, reason, true);
|
| - PromiseSet(promise, kRejected, reason);
|
| }
|
|
|
| // The resultCapability.promise is only ever fulfilled internally,
|
| @@ -254,7 +176,7 @@ function DoRejectPromise(promise, reason) {
|
| // calling them multiple times.
|
| function CreateInternalPromiseCapability() {
|
| return {
|
| - promise: PromiseCreate(),
|
| + promise: %promise_internal_constructor(),
|
| resolve: UNDEFINED,
|
| reject: UNDEFINED
|
| };
|
| @@ -265,7 +187,7 @@ function CreateInternalPromiseCapability() {
|
| function NewPromiseCapability(C, debugEvent) {
|
| if (C === GlobalPromise) {
|
| // Optimized case, avoid extra closure.
|
| - var promise = PromiseCreate();
|
| + var promise = %promise_internal_constructor();
|
| // TODO(gsathya): Remove container for callbacks when this is
|
| // moved to CPP/TF.
|
| var callbacks = %create_resolving_functions(promise, debugEvent);
|
| @@ -298,7 +220,7 @@ function PromiseReject(r) {
|
| }
|
| if (this === GlobalPromise) {
|
| // Optimized case, avoid extra closure.
|
| - var promise = PromiseCreateAndSet(kRejected, r);
|
| + var promise = %promise_create_and_set(kRejected, r);
|
| // Trigger debug events if the debugger is on, as Promise.reject is
|
| // equivalent to throwing an exception directly.
|
| %PromiseRejectEventFromStack(promise, r);
|
| @@ -310,55 +232,6 @@ function PromiseReject(r) {
|
| }
|
| }
|
|
|
| -function PerformPromiseThen(promise, onResolve, onReject, resultCapability) {
|
| - if (!IS_CALLABLE(onResolve)) onResolve = PromiseIdResolveHandler;
|
| - if (!IS_CALLABLE(onReject)) onReject = PromiseIdRejectHandler;
|
| -
|
| - var status = GET_PRIVATE(promise, promiseStateSymbol);
|
| - switch (status) {
|
| - case kPending:
|
| - PromiseAttachCallbacks(promise, resultCapability, onResolve, onReject);
|
| - break;
|
| - case kFulfilled:
|
| - %EnqueuePromiseReactionJob(GET_PRIVATE(promise, promiseResultSymbol),
|
| - onResolve, resultCapability, kFulfilled);
|
| - break;
|
| - case kRejected:
|
| - if (!HAS_DEFINED_PRIVATE(promise, promiseHasHandlerSymbol)) {
|
| - // Promise has already been rejected, but had no handler.
|
| - // Revoke previously triggered reject event.
|
| - %PromiseRevokeReject(promise);
|
| - }
|
| - %EnqueuePromiseReactionJob(GET_PRIVATE(promise, promiseResultSymbol),
|
| - onReject, resultCapability, kRejected);
|
| - break;
|
| - }
|
| -
|
| - // Mark this promise as having handler.
|
| - SET_PRIVATE(promise, promiseHasHandlerSymbol, true);
|
| - return resultCapability.promise;
|
| -}
|
| -
|
| -// ES#sec-promise.prototype.then
|
| -// Promise.prototype.then ( onFulfilled, onRejected )
|
| -// Multi-unwrapped chaining with thenable coercion.
|
| -function PromiseThen(onResolve, onReject) {
|
| - if (!%is_promise(this)) {
|
| - throw %make_type_error(kNotAPromise, this);
|
| - }
|
| -
|
| - var constructor = SpeciesConstructor(this, GlobalPromise);
|
| - var resultCapability;
|
| - if (constructor === GlobalPromise) {
|
| - resultCapability = CreateInternalPromiseCapability();
|
| - } else {
|
| - // Pass false for debugEvent so .then chaining does not trigger
|
| - // redundant ExceptionEvents.
|
| - resultCapability = NewPromiseCapability(constructor, false);
|
| - }
|
| - return PerformPromiseThen(this, onResolve, onReject, resultCapability);
|
| -}
|
| -
|
| // ES#sec-promise.prototype.catch
|
| // Promise.prototype.catch ( onRejected )
|
| function PromiseCatch(onReject) {
|
| @@ -377,7 +250,7 @@ function PromiseResolve(x) {
|
|
|
| // Avoid creating resolving functions.
|
| if (this === GlobalPromise) {
|
| - var promise = PromiseCreate();
|
| + var promise = %promise_internal_constructor();
|
| ResolvePromise(promise, x);
|
| return promise;
|
| }
|
| @@ -520,8 +393,10 @@ function PromiseHasUserDefinedRejectHandlerRecursive(promise) {
|
| return true;
|
| }
|
|
|
| - var queue = GET_PRIVATE(promise, promiseRejectReactionsSymbol);
|
| - var deferred = GET_PRIVATE(promise, promiseDeferredReactionSymbol);
|
| + if (!%is_promise(promise)) return false;
|
| +
|
| + var queue = %PromiseRejectReactions(promise);
|
| + var deferred = %PromiseDeferred(promise);
|
|
|
| if (IS_UNDEFINED(queue)) return false;
|
|
|
| @@ -529,8 +404,8 @@ function PromiseHasUserDefinedRejectHandlerRecursive(promise) {
|
| return PromiseHasUserDefinedRejectHandlerCheck(queue, deferred);
|
| }
|
|
|
| - for (var i = 0; i < queue.length; i += 2) {
|
| - if (PromiseHasUserDefinedRejectHandlerCheck(queue[i], queue[i + 1])) {
|
| + for (var i = 0; i < queue.length; i++) {
|
| + if (PromiseHasUserDefinedRejectHandlerCheck(queue[i], deferred[i])) {
|
| return true;
|
| }
|
| }
|
| @@ -568,7 +443,6 @@ utils.InstallFunctions(GlobalPromise, DONT_ENUM, [
|
| utils.InstallGetter(GlobalPromise, speciesSymbol, PromiseSpecies);
|
|
|
| utils.InstallFunctions(GlobalPromise.prototype, DONT_ENUM, [
|
| - "then", PromiseThen,
|
| "catch", PromiseCatch
|
| ]);
|
|
|
| @@ -582,7 +456,11 @@ utils.InstallFunctions(GlobalPromise.prototype, DONT_ENUM, [
|
| "promise_resolve", ResolvePromise,
|
| "promise_then", PromiseThen,
|
| "promise_handle", PromiseHandle,
|
| - "promise_debug_get_info", PromiseDebugGetInfo
|
| + "promise_debug_get_info", PromiseDebugGetInfo,
|
| + "new_promise_capability", NewPromiseCapability,
|
| + "internal_promise_capability", CreateInternalPromiseCapability,
|
| + "promise_id_resolve_handler", PromiseIdResolveHandler,
|
| + "promise_id_reject_handler", PromiseIdRejectHandler
|
| ]);
|
|
|
| // This allows extras to create promises quickly without building extra
|
| @@ -600,7 +478,6 @@ utils.Export(function(to) {
|
| to.PromiseThen = PromiseThen;
|
|
|
| to.CreateInternalPromiseCapability = CreateInternalPromiseCapability;
|
| - to.PerformPromiseThen = PerformPromiseThen;
|
| to.ResolvePromise = ResolvePromise;
|
| to.RejectPromise = RejectPromise;
|
| });
|
|
|