mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-22 15:17:29 +09:00
Bug 1379525 - Part 1: Await on the value before yielding or returning inside async generator.
Tag #1287
This commit is contained in:
parent
ba1cf5608c
commit
9e8369d01f
4 changed files with 344 additions and 258 deletions
|
|
@ -36,18 +36,30 @@ MillisecondsSinceStartup()
|
||||||
enum PromiseHandler {
|
enum PromiseHandler {
|
||||||
PromiseHandlerIdentity = 0,
|
PromiseHandlerIdentity = 0,
|
||||||
PromiseHandlerThrower,
|
PromiseHandlerThrower,
|
||||||
PromiseHandlerAsyncFunctionAwaitFulfilled,
|
|
||||||
PromiseHandlerAsyncFunctionAwaitRejected,
|
|
||||||
PromiseHandlerAsyncGeneratorAwaitFulfilled,
|
|
||||||
PromiseHandlerAsyncGeneratorAwaitRejected,
|
|
||||||
|
|
||||||
// Async Iteration proposal 6.1.1.2.1.
|
// ES 2018 draft 25.5.5.4-5.
|
||||||
// Async iterator handlers take the resolved value and create new iterator
|
PromiseHandlerAsyncFunctionAwaitedFulfilled,
|
||||||
// objects. To do so it needs to forward whether the iterator is done. In
|
PromiseHandlerAsyncFunctionAwaitedRejected,
|
||||||
// spec, this is achieved via the [[Done]] internal slot. We enumerate both
|
|
||||||
// true and false cases here.
|
// Async Iteration proposal 4.1.
|
||||||
PromiseHandlerAsyncIteratorValueUnwrapDone,
|
PromiseHandlerAsyncGeneratorAwaitedFulfilled,
|
||||||
PromiseHandlerAsyncIteratorValueUnwrapNotDone,
|
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 {
|
enum ResolutionMode {
|
||||||
|
|
@ -197,8 +209,8 @@ enum ReactionRecordSlots {
|
||||||
#define REACTION_FLAG_RESOLVED 0x1
|
#define REACTION_FLAG_RESOLVED 0x1
|
||||||
#define REACTION_FLAG_FULFILLED 0x2
|
#define REACTION_FLAG_FULFILLED 0x2
|
||||||
#define REACTION_FLAG_IGNORE_DEFAULT_RESOLUTION 0x4
|
#define REACTION_FLAG_IGNORE_DEFAULT_RESOLUTION 0x4
|
||||||
#define REACTION_FLAG_ASYNC_FUNCTION_AWAIT 0x8
|
#define REACTION_FLAG_ASYNC_FUNCTION 0x8
|
||||||
#define REACTION_FLAG_ASYNC_GENERATOR_AWAIT 0x10
|
#define REACTION_FLAG_ASYNC_GENERATOR 0x10
|
||||||
|
|
||||||
// ES2016, 25.4.1.2.
|
// ES2016, 25.4.1.2.
|
||||||
class PromiseReactionRecord : public NativeObject
|
class PromiseReactionRecord : public NativeObject
|
||||||
|
|
@ -225,28 +237,28 @@ class PromiseReactionRecord : public NativeObject
|
||||||
flags |= REACTION_FLAG_FULFILLED;
|
flags |= REACTION_FLAG_FULFILLED;
|
||||||
setFixedSlot(ReactionRecordSlot_Flags, Int32Value(flags));
|
setFixedSlot(ReactionRecordSlot_Flags, Int32Value(flags));
|
||||||
}
|
}
|
||||||
void setIsAsyncFunctionAwait() {
|
void setIsAsyncFunction() {
|
||||||
int32_t flags = this->flags();
|
int32_t flags = this->flags();
|
||||||
flags |= REACTION_FLAG_ASYNC_FUNCTION_AWAIT;
|
flags |= REACTION_FLAG_ASYNC_FUNCTION;
|
||||||
setFixedSlot(ReactionRecordSlot_Flags, Int32Value(flags));
|
setFixedSlot(ReactionRecordSlot_Flags, Int32Value(flags));
|
||||||
}
|
}
|
||||||
bool isAsyncFunctionAwait() {
|
bool isAsyncFunction() {
|
||||||
int32_t flags = this->flags();
|
int32_t flags = this->flags();
|
||||||
return flags & REACTION_FLAG_ASYNC_FUNCTION_AWAIT;
|
return flags & REACTION_FLAG_ASYNC_FUNCTION;
|
||||||
}
|
}
|
||||||
void setIsAsyncGeneratorAwait(Handle<AsyncGeneratorObject*> asyncGenObj) {
|
void setIsAsyncGenerator(Handle<AsyncGeneratorObject*> asyncGenObj) {
|
||||||
int32_t flags = this->flags();
|
int32_t flags = this->flags();
|
||||||
flags |= REACTION_FLAG_ASYNC_GENERATOR_AWAIT;
|
flags |= REACTION_FLAG_ASYNC_GENERATOR;
|
||||||
setFixedSlot(ReactionRecordSlot_Flags, Int32Value(flags));
|
setFixedSlot(ReactionRecordSlot_Flags, Int32Value(flags));
|
||||||
|
|
||||||
setFixedSlot(ReactionRecordSlot_Generator, ObjectValue(*asyncGenObj));
|
setFixedSlot(ReactionRecordSlot_Generator, ObjectValue(*asyncGenObj));
|
||||||
}
|
}
|
||||||
bool isAsyncGeneratorAwait() {
|
bool isAsyncGenerator() {
|
||||||
int32_t flags = this->flags();
|
int32_t flags = this->flags();
|
||||||
return flags & REACTION_FLAG_ASYNC_GENERATOR_AWAIT;
|
return flags & REACTION_FLAG_ASYNC_GENERATOR;
|
||||||
}
|
}
|
||||||
AsyncGeneratorObject* asyncGenerator() {
|
AsyncGeneratorObject* asyncGenerator() {
|
||||||
MOZ_ASSERT(isAsyncGeneratorAwait());
|
MOZ_ASSERT(isAsyncGenerator());
|
||||||
return &getFixedSlot(ReactionRecordSlot_Generator).toObject()
|
return &getFixedSlot(ReactionRecordSlot_Generator).toObject()
|
||||||
.as<AsyncGeneratorObject>();
|
.as<AsyncGeneratorObject>();
|
||||||
}
|
}
|
||||||
|
|
@ -848,10 +860,10 @@ TriggerPromiseReactions(JSContext* cx, HandleValue reactionsVal, JS::PromiseStat
|
||||||
}
|
}
|
||||||
|
|
||||||
static MOZ_MUST_USE bool
|
static MOZ_MUST_USE bool
|
||||||
AsyncFunctionAwaitPromiseReactionJob(JSContext* cx, Handle<PromiseReactionRecord*> reaction,
|
AsyncFunctionPromiseReactionJob(JSContext* cx, Handle<PromiseReactionRecord*> reaction,
|
||||||
MutableHandleValue rval)
|
MutableHandleValue rval)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(reaction->isAsyncFunctionAwait());
|
MOZ_ASSERT(reaction->isAsyncFunction());
|
||||||
|
|
||||||
RootedValue handlerVal(cx, reaction->handler());
|
RootedValue handlerVal(cx, reaction->handler());
|
||||||
RootedValue argument(cx, reaction->handlerArg());
|
RootedValue argument(cx, reaction->handlerArg());
|
||||||
|
|
@ -859,15 +871,14 @@ AsyncFunctionAwaitPromiseReactionJob(JSContext* cx, Handle<PromiseReactionRecord
|
||||||
RootedValue generatorVal(cx, resultPromise->getFixedSlot(PromiseSlot_AwaitGenerator));
|
RootedValue generatorVal(cx, resultPromise->getFixedSlot(PromiseSlot_AwaitGenerator));
|
||||||
|
|
||||||
int32_t handlerNum = int32_t(handlerVal.toNumber());
|
int32_t handlerNum = int32_t(handlerVal.toNumber());
|
||||||
MOZ_ASSERT(handlerNum == PromiseHandlerAsyncFunctionAwaitFulfilled ||
|
|
||||||
handlerNum == PromiseHandlerAsyncFunctionAwaitRejected);
|
|
||||||
|
|
||||||
// Await's handlers don't return a value, nor throw exception.
|
// Await's handlers don't return a value, nor throw exception.
|
||||||
// They fail only on OOM.
|
// They fail only on OOM.
|
||||||
if (handlerNum == PromiseHandlerAsyncFunctionAwaitFulfilled) {
|
if (handlerNum == PromiseHandlerAsyncFunctionAwaitedFulfilled) {
|
||||||
if (!AsyncFunctionAwaitedFulfilled(cx, resultPromise, generatorVal, argument))
|
if (!AsyncFunctionAwaitedFulfilled(cx, resultPromise, generatorVal, argument))
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
MOZ_ASSERT(handlerNum == PromiseHandlerAsyncFunctionAwaitedRejected);
|
||||||
if (!AsyncFunctionAwaitedRejected(cx, resultPromise, generatorVal, argument))
|
if (!AsyncFunctionAwaitedRejected(cx, resultPromise, generatorVal, argument))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -877,27 +888,48 @@ AsyncFunctionAwaitPromiseReactionJob(JSContext* cx, Handle<PromiseReactionRecord
|
||||||
}
|
}
|
||||||
|
|
||||||
static MOZ_MUST_USE bool
|
static MOZ_MUST_USE bool
|
||||||
AsyncGeneratorAwaitPromiseReactionJob(JSContext* cx, Handle<PromiseReactionRecord*> reaction,
|
AsyncGeneratorPromiseReactionJob(JSContext* cx, Handle<PromiseReactionRecord*> reaction,
|
||||||
MutableHandleValue rval)
|
MutableHandleValue rval)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(reaction->isAsyncGeneratorAwait());
|
MOZ_ASSERT(reaction->isAsyncGenerator());
|
||||||
|
|
||||||
RootedValue handlerVal(cx, reaction->handler());
|
RootedValue handlerVal(cx, reaction->handler());
|
||||||
RootedValue argument(cx, reaction->handlerArg());
|
RootedValue argument(cx, reaction->handlerArg());
|
||||||
Rooted<AsyncGeneratorObject*> asyncGenObj(cx, reaction->asyncGenerator());
|
Rooted<AsyncGeneratorObject*> asyncGenObj(cx, reaction->asyncGenerator());
|
||||||
|
|
||||||
int32_t handlerNum = int32_t(handlerVal.toNumber());
|
int32_t handlerNum = int32_t(handlerVal.toNumber());
|
||||||
MOZ_ASSERT(handlerNum == PromiseHandlerAsyncGeneratorAwaitFulfilled ||
|
|
||||||
handlerNum == PromiseHandlerAsyncGeneratorAwaitRejected);
|
|
||||||
|
|
||||||
// Await's handlers don't return a value, nor throw exception.
|
// Await's handlers don't return a value, nor throw exception.
|
||||||
// They fail only on OOM.
|
// They fail only on OOM.
|
||||||
if (handlerNum == PromiseHandlerAsyncGeneratorAwaitFulfilled) {
|
if (handlerNum == PromiseHandlerAsyncGeneratorAwaitedFulfilled) {
|
||||||
|
// 4.1.1.
|
||||||
if (!AsyncGeneratorAwaitedFulfilled(cx, asyncGenObj, argument))
|
if (!AsyncGeneratorAwaitedFulfilled(cx, asyncGenObj, argument))
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else if (handlerNum == PromiseHandlerAsyncGeneratorAwaitedRejected) {
|
||||||
|
// 4.1.2.
|
||||||
if (!AsyncGeneratorAwaitedRejected(cx, asyncGenObj, argument))
|
if (!AsyncGeneratorAwaitedRejected(cx, asyncGenObj, argument))
|
||||||
return false;
|
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();
|
rval.setUndefined();
|
||||||
|
|
@ -947,10 +979,10 @@ PromiseReactionJob(JSContext* cx, unsigned argc, Value* vp)
|
||||||
|
|
||||||
// Steps 1-2.
|
// Steps 1-2.
|
||||||
Rooted<PromiseReactionRecord*> reaction(cx, &reactionObj->as<PromiseReactionRecord>());
|
Rooted<PromiseReactionRecord*> reaction(cx, &reactionObj->as<PromiseReactionRecord>());
|
||||||
if (reaction->isAsyncFunctionAwait())
|
if (reaction->isAsyncFunction())
|
||||||
return AsyncFunctionAwaitPromiseReactionJob(cx, reaction, args.rval());
|
return AsyncFunctionPromiseReactionJob(cx, reaction, args.rval());
|
||||||
if (reaction->isAsyncGeneratorAwait())
|
if (reaction->isAsyncGenerator())
|
||||||
return AsyncGeneratorAwaitPromiseReactionJob(cx, reaction, args.rval());
|
return AsyncGeneratorPromiseReactionJob(cx, reaction, args.rval());
|
||||||
|
|
||||||
// Step 3.
|
// Step 3.
|
||||||
RootedValue handlerVal(cx, reaction->handler());
|
RootedValue handlerVal(cx, reaction->handler());
|
||||||
|
|
@ -972,11 +1004,11 @@ PromiseReactionJob(JSContext* cx, unsigned argc, Value* vp)
|
||||||
resolutionMode = RejectMode;
|
resolutionMode = RejectMode;
|
||||||
handlerResult = argument;
|
handlerResult = argument;
|
||||||
} else {
|
} else {
|
||||||
MOZ_ASSERT(handlerNum == PromiseHandlerAsyncIteratorValueUnwrapDone ||
|
MOZ_ASSERT(handlerNum == PromiseHandlerAsyncFromSyncIteratorValueUnwrapDone ||
|
||||||
handlerNum == PromiseHandlerAsyncIteratorValueUnwrapNotDone);
|
handlerNum == PromiseHandlerAsyncFromSyncIteratorValueUnwrapNotDone);
|
||||||
|
|
||||||
bool done = handlerNum == PromiseHandlerAsyncIteratorValueUnwrapDone;
|
bool done = handlerNum == PromiseHandlerAsyncFromSyncIteratorValueUnwrapDone;
|
||||||
// Async Iteration proposal 6.1.1.2.1 step 1.
|
// Async Iteration proposal 11.1.3.2.5 step 1.
|
||||||
RootedObject resultObj(cx, CreateIterResultObject(cx, argument, done));
|
RootedObject resultObj(cx, CreateIterResultObject(cx, argument, done));
|
||||||
if (!resultObj)
|
if (!resultObj)
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -2214,7 +2246,7 @@ static MOZ_MUST_USE bool PerformPromiseThenWithReaction(JSContext* cx,
|
||||||
// Some async/await functions are implemented here instead of
|
// Some async/await functions are implemented here instead of
|
||||||
// js/src/builtin/AsyncFunction.cpp, to call Promise internal functions.
|
// 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*
|
MOZ_MUST_USE PromiseObject*
|
||||||
js::CreatePromiseObjectForAsync(JSContext* cx, HandleValue generatorVal)
|
js::CreatePromiseObjectForAsync(JSContext* cx, HandleValue generatorVal)
|
||||||
{
|
{
|
||||||
|
|
@ -2228,7 +2260,7 @@ js::CreatePromiseObjectForAsync(JSContext* cx, HandleValue generatorVal)
|
||||||
return promise;
|
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
|
MOZ_MUST_USE bool
|
||||||
js::AsyncFunctionThrown(JSContext* cx, Handle<PromiseObject*> resultPromise)
|
js::AsyncFunctionThrown(JSContext* cx, Handle<PromiseObject*> resultPromise)
|
||||||
{
|
{
|
||||||
|
|
@ -2244,7 +2276,7 @@ js::AsyncFunctionThrown(JSContext* cx, Handle<PromiseObject*> resultPromise)
|
||||||
return true;
|
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
|
MOZ_MUST_USE bool
|
||||||
js::AsyncFunctionReturned(JSContext* cx, Handle<PromiseObject*> resultPromise, HandleValue value)
|
js::AsyncFunctionReturned(JSContext* cx, Handle<PromiseObject*> resultPromise, HandleValue value)
|
||||||
{
|
{
|
||||||
|
|
@ -2256,28 +2288,27 @@ js::AsyncFunctionReturned(JSContext* cx, Handle<PromiseObject*> resultPromise, H
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Async Functions proposal 2.3 steps 2-8.
|
// Helper function that performs the equivalent steps as
|
||||||
MOZ_MUST_USE bool
|
// Async Iteration proposal 4.1 Await steps 2-3, 6-9 or similar.
|
||||||
js::AsyncFunctionAwait(JSContext* cx, Handle<PromiseObject*> resultPromise, HandleValue value)
|
template <typename T>
|
||||||
|
static MOZ_MUST_USE bool
|
||||||
|
InternalAwait(JSContext* cx, HandleValue value, HandleObject resultPromise,
|
||||||
|
HandleValue onFulfilled, HandleValue onRejected, T extraStep)
|
||||||
{
|
{
|
||||||
// Step 2.
|
// Step 2.
|
||||||
Rooted<PromiseObject*> promise(cx, CreatePromiseObjectWithoutResolutionFunctions(cx));
|
Rooted<PromiseObject*> promise(cx, CreatePromiseObjectWithoutResolutionFunctions(cx));
|
||||||
if (!promise)
|
if (!promise)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Steps 3.
|
// Step 3.
|
||||||
if (!ResolvePromiseInternal(cx, promise, value))
|
if (!ResolvePromiseInternal(cx, promise, value))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Steps 4-5.
|
|
||||||
RootedValue onFulfilled(cx, Int32Value(PromiseHandlerAsyncFunctionAwaitFulfilled));
|
|
||||||
RootedValue onRejected(cx, Int32Value(PromiseHandlerAsyncFunctionAwaitRejected));
|
|
||||||
|
|
||||||
RootedObject incumbentGlobal(cx);
|
RootedObject incumbentGlobal(cx);
|
||||||
if (!GetObjectFromIncumbentGlobal(cx, &incumbentGlobal))
|
if (!GetObjectFromIncumbentGlobal(cx, &incumbentGlobal))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Steps 6-7.
|
// Steps 7-8.
|
||||||
Rooted<PromiseReactionRecord*> reaction(cx, NewReactionRecord(cx, resultPromise,
|
Rooted<PromiseReactionRecord*> reaction(cx, NewReactionRecord(cx, resultPromise,
|
||||||
onFulfilled, onRejected,
|
onFulfilled, onRejected,
|
||||||
nullptr, nullptr,
|
nullptr, nullptr,
|
||||||
|
|
@ -2285,53 +2316,47 @@ js::AsyncFunctionAwait(JSContext* cx, Handle<PromiseObject*> resultPromise, Hand
|
||||||
if (!reaction)
|
if (!reaction)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
reaction->setIsAsyncFunctionAwait();
|
// Step 6.
|
||||||
|
extraStep(reaction);
|
||||||
// Step 8.
|
|
||||||
return PerformPromiseThenWithReaction(cx, promise, reaction);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Async Iteration proposal 5.1 steps 2-9.
|
|
||||||
MOZ_MUST_USE bool
|
|
||||||
js::AsyncGeneratorAwait(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
|
||||||
HandleValue value)
|
|
||||||
{
|
|
||||||
// Step 2.
|
|
||||||
Rooted<PromiseObject*> promise(cx, CreatePromiseObjectWithoutResolutionFunctions(cx));
|
|
||||||
if (!promise)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Steps 3.
|
|
||||||
if (!ResolvePromiseInternal(cx, promise, value))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Steps 4-5.
|
|
||||||
RootedValue onFulfilled(cx, Int32Value(PromiseHandlerAsyncGeneratorAwaitFulfilled));
|
|
||||||
RootedValue onRejected(cx, Int32Value(PromiseHandlerAsyncGeneratorAwaitRejected));
|
|
||||||
|
|
||||||
RootedObject incumbentGlobal(cx);
|
|
||||||
if (!GetObjectFromIncumbentGlobal(cx, &incumbentGlobal))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Step 6 (skipped).
|
|
||||||
|
|
||||||
// Steps 7-8.
|
|
||||||
Rooted<PromiseReactionRecord*> reaction(cx, NewReactionRecord(cx, nullptr,
|
|
||||||
onFulfilled, onRejected,
|
|
||||||
nullptr, nullptr,
|
|
||||||
incumbentGlobal));
|
|
||||||
if (!reaction)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
reaction->setIsAsyncGeneratorAwait(asyncGenObj);
|
|
||||||
|
|
||||||
// Step 9.
|
// Step 9.
|
||||||
return PerformPromiseThenWithReaction(cx, promise, reaction);
|
return PerformPromiseThenWithReaction(cx, promise, reaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Async Iteration proposal 6.1.3.2.1 %AsyncFromSyncIteratorPrototype%.next
|
// ES 2018 draft 25.5.5.3 steps 2-10.
|
||||||
// Async Iteration proposal 6.1.3.2.2 %AsyncFromSyncIteratorPrototype%.return
|
MOZ_MUST_USE bool
|
||||||
// Async Iteration proposal 6.1.3.2.3 %AsyncFromSyncIteratorPrototype%.throw
|
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
|
bool
|
||||||
js::AsyncFromSyncIteratorMethod(JSContext* cx, CallArgs& args, CompletionKind completionKind)
|
js::AsyncFromSyncIteratorMethod(JSContext* cx, CallArgs& args, CompletionKind completionKind)
|
||||||
{
|
{
|
||||||
|
|
@ -2368,11 +2393,11 @@ js::AsyncFromSyncIteratorMethod(JSContext* cx, CallArgs& args, CompletionKind co
|
||||||
RootedValue resultVal(cx);
|
RootedValue resultVal(cx);
|
||||||
RootedValue func(cx);
|
RootedValue func(cx);
|
||||||
if (completionKind == CompletionKind::Normal) {
|
if (completionKind == CompletionKind::Normal) {
|
||||||
// 6.1.3.2.1 steps 5-6 (partially).
|
// 11.1.3.2.1 steps 5-6 (partially).
|
||||||
if (!GetProperty(cx, iter, iter, cx->names().next, &func))
|
if (!GetProperty(cx, iter, iter, cx->names().next, &func))
|
||||||
return AbruptRejectPromise(cx, args, resultPromise, nullptr);
|
return AbruptRejectPromise(cx, args, resultPromise, nullptr);
|
||||||
} else if (completionKind == CompletionKind::Return) {
|
} else if (completionKind == CompletionKind::Return) {
|
||||||
// 6.1.3.2.2 steps 5-6.
|
// 11.1.3.2.2 steps 5-6.
|
||||||
if (!GetProperty(cx, iter, iter, cx->names().return_, &func))
|
if (!GetProperty(cx, iter, iter, cx->names().return_, &func))
|
||||||
return AbruptRejectPromise(cx, args, resultPromise, nullptr);
|
return AbruptRejectPromise(cx, args, resultPromise, nullptr);
|
||||||
|
|
||||||
|
|
@ -2394,7 +2419,7 @@ js::AsyncFromSyncIteratorMethod(JSContext* cx, CallArgs& args, CompletionKind co
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 6.1.3.2.3 steps 5-6.
|
// 11.1.3.2.3 steps 5-6.
|
||||||
MOZ_ASSERT(completionKind == CompletionKind::Throw);
|
MOZ_ASSERT(completionKind == CompletionKind::Throw);
|
||||||
if (!GetProperty(cx, iter, iter, cx->names().throw_, &func))
|
if (!GetProperty(cx, iter, iter, cx->names().throw_, &func))
|
||||||
return AbruptRejectPromise(cx, args, resultPromise, nullptr);
|
return AbruptRejectPromise(cx, args, resultPromise, nullptr);
|
||||||
|
|
@ -2411,16 +2436,16 @@ js::AsyncFromSyncIteratorMethod(JSContext* cx, CallArgs& args, CompletionKind co
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6.1.3.2.1 steps 5-6 (partially).
|
// 11.1.3.2.1 steps 5-6 (partially).
|
||||||
// 6.1.3.2.2, 6.1.3.2.3 steps 8-9.
|
// 11.1.3.2.2, 11.1.3.2.3 steps 8-9.
|
||||||
RootedValue iterVal(cx, ObjectValue(*iter));
|
RootedValue iterVal(cx, ObjectValue(*iter));
|
||||||
FixedInvokeArgs<1> args2(cx);
|
FixedInvokeArgs<1> args2(cx);
|
||||||
args2[0].set(args.get(0));
|
args2[0].set(args.get(0));
|
||||||
if (!js::Call(cx, func, iterVal, args2, &resultVal))
|
if (!js::Call(cx, func, iterVal, args2, &resultVal))
|
||||||
return AbruptRejectPromise(cx, args, resultPromise, nullptr);
|
return AbruptRejectPromise(cx, args, resultPromise, nullptr);
|
||||||
|
|
||||||
// 6.1.3.2.1 steps 5-6 (partially).
|
// 11.1.3.2.1 steps 5-6 (partially).
|
||||||
// 6.1.3.2.2, 6.1.3.2.3 steps 10.
|
// 11.1.3.2.2, 11.1.3.2.3 steps 10.
|
||||||
if (!resultVal.isObject()) {
|
if (!resultVal.isObject()) {
|
||||||
CheckIsObjectKind kind;
|
CheckIsObjectKind kind;
|
||||||
switch (completionKind) {
|
switch (completionKind) {
|
||||||
|
|
@ -2440,8 +2465,8 @@ js::AsyncFromSyncIteratorMethod(JSContext* cx, CallArgs& args, CompletionKind co
|
||||||
|
|
||||||
RootedObject resultObj(cx, &resultVal.toObject());
|
RootedObject resultObj(cx, &resultVal.toObject());
|
||||||
|
|
||||||
// Following step numbers are for 6.1.3.2.1.
|
// Following step numbers are for 11.1.3.2.1.
|
||||||
// For 6.1.3.2.2 and 6.1.3.2.3, steps 7-16 corresponds to steps 11-20.
|
// For 11.1.3.2.2 and 11.1.3.2.3, steps 7-16 corresponds to steps 11-20.
|
||||||
|
|
||||||
// Steps 7-8.
|
// Steps 7-8.
|
||||||
RootedValue doneVal(cx);
|
RootedValue doneVal(cx);
|
||||||
|
|
@ -2454,33 +2479,15 @@ js::AsyncFromSyncIteratorMethod(JSContext* cx, CallArgs& args, CompletionKind co
|
||||||
if (!GetProperty(cx, resultObj, resultObj, cx->names().value, &value))
|
if (!GetProperty(cx, resultObj, resultObj, cx->names().value, &value))
|
||||||
return AbruptRejectPromise(cx, args, resultPromise, nullptr);
|
return AbruptRejectPromise(cx, args, resultPromise, nullptr);
|
||||||
|
|
||||||
// Step 11.
|
|
||||||
Rooted<PromiseObject*> promise(cx, CreatePromiseObjectWithoutResolutionFunctions(cx));
|
|
||||||
if (!promise)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Step 12.
|
|
||||||
if (!ResolvePromiseInternal(cx, promise, value))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Steps 13-14.
|
// Steps 13-14.
|
||||||
RootedValue onFulfilled(cx, Int32Value(done
|
RootedValue onFulfilled(cx, Int32Value(done
|
||||||
? PromiseHandlerAsyncIteratorValueUnwrapDone
|
? PromiseHandlerAsyncFromSyncIteratorValueUnwrapDone
|
||||||
: PromiseHandlerAsyncIteratorValueUnwrapNotDone));
|
: PromiseHandlerAsyncFromSyncIteratorValueUnwrapNotDone));
|
||||||
|
|
||||||
RootedObject incumbentGlobal(cx);
|
// Steps 11-12, 15.
|
||||||
if (!GetObjectFromIncumbentGlobal(cx, &incumbentGlobal))
|
auto extra = [](Handle<PromiseReactionRecord*> reaction) {
|
||||||
return false;
|
};
|
||||||
|
if (!InternalAwait(cx, value, resultPromise, onFulfilled, UndefinedHandleValue, extra))
|
||||||
// Step 15.
|
|
||||||
Rooted<PromiseReactionRecord*> reaction(cx, NewReactionRecord(cx, resultPromise, onFulfilled,
|
|
||||||
UndefinedHandleValue,
|
|
||||||
nullptr, nullptr,
|
|
||||||
incumbentGlobal));
|
|
||||||
if (!reaction)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!PerformPromiseThenWithReaction(cx, promise, reaction))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Step 16.
|
// Step 16.
|
||||||
|
|
@ -2488,7 +2495,10 @@ js::AsyncFromSyncIteratorMethod(JSContext* cx, CallArgs& args, CompletionKind co
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Async Iteration proposal 6.4.3.3.
|
static MOZ_MUST_USE bool
|
||||||
|
AsyncGeneratorResumeNext(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj);
|
||||||
|
|
||||||
|
// Async Iteration proposal 11.4.3.3.
|
||||||
MOZ_MUST_USE bool
|
MOZ_MUST_USE bool
|
||||||
js::AsyncGeneratorResolve(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
js::AsyncGeneratorResolve(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||||
HandleValue value, bool done)
|
HandleValue value, bool done)
|
||||||
|
|
@ -2508,43 +2518,25 @@ js::AsyncGeneratorResolve(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenO
|
||||||
RootedObject resultPromise(cx, request->promise());
|
RootedObject resultPromise(cx, request->promise());
|
||||||
|
|
||||||
// Step 6.
|
// Step 6.
|
||||||
Rooted<PromiseObject*> promise(cx, CreatePromiseObjectWithoutResolutionFunctions(cx));
|
RootedObject resultObj(cx, CreateIterResultObject(cx, value, done));
|
||||||
if (!promise)
|
if (!resultObj)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
RootedValue resultValue(cx, ObjectValue(*resultObj));
|
||||||
|
|
||||||
// Step 7.
|
// Step 7.
|
||||||
if (!ResolvePromiseInternal(cx, promise, value))
|
if (!ResolvePromiseInternal(cx, resultPromise, resultValue))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Steps 8-9.
|
// Step 8.
|
||||||
RootedValue onFulfilled(cx, Int32Value(done
|
|
||||||
? PromiseHandlerAsyncIteratorValueUnwrapDone
|
|
||||||
: PromiseHandlerAsyncIteratorValueUnwrapNotDone));
|
|
||||||
|
|
||||||
RootedObject incumbentGlobal(cx);
|
|
||||||
if (!GetObjectFromIncumbentGlobal(cx, &incumbentGlobal))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Step 10.
|
|
||||||
Rooted<PromiseReactionRecord*> reaction(cx, NewReactionRecord(cx, resultPromise, onFulfilled,
|
|
||||||
UndefinedHandleValue,
|
|
||||||
nullptr, nullptr,
|
|
||||||
incumbentGlobal));
|
|
||||||
if (!reaction)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!PerformPromiseThenWithReaction(cx, promise, reaction))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Step 11.
|
|
||||||
if (!AsyncGeneratorResumeNext(cx, asyncGenObj))
|
if (!AsyncGeneratorResumeNext(cx, asyncGenObj))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Step 12.
|
// Step 9.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Async Iteration proposal 6.4.3.4.
|
// Async Iteration proposal 11.4.3.4.
|
||||||
MOZ_MUST_USE bool
|
MOZ_MUST_USE bool
|
||||||
js::AsyncGeneratorReject(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
js::AsyncGeneratorReject(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||||
HandleValue exception)
|
HandleValue exception)
|
||||||
|
|
@ -2575,7 +2567,98 @@ js::AsyncGeneratorReject(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenOb
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Async Iteration proposal 6.4.3.6.
|
// 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
|
MOZ_MUST_USE bool
|
||||||
js::AsyncGeneratorEnqueue(JSContext* cx, HandleValue asyncGenVal,
|
js::AsyncGeneratorEnqueue(JSContext* cx, HandleValue asyncGenVal,
|
||||||
CompletionKind completionKind, HandleValue completionValue,
|
CompletionKind completionKind, HandleValue completionValue,
|
||||||
|
|
|
||||||
|
|
@ -8578,6 +8578,13 @@ BytecodeEmitter::emitReturn(ParseNode* pn)
|
||||||
if (ParseNode* pn2 = pn->pn_kid) {
|
if (ParseNode* pn2 = pn->pn_kid) {
|
||||||
if (!emitTree(pn2))
|
if (!emitTree(pn2))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
bool isAsyncGenerator = sc->asFunctionBox()->isAsync() &&
|
||||||
|
sc->asFunctionBox()->isStarGenerator();
|
||||||
|
if (isAsyncGenerator) {
|
||||||
|
if (!emitAwait())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* No explicit return value provided */
|
/* No explicit return value provided */
|
||||||
if (!emit1(JSOP_UNDEFINED))
|
if (!emit1(JSOP_UNDEFINED))
|
||||||
|
|
@ -8690,6 +8697,14 @@ BytecodeEmitter::emitYield(ParseNode* pn)
|
||||||
if (!emit1(JSOP_UNDEFINED))
|
if (!emit1(JSOP_UNDEFINED))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 11.4.3.7 AsyncGeneratorYield step 5.
|
||||||
|
bool isAsyncGenerator = sc->asFunctionBox()->isAsync();
|
||||||
|
if (isAsyncGenerator) {
|
||||||
|
if (!emitAwait()) // RESULT
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (needsIteratorResult) {
|
if (needsIteratorResult) {
|
||||||
if (!emitFinishIteratorResult(false))
|
if (!emitFinishIteratorResult(false))
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -8762,6 +8777,12 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter)
|
||||||
|
|
||||||
MOZ_ASSERT(this->stackDepth == startDepth);
|
MOZ_ASSERT(this->stackDepth == startDepth);
|
||||||
|
|
||||||
|
// 11.4.3.7 AsyncGeneratorYield step 5.
|
||||||
|
if (isAsyncGenerator) {
|
||||||
|
if (!emitAwait()) // ITER RESULT
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Load the generator object.
|
// Load the generator object.
|
||||||
if (!emitGetDotGenerator()) // ITER RESULT GENOBJ
|
if (!emitGetDotGenerator()) // ITER RESULT GENOBJ
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -8910,10 +8931,6 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter)
|
||||||
return false;
|
return false;
|
||||||
if (!emitAtomOp(cx->names().value, JSOP_GETPROP)) // ITER OLDRESULT FTYPE FVALUE VALUE
|
if (!emitAtomOp(cx->names().value, JSOP_GETPROP)) // ITER OLDRESULT FTYPE FVALUE VALUE
|
||||||
return false;
|
return false;
|
||||||
if (isAsyncGenerator) {
|
|
||||||
if (!emitAwait()) // ITER OLDRESULT FTYPE FVALUE VALUE
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!emitPrepareIteratorResult()) // ITER OLDRESULT FTYPE FVALUE VALUE RESULT
|
if (!emitPrepareIteratorResult()) // ITER OLDRESULT FTYPE FVALUE VALUE RESULT
|
||||||
return false;
|
return false;
|
||||||
if (!emit1(JSOP_SWAP)) // ITER OLDRESULT FTYPE FVALUE RESULT VALUE
|
if (!emit1(JSOP_SWAP)) // ITER OLDRESULT FTYPE FVALUE RESULT VALUE
|
||||||
|
|
@ -9006,11 +9023,6 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter)
|
||||||
if (!emitAtomOp(cx->names().value, JSOP_GETPROP)) // VALUE
|
if (!emitAtomOp(cx->names().value, JSOP_GETPROP)) // VALUE
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (isAsyncGenerator) {
|
|
||||||
if (!emitAwait()) // VALUE
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
MOZ_ASSERT(this->stackDepth == startDepth - 1);
|
MOZ_ASSERT(this->stackDepth == startDepth - 1);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ using namespace js::gc;
|
||||||
#define UNWRAPPED_ASYNC_WRAPPED_SLOT 1
|
#define UNWRAPPED_ASYNC_WRAPPED_SLOT 1
|
||||||
#define WRAPPED_ASYNC_UNWRAPPED_SLOT 0
|
#define WRAPPED_ASYNC_UNWRAPPED_SLOT 0
|
||||||
|
|
||||||
// Async Iteration proposal 2.3.10 Runtime Semantics: EvaluateBody.
|
// Async Iteration proposal 8.3.10 Runtime Semantics: EvaluateBody.
|
||||||
static bool
|
static bool
|
||||||
WrappedAsyncGenerator(JSContext* cx, unsigned argc, Value* vp)
|
WrappedAsyncGenerator(JSContext* cx, unsigned argc, Value* vp)
|
||||||
{
|
{
|
||||||
|
|
@ -128,11 +128,7 @@ js::GetUnwrappedAsyncGenerator(JSFunction* wrapped)
|
||||||
return unwrapped;
|
return unwrapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
static MOZ_MUST_USE bool
|
// Async Iteration proposal 4.1.1 Await Fulfilled Functions.
|
||||||
AsyncGeneratorResume(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
|
||||||
CompletionKind completionKind, HandleValue argument);
|
|
||||||
|
|
||||||
// Async Iteration proposal 5.1.1 Await Fulfilled Functions.
|
|
||||||
MOZ_MUST_USE bool
|
MOZ_MUST_USE bool
|
||||||
js::AsyncGeneratorAwaitedFulfilled(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
js::AsyncGeneratorAwaitedFulfilled(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||||
HandleValue value)
|
HandleValue value)
|
||||||
|
|
@ -140,7 +136,7 @@ js::AsyncGeneratorAwaitedFulfilled(JSContext* cx, Handle<AsyncGeneratorObject*>
|
||||||
return AsyncGeneratorResume(cx, asyncGenObj, CompletionKind::Normal, value);
|
return AsyncGeneratorResume(cx, asyncGenObj, CompletionKind::Normal, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Async Iteration proposal 5.1.2 Await Rejected Functions.
|
// Async Iteration proposal 4.1.2 Await Rejected Functions.
|
||||||
MOZ_MUST_USE bool
|
MOZ_MUST_USE bool
|
||||||
js::AsyncGeneratorAwaitedRejected(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
js::AsyncGeneratorAwaitedRejected(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||||
HandleValue reason)
|
HandleValue reason)
|
||||||
|
|
@ -148,12 +144,30 @@ js::AsyncGeneratorAwaitedRejected(JSContext* cx, Handle<AsyncGeneratorObject*> a
|
||||||
return AsyncGeneratorResume(cx, asyncGenObj, CompletionKind::Throw, reason);
|
return AsyncGeneratorResume(cx, asyncGenObj, CompletionKind::Throw, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Async Iteration proposal 11.4.3.7 step 8.d-e.
|
||||||
|
MOZ_MUST_USE bool
|
||||||
|
js::AsyncGeneratorYieldReturnAwaitedFulfilled(JSContext* cx,
|
||||||
|
Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||||
|
HandleValue value)
|
||||||
|
{
|
||||||
|
return AsyncGeneratorResume(cx, asyncGenObj, CompletionKind::Return, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Async Iteration proposal 11.4.3.7 step 8.d-e.
|
||||||
|
MOZ_MUST_USE bool
|
||||||
|
js::AsyncGeneratorYieldReturnAwaitedRejected(JSContext* cx,
|
||||||
|
Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||||
|
HandleValue reason)
|
||||||
|
{
|
||||||
|
return AsyncGeneratorResume(cx, asyncGenObj, CompletionKind::Throw, reason);
|
||||||
|
}
|
||||||
|
|
||||||
const Class AsyncFromSyncIteratorObject::class_ = {
|
const Class AsyncFromSyncIteratorObject::class_ = {
|
||||||
"AsyncFromSyncIteratorObject",
|
"AsyncFromSyncIteratorObject",
|
||||||
JSCLASS_HAS_RESERVED_SLOTS(AsyncFromSyncIteratorObject::Slots)
|
JSCLASS_HAS_RESERVED_SLOTS(AsyncFromSyncIteratorObject::Slots)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Async Iteration proposal 6.1.3.1.
|
// Async Iteration proposal 11.1.3.1.
|
||||||
JSObject*
|
JSObject*
|
||||||
js::CreateAsyncFromSyncIterator(JSContext* cx, HandleObject iter)
|
js::CreateAsyncFromSyncIterator(JSContext* cx, HandleObject iter)
|
||||||
{
|
{
|
||||||
|
|
@ -164,7 +178,7 @@ js::CreateAsyncFromSyncIterator(JSContext* cx, HandleObject iter)
|
||||||
return AsyncFromSyncIteratorObject::create(cx, iter);
|
return AsyncFromSyncIteratorObject::create(cx, iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Async Iteration proposal 6.1.3.1 steps 2-4.
|
// Async Iteration proposal 11.1.3.1 steps 2-4.
|
||||||
/* static */ JSObject*
|
/* static */ JSObject*
|
||||||
AsyncFromSyncIteratorObject::create(JSContext* cx, HandleObject iter)
|
AsyncFromSyncIteratorObject::create(JSContext* cx, HandleObject iter)
|
||||||
{
|
{
|
||||||
|
|
@ -187,7 +201,7 @@ AsyncFromSyncIteratorObject::create(JSContext* cx, HandleObject iter)
|
||||||
return asyncIter;
|
return asyncIter;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Async Iteration proposal 6.1.3.2.1 %AsyncFromSyncIteratorPrototype%.next.
|
// Async Iteration proposal 11.1.3.2.1 %AsyncFromSyncIteratorPrototype%.next.
|
||||||
static bool
|
static bool
|
||||||
AsyncFromSyncIteratorNext(JSContext* cx, unsigned argc, Value* vp)
|
AsyncFromSyncIteratorNext(JSContext* cx, unsigned argc, Value* vp)
|
||||||
{
|
{
|
||||||
|
|
@ -195,7 +209,7 @@ AsyncFromSyncIteratorNext(JSContext* cx, unsigned argc, Value* vp)
|
||||||
return AsyncFromSyncIteratorMethod(cx, args, CompletionKind::Normal);
|
return AsyncFromSyncIteratorMethod(cx, args, CompletionKind::Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Async Iteration proposal 6.1.3.2.2 %AsyncFromSyncIteratorPrototype%.return.
|
// Async Iteration proposal 11.1.3.2.2 %AsyncFromSyncIteratorPrototype%.return.
|
||||||
static bool
|
static bool
|
||||||
AsyncFromSyncIteratorReturn(JSContext* cx, unsigned argc, Value* vp)
|
AsyncFromSyncIteratorReturn(JSContext* cx, unsigned argc, Value* vp)
|
||||||
{
|
{
|
||||||
|
|
@ -203,7 +217,7 @@ AsyncFromSyncIteratorReturn(JSContext* cx, unsigned argc, Value* vp)
|
||||||
return AsyncFromSyncIteratorMethod(cx, args, CompletionKind::Return);
|
return AsyncFromSyncIteratorMethod(cx, args, CompletionKind::Return);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Async Iteration proposal 6.1.3.2.3 %AsyncFromSyncIteratorPrototype%.throw.
|
// Async Iteration proposal 11.1.3.2.3 %AsyncFromSyncIteratorPrototype%.throw.
|
||||||
static bool
|
static bool
|
||||||
AsyncFromSyncIteratorThrow(JSContext* cx, unsigned argc, Value* vp)
|
AsyncFromSyncIteratorThrow(JSContext* cx, unsigned argc, Value* vp)
|
||||||
{
|
{
|
||||||
|
|
@ -211,7 +225,7 @@ AsyncFromSyncIteratorThrow(JSContext* cx, unsigned argc, Value* vp)
|
||||||
return AsyncFromSyncIteratorMethod(cx, args, CompletionKind::Throw);
|
return AsyncFromSyncIteratorMethod(cx, args, CompletionKind::Throw);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Async Iteration proposal 6.4.1.2 AsyncGenerator.prototype.next.
|
// Async Iteration proposal 11.4.1.2 AsyncGenerator.prototype.next.
|
||||||
static bool
|
static bool
|
||||||
AsyncGeneratorNext(JSContext* cx, unsigned argc, Value* vp)
|
AsyncGeneratorNext(JSContext* cx, unsigned argc, Value* vp)
|
||||||
{
|
{
|
||||||
|
|
@ -222,7 +236,7 @@ AsyncGeneratorNext(JSContext* cx, unsigned argc, Value* vp)
|
||||||
args.rval());
|
args.rval());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Async Iteration proposal 6.4.1.3 AsyncGenerator.prototype.return.
|
// Async Iteration proposal 11.4.1.3 AsyncGenerator.prototype.return.
|
||||||
static bool
|
static bool
|
||||||
AsyncGeneratorReturn(JSContext* cx, unsigned argc, Value* vp)
|
AsyncGeneratorReturn(JSContext* cx, unsigned argc, Value* vp)
|
||||||
{
|
{
|
||||||
|
|
@ -233,7 +247,7 @@ AsyncGeneratorReturn(JSContext* cx, unsigned argc, Value* vp)
|
||||||
args.rval());
|
args.rval());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Async Iteration proposal 6.4.1.4 AsyncGenerator.prototype.throw.
|
// Async Iteration proposal 11.4.1.4 AsyncGenerator.prototype.throw.
|
||||||
static bool
|
static bool
|
||||||
AsyncGeneratorThrow(JSContext* cx, unsigned argc, Value* vp)
|
AsyncGeneratorThrow(JSContext* cx, unsigned argc, Value* vp)
|
||||||
{
|
{
|
||||||
|
|
@ -371,7 +385,7 @@ const Class AsyncGeneratorRequest::class_ = {
|
||||||
JSCLASS_HAS_RESERVED_SLOTS(AsyncGeneratorRequest::Slots)
|
JSCLASS_HAS_RESERVED_SLOTS(AsyncGeneratorRequest::Slots)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Async Iteration proposal 6.4.3.1.
|
// Async Iteration proposal 11.4.3.1.
|
||||||
/* static */ AsyncGeneratorRequest*
|
/* static */ AsyncGeneratorRequest*
|
||||||
AsyncGeneratorRequest::create(JSContext* cx, CompletionKind completionKind_,
|
AsyncGeneratorRequest::create(JSContext* cx, CompletionKind completionKind_,
|
||||||
HandleValue completionValue_, HandleObject promise_)
|
HandleValue completionValue_, HandleObject promise_)
|
||||||
|
|
@ -387,7 +401,7 @@ AsyncGeneratorRequest::create(JSContext* cx, CompletionKind completionKind_,
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Async Iteration proposal 6.4.3.2 steps 5.d-g.
|
// Async Iteration proposal 11.4.3.2 AsyncGeneratorStart steps 5.d-g.
|
||||||
static MOZ_MUST_USE bool
|
static MOZ_MUST_USE bool
|
||||||
AsyncGeneratorReturned(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
AsyncGeneratorReturned(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||||
HandleValue value)
|
HandleValue value)
|
||||||
|
|
@ -402,7 +416,7 @@ AsyncGeneratorReturned(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||||
return AsyncGeneratorResolve(cx, asyncGenObj, value, true);
|
return AsyncGeneratorResolve(cx, asyncGenObj, value, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Async Iteration proposal 6.4.3.2 steps 5.d, f.
|
// Async Iteration proposal 11.4.3.2 AsyncGeneratorStart steps 5.d, f.
|
||||||
static MOZ_MUST_USE bool
|
static MOZ_MUST_USE bool
|
||||||
AsyncGeneratorThrown(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj)
|
AsyncGeneratorThrown(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj)
|
||||||
{
|
{
|
||||||
|
|
@ -422,85 +436,33 @@ AsyncGeneratorThrown(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj)
|
||||||
return AsyncGeneratorReject(cx, asyncGenObj, value);
|
return AsyncGeneratorReject(cx, asyncGenObj, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Async Iteration proposal 6.4.3.5.
|
// Async Iteration proposal 11.4.3.7 (partially).
|
||||||
MOZ_MUST_USE bool
|
|
||||||
js::AsyncGeneratorResumeNext(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj)
|
|
||||||
{
|
|
||||||
// Step 1 (implicit).
|
|
||||||
|
|
||||||
// Steps 2-3.
|
|
||||||
MOZ_ASSERT(!asyncGenObj->isExecuting());
|
|
||||||
|
|
||||||
// Steps 4-5.
|
|
||||||
if (asyncGenObj->isQueueEmpty())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// Steps 6-7.
|
|
||||||
Rooted<AsyncGeneratorRequest*> request(
|
|
||||||
cx, AsyncGeneratorObject::peekRequest(cx, asyncGenObj));
|
|
||||||
if (!request)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Step 8.
|
|
||||||
CompletionKind completionKind = request->completionKind();
|
|
||||||
|
|
||||||
// Step 9.
|
|
||||||
if (completionKind != CompletionKind::Normal) {
|
|
||||||
// Step 9.a.
|
|
||||||
if (asyncGenObj->isSuspendedStart())
|
|
||||||
asyncGenObj->setCompleted();
|
|
||||||
|
|
||||||
// Step 9.b.
|
|
||||||
if (asyncGenObj->isCompleted()) {
|
|
||||||
// Step 9.b.i.
|
|
||||||
RootedValue value(cx, request->completionValue());
|
|
||||||
if (completionKind == CompletionKind::Return)
|
|
||||||
return AsyncGeneratorResolve(cx, asyncGenObj, value, true);
|
|
||||||
// Step 9.b.ii.
|
|
||||||
return AsyncGeneratorReject(cx, asyncGenObj, value);
|
|
||||||
}
|
|
||||||
} else if (asyncGenObj->isCompleted()) {
|
|
||||||
// Step 10.
|
|
||||||
return AsyncGeneratorResolve(cx, asyncGenObj, UndefinedHandleValue, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 11.
|
|
||||||
MOZ_ASSERT(asyncGenObj->isSuspendedStart() || asyncGenObj->isSuspendedYield());
|
|
||||||
|
|
||||||
// Step 15 (reordered).
|
|
||||||
asyncGenObj->setExecuting();
|
|
||||||
|
|
||||||
RootedValue argument(cx, request->completionValue());
|
|
||||||
|
|
||||||
// Steps 12-14, 16-20.
|
|
||||||
return AsyncGeneratorResume(cx, asyncGenObj, completionKind, argument);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Async Iteration proposal 6.2.1.3 (partially).
|
|
||||||
// Most steps are done in generator.
|
// Most steps are done in generator.
|
||||||
static MOZ_MUST_USE bool
|
static MOZ_MUST_USE bool
|
||||||
AsyncGeneratorYield(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
AsyncGeneratorYield(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj, HandleValue value)
|
||||||
HandleValue value)
|
|
||||||
{
|
{
|
||||||
// Step 5.
|
// Step 5 is done in bytecode.
|
||||||
|
|
||||||
|
// Step 6.
|
||||||
asyncGenObj->setSuspendedYield();
|
asyncGenObj->setSuspendedYield();
|
||||||
|
|
||||||
// Step 8.
|
// Step 9.
|
||||||
return AsyncGeneratorResolve(cx, asyncGenObj, value, false);
|
return AsyncGeneratorResolve(cx, asyncGenObj, value, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Async Iteration proposal 6.4.3.5 steps 12-14, 16-20.
|
// Async Iteration proposal 4.1 Await steps 2-9.
|
||||||
// Async Iteration proposal 6.2.1.2 step 10.
|
// Async Iteration proposal 8.2.1 yield* steps 6.a.vii, 6.b.ii.7, 6.c.ix.
|
||||||
// Async Iteration proposal 6.4.3.2 step 5.f-g.
|
// Async Iteration proposal 11.4.3.2 AsyncGeneratorStart step 5.f-g.
|
||||||
// Async Iteration proposal 5.1 steps 2-9.
|
// Async Iteration proposal 11.4.3.5 AsyncGeneratorResumeNext
|
||||||
|
// steps 12-14, 16-20.
|
||||||
// Execution context switching is handled in generator.
|
// Execution context switching is handled in generator.
|
||||||
static MOZ_MUST_USE bool
|
MOZ_MUST_USE bool
|
||||||
AsyncGeneratorResume(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
js::AsyncGeneratorResume(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||||
CompletionKind completionKind, HandleValue argument)
|
CompletionKind completionKind, HandleValue argument)
|
||||||
{
|
{
|
||||||
RootedValue generatorVal(cx, asyncGenObj->generatorVal());
|
RootedValue generatorVal(cx, asyncGenObj->generatorVal());
|
||||||
|
|
||||||
// 6.4.3.5 steps 12-14, 16-20.
|
// 11.4.3.5 steps 12-14, 16-20.
|
||||||
HandlePropertyName funName = completionKind == CompletionKind::Normal
|
HandlePropertyName funName = completionKind == CompletionKind::Normal
|
||||||
? cx->names().StarGeneratorNext
|
? cx->names().StarGeneratorNext
|
||||||
: completionKind == CompletionKind::Throw
|
: completionKind == CompletionKind::Throw
|
||||||
|
|
@ -510,10 +472,11 @@ AsyncGeneratorResume(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||||
args[0].set(argument);
|
args[0].set(argument);
|
||||||
RootedValue result(cx);
|
RootedValue result(cx);
|
||||||
if (!CallSelfHostedFunction(cx, funName, generatorVal, args, &result)) {
|
if (!CallSelfHostedFunction(cx, funName, generatorVal, args, &result)) {
|
||||||
// 6.4.3.2 step 5.d, f.
|
// 11.4.3.2 step 5.d, f.
|
||||||
return AsyncGeneratorThrown(cx, asyncGenObj);
|
return AsyncGeneratorThrown(cx, asyncGenObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 4.1 steps 2-9.
|
||||||
if (asyncGenObj->generatorObj()->isAfterAwait())
|
if (asyncGenObj->generatorObj()->isAfterAwait())
|
||||||
return AsyncGeneratorAwait(cx, asyncGenObj, result);
|
return AsyncGeneratorAwait(cx, asyncGenObj, result);
|
||||||
|
|
||||||
|
|
@ -525,8 +488,10 @@ AsyncGeneratorResume(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||||
// object and it's not observable.
|
// object and it's not observable.
|
||||||
// For yield*, it's done on a possibly user-provided result object, and
|
// For yield*, it's done on a possibly user-provided result object, and
|
||||||
// it's observable.
|
// it's observable.
|
||||||
|
//
|
||||||
|
// Note that IteratorComplete steps in 8.2.1 are done in bytecode.
|
||||||
|
|
||||||
// 2.2.1 yield* steps 6.a.vii, 6.b.ii.7, 6.c.ix.
|
// 8.2.1 yield* steps 6.a.vii, 6.b.ii.7, 6.c.ix.
|
||||||
RootedObject resultObj(cx, &result.toObject());
|
RootedObject resultObj(cx, &result.toObject());
|
||||||
RootedValue value(cx);
|
RootedValue value(cx);
|
||||||
|
|
||||||
|
|
@ -536,7 +501,7 @@ AsyncGeneratorResume(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||||
if (asyncGenObj->generatorObj()->isAfterYield())
|
if (asyncGenObj->generatorObj()->isAfterYield())
|
||||||
return AsyncGeneratorYield(cx, asyncGenObj, value);
|
return AsyncGeneratorYield(cx, asyncGenObj, value);
|
||||||
|
|
||||||
// 6.4.3.2 step 5.d-g.
|
// 11.4.3.2 step 5.d-g.
|
||||||
return AsyncGeneratorReturned(cx, asyncGenObj, value);
|
return AsyncGeneratorReturned(cx, asyncGenObj, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -565,14 +530,14 @@ GlobalObject::initAsyncGenerators(JSContext* cx, Handle<GlobalObject*> global)
|
||||||
if (global->getReservedSlot(ASYNC_ITERATOR_PROTO).isObject())
|
if (global->getReservedSlot(ASYNC_ITERATOR_PROTO).isObject())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Async Iteration proposal 6.1.2 %AsyncIteratorPrototype%.
|
// Async Iteration proposal 11.1.2 %AsyncIteratorPrototype%.
|
||||||
RootedObject asyncIterProto(cx, GlobalObject::createBlankPrototype<PlainObject>(cx, global));
|
RootedObject asyncIterProto(cx, GlobalObject::createBlankPrototype<PlainObject>(cx, global));
|
||||||
if (!asyncIterProto)
|
if (!asyncIterProto)
|
||||||
return false;
|
return false;
|
||||||
if (!DefinePropertiesAndFunctions(cx, asyncIterProto, nullptr, async_iterator_proto_methods))
|
if (!DefinePropertiesAndFunctions(cx, asyncIterProto, nullptr, async_iterator_proto_methods))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Async Iteration proposal 6.1.3.2 %AsyncFromSyncIteratorPrototype%.
|
// Async Iteration proposal 11.1.3.2 %AsyncFromSyncIteratorPrototype%.
|
||||||
RootedObject asyncFromSyncIterProto(
|
RootedObject asyncFromSyncIterProto(
|
||||||
cx, GlobalObject::createBlankPrototypeInheriting(cx, global, &PlainObject::class_,
|
cx, GlobalObject::createBlankPrototypeInheriting(cx, global, &PlainObject::class_,
|
||||||
asyncIterProto));
|
asyncIterProto));
|
||||||
|
|
@ -585,7 +550,7 @@ GlobalObject::initAsyncGenerators(JSContext* cx, Handle<GlobalObject*> global)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Async Iteration proposal 6.4.1 %AsyncGeneratorPrototype%.
|
// Async Iteration proposal 11.4.1 %AsyncGeneratorPrototype%.
|
||||||
RootedObject asyncGenProto(
|
RootedObject asyncGenProto(
|
||||||
cx, GlobalObject::createBlankPrototypeInheriting(cx, global, &PlainObject::class_,
|
cx, GlobalObject::createBlankPrototypeInheriting(cx, global, &PlainObject::class_,
|
||||||
asyncIterProto));
|
asyncIterProto));
|
||||||
|
|
@ -597,7 +562,7 @@ GlobalObject::initAsyncGenerators(JSContext* cx, Handle<GlobalObject*> global)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Async Iteration proposal 6.3.3 %AsyncGenerator%.
|
// Async Iteration proposal 11.3.3 %AsyncGenerator%.
|
||||||
RootedObject asyncGenerator(cx, NewSingletonObjectWithFunctionPrototype(cx, global));
|
RootedObject asyncGenerator(cx, NewSingletonObjectWithFunctionPrototype(cx, global));
|
||||||
if (!asyncGenerator)
|
if (!asyncGenerator)
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -616,7 +581,7 @@ GlobalObject::initAsyncGenerators(JSContext* cx, Handle<GlobalObject*> global)
|
||||||
RootedObject proto(cx, &function.toObject());
|
RootedObject proto(cx, &function.toObject());
|
||||||
RootedAtom name(cx, cx->names().AsyncGeneratorFunction);
|
RootedAtom name(cx, cx->names().AsyncGeneratorFunction);
|
||||||
|
|
||||||
// Async Iteration proposal 6.3.2 %AsyncGeneratorFunction%.
|
// Async Iteration proposal 11.3.2 %AsyncGeneratorFunction%.
|
||||||
RootedObject asyncGenFunction(
|
RootedObject asyncGenFunction(
|
||||||
cx, NewFunctionWithProto(cx, AsyncGeneratorConstructor, 1, JSFunction::NATIVE_CTOR,
|
cx, NewFunctionWithProto(cx, AsyncGeneratorConstructor, 1, JSFunction::NATIVE_CTOR,
|
||||||
nullptr, name, proto, gc::AllocKind::FUNCTION, SingletonObject));
|
nullptr, name, proto, gc::AllocKind::FUNCTION, SingletonObject));
|
||||||
|
|
|
||||||
|
|
@ -38,11 +38,18 @@ GetUnwrappedAsyncGenerator(JSFunction* wrapped);
|
||||||
|
|
||||||
MOZ_MUST_USE bool
|
MOZ_MUST_USE bool
|
||||||
AsyncGeneratorAwaitedFulfilled(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
AsyncGeneratorAwaitedFulfilled(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||||
HandleValue value);
|
HandleValue value);
|
||||||
|
|
||||||
MOZ_MUST_USE bool
|
MOZ_MUST_USE bool
|
||||||
AsyncGeneratorAwaitedRejected(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
AsyncGeneratorAwaitedRejected(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||||
HandleValue reason);
|
HandleValue reason);
|
||||||
|
MOZ_MUST_USE bool
|
||||||
|
AsyncGeneratorYieldReturnAwaitedFulfilled(JSContext* cx,
|
||||||
|
Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||||
|
HandleValue value);
|
||||||
|
MOZ_MUST_USE bool
|
||||||
|
AsyncGeneratorYieldReturnAwaitedRejected(JSContext* cx,
|
||||||
|
Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||||
|
HandleValue reason);
|
||||||
|
|
||||||
class AsyncGeneratorRequest : public NativeObject
|
class AsyncGeneratorRequest : public NativeObject
|
||||||
{
|
{
|
||||||
|
|
@ -97,6 +104,12 @@ class AsyncGeneratorObject : public NativeObject
|
||||||
State_SuspendedStart,
|
State_SuspendedStart,
|
||||||
State_SuspendedYield,
|
State_SuspendedYield,
|
||||||
State_Executing,
|
State_Executing,
|
||||||
|
// State_AwaitingYieldReturn corresponds to the case that
|
||||||
|
// AsyncGenerator#return is called while State_Executing,
|
||||||
|
// just like the case that AsyncGenerator#return is called
|
||||||
|
// while State_Completed.
|
||||||
|
State_AwaitingYieldReturn,
|
||||||
|
State_AwaitingReturn,
|
||||||
State_Completed
|
State_Completed
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -155,6 +168,12 @@ class AsyncGeneratorObject : public NativeObject
|
||||||
bool isExecuting() const {
|
bool isExecuting() const {
|
||||||
return state() == State_Executing;
|
return state() == State_Executing;
|
||||||
}
|
}
|
||||||
|
bool isAwaitingYieldReturn() const {
|
||||||
|
return state() == State_AwaitingYieldReturn;
|
||||||
|
}
|
||||||
|
bool isAwaitingReturn() const {
|
||||||
|
return state() == State_AwaitingReturn;
|
||||||
|
}
|
||||||
bool isCompleted() const {
|
bool isCompleted() const {
|
||||||
return state() == State_Completed;
|
return state() == State_Completed;
|
||||||
}
|
}
|
||||||
|
|
@ -168,6 +187,12 @@ class AsyncGeneratorObject : public NativeObject
|
||||||
void setExecuting() {
|
void setExecuting() {
|
||||||
setState(State_Executing);
|
setState(State_Executing);
|
||||||
}
|
}
|
||||||
|
void setAwaitingYieldReturn() {
|
||||||
|
setState(State_AwaitingYieldReturn);
|
||||||
|
}
|
||||||
|
void setAwaitingReturn() {
|
||||||
|
setState(State_AwaitingReturn);
|
||||||
|
}
|
||||||
void setCompleted() {
|
void setCompleted() {
|
||||||
setState(State_Completed);
|
setState(State_Completed);
|
||||||
}
|
}
|
||||||
|
|
@ -223,7 +248,8 @@ class AsyncFromSyncIteratorObject : public NativeObject
|
||||||
};
|
};
|
||||||
|
|
||||||
MOZ_MUST_USE bool
|
MOZ_MUST_USE bool
|
||||||
AsyncGeneratorResumeNext(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj);
|
AsyncGeneratorResume(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||||
|
CompletionKind completionKind, HandleValue argument);
|
||||||
|
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue