summaryrefslogtreecommitdiffstats
path: root/js/src/vm/AsyncIteration.cpp
diff options
context:
space:
mode:
authorGaming4JC <g4jc@hyperbola.info>2019-12-14 09:16:32 -0500
committerGaming4JC <g4jc@hyperbola.info>2019-12-17 06:25:28 -0500
commitef44324d916b89b95fa0ea77a3d91eafb4359bf8 (patch)
tree38ce7009388ceef8cb6793f5d0dcd5388d1d3a3f /js/src/vm/AsyncIteration.cpp
parentbbd1fef7840d97801307f9ace021b52d94c5f61f (diff)
downloadUXP-ef44324d916b89b95fa0ea77a3d91eafb4359bf8.tar
UXP-ef44324d916b89b95fa0ea77a3d91eafb4359bf8.tar.gz
UXP-ef44324d916b89b95fa0ea77a3d91eafb4359bf8.tar.lz
UXP-ef44324d916b89b95fa0ea77a3d91eafb4359bf8.tar.xz
UXP-ef44324d916b89b95fa0ea77a3d91eafb4359bf8.zip
Bug 1331092 - Part 7: Implement Async Generator yield*.
Tag #1287
Diffstat (limited to 'js/src/vm/AsyncIteration.cpp')
-rw-r--r--js/src/vm/AsyncIteration.cpp125
1 files changed, 99 insertions, 26 deletions
diff --git a/js/src/vm/AsyncIteration.cpp b/js/src/vm/AsyncIteration.cpp
index 04effe1b1..74f6389c1 100644
--- a/js/src/vm/AsyncIteration.cpp
+++ b/js/src/vm/AsyncIteration.cpp
@@ -148,6 +148,69 @@ js::AsyncGeneratorAwaitedRejected(JSContext* cx, Handle<AsyncGeneratorObject*> a
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.
+JSObject*
+js::CreateAsyncFromSyncIterator(JSContext* cx, HandleObject iter)
+{
+ // Step 1 (implicit).
+ // Done in bytecode emitted by emitAsyncIterator.
+
+ // Steps 2-4.
+ return AsyncFromSyncIteratorObject::create(cx, iter);
+}
+
+// Async Iteration proposal 6.1.3.1 steps 2-4.
+/* static */ JSObject*
+AsyncFromSyncIteratorObject::create(JSContext* cx, HandleObject iter)
+{
+ // Step 2.
+ RootedObject proto(cx, GlobalObject::getOrCreateAsyncFromSyncIteratorPrototype(cx,
+ cx->global()));
+ if (!proto)
+ return nullptr;
+
+ RootedObject obj(cx, NewNativeObjectWithGivenProto(cx, &class_, proto));
+ if (!obj)
+ return nullptr;
+
+ Handle<AsyncFromSyncIteratorObject*> asyncIter = obj.as<AsyncFromSyncIteratorObject>();
+
+ // Step 3.
+ asyncIter->setIterator(iter);
+
+ // Step 4.
+ return asyncIter;
+}
+
+// Async Iteration proposal 6.1.3.2.1 %AsyncFromSyncIteratorPrototype%.next.
+static bool
+AsyncFromSyncIteratorNext(JSContext* cx, unsigned argc, Value* vp)
+{
+ CallArgs args = CallArgsFromVp(argc, vp);
+ return AsyncFromSyncIteratorMethod(cx, args, CompletionKind::Normal);
+}
+
+// Async Iteration proposal 6.1.3.2.2 %AsyncFromSyncIteratorPrototype%.return.
+static bool
+AsyncFromSyncIteratorReturn(JSContext* cx, unsigned argc, Value* vp)
+{
+ CallArgs args = CallArgsFromVp(argc, vp);
+ return AsyncFromSyncIteratorMethod(cx, args, CompletionKind::Return);
+}
+
+// Async Iteration proposal 6.1.3.2.3 %AsyncFromSyncIteratorPrototype%.throw.
+static bool
+AsyncFromSyncIteratorThrow(JSContext* cx, unsigned argc, Value* vp)
+{
+ CallArgs args = CallArgsFromVp(argc, vp);
+ return AsyncFromSyncIteratorMethod(cx, args, CompletionKind::Throw);
+}
+
// Async Iteration proposal 6.4.1.2 AsyncGenerator.prototype.next.
static bool
AsyncGeneratorNext(JSContext* cx, unsigned argc, Value* vp)
@@ -413,17 +476,17 @@ js::AsyncGeneratorResumeNext(JSContext* cx, Handle<AsyncGeneratorObject*> asyncG
return AsyncGeneratorResume(cx, asyncGenObj, completionKind, argument);
}
-// Async Iteration proposal 6.2.1.2 (partially).
+// Async Iteration proposal 6.2.1.3 (partially).
// Most steps are done in generator.
static MOZ_MUST_USE bool
AsyncGeneratorYield(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
- HandleValue value, bool done)
+ HandleValue value)
{
- // Step 6.
+ // Step 5.
asyncGenObj->setSuspendedYield();
- // Step 10.c.
- return AsyncGeneratorResolve(cx, asyncGenObj, value, done);
+ // Step 8.
+ return AsyncGeneratorResolve(cx, asyncGenObj, value, false);
}
// Async Iteration proposal 6.4.3.5 steps 12-14, 16-20.
@@ -451,41 +514,30 @@ AsyncGeneratorResume(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
return AsyncGeneratorThrown(cx, asyncGenObj);
}
+ if (asyncGenObj->generatorObj()->isAfterAwait())
+ return AsyncGeneratorAwait(cx, asyncGenObj, result);
+
// The following code corresponds to the following 3 cases:
// * yield
- // * await
+ // * yield*
// * return
- // For await and return, property access is done on an internal result
+ // For yield and return, property access is done on an internal result
// object and it's not observable.
- // For yield, it's done on an user-provided result object, and it's
- // observable, so perform in that order in all cases.
+ // For yield*, it's done on a possibly user-provided result object, and
+ // it's observable.
+ // 2.2.1 yield* steps 6.a.vii, 6.b.ii.7, 6.c.ix.
RootedObject resultObj(cx, &result.toObject());
RootedValue value(cx);
- RootedValue doneVal(cx);
- // 6.2.1.2 step 10.a.
if (!GetProperty(cx, resultObj, resultObj, cx->names().value, &value))
return false;
- // 6.2.1.2 step 10.b.
- if (!GetProperty(cx, resultObj, resultObj, cx->names().done, &doneVal))
- return false;
-
- // 6.2.1.2 step 10.c.
if (asyncGenObj->generatorObj()->isAfterYield())
- return AsyncGeneratorYield(cx, asyncGenObj, value, ToBoolean(doneVal));
+ return AsyncGeneratorYield(cx, asyncGenObj, value);
// 6.4.3.2 step 5.d-g.
- if (ToBoolean(doneVal)) {
- MOZ_ASSERT(!asyncGenObj->generatorObj()->isAfterAwait());
- return AsyncGeneratorReturned(cx, asyncGenObj, value);
- }
-
- MOZ_ASSERT(asyncGenObj->generatorObj()->isAfterAwait());
-
- // 5.1 steps 2-9.
- return AsyncGeneratorAwait(cx, asyncGenObj, value);
+ return AsyncGeneratorReturned(cx, asyncGenObj, value);
}
static const JSFunctionSpec async_iterator_proto_methods[] = {
@@ -493,6 +545,13 @@ static const JSFunctionSpec async_iterator_proto_methods[] = {
JS_FS_END
};
+static const JSFunctionSpec async_from_sync_iter_methods[] = {
+ JS_FN("next", AsyncFromSyncIteratorNext, 1, 0),
+ JS_FN("throw", AsyncFromSyncIteratorThrow, 1, 0),
+ JS_FN("return", AsyncFromSyncIteratorReturn, 1, 0),
+ JS_FS_END
+};
+
static const JSFunctionSpec async_generator_methods[] = {
JS_FN("next", AsyncGeneratorNext, 1, 0),
JS_FN("throw", AsyncGeneratorThrow, 1, 0),
@@ -513,6 +572,19 @@ GlobalObject::initAsyncGenerators(JSContext* cx, Handle<GlobalObject*> global)
if (!DefinePropertiesAndFunctions(cx, asyncIterProto, nullptr, async_iterator_proto_methods))
return false;
+ // Async Iteration proposal 6.1.3.2 %AsyncFromSyncIteratorPrototype%.
+ RootedObject asyncFromSyncIterProto(
+ cx, GlobalObject::createBlankPrototypeInheriting(cx, global, &PlainObject::class_,
+ asyncIterProto));
+ if (!asyncFromSyncIterProto)
+ return false;
+ if (!DefinePropertiesAndFunctions(cx, asyncFromSyncIterProto, nullptr,
+ async_from_sync_iter_methods) ||
+ !DefineToStringTag(cx, asyncFromSyncIterProto, cx->names().AsyncFromSyncIterator))
+ {
+ return false;
+ }
+
// Async Iteration proposal 6.4.1 %AsyncGeneratorPrototype%.
RootedObject asyncGenProto(
cx, GlobalObject::createBlankPrototypeInheriting(cx, global, &PlainObject::class_,
@@ -557,6 +629,7 @@ GlobalObject::initAsyncGenerators(JSContext* cx, Handle<GlobalObject*> global)
}
global->setReservedSlot(ASYNC_ITERATOR_PROTO, ObjectValue(*asyncIterProto));
+ global->setReservedSlot(ASYNC_FROM_SYNC_ITERATOR_PROTO, ObjectValue(*asyncFromSyncIterProto));
global->setReservedSlot(ASYNC_GENERATOR, ObjectValue(*asyncGenerator));
global->setReservedSlot(ASYNC_GENERATOR_FUNCTION, ObjectValue(*asyncGenFunction));
global->setReservedSlot(ASYNC_GENERATOR_PROTO, ObjectValue(*asyncGenProto));