summaryrefslogtreecommitdiffstats
path: root/js/src/builtin
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/builtin')
-rw-r--r--js/src/builtin/AsyncIteration.js7
-rw-r--r--js/src/builtin/Promise.cpp738
-rw-r--r--js/src/builtin/Promise.h22
-rw-r--r--js/src/builtin/ReflectParse.cpp20
4 files changed, 653 insertions, 134 deletions
diff --git a/js/src/builtin/AsyncIteration.js b/js/src/builtin/AsyncIteration.js
new file mode 100644
index 000000000..029c7c0f8
--- /dev/null
+++ b/js/src/builtin/AsyncIteration.js
@@ -0,0 +1,7 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+function AsyncIteratorIdentity() {
+ return this;
+}
diff --git a/js/src/builtin/Promise.cpp b/js/src/builtin/Promise.cpp
index 1d068f8c6..4900a91cb 100644
--- a/js/src/builtin/Promise.cpp
+++ b/js/src/builtin/Promise.cpp
@@ -11,11 +11,13 @@
#include "mozilla/TimeStamp.h"
#include "jscntxt.h"
+#include "jsexn.h"
+#include "jsiter.h"
#include "gc/Heap.h"
#include "js/Debug.h"
#include "vm/AsyncFunction.h"
-#include "vm/SelfHosting.h"
+#include "vm/AsyncIteration.h"
#include "jsobjinlines.h"
@@ -31,10 +33,34 @@ MillisecondsSinceStartup()
return (now - mozilla::TimeStamp::ProcessCreation(ignored)).ToMilliseconds();
}
-#define PROMISE_HANDLER_IDENTITY 0
-#define PROMISE_HANDLER_THROWER 1
-#define PROMISE_HANDLER_AWAIT_FULFILLED 2
-#define PROMISE_HANDLER_AWAIT_REJECTED 3
+enum PromiseHandler {
+ PromiseHandlerIdentity = 0,
+ PromiseHandlerThrower,
+
+ // ES 2018 draft 25.5.5.4-5.
+ PromiseHandlerAsyncFunctionAwaitedFulfilled,
+ PromiseHandlerAsyncFunctionAwaitedRejected,
+
+ // Async Iteration proposal 4.1.
+ PromiseHandlerAsyncGeneratorAwaitedFulfilled,
+ PromiseHandlerAsyncGeneratorAwaitedRejected,
+
+ // Async Iteration proposal 11.4.3.5.1-2.
+ PromiseHandlerAsyncGeneratorResumeNextReturnFulfilled,
+ PromiseHandlerAsyncGeneratorResumeNextReturnRejected,
+
+ // Async Iteration proposal 11.4.3.7 steps 8.c-e.
+ PromiseHandlerAsyncGeneratorYieldReturnAwaitedFulfilled,
+ PromiseHandlerAsyncGeneratorYieldReturnAwaitedRejected,
+
+ // Async Iteration proposal 11.1.3.2.5.
+ // Async-from-Sync iterator handlers take the resolved value and create new
+ // iterator objects. To do so it needs to forward whether the iterator is
+ // done. In spec, this is achieved via the [[Done]] internal slot. We
+ // enumerate both true and false cases here.
+ PromiseHandlerAsyncFromSyncIteratorValueUnwrapDone,
+ PromiseHandlerAsyncFromSyncIteratorValueUnwrapNotDone,
+};
enum ResolutionMode {
ResolveMode,
@@ -47,9 +73,8 @@ enum ResolveFunctionSlots {
};
enum RejectFunctionSlots {
- RejectFunctionSlot_Promise = ResolveFunctionSlot_Promise,
+ RejectFunctionSlot_Promise = 0,
RejectFunctionSlot_ResolveFunction,
- RejectFunctionSlot_PromiseAllData = RejectFunctionSlot_ResolveFunction,
};
enum PromiseAllResolveElementFunctionSlots {
@@ -86,7 +111,7 @@ class PromiseAllDataHolder : public NativeObject
static const Class class_;
JSObject* promiseObj() { return &getFixedSlot(PromiseAllDataHolderSlot_Promise).toObject(); }
JSObject* resolveObj() {
- return getFixedSlot(PromiseAllDataHolderSlot_ResolveFunction).toObjectOrNull();
+ return &getFixedSlot(PromiseAllDataHolderSlot_ResolveFunction).toObject();
}
Value valuesArray() { return getFixedSlot(PromiseAllDataHolderSlot_ValuesArray); }
int32_t remainingCount() {
@@ -126,7 +151,7 @@ NewPromiseAllDataHolder(JSContext* cx, HandleObject resultPromise, HandleValue v
dataHolder->setFixedSlot(PromiseAllDataHolderSlot_Promise, ObjectValue(*resultPromise));
dataHolder->setFixedSlot(PromiseAllDataHolderSlot_RemainingElements, Int32Value(1));
dataHolder->setFixedSlot(PromiseAllDataHolderSlot_ValuesArray, valuesArray);
- dataHolder->setFixedSlot(PromiseAllDataHolderSlot_ResolveFunction, ObjectOrNullValue(resolve));
+ dataHolder->setFixedSlot(PromiseAllDataHolderSlot_ResolveFunction, ObjectValue(*resolve));
return dataHolder;
}
@@ -177,13 +202,15 @@ enum ReactionRecordSlots {
ReactionRecordSlot_IncumbentGlobalObject,
ReactionRecordSlot_Flags,
ReactionRecordSlot_HandlerArg,
+ ReactionRecordSlot_Generator,
ReactionRecordSlots,
};
#define REACTION_FLAG_RESOLVED 0x1
#define REACTION_FLAG_FULFILLED 0x2
#define REACTION_FLAG_IGNORE_DEFAULT_RESOLUTION 0x4
-#define REACTION_FLAG_AWAIT 0x8
+#define REACTION_FLAG_ASYNC_FUNCTION 0x8
+#define REACTION_FLAG_ASYNC_GENERATOR 0x10
// ES2016, 25.4.1.2.
class PromiseReactionRecord : public NativeObject
@@ -210,14 +237,30 @@ class PromiseReactionRecord : public NativeObject
flags |= REACTION_FLAG_FULFILLED;
setFixedSlot(ReactionRecordSlot_Flags, Int32Value(flags));
}
- void setIsAwait() {
+ void setIsAsyncFunction() {
+ int32_t flags = this->flags();
+ flags |= REACTION_FLAG_ASYNC_FUNCTION;
+ setFixedSlot(ReactionRecordSlot_Flags, Int32Value(flags));
+ }
+ bool isAsyncFunction() {
int32_t flags = this->flags();
- flags |= REACTION_FLAG_AWAIT;
+ return flags & REACTION_FLAG_ASYNC_FUNCTION;
+ }
+ void setIsAsyncGenerator(Handle<AsyncGeneratorObject*> asyncGenObj) {
+ int32_t flags = this->flags();
+ flags |= REACTION_FLAG_ASYNC_GENERATOR;
setFixedSlot(ReactionRecordSlot_Flags, Int32Value(flags));
+
+ setFixedSlot(ReactionRecordSlot_Generator, ObjectValue(*asyncGenObj));
}
- bool isAwait() {
+ bool isAsyncGenerator() {
int32_t flags = this->flags();
- return flags & REACTION_FLAG_AWAIT;
+ return flags & REACTION_FLAG_ASYNC_GENERATOR;
+ }
+ AsyncGeneratorObject* asyncGenerator() {
+ MOZ_ASSERT(isAsyncGenerator());
+ return &getFixedSlot(ReactionRecordSlot_Generator).toObject()
+ .as<AsyncGeneratorObject>();
}
Value handler() {
MOZ_ASSERT(targetState() != JS::PromiseState::Pending);
@@ -277,12 +320,6 @@ CreateResolvingFunctions(JSContext* cx, HandleValue promise,
if (!reject)
return false;
- // TODO: remove this once all self-hosted promise code is gone.
- // The resolving functions are trusted, so self-hosted code should be able
- // to call them using callFunction instead of callContentFunction.
- resolve->setFlags(resolve->flags() | JSFunction::SELF_HOSTED);
- reject->setFlags(reject->flags() | JSFunction::SELF_HOSTED);
-
resolve->setExtendedSlot(ResolveFunctionSlot_Promise, promise);
resolve->setExtendedSlot(ResolveFunctionSlot_RejectFunction, ObjectValue(*reject));
@@ -319,28 +356,27 @@ RejectPromiseFunction(JSContext* cx, unsigned argc, Value* vp)
return true;
}
+ // Step 5.
+ // Here, we only remove the Promise reference from the resolution
+ // functions. Actually marking it as fulfilled/rejected happens later.
+ ClearResolutionFunctionSlots(reject);
+
RootedObject promise(cx, &promiseVal.toObject());
// In some cases the Promise reference on the resolution function won't
// have been removed during resolution, so we need to check that here,
// too.
if (promise->is<PromiseObject>() &&
- PromiseHasAnyFlag(promise->as<PromiseObject>(), PROMISE_FLAG_RESOLVED))
+ promise->as<PromiseObject>().state() != JS::PromiseState::Pending)
{
- args.rval().setUndefined();
return true;
}
- // Step 5.
- // Here, we only remove the Promise reference from the resolution
- // functions. Actually marking it as fulfilled/rejected happens later.
- ClearResolutionFunctionSlots(reject);
-
// Step 6.
- bool result = RejectMaybeWrappedPromise(cx, promise, reasonVal);
- if (result)
- args.rval().setUndefined();
- return result;
+ if (!RejectMaybeWrappedPromise(cx, promise, reasonVal))
+ return false;
+ args.rval().setUndefined();
+ return true;
}
static MOZ_MUST_USE bool FulfillMaybeWrappedPromise(JSContext *cx, HandleObject promiseObj,
@@ -351,16 +387,28 @@ static MOZ_MUST_USE bool EnqueuePromiseResolveThenableJob(JSContext* cx,
HandleValue thenable,
HandleValue thenVal);
-// ES2016, 25.4.1.3.2, steps 7-13.
+// ES2016, 25.4.1.3.2, steps 6-13.
static MOZ_MUST_USE bool
ResolvePromiseInternal(JSContext* cx, HandleObject promise, HandleValue resolutionVal)
{
- // Step 7.
+ // Step 7 (reordered).
if (!resolutionVal.isObject())
return FulfillMaybeWrappedPromise(cx, promise, resolutionVal);
RootedObject resolution(cx, &resolutionVal.toObject());
+ // Step 6.
+ if (resolution == promise) {
+ // Step 6.a.
+ JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
+ JSMSG_CANNOT_RESOLVE_PROMISE_WITH_ITSELF);
+ RootedValue selfResolutionError(cx);
+ MOZ_ALWAYS_TRUE(GetAndClearException(cx, &selfResolutionError));
+
+ // Step 6.b.
+ return RejectMaybeWrappedPromise(cx, promise, selfResolutionError);
+ }
+
// Step 8.
RootedValue thenVal(cx);
bool status = GetProperty(cx, resolution, resolution, cx->names().then, &thenVal);
@@ -398,10 +446,7 @@ ResolvePromiseFunction(JSContext* cx, unsigned argc, Value* vp)
RootedFunction resolve(cx, &args.callee().as<JSFunction>());
RootedValue resolutionVal(cx, args.get(0));
- // Steps 1-2.
- RootedValue promiseVal(cx, resolve->getExtendedSlot(ResolveFunctionSlot_Promise));
-
- // Steps 3-4.
+ // Steps 3-4 (reordered).
// We use the reference to the reject function as a signal for whether
// the resolve or reject function was already called, at which point
// the references on each of the functions are cleared.
@@ -410,43 +455,28 @@ ResolvePromiseFunction(JSContext* cx, unsigned argc, Value* vp)
return true;
}
- RootedObject promise(cx, &promiseVal.toObject());
+ // Steps 1-2 (reordered).
+ RootedObject promise(cx, &resolve->getExtendedSlot(ResolveFunctionSlot_Promise).toObject());
+
+ // Step 5.
+ // Here, we only remove the Promise reference from the resolution
+ // functions. Actually marking it as fulfilled/rejected happens later.
+ ClearResolutionFunctionSlots(resolve);
// In some cases the Promise reference on the resolution function won't
// have been removed during resolution, so we need to check that here,
// too.
if (promise->is<PromiseObject>() &&
- PromiseHasAnyFlag(promise->as<PromiseObject>(), PROMISE_FLAG_RESOLVED))
+ promise->as<PromiseObject>().state() != JS::PromiseState::Pending)
{
- args.rval().setUndefined();
return true;
}
- // Step 5.
- // Here, we only remove the Promise reference from the resolution
- // functions. Actually marking it as fulfilled/rejected happens later.
- ClearResolutionFunctionSlots(resolve);
-
- // Step 6.
- if (resolutionVal == promiseVal) {
- // Step 6.a.
- JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
- JSMSG_CANNOT_RESOLVE_PROMISE_WITH_ITSELF);
- RootedValue selfResolutionError(cx);
- bool status = GetAndClearException(cx, &selfResolutionError);
- MOZ_ASSERT(status);
-
- // Step 6.b.
- status = RejectMaybeWrappedPromise(cx, promise, selfResolutionError);
- if (status)
- args.rval().setUndefined();
- return status;
- }
-
- bool status = ResolvePromiseInternal(cx, promise, resolutionVal);
- if (status)
- args.rval().setUndefined();
- return status;
+ // Steps 6-13.
+ if (!ResolvePromiseInternal(cx, promise, resolutionVal))
+ return false;
+ args.rval().setUndefined();
+ return true;
}
static bool PromiseReactionJob(JSContext* cx, unsigned argc, Value* vp);
@@ -652,7 +682,7 @@ enum GetCapabilitiesExecutorSlots {
};
static MOZ_MUST_USE PromiseObject*
-CreatePromiseObjectWithDefaultResolution(JSContext* cx)
+CreatePromiseObjectWithoutResolutionFunctions(JSContext* cx)
{
Rooted<PromiseObject*> promise(cx, CreatePromiseObjectInternal(cx));
if (!promise)
@@ -687,7 +717,7 @@ NewPromiseCapability(JSContext* cx, HandleObject C, MutableHandleObject promise,
// in the list passed to all/race, which (potentially) means exposing them
// to content.
if (canOmitResolutionFunctions && IsNativeFunction(cVal, PromiseConstructor)) {
- promise.set(CreatePromiseObjectWithDefaultResolution(cx));
+ promise.set(CreatePromiseObjectWithoutResolutionFunctions(cx));
if (!promise)
return false;
return true;
@@ -795,9 +825,7 @@ RejectMaybeWrappedPromise(JSContext *cx, HandleObject promiseObj, HandleValue re
// interpreter frame active right now. If a thenable job with a
// throwing `then` function got us here, that'll not be the case,
// so we add one by throwing the error from self-hosted code.
- FixedInvokeArgs<1> getErrorArgs(cx);
- getErrorArgs[0].set(Int32Value(JSMSG_PROMISE_ERROR_IN_WRAPPED_REJECTION_REASON));
- if (!CallSelfHostedFunction(cx, "GetInternalError", reason, getErrorArgs, &reason))
+ if (!GetInternalError(cx, JSMSG_PROMISE_ERROR_IN_WRAPPED_REJECTION_REASON, &reason))
return false;
}
}
@@ -832,10 +860,10 @@ TriggerPromiseReactions(JSContext* cx, HandleValue reactionsVal, JS::PromiseStat
}
static MOZ_MUST_USE bool
-AwaitPromiseReactionJob(JSContext* cx, Handle<PromiseReactionRecord*> reaction,
- MutableHandleValue rval)
+AsyncFunctionPromiseReactionJob(JSContext* cx, Handle<PromiseReactionRecord*> reaction,
+ MutableHandleValue rval)
{
- MOZ_ASSERT(reaction->isAwait());
+ MOZ_ASSERT(reaction->isAsyncFunction());
RootedValue handlerVal(cx, reaction->handler());
RootedValue argument(cx, reaction->handlerArg());
@@ -843,15 +871,14 @@ AwaitPromiseReactionJob(JSContext* cx, Handle<PromiseReactionRecord*> reaction,
RootedValue generatorVal(cx, resultPromise->getFixedSlot(PromiseSlot_AwaitGenerator));
int32_t handlerNum = int32_t(handlerVal.toNumber());
- MOZ_ASSERT(handlerNum == PROMISE_HANDLER_AWAIT_FULFILLED
- || handlerNum == PROMISE_HANDLER_AWAIT_REJECTED);
// Await's handlers don't return a value, nor throw exception.
// They fail only on OOM.
- if (handlerNum == PROMISE_HANDLER_AWAIT_FULFILLED) {
+ if (handlerNum == PromiseHandlerAsyncFunctionAwaitedFulfilled) {
if (!AsyncFunctionAwaitedFulfilled(cx, resultPromise, generatorVal, argument))
return false;
} else {
+ MOZ_ASSERT(handlerNum == PromiseHandlerAsyncFunctionAwaitedRejected);
if (!AsyncFunctionAwaitedRejected(cx, resultPromise, generatorVal, argument))
return false;
}
@@ -860,6 +887,55 @@ AwaitPromiseReactionJob(JSContext* cx, Handle<PromiseReactionRecord*> reaction,
return true;
}
+static MOZ_MUST_USE bool
+AsyncGeneratorPromiseReactionJob(JSContext* cx, Handle<PromiseReactionRecord*> reaction,
+ MutableHandleValue rval)
+{
+ MOZ_ASSERT(reaction->isAsyncGenerator());
+
+ RootedValue handlerVal(cx, reaction->handler());
+ RootedValue argument(cx, reaction->handlerArg());
+ Rooted<AsyncGeneratorObject*> asyncGenObj(cx, reaction->asyncGenerator());
+
+ int32_t handlerNum = int32_t(handlerVal.toNumber());
+
+ // Await's handlers don't return a value, nor throw exception.
+ // They fail only on OOM.
+ if (handlerNum == PromiseHandlerAsyncGeneratorAwaitedFulfilled) {
+ // 4.1.1.
+ if (!AsyncGeneratorAwaitedFulfilled(cx, asyncGenObj, argument))
+ return false;
+ } else if (handlerNum == PromiseHandlerAsyncGeneratorAwaitedRejected) {
+ // 4.1.2.
+ if (!AsyncGeneratorAwaitedRejected(cx, asyncGenObj, argument))
+ return false;
+ } else if (handlerNum == PromiseHandlerAsyncGeneratorResumeNextReturnFulfilled) {
+ asyncGenObj->setCompleted();
+ // 11.4.3.5.1 step 1.
+ if (!AsyncGeneratorResolve(cx, asyncGenObj, argument, true))
+ return false;
+ } else if (handlerNum == PromiseHandlerAsyncGeneratorResumeNextReturnRejected) {
+ asyncGenObj->setCompleted();
+ // 11.4.3.5.2 step 1.
+ if (!AsyncGeneratorReject(cx, asyncGenObj, argument))
+ return false;
+ } else if (handlerNum == PromiseHandlerAsyncGeneratorYieldReturnAwaitedFulfilled) {
+ asyncGenObj->setExecuting();
+ // 11.4.3.7 steps 8.d-e.
+ if (!AsyncGeneratorYieldReturnAwaitedFulfilled(cx, asyncGenObj, argument))
+ return false;
+ } else {
+ MOZ_ASSERT(handlerNum == PromiseHandlerAsyncGeneratorYieldReturnAwaitedRejected);
+ asyncGenObj->setExecuting();
+ // 11.4.3.7 step 8.c.
+ if (!AsyncGeneratorYieldReturnAwaitedRejected(cx, asyncGenObj, argument))
+ return false;
+ }
+
+ rval.setUndefined();
+ return true;
+}
+
// ES2016, 25.4.2.1.
/**
* Callback triggering the fulfill/reject reaction for a resolved Promise,
@@ -903,8 +979,10 @@ PromiseReactionJob(JSContext* cx, unsigned argc, Value* vp)
// Steps 1-2.
Rooted<PromiseReactionRecord*> reaction(cx, &reactionObj->as<PromiseReactionRecord>());
- if (reaction->isAwait())
- return AwaitPromiseReactionJob(cx, reaction, args.rval());
+ if (reaction->isAsyncFunction())
+ return AsyncFunctionPromiseReactionJob(cx, reaction, args.rval());
+ if (reaction->isAsyncGenerator())
+ return AsyncGeneratorPromiseReactionJob(cx, reaction, args.rval());
// Step 3.
RootedValue handlerVal(cx, reaction->handler());
@@ -919,13 +997,23 @@ PromiseReactionJob(JSContext* cx, unsigned argc, Value* vp)
int32_t handlerNum = int32_t(handlerVal.toNumber());
// Step 4.
- if (handlerNum == PROMISE_HANDLER_IDENTITY) {
+ if (handlerNum == PromiseHandlerIdentity) {
handlerResult = argument;
- } else {
+ } else if (handlerNum == PromiseHandlerThrower) {
// Step 5.
- MOZ_ASSERT(handlerNum == PROMISE_HANDLER_THROWER);
resolutionMode = RejectMode;
handlerResult = argument;
+ } else {
+ MOZ_ASSERT(handlerNum == PromiseHandlerAsyncFromSyncIteratorValueUnwrapDone ||
+ handlerNum == PromiseHandlerAsyncFromSyncIteratorValueUnwrapNotDone);
+
+ bool done = handlerNum == PromiseHandlerAsyncFromSyncIteratorValueUnwrapDone;
+ // Async Iteration proposal 11.1.3.2.5 step 1.
+ RootedObject resultObj(cx, CreateIterResultObject(cx, argument, done));
+ if (!resultObj)
+ return false;
+
+ handlerResult = ObjectValue(*resultObj);
}
} else {
// Step 6.
@@ -964,8 +1052,8 @@ PromiseReactionJob(JSContext* cx, unsigned argc, Value* vp)
*
* Usage of the function's extended slots is as follows:
* ThenableJobSlot_Handler: The handler to use as the Promise reaction.
- * This can be PROMISE_HANDLER_IDENTITY,
- * PROMISE_HANDLER_THROWER, or a callable. In the
+ * This can be PromiseHandlerIdentity,
+ * PromiseHandlerThrower, or a callable. In the
* latter case, it's guaranteed to be an object
* from the same compartment as the
* PromiseReactionJob.
@@ -1100,11 +1188,17 @@ GetResolveFunctionFromReject(JSFunction* reject)
{
MOZ_ASSERT(reject->maybeNative() == RejectPromiseFunction);
Value resolveFunVal = reject->getExtendedSlot(RejectFunctionSlot_ResolveFunction);
- if (IsNativeFunction(resolveFunVal, ResolvePromiseFunction))
- return &resolveFunVal.toObject().as<JSFunction>();
+ MOZ_ASSERT(IsNativeFunction(resolveFunVal, ResolvePromiseFunction));
+ return &resolveFunVal.toObject().as<JSFunction>();
+}
- PromiseAllDataHolder* resolveFunObj = &resolveFunVal.toObject().as<PromiseAllDataHolder>();
- return &resolveFunObj->resolveObj()->as<JSFunction>();
+static JSFunction*
+GetRejectFunctionFromResolve(JSFunction* resolve)
+{
+ MOZ_ASSERT(resolve->maybeNative() == ResolvePromiseFunction);
+ Value rejectFunVal = resolve->getExtendedSlot(ResolveFunctionSlot_RejectFunction);
+ MOZ_ASSERT(IsNativeFunction(rejectFunVal, RejectPromiseFunction));
+ return &rejectFunVal.toObject().as<JSFunction>();
}
static JSFunction*
@@ -1140,8 +1234,7 @@ ClearResolutionFunctionSlots(JSFunction* resolutionFun)
JSFunction* reject;
if (resolutionFun->maybeNative() == ResolvePromiseFunction) {
resolve = resolutionFun;
- reject = &resolutionFun->getExtendedSlot(ResolveFunctionSlot_RejectFunction)
- .toObject().as<JSFunction>();
+ reject = GetRejectFunctionFromResolve(resolutionFun);
} else {
resolve = GetResolveFunctionFromReject(resolutionFun);
reject = resolutionFun;
@@ -1367,6 +1460,14 @@ PromiseObject::create(JSContext* cx, HandleObject executor, HandleObject proto /
return promise;
}
+// ES2016, 25.4.3.1. skipping creation of resolution functions and executor
+// function invocation.
+/* static */ PromiseObject*
+PromiseObject::createSkippingExecutor(JSContext* cx)
+{
+ return CreatePromiseObjectWithoutResolutionFunctions(cx);
+}
+
static MOZ_MUST_USE bool PerformPromiseAll(JSContext *cx, JS::ForOfIterator& iterator,
HandleObject C, HandleObject promiseObj,
HandleObject resolve, HandleObject reject,
@@ -1585,7 +1686,6 @@ RunResolutionFunction(JSContext *cx, HandleObject resolutionFun, HandleValue res
if (promise->state() != JS::PromiseState::Pending)
return true;
-
if (mode == ResolveMode) {
if (!PromiseHasAnyFlag(*promise, PROMISE_FLAG_DEFAULT_RESOLVE_FUNCTION))
return true;
@@ -1595,7 +1695,6 @@ RunResolutionFunction(JSContext *cx, HandleObject resolutionFun, HandleValue res
if (!PromiseHasAnyFlag(*promise, PROMISE_FLAG_DEFAULT_REJECT_FUNCTION))
return true;
return RejectMaybeWrappedPromise(cx, promiseObj, result);
-
}
// ES2016, 25.4.4.1.1.
@@ -1669,7 +1768,7 @@ PerformPromiseAll(JSContext *cx, JS::ForOfIterator& iterator, HandleObject C,
// Step 6.
RootedValue nextValue(cx);
RootedId indexId(cx);
- RootedValue rejectFunVal(cx, ObjectOrNullValue(reject));
+ RootedValue rejectFunVal(cx, ObjectValue(*reject));
while (true) {
// Steps a-c, e-g.
@@ -1690,11 +1789,8 @@ PerformPromiseAll(JSContext *cx, JS::ForOfIterator& iterator, HandleObject C,
// Steps d.iii-iv.
if (remainingCount == 0) {
- if (resolve) {
- return RunResolutionFunction(cx, resolve, valuesArrayVal, ResolveMode,
- promiseObj);
- }
- return ResolvePromiseInternal(cx, promiseObj, valuesArrayVal);
+ return RunResolutionFunction(cx, resolve, valuesArrayVal, ResolveMode,
+ promiseObj);
}
// We're all set for now!
@@ -1817,13 +1913,8 @@ PromiseAllResolveElementFunction(JSContext* cx, unsigned argc, Value* vp)
// Step 6 (Adapted to work with PromiseAllDataHolder's layout).
RootedObject resolveAllFun(cx, data->resolveObj());
RootedObject promiseObj(cx, data->promiseObj());
- if (!resolveAllFun) {
- if (!FulfillMaybeWrappedPromise(cx, promiseObj, valuesVal))
- return false;
- } else {
- if (!RunResolutionFunction(cx, resolveAllFun, valuesVal, ResolveMode, promiseObj))
- return false;
- }
+ if (!RunResolutionFunction(cx, resolveAllFun, valuesVal, ResolveMode, promiseObj))
+ return false;
}
// Step 11.
@@ -1904,8 +1995,8 @@ PerformPromiseRace(JSContext *cx, JS::ForOfIterator& iterator, HandleObject C,
RootedValue CVal(cx, ObjectValue(*C));
RootedValue nextValue(cx);
- RootedValue resolveFunVal(cx, ObjectOrNullValue(resolve));
- RootedValue rejectFunVal(cx, ObjectOrNullValue(reject));
+ RootedValue resolveFunVal(cx, ObjectValue(*resolve));
+ RootedValue rejectFunVal(cx, ObjectValue(*reject));
while (true) {
// Steps a-c, e-g.
@@ -2155,12 +2246,12 @@ static MOZ_MUST_USE bool PerformPromiseThenWithReaction(JSContext* cx,
// Some async/await functions are implemented here instead of
// js/src/builtin/AsyncFunction.cpp, to call Promise internal functions.
-// Async Functions proposal 1.1.8 and 1.2.14 step 1.
+// ES 2018 draft 14.6.11 and 14.7.14 step 1.
MOZ_MUST_USE PromiseObject*
js::CreatePromiseObjectForAsync(JSContext* cx, HandleValue generatorVal)
{
// Step 1.
- Rooted<PromiseObject*> promise(cx, CreatePromiseObjectWithDefaultResolution(cx));
+ Rooted<PromiseObject*> promise(cx, CreatePromiseObjectWithoutResolutionFunctions(cx));
if (!promise)
return nullptr;
@@ -2169,7 +2260,7 @@ js::CreatePromiseObjectForAsync(JSContext* cx, HandleValue generatorVal)
return promise;
}
-// Async Functions proposal 2.2 steps 3.f, 3.g.
+// ES 2018 draft 25.5.5.2 steps 3.f, 3.g.
MOZ_MUST_USE bool
js::AsyncFunctionThrown(JSContext* cx, Handle<PromiseObject*> resultPromise)
{
@@ -2185,7 +2276,7 @@ js::AsyncFunctionThrown(JSContext* cx, Handle<PromiseObject*> resultPromise)
return true;
}
-// Async Functions proposal 2.2 steps 3.d-e, 3.g.
+// ES 2018 draft 25.5.5.2 steps 3.d-e, 3.g.
MOZ_MUST_USE bool
js::AsyncFunctionReturned(JSContext* cx, Handle<PromiseObject*> resultPromise, HandleValue value)
{
@@ -2197,28 +2288,30 @@ js::AsyncFunctionReturned(JSContext* cx, Handle<PromiseObject*> resultPromise, H
return true;
}
-// Async Functions proposal 2.3 steps 2-8.
-MOZ_MUST_USE bool
-js::AsyncFunctionAwait(JSContext* cx, Handle<PromiseObject*> resultPromise, HandleValue value)
+// Helper function that performs the equivalent steps as
+// Async Iteration proposal 4.1 Await steps 2-3, 6-9 or similar.
+template <typename T>
+static MOZ_MUST_USE bool
+InternalAwait(JSContext* cx, HandleValue value, HandleObject resultPromise,
+ HandleValue onFulfilled, HandleValue onRejected, T extraStep)
{
+ MOZ_ASSERT(onFulfilled.isNumber() || onFulfilled.isObject());
+ MOZ_ASSERT(onRejected.isNumber() || onRejected.isObject());
+
// Step 2.
- Rooted<PromiseObject*> promise(cx, CreatePromiseObjectWithDefaultResolution(cx));
+ Rooted<PromiseObject*> promise(cx, CreatePromiseObjectWithoutResolutionFunctions(cx));
if (!promise)
return false;
- // Steps 3.
+ // Step 3.
if (!ResolvePromiseInternal(cx, promise, value))
return false;
- // Steps 4-5.
- RootedValue onFulfilled(cx, Int32Value(PROMISE_HANDLER_AWAIT_FULFILLED));
- RootedValue onRejected(cx, Int32Value(PROMISE_HANDLER_AWAIT_REJECTED));
-
RootedObject incumbentGlobal(cx);
if (!GetObjectFromIncumbentGlobal(cx, &incumbentGlobal))
return false;
- // Steps 6-7.
+ // Steps 7-8.
Rooted<PromiseReactionRecord*> reaction(cx, NewReactionRecord(cx, resultPromise,
onFulfilled, onRejected,
nullptr, nullptr,
@@ -2226,12 +2319,403 @@ js::AsyncFunctionAwait(JSContext* cx, Handle<PromiseObject*> resultPromise, Hand
if (!reaction)
return false;
- reaction->setIsAwait();
+ // Step 6.
+ extraStep(reaction);
- // Step 8.
+ // Step 9.
return PerformPromiseThenWithReaction(cx, promise, reaction);
}
+// ES 2018 draft 25.5.5.3 steps 2-10.
+MOZ_MUST_USE bool
+js::AsyncFunctionAwait(JSContext* cx, Handle<PromiseObject*> resultPromise, HandleValue value)
+{
+ // Steps 4-5.
+ RootedValue onFulfilled(cx, Int32Value(PromiseHandlerAsyncFunctionAwaitedFulfilled));
+ RootedValue onRejected(cx, Int32Value(PromiseHandlerAsyncFunctionAwaitedRejected));
+
+ // Steps 2-3, 6-10.
+ auto extra = [](Handle<PromiseReactionRecord*> reaction) {
+ reaction->setIsAsyncFunction();
+ };
+ return InternalAwait(cx, value, resultPromise, onFulfilled, onRejected, extra);
+}
+
+// Async Iteration proposal 4.1 Await steps 2-9.
+MOZ_MUST_USE bool
+js::AsyncGeneratorAwait(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
+ HandleValue value)
+{
+ // Steps 4-5.
+ RootedValue onFulfilled(cx, Int32Value(PromiseHandlerAsyncGeneratorAwaitedFulfilled));
+ RootedValue onRejected(cx, Int32Value(PromiseHandlerAsyncGeneratorAwaitedRejected));
+
+ // Steps 2-3, 6-9.
+ auto extra = [&](Handle<PromiseReactionRecord*> reaction) {
+ reaction->setIsAsyncGenerator(asyncGenObj);
+ };
+ return InternalAwait(cx, value, nullptr, onFulfilled, onRejected, extra);
+}
+
+// Async Iteration proposal 11.1.3.2.1 %AsyncFromSyncIteratorPrototype%.next
+// Async Iteration proposal 11.1.3.2.2 %AsyncFromSyncIteratorPrototype%.return
+// Async Iteration proposal 11.1.3.2.3 %AsyncFromSyncIteratorPrototype%.throw
+bool
+js::AsyncFromSyncIteratorMethod(JSContext* cx, CallArgs& args, CompletionKind completionKind)
+{
+ // Step 1.
+ RootedValue thisVal(cx, args.thisv());
+
+ // Step 2.
+ RootedObject resultPromise(cx, CreatePromiseObjectWithoutResolutionFunctions(cx));
+ if (!resultPromise)
+ return false;
+
+ // Step 3.
+ if (!thisVal.isObject() || !thisVal.toObject().is<AsyncFromSyncIteratorObject>()) {
+ // Step 3.a.
+ RootedValue badGeneratorError(cx);
+ if (!GetTypeError(cx, JSMSG_NOT_AN_ASYNC_ITERATOR, &badGeneratorError))
+ return false;
+
+ // Step 3.b.
+ if (!RejectMaybeWrappedPromise(cx, resultPromise, badGeneratorError))
+ return false;
+
+ // Step 3.c.
+ args.rval().setObject(*resultPromise);
+ return true;
+ }
+
+ Rooted<AsyncFromSyncIteratorObject*> asyncIter(
+ cx, &thisVal.toObject().as<AsyncFromSyncIteratorObject>());
+
+ // Step 4.
+ RootedObject iter(cx, asyncIter->iterator());
+
+ RootedValue resultVal(cx);
+ RootedValue func(cx);
+ if (completionKind == CompletionKind::Normal) {
+ // 11.1.3.2.1 steps 5-6 (partially).
+ if (!GetProperty(cx, iter, iter, cx->names().next, &func))
+ return AbruptRejectPromise(cx, args, resultPromise, nullptr);
+ } else if (completionKind == CompletionKind::Return) {
+ // 11.1.3.2.2 steps 5-6.
+ if (!GetProperty(cx, iter, iter, cx->names().return_, &func))
+ return AbruptRejectPromise(cx, args, resultPromise, nullptr);
+
+ // Step 7.
+ if (func.isNullOrUndefined()) {
+ // Step 7.a.
+ RootedObject resultObj(cx, CreateIterResultObject(cx, args.get(0), true));
+ if (!resultObj)
+ return AbruptRejectPromise(cx, args, resultPromise, nullptr);
+
+ RootedValue resultVal(cx, ObjectValue(*resultObj));
+
+ // Step 7.b.
+ if (!ResolvePromiseInternal(cx, resultPromise, resultVal))
+ return AbruptRejectPromise(cx, args, resultPromise, nullptr);
+
+ // Step 7.c.
+ args.rval().setObject(*resultPromise);
+ return true;
+ }
+ } else {
+ // 11.1.3.2.3 steps 5-6.
+ MOZ_ASSERT(completionKind == CompletionKind::Throw);
+ if (!GetProperty(cx, iter, iter, cx->names().throw_, &func))
+ return AbruptRejectPromise(cx, args, resultPromise, nullptr);
+
+ // Step 7.
+ if (func.isNullOrUndefined()) {
+ // Step 7.a.
+ if (!RejectMaybeWrappedPromise(cx, resultPromise, args.get(0)))
+ return AbruptRejectPromise(cx, args, resultPromise, nullptr);
+
+ // Step 7.b.
+ args.rval().setObject(*resultPromise);
+ return true;
+ }
+ }
+
+ // 11.1.3.2.1 steps 5-6 (partially).
+ // 11.1.3.2.2, 11.1.3.2.3 steps 8-9.
+ RootedValue iterVal(cx, ObjectValue(*iter));
+ FixedInvokeArgs<1> args2(cx);
+ args2[0].set(args.get(0));
+ if (!js::Call(cx, func, iterVal, args2, &resultVal))
+ return AbruptRejectPromise(cx, args, resultPromise, nullptr);
+
+ // 11.1.3.2.1 steps 5-6 (partially).
+ // 11.1.3.2.2, 11.1.3.2.3 steps 10.
+ if (!resultVal.isObject()) {
+ CheckIsObjectKind kind;
+ switch (completionKind) {
+ case CompletionKind::Normal:
+ kind = CheckIsObjectKind::IteratorNext;
+ break;
+ case CompletionKind::Throw:
+ kind = CheckIsObjectKind::IteratorThrow;
+ break;
+ case CompletionKind::Return:
+ kind = CheckIsObjectKind::IteratorReturn;
+ break;
+ }
+ MOZ_ALWAYS_FALSE(ThrowCheckIsObject(cx, kind));
+ return AbruptRejectPromise(cx, args, resultPromise, nullptr);
+ }
+
+ RootedObject resultObj(cx, &resultVal.toObject());
+
+ // Following step numbers are for 11.1.3.2.1.
+ // For 11.1.3.2.2 and 11.1.3.2.3, steps 7-16 corresponds to steps 11-20.
+
+ // Steps 7-8.
+ RootedValue doneVal(cx);
+ if (!GetProperty(cx, resultObj, resultObj, cx->names().done, &doneVal))
+ return AbruptRejectPromise(cx, args, resultPromise, nullptr);
+ bool done = ToBoolean(doneVal);
+
+ // Steps 9-10.
+ RootedValue value(cx);
+ if (!GetProperty(cx, resultObj, resultObj, cx->names().value, &value))
+ return AbruptRejectPromise(cx, args, resultPromise, nullptr);
+
+ // Steps 13-14.
+ RootedValue onFulfilled(cx, Int32Value(done
+ ? PromiseHandlerAsyncFromSyncIteratorValueUnwrapDone
+ : PromiseHandlerAsyncFromSyncIteratorValueUnwrapNotDone));
+ RootedValue onRejected(cx, Int32Value(PromiseHandlerThrower));
+
+ // Steps 11-12, 15.
+ auto extra = [](Handle<PromiseReactionRecord*> reaction) {
+ };
+ if (!InternalAwait(cx, value, resultPromise, onFulfilled, onRejected, extra))
+ return false;
+
+ // Step 16.
+ args.rval().setObject(*resultPromise);
+ return true;
+}
+
+static MOZ_MUST_USE bool
+AsyncGeneratorResumeNext(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj);
+
+// Async Iteration proposal 11.4.3.3.
+MOZ_MUST_USE bool
+js::AsyncGeneratorResolve(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
+ HandleValue value, bool done)
+{
+ // Step 1 (implicit).
+
+ // Steps 2-3.
+ MOZ_ASSERT(!asyncGenObj->isQueueEmpty());
+
+ // Step 4.
+ Rooted<AsyncGeneratorRequest*> request(
+ cx, AsyncGeneratorObject::dequeueRequest(cx, asyncGenObj));
+ if (!request)
+ return false;
+
+ // Step 5.
+ RootedObject resultPromise(cx, request->promise());
+
+ // Step 6.
+ RootedObject resultObj(cx, CreateIterResultObject(cx, value, done));
+ if (!resultObj)
+ return false;
+
+ RootedValue resultValue(cx, ObjectValue(*resultObj));
+
+ // Step 7.
+ if (!ResolvePromiseInternal(cx, resultPromise, resultValue))
+ return false;
+
+ // Step 8.
+ if (!AsyncGeneratorResumeNext(cx, asyncGenObj))
+ return false;
+
+ // Step 9.
+ return true;
+}
+
+// Async Iteration proposal 11.4.3.4.
+MOZ_MUST_USE bool
+js::AsyncGeneratorReject(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
+ HandleValue exception)
+{
+ // Step 1 (implicit).
+
+ // Steps 2-3.
+ MOZ_ASSERT(!asyncGenObj->isQueueEmpty());
+
+ // Step 4.
+ Rooted<AsyncGeneratorRequest*> request(
+ cx, AsyncGeneratorObject::dequeueRequest(cx, asyncGenObj));
+ if (!request)
+ return false;
+
+ // Step 5.
+ RootedObject resultPromise(cx, request->promise());
+
+ // Step 6.
+ if (!RejectMaybeWrappedPromise(cx, resultPromise, exception))
+ return false;
+
+ // Step 7.
+ if (!AsyncGeneratorResumeNext(cx, asyncGenObj))
+ return false;
+
+ // Step 8.
+ return true;
+}
+
+// Async Iteration proposal 11.4.3.5.
+static MOZ_MUST_USE bool
+AsyncGeneratorResumeNext(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj)
+{
+ // Step 1 (implicit).
+
+ // Steps 2-3.
+ MOZ_ASSERT(!asyncGenObj->isExecuting());
+
+ // Step 4.
+ if (asyncGenObj->isAwaitingYieldReturn() || asyncGenObj->isAwaitingReturn())
+ return true;
+
+ // Steps 5-6.
+ if (asyncGenObj->isQueueEmpty())
+ return true;
+
+ // Steps 7-8.
+ Rooted<AsyncGeneratorRequest*> request(
+ cx, AsyncGeneratorObject::peekRequest(cx, asyncGenObj));
+ if (!request)
+ return false;
+
+ // Step 9.
+ CompletionKind completionKind = request->completionKind();
+
+ // Step 10.
+ if (completionKind != CompletionKind::Normal) {
+ // Step 10.a.
+ if (asyncGenObj->isSuspendedStart())
+ asyncGenObj->setCompleted();
+
+ // Step 10.b.
+ if (asyncGenObj->isCompleted()) {
+ RootedValue value(cx, request->completionValue());
+
+ // Step 10.b.i.
+ if (completionKind == CompletionKind::Return) {
+ // Steps 10.b.i.1.
+ asyncGenObj->setAwaitingReturn();
+
+ // Steps 10.b.i.4-6 (reordered).
+ RootedValue onFulfilled(cx, Int32Value(PromiseHandlerAsyncGeneratorResumeNextReturnFulfilled));
+ RootedValue onRejected(cx, Int32Value(PromiseHandlerAsyncGeneratorResumeNextReturnRejected));
+
+ // Steps 10.b.i.2-3, 7-10.
+ auto extra = [&](Handle<PromiseReactionRecord*> reaction) {
+ reaction->setIsAsyncGenerator(asyncGenObj);
+ };
+ return InternalAwait(cx, value, nullptr, onFulfilled, onRejected, extra);
+ }
+
+ // Step 10.b.ii.1.
+ MOZ_ASSERT(completionKind == CompletionKind::Throw);
+
+ // Steps 10.b.ii.2-3.
+ return AsyncGeneratorReject(cx, asyncGenObj, value);
+ }
+ } else if (asyncGenObj->isCompleted()) {
+ // Step 11.
+ return AsyncGeneratorResolve(cx, asyncGenObj, UndefinedHandleValue, true);
+ }
+
+ // Step 12.
+ MOZ_ASSERT(asyncGenObj->isSuspendedStart() || asyncGenObj->isSuspendedYield());
+
+ // Step 16 (reordered).
+ asyncGenObj->setExecuting();
+
+ RootedValue argument(cx, request->completionValue());
+
+ if (completionKind == CompletionKind::Return) {
+ // 11.4.3.7 AsyncGeneratorYield step 8.b-e.
+ // Since we don't have the place that handles return from yield
+ // inside the generator, handle the case here, with extra state
+ // State_AwaitingYieldReturn.
+ asyncGenObj->setAwaitingYieldReturn();
+
+ RootedValue onFulfilled(cx, Int32Value(PromiseHandlerAsyncGeneratorYieldReturnAwaitedFulfilled));
+ RootedValue onRejected(cx, Int32Value(PromiseHandlerAsyncGeneratorYieldReturnAwaitedRejected));
+
+ auto extra = [&](Handle<PromiseReactionRecord*> reaction) {
+ reaction->setIsAsyncGenerator(asyncGenObj);
+ };
+ return InternalAwait(cx, argument, nullptr, onFulfilled, onRejected, extra);
+ }
+
+ // Steps 13-15, 17-21.
+ return AsyncGeneratorResume(cx, asyncGenObj, completionKind, argument);
+}
+
+// Async Iteration proposal 11.4.3.6.
+MOZ_MUST_USE bool
+js::AsyncGeneratorEnqueue(JSContext* cx, HandleValue asyncGenVal,
+ CompletionKind completionKind, HandleValue completionValue,
+ MutableHandleValue result)
+{
+ // Step 1 (implicit).
+
+ // Step 2.
+ RootedObject resultPromise(cx, CreatePromiseObjectWithoutResolutionFunctions(cx));
+ if (!resultPromise)
+ return false;
+
+ // Step 3.
+ if (!asyncGenVal.isObject() || !asyncGenVal.toObject().is<AsyncGeneratorObject>()) {
+ // Step 3.a.
+ RootedValue badGeneratorError(cx);
+ if (!GetTypeError(cx, JSMSG_NOT_AN_ASYNC_GENERATOR, &badGeneratorError))
+ return false;
+
+ // Step 3.b.
+ if (!RejectMaybeWrappedPromise(cx, resultPromise, badGeneratorError))
+ return false;
+
+ // Step 3.c.
+ result.setObject(*resultPromise);
+ return true;
+ }
+
+ Rooted<AsyncGeneratorObject*> asyncGenObj(
+ cx, &asyncGenVal.toObject().as<AsyncGeneratorObject>());
+
+ // Step 5 (reordered).
+ Rooted<AsyncGeneratorRequest*> request(
+ cx, AsyncGeneratorRequest::create(cx, completionKind, completionValue, resultPromise));
+ if (!request)
+ return false;
+
+ // Steps 4, 6.
+ if (!AsyncGeneratorObject::enqueueRequest(cx, asyncGenObj, request))
+ return false;
+
+ // Step 7.
+ if (!asyncGenObj->isExecuting()) {
+ // Step 8.
+ if (!AsyncGeneratorResumeNext(cx, asyncGenObj))
+ return false;
+ }
+
+ // Step 9.
+ result.setObject(*resultPromise);
+ return true;
+}
+
// ES2016, 25.4.5.3.
bool
js::Promise_then(JSContext* cx, unsigned argc, Value* vp)
@@ -2291,12 +2775,12 @@ PerformPromiseThen(JSContext* cx, Handle<PromiseObject*> promise, HandleValue on
// Step 3.
RootedValue onFulfilled(cx, onFulfilled_);
if (!IsCallable(onFulfilled))
- onFulfilled = Int32Value(PROMISE_HANDLER_IDENTITY);
+ onFulfilled = Int32Value(PromiseHandlerIdentity);
// Step 4.
RootedValue onRejected(cx, onRejected_);
if (!IsCallable(onRejected))
- onRejected = Int32Value(PROMISE_HANDLER_THROWER);
+ onRejected = Int32Value(PromiseHandlerThrower);
RootedObject incumbentGlobal(cx);
if (!GetObjectFromIncumbentGlobal(cx, &incumbentGlobal))
@@ -2645,6 +3129,9 @@ PromiseObject::resolve(JSContext* cx, Handle<PromiseObject*> promise, HandleValu
if (promise->state() != JS::PromiseState::Pending)
return true;
+ if (PromiseHasAnyFlag(*promise, PROMISE_FLAG_DEFAULT_RESOLVE_FUNCTION))
+ return ResolvePromiseInternal(cx, promise, resolutionValue);
+
RootedObject resolveFun(cx, GetResolveFunctionFromPromise(promise));
RootedValue funVal(cx, ObjectValue(*resolveFun));
@@ -2668,6 +3155,9 @@ PromiseObject::reject(JSContext* cx, Handle<PromiseObject*> promise, HandleValue
if (promise->state() != JS::PromiseState::Pending)
return true;
+ if (PromiseHasAnyFlag(*promise, PROMISE_FLAG_DEFAULT_REJECT_FUNCTION))
+ return RejectMaybeWrappedPromise(cx, promise, rejectionValue);
+
RootedValue funVal(cx, promise->getFixedSlot(PromiseSlot_RejectFunction));
MOZ_ASSERT(IsCallable(funVal));
diff --git a/js/src/builtin/Promise.h b/js/src/builtin/Promise.h
index 6a6453e46..b04bd0e2a 100644
--- a/js/src/builtin/Promise.h
+++ b/js/src/builtin/Promise.h
@@ -44,6 +44,8 @@ class PromiseObject : public NativeObject
static PromiseObject* create(JSContext* cx, HandleObject executor,
HandleObject proto = nullptr, bool needsWrapping = false);
+ static PromiseObject* createSkippingExecutor(JSContext* cx);
+
static JSObject* unforgeableResolve(JSContext* cx, HandleValue value);
static JSObject* unforgeableReject(JSContext* cx, HandleValue value);
@@ -149,6 +151,26 @@ AsyncFunctionThrown(JSContext* cx, Handle<PromiseObject*> resultPromise);
MOZ_MUST_USE bool
AsyncFunctionAwait(JSContext* cx, Handle<PromiseObject*> resultPromise, HandleValue value);
+class AsyncGeneratorObject;
+
+MOZ_MUST_USE bool
+AsyncGeneratorAwait(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj, HandleValue value);
+
+MOZ_MUST_USE bool
+AsyncGeneratorResolve(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
+ HandleValue value, bool done);
+
+MOZ_MUST_USE bool
+AsyncGeneratorReject(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
+ HandleValue exception);
+
+MOZ_MUST_USE bool
+AsyncGeneratorEnqueue(JSContext* cx, HandleValue asyncGenVal, CompletionKind completionKind,
+ HandleValue completionValue, MutableHandleValue result);
+
+bool
+AsyncFromSyncIteratorMethod(JSContext* cx, CallArgs& args, CompletionKind completionKind);
+
/**
* A PromiseTask represents a task that can be dispatched to a helper thread
* (via StartPromiseTask), executed (by implementing PromiseTask::execute()),
diff --git a/js/src/builtin/ReflectParse.cpp b/js/src/builtin/ReflectParse.cpp
index 8e8bb2417..22c958d4c 100644
--- a/js/src/builtin/ReflectParse.cpp
+++ b/js/src/builtin/ReflectParse.cpp
@@ -2800,11 +2800,11 @@ ASTSerializer::generatorExpression(ParseNode* pn, MutableHandleValue dst)
LOCAL_ASSERT(next->isKind(PNK_SEMI) &&
next->pn_kid->isKind(PNK_YIELD) &&
- next->pn_kid->pn_left);
+ next->pn_kid->pn_kid);
RootedValue body(cx);
- return expression(next->pn_kid->pn_left, &body) &&
+ return expression(next->pn_kid->pn_kid, &body) &&
builder.generatorExpression(body, blocks, filter, isLegacy, &pn->pn_pos, dst);
}
@@ -3146,7 +3146,7 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
case PNK_YIELD_STAR:
{
- MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos));
+ MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid->pn_pos));
RootedValue arg(cx);
return expression(pn->pn_left, &arg) &&
@@ -3155,10 +3155,10 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
case PNK_YIELD:
{
- MOZ_ASSERT_IF(pn->pn_left, pn->pn_pos.encloses(pn->pn_left->pn_pos));
+ MOZ_ASSERT_IF(pn->pn_kid, pn->pn_pos.encloses(pn->pn_kid->pn_pos));
RootedValue arg(cx);
- return optExpression(pn->pn_left, &arg) &&
+ return optExpression(pn->pn_kid, &arg) &&
builder.yieldExpression(arg, NotDelegating, &pn->pn_pos, dst);
}
@@ -3422,10 +3422,10 @@ ASTSerializer::function(ParseNode* pn, ASTType type, MutableHandleValue dst)
RootedFunction func(cx, pn->pn_funbox->function());
GeneratorStyle generatorStyle =
- pn->pn_funbox->isGenerator()
- ? (pn->pn_funbox->isLegacyGenerator()
- ? GeneratorStyle::Legacy
- : GeneratorStyle::ES6)
+ pn->pn_funbox->isStarGenerator()
+ ? GeneratorStyle::ES6
+ : pn->pn_funbox->isLegacyGenerator()
+ ? GeneratorStyle::Legacy
: GeneratorStyle::None;
bool isAsync = pn->pn_funbox->isAsync();
@@ -3480,7 +3480,7 @@ ASTSerializer::functionArgsAndBody(ParseNode* pn, NodeVector& args, NodeVector&
ParseNode* pnstart = pnbody->pn_head;
// Skip over initial yield in generator.
- if (pnstart && pnstart->isKind(PNK_YIELD)) {
+ if (pnstart && pnstart->isKind(PNK_INITIALYIELD)) {
MOZ_ASSERT(pnstart->getOp() == JSOP_INITIALYIELD);
pnstart = pnstart->pn_next;
}