summaryrefslogtreecommitdiff
path: root/js/src/vm
diff options
context:
space:
mode:
authorGaming4JC <g4jc@hyperbola.info>2019-12-14 10:30:54 -0500
committerGaming4JC <g4jc@hyperbola.info>2019-12-17 06:25:29 -0500
commit38c1d558afd03d61bd9932032f47d9c36f177b08 (patch)
treeff90c1f5c04d410a9ff706c3767869de96d3259d /js/src/vm
parentdd1cbde1569e823e5e76e8c3ef0ecba66408719d (diff)
downloaduxp-38c1d558afd03d61bd9932032f47d9c36f177b08.tar.gz
Bug 1379525 - Part 1: Await on the value before yielding or returning inside async generator.
Tag #1287
Diffstat (limited to 'js/src/vm')
-rw-r--r--js/src/vm/AsyncIteration.cpp151
-rw-r--r--js/src/vm/AsyncIteration.h34
2 files changed, 88 insertions, 97 deletions
diff --git a/js/src/vm/AsyncIteration.cpp b/js/src/vm/AsyncIteration.cpp
index 74f6389c10..256f247b09 100644
--- a/js/src/vm/AsyncIteration.cpp
+++ b/js/src/vm/AsyncIteration.cpp
@@ -26,7 +26,7 @@ using namespace js::gc;
#define UNWRAPPED_ASYNC_WRAPPED_SLOT 1
#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
WrappedAsyncGenerator(JSContext* cx, unsigned argc, Value* vp)
{
@@ -128,11 +128,7 @@ js::GetUnwrappedAsyncGenerator(JSFunction* wrapped)
return unwrapped;
}
-static MOZ_MUST_USE bool
-AsyncGeneratorResume(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
- CompletionKind completionKind, HandleValue argument);
-
-// Async Iteration proposal 5.1.1 Await Fulfilled Functions.
+// Async Iteration proposal 4.1.1 Await Fulfilled Functions.
MOZ_MUST_USE bool
js::AsyncGeneratorAwaitedFulfilled(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
HandleValue value)
@@ -140,7 +136,7 @@ js::AsyncGeneratorAwaitedFulfilled(JSContext* cx, Handle<AsyncGeneratorObject*>
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
js::AsyncGeneratorAwaitedRejected(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
HandleValue reason)
@@ -148,12 +144,30 @@ js::AsyncGeneratorAwaitedRejected(JSContext* cx, Handle<AsyncGeneratorObject*> a
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_ = {
"AsyncFromSyncIteratorObject",
JSCLASS_HAS_RESERVED_SLOTS(AsyncFromSyncIteratorObject::Slots)
};
-// Async Iteration proposal 6.1.3.1.
+// Async Iteration proposal 11.1.3.1.
JSObject*
js::CreateAsyncFromSyncIterator(JSContext* cx, HandleObject iter)
{
@@ -164,7 +178,7 @@ js::CreateAsyncFromSyncIterator(JSContext* cx, HandleObject 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*
AsyncFromSyncIteratorObject::create(JSContext* cx, HandleObject iter)
{
@@ -187,7 +201,7 @@ AsyncFromSyncIteratorObject::create(JSContext* cx, HandleObject iter)
return asyncIter;
}
-// Async Iteration proposal 6.1.3.2.1 %AsyncFromSyncIteratorPrototype%.next.
+// Async Iteration proposal 11.1.3.2.1 %AsyncFromSyncIteratorPrototype%.next.
static bool
AsyncFromSyncIteratorNext(JSContext* cx, unsigned argc, Value* vp)
{
@@ -195,7 +209,7 @@ AsyncFromSyncIteratorNext(JSContext* cx, unsigned argc, Value* vp)
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
AsyncFromSyncIteratorReturn(JSContext* cx, unsigned argc, Value* vp)
{
@@ -203,7 +217,7 @@ AsyncFromSyncIteratorReturn(JSContext* cx, unsigned argc, Value* vp)
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
AsyncFromSyncIteratorThrow(JSContext* cx, unsigned argc, Value* vp)
{
@@ -211,7 +225,7 @@ AsyncFromSyncIteratorThrow(JSContext* cx, unsigned argc, Value* vp)
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
AsyncGeneratorNext(JSContext* cx, unsigned argc, Value* vp)
{
@@ -222,7 +236,7 @@ AsyncGeneratorNext(JSContext* cx, unsigned argc, Value* vp)
args.rval());
}
-// Async Iteration proposal 6.4.1.3 AsyncGenerator.prototype.return.
+// Async Iteration proposal 11.4.1.3 AsyncGenerator.prototype.return.
static bool
AsyncGeneratorReturn(JSContext* cx, unsigned argc, Value* vp)
{
@@ -233,7 +247,7 @@ AsyncGeneratorReturn(JSContext* cx, unsigned argc, Value* vp)
args.rval());
}
-// Async Iteration proposal 6.4.1.4 AsyncGenerator.prototype.throw.
+// Async Iteration proposal 11.4.1.4 AsyncGenerator.prototype.throw.
static bool
AsyncGeneratorThrow(JSContext* cx, unsigned argc, Value* vp)
{
@@ -371,7 +385,7 @@ const Class AsyncGeneratorRequest::class_ = {
JSCLASS_HAS_RESERVED_SLOTS(AsyncGeneratorRequest::Slots)
};
-// Async Iteration proposal 6.4.3.1.
+// Async Iteration proposal 11.4.3.1.
/* static */ AsyncGeneratorRequest*
AsyncGeneratorRequest::create(JSContext* cx, CompletionKind completionKind_,
HandleValue completionValue_, HandleObject promise_)
@@ -387,7 +401,7 @@ AsyncGeneratorRequest::create(JSContext* cx, CompletionKind completionKind_,
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
AsyncGeneratorReturned(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
HandleValue value)
@@ -402,7 +416,7 @@ AsyncGeneratorReturned(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
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
AsyncGeneratorThrown(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj)
{
@@ -422,85 +436,33 @@ AsyncGeneratorThrown(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj)
return AsyncGeneratorReject(cx, asyncGenObj, value);
}
-// Async Iteration proposal 6.4.3.5.
-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).
+// Async Iteration proposal 11.4.3.7 (partially).
// Most steps are done in generator.
static MOZ_MUST_USE bool
-AsyncGeneratorYield(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
- HandleValue value)
+AsyncGeneratorYield(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj, HandleValue value)
{
- // Step 5.
+ // Step 5 is done in bytecode.
+
+ // Step 6.
asyncGenObj->setSuspendedYield();
- // Step 8.
+ // Step 9.
return AsyncGeneratorResolve(cx, asyncGenObj, value, false);
}
-// Async Iteration proposal 6.4.3.5 steps 12-14, 16-20.
-// Async Iteration proposal 6.2.1.2 step 10.
-// Async Iteration proposal 6.4.3.2 step 5.f-g.
-// Async Iteration proposal 5.1 steps 2-9.
+// Async Iteration proposal 4.1 Await steps 2-9.
+// Async Iteration proposal 8.2.1 yield* steps 6.a.vii, 6.b.ii.7, 6.c.ix.
+// Async Iteration proposal 11.4.3.2 AsyncGeneratorStart step 5.f-g.
+// Async Iteration proposal 11.4.3.5 AsyncGeneratorResumeNext
+// steps 12-14, 16-20.
// Execution context switching is handled in generator.
-static MOZ_MUST_USE bool
-AsyncGeneratorResume(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
- CompletionKind completionKind, HandleValue argument)
+MOZ_MUST_USE bool
+js::AsyncGeneratorResume(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
+ CompletionKind completionKind, HandleValue argument)
{
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
? cx->names().StarGeneratorNext
: completionKind == CompletionKind::Throw
@@ -510,10 +472,11 @@ AsyncGeneratorResume(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
args[0].set(argument);
RootedValue result(cx);
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);
}
+ // 4.1 steps 2-9.
if (asyncGenObj->generatorObj()->isAfterAwait())
return AsyncGeneratorAwait(cx, asyncGenObj, result);
@@ -525,8 +488,10 @@ AsyncGeneratorResume(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
// object and it's not observable.
// For yield*, it's done on a possibly user-provided result object, and
// 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());
RootedValue value(cx);
@@ -536,7 +501,7 @@ AsyncGeneratorResume(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
if (asyncGenObj->generatorObj()->isAfterYield())
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);
}
@@ -565,14 +530,14 @@ GlobalObject::initAsyncGenerators(JSContext* cx, Handle<GlobalObject*> global)
if (global->getReservedSlot(ASYNC_ITERATOR_PROTO).isObject())
return true;
- // Async Iteration proposal 6.1.2 %AsyncIteratorPrototype%.
+ // Async Iteration proposal 11.1.2 %AsyncIteratorPrototype%.
RootedObject asyncIterProto(cx, GlobalObject::createBlankPrototype<PlainObject>(cx, global));
if (!asyncIterProto)
return false;
if (!DefinePropertiesAndFunctions(cx, asyncIterProto, nullptr, async_iterator_proto_methods))
return false;
- // Async Iteration proposal 6.1.3.2 %AsyncFromSyncIteratorPrototype%.
+ // Async Iteration proposal 11.1.3.2 %AsyncFromSyncIteratorPrototype%.
RootedObject asyncFromSyncIterProto(
cx, GlobalObject::createBlankPrototypeInheriting(cx, global, &PlainObject::class_,
asyncIterProto));
@@ -585,7 +550,7 @@ GlobalObject::initAsyncGenerators(JSContext* cx, Handle<GlobalObject*> global)
return false;
}
- // Async Iteration proposal 6.4.1 %AsyncGeneratorPrototype%.
+ // Async Iteration proposal 11.4.1 %AsyncGeneratorPrototype%.
RootedObject asyncGenProto(
cx, GlobalObject::createBlankPrototypeInheriting(cx, global, &PlainObject::class_,
asyncIterProto));
@@ -597,7 +562,7 @@ GlobalObject::initAsyncGenerators(JSContext* cx, Handle<GlobalObject*> global)
return false;
}
- // Async Iteration proposal 6.3.3 %AsyncGenerator%.
+ // Async Iteration proposal 11.3.3 %AsyncGenerator%.
RootedObject asyncGenerator(cx, NewSingletonObjectWithFunctionPrototype(cx, global));
if (!asyncGenerator)
return false;
@@ -616,7 +581,7 @@ GlobalObject::initAsyncGenerators(JSContext* cx, Handle<GlobalObject*> global)
RootedObject proto(cx, &function.toObject());
RootedAtom name(cx, cx->names().AsyncGeneratorFunction);
- // Async Iteration proposal 6.3.2 %AsyncGeneratorFunction%.
+ // Async Iteration proposal 11.3.2 %AsyncGeneratorFunction%.
RootedObject asyncGenFunction(
cx, NewFunctionWithProto(cx, AsyncGeneratorConstructor, 1, JSFunction::NATIVE_CTOR,
nullptr, name, proto, gc::AllocKind::FUNCTION, SingletonObject));
diff --git a/js/src/vm/AsyncIteration.h b/js/src/vm/AsyncIteration.h
index 974c209a01..58c43131b4 100644
--- a/js/src/vm/AsyncIteration.h
+++ b/js/src/vm/AsyncIteration.h
@@ -38,11 +38,18 @@ GetUnwrappedAsyncGenerator(JSFunction* wrapped);
MOZ_MUST_USE bool
AsyncGeneratorAwaitedFulfilled(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
- HandleValue value);
-
+ HandleValue value);
MOZ_MUST_USE bool
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
{
@@ -97,6 +104,12 @@ class AsyncGeneratorObject : public NativeObject
State_SuspendedStart,
State_SuspendedYield,
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
};
@@ -155,6 +168,12 @@ class AsyncGeneratorObject : public NativeObject
bool isExecuting() const {
return state() == State_Executing;
}
+ bool isAwaitingYieldReturn() const {
+ return state() == State_AwaitingYieldReturn;
+ }
+ bool isAwaitingReturn() const {
+ return state() == State_AwaitingReturn;
+ }
bool isCompleted() const {
return state() == State_Completed;
}
@@ -168,6 +187,12 @@ class AsyncGeneratorObject : public NativeObject
void setExecuting() {
setState(State_Executing);
}
+ void setAwaitingYieldReturn() {
+ setState(State_AwaitingYieldReturn);
+ }
+ void setAwaitingReturn() {
+ setState(State_AwaitingReturn);
+ }
void setCompleted() {
setState(State_Completed);
}
@@ -223,7 +248,8 @@ class AsyncFromSyncIteratorObject : public NativeObject
};
MOZ_MUST_USE bool
-AsyncGeneratorResumeNext(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj);
+AsyncGeneratorResume(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
+ CompletionKind completionKind, HandleValue argument);
} // namespace js