summaryrefslogtreecommitdiffstats
path: root/js/src/builtin/Promise.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/builtin/Promise.cpp')
-rw-r--r--js/src/builtin/Promise.cpp159
1 files changed, 159 insertions, 0 deletions
diff --git a/js/src/builtin/Promise.cpp b/js/src/builtin/Promise.cpp
index 59e710935..d2b7b543b 100644
--- a/js/src/builtin/Promise.cpp
+++ b/js/src/builtin/Promise.cpp
@@ -2329,6 +2329,165 @@ js::AsyncGeneratorAwait(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj
return PerformPromiseThenWithReaction(cx, promise, reaction);
}
+// Async Iteration proposal 6.1.3.2.1 %AsyncFromSyncIteratorPrototype%.next
+// Async Iteration proposal 6.1.3.2.2 %AsyncFromSyncIteratorPrototype%.return
+// Async Iteration proposal 6.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) {
+ // 6.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) {
+ // 6.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 {
+ // 6.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;
+ }
+ }
+
+ // 6.1.3.2.1 steps 5-6 (partially).
+ // 6.1.3.2.2, 6.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);
+
+ // 6.1.3.2.1 steps 5-6 (partially).
+ // 6.1.3.2.2, 6.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 6.1.3.2.1.
+ // For 6.1.3.2.2 and 6.1.3.2.3, steps 7-16 corresponds to steps 11-20.
+
+ // Steps 7-8.
+ RootedValue value(cx);
+ if (!GetProperty(cx, resultObj, resultObj, cx->names().value, &value))
+ return AbruptRejectPromise(cx, args, resultPromise, nullptr);
+
+ // Steps 9-10.
+ RootedValue doneVal(cx);
+ if (!GetProperty(cx, resultObj, resultObj, cx->names().done, &doneVal))
+ return AbruptRejectPromise(cx, args, resultPromise, nullptr);
+ bool done = ToBoolean(doneVal);
+
+ // Step 11.
+ Rooted<PromiseObject*> promise(cx, CreatePromiseObjectWithoutResolutionFunctions(cx));
+ if (!promise)
+ return false;
+
+ // Step 12.
+ if (!ResolvePromiseInternal(cx, promise, value))
+ return false;
+
+ // Steps 13-14.
+ RootedValue onFulfilled(cx, Int32Value(done
+ ? PromiseHandlerAsyncIteratorValueUnwrapDone
+ : PromiseHandlerAsyncIteratorValueUnwrapNotDone));
+
+ RootedObject incumbentGlobal(cx);
+ if (!GetObjectFromIncumbentGlobal(cx, &incumbentGlobal))
+ return false;
+
+ // 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;
+
+ // Step 16.
+ args.rval().setObject(*resultPromise);
+ return true;
+}
+
// Async Iteration proposal 6.4.3.3.
MOZ_MUST_USE bool
js::AsyncGeneratorResolve(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,