From ee7e0200906f50175c6aebd510c3e060a6383b4f Mon Sep 17 00:00:00 2001 From: Sebastian Hengst Date: Mon, 27 Mar 2017 17:25:37 +0200 Subject: [PATCH] Backed out changeset 0705d5b86ad7 (bug 1331092) --- js/public/Class.h | 2 +- js/src/builtin/AsyncIteration.js | 7 - js/src/builtin/Promise.cpp | 253 +------- js/src/builtin/Promise.h | 17 - js/src/frontend/BytecodeCompiler.cpp | 12 - js/src/frontend/BytecodeCompiler.h | 6 - js/src/frontend/BytecodeEmitter.cpp | 26 +- js/src/frontend/BytecodeEmitter.h | 3 +- js/src/frontend/Parser.cpp | 17 +- js/src/js.msg | 3 - js/src/jsapi.cpp | 6 - js/src/jsfun.cpp | 95 +-- js/src/jsfun.h | 3 - js/src/jsiter.cpp | 28 +- js/src/jsiter.h | 4 +- js/src/moz.build | 2 - js/src/shell/js.cpp | 3 - .../tests/ecma_2017/AsyncFunctions/syntax.js | 3 + js/src/vm/AsyncIteration.cpp | 564 ------------------ js/src/vm/AsyncIteration.h | 204 ------- js/src/vm/CommonPropertyNames.h | 3 - js/src/vm/GlobalObject.h | 30 - js/src/vm/Interpreter.cpp | 14 +- js/src/vm/Opcodes.h | 10 +- 24 files changed, 55 insertions(+), 1260 deletions(-) delete mode 100644 js/src/builtin/AsyncIteration.js delete mode 100644 js/src/vm/AsyncIteration.cpp delete mode 100644 js/src/vm/AsyncIteration.h diff --git a/js/public/Class.h b/js/public/Class.h index 2e4071066a42..5b68fd29667c 100644 --- a/js/public/Class.h +++ b/js/public/Class.h @@ -852,7 +852,7 @@ struct JSClass { // application. #define JSCLASS_GLOBAL_APPLICATION_SLOTS 5 #define JSCLASS_GLOBAL_SLOT_COUNT \ - (JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 45) + (JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 41) #define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \ (JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n))) #define JSCLASS_GLOBAL_FLAGS \ diff --git a/js/src/builtin/AsyncIteration.js b/js/src/builtin/AsyncIteration.js deleted file mode 100644 index 029c7c0f81e3..000000000000 --- a/js/src/builtin/AsyncIteration.js +++ /dev/null @@ -1,7 +0,0 @@ -/* 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 d41f566cbf7c..63acb055f9d8 100644 --- a/js/src/builtin/Promise.cpp +++ b/js/src/builtin/Promise.cpp @@ -12,12 +12,10 @@ #include "jscntxt.h" #include "jsexn.h" -#include "jsiter.h" #include "gc/Heap.h" #include "js/Debug.h" #include "vm/AsyncFunction.h" -#include "vm/AsyncIteration.h" #include "jsobjinlines.h" @@ -38,16 +36,6 @@ enum PromiseHandler { PromiseHandlerThrower, PromiseHandlerAsyncFunctionAwaitFulfilled, PromiseHandlerAsyncFunctionAwaitRejected, - PromiseHandlerAsyncGeneratorAwaitFulfilled, - PromiseHandlerAsyncGeneratorAwaitRejected, - - // Async Iteration proposal 6.1.1.2.1. - // Async 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. - PromiseHandlerAsyncIteratorValueUnwrapDone, - PromiseHandlerAsyncIteratorValueUnwrapNotDone, }; enum ResolutionMode { @@ -190,7 +178,6 @@ enum ReactionRecordSlots { ReactionRecordSlot_IncumbentGlobalObject, ReactionRecordSlot_Flags, ReactionRecordSlot_HandlerArg, - ReactionRecordSlot_Generator, ReactionRecordSlots, }; @@ -198,7 +185,6 @@ enum ReactionRecordSlots { #define REACTION_FLAG_FULFILLED 0x2 #define REACTION_FLAG_IGNORE_DEFAULT_RESOLUTION 0x4 #define REACTION_FLAG_ASYNC_FUNCTION_AWAIT 0x8 -#define REACTION_FLAG_ASYNC_GENERATOR_AWAIT 0x10 // ES2016, 25.4.1.2. class PromiseReactionRecord : public NativeObject @@ -234,22 +220,6 @@ class PromiseReactionRecord : public NativeObject int32_t flags = this->flags(); return flags & REACTION_FLAG_ASYNC_FUNCTION_AWAIT; } - void setIsAsyncGeneratorAwait(Handle asyncGenObj) { - int32_t flags = this->flags(); - flags |= REACTION_FLAG_ASYNC_GENERATOR_AWAIT; - setFixedSlot(ReactionRecordSlot_Flags, Int32Value(flags)); - - setFixedSlot(ReactionRecordSlot_Generator, ObjectValue(*asyncGenObj)); - } - bool isAsyncGeneratorAwait() { - int32_t flags = this->flags(); - return flags & REACTION_FLAG_ASYNC_GENERATOR_AWAIT; - } - AsyncGeneratorObject* asyncGenerator() { - MOZ_ASSERT(isAsyncGeneratorAwait()); - return &getFixedSlot(ReactionRecordSlot_Generator).toObject() - .as(); - } Value handler() { MOZ_ASSERT(targetState() != JS::PromiseState::Pending); uint32_t slot = targetState() == JS::PromiseState::Fulfilled @@ -874,34 +844,6 @@ AsyncFunctionAwaitPromiseReactionJob(JSContext* cx, Handle reaction, - MutableHandleValue rval) -{ - MOZ_ASSERT(reaction->isAsyncGeneratorAwait()); - - RootedValue handlerVal(cx, reaction->handler()); - RootedValue argument(cx, reaction->handlerArg()); - Rooted asyncGenObj(cx, reaction->asyncGenerator()); - - int32_t handlerNum = int32_t(handlerVal.toNumber()); - MOZ_ASSERT(handlerNum == PromiseHandlerAsyncGeneratorAwaitFulfilled || - handlerNum == PromiseHandlerAsyncGeneratorAwaitRejected); - - // Await's handlers don't return a value, nor throw exception. - // They fail only on OOM. - if (handlerNum == PromiseHandlerAsyncGeneratorAwaitFulfilled) { - if (!AsyncGeneratorAwaitedFulfilled(cx, asyncGenObj, argument)) - return false; - } else { - if (!AsyncGeneratorAwaitedRejected(cx, asyncGenObj, argument)) - return false; - } - - rval.setUndefined(); - return true; -} - // ES2016, 25.4.2.1. /** * Callback triggering the fulfill/reject reaction for a resolved Promise, @@ -940,8 +882,6 @@ PromiseReactionJob(JSContext* cx, unsigned argc, Value* vp) Rooted reaction(cx, &reactionObj->as()); if (reaction->isAsyncFunctionAwait()) return AsyncFunctionAwaitPromiseReactionJob(cx, reaction, args.rval()); - if (reaction->isAsyncGeneratorAwait()) - return AsyncGeneratorAwaitPromiseReactionJob(cx, reaction, args.rval()); // Step 3. RootedValue handlerVal(cx, reaction->handler()); @@ -958,21 +898,11 @@ PromiseReactionJob(JSContext* cx, unsigned argc, Value* vp) // Step 4. if (handlerNum == PromiseHandlerIdentity) { handlerResult = argument; - } else if (handlerNum == PromiseHandlerThrower) { + } else { // Step 5. + MOZ_ASSERT(handlerNum == PromiseHandlerThrower); resolutionMode = RejectMode; handlerResult = argument; - } else { - MOZ_ASSERT(handlerNum == PromiseHandlerAsyncIteratorValueUnwrapDone || - handlerNum == PromiseHandlerAsyncIteratorValueUnwrapNotDone); - - bool done = handlerNum == PromiseHandlerAsyncIteratorValueUnwrapDone; - // Async Iteration proposal 6.1.1.2.1 step 1. - RootedObject resultObj(cx, CreateIterResultObject(cx, argument, done)); - if (!resultObj) - return false; - - handlerResult = ObjectValue(*resultObj); } } else { // Step 6. @@ -2261,185 +2191,6 @@ js::AsyncFunctionAwait(JSContext* cx, Handle resultPromise, Hand return PerformPromiseThenWithReaction(cx, promise, reaction); } -// Async Iteration proposal 5.1 steps 2-9. -MOZ_MUST_USE bool -js::AsyncGeneratorAwait(JSContext* cx, Handle asyncGenObj, - HandleValue value) -{ - // Step 2. - Rooted 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 reaction(cx, NewReactionRecord(cx, nullptr, - onFulfilled, onRejected, - nullptr, nullptr, - incumbentGlobal)); - if (!reaction) - return false; - - reaction->setIsAsyncGeneratorAwait(asyncGenObj); - - // Step 9. - return PerformPromiseThenWithReaction(cx, promise, reaction); -} - -// Async Iteration proposal 6.4.3.3. -MOZ_MUST_USE bool -js::AsyncGeneratorResolve(JSContext* cx, Handle asyncGenObj, - HandleValue value, bool done) -{ - // Step 1 (implicit). - - // Steps 2-3. - MOZ_ASSERT(!asyncGenObj->isQueueEmpty()); - - // Step 4. - Rooted request( - cx, AsyncGeneratorObject::dequeueRequest(cx, asyncGenObj)); - if (!request) - return false; - - // Step 5. - RootedObject resultPromise(cx, request->promise()); - - // Step 6. - Rooted promise(cx, CreatePromiseObjectWithoutResolutionFunctions(cx)); - if (!promise) - return false; - - // Step 7. - if (!ResolvePromiseInternal(cx, promise, value)) - return false; - - // Steps 8-9. - RootedValue onFulfilled(cx, Int32Value(done - ? PromiseHandlerAsyncIteratorValueUnwrapDone - : PromiseHandlerAsyncIteratorValueUnwrapNotDone)); - - RootedObject incumbentGlobal(cx); - if (!GetObjectFromIncumbentGlobal(cx, &incumbentGlobal)) - return false; - - // Step 10. - Rooted 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)) - return false; - - // Step 12. - return true; -} - -// Async Iteration proposal 6.4.3.4. -MOZ_MUST_USE bool -js::AsyncGeneratorReject(JSContext* cx, Handle asyncGenObj, - HandleValue exception) -{ - // Step 1 (implicit). - - // Steps 2-3. - MOZ_ASSERT(!asyncGenObj->isQueueEmpty()); - - // Step 4. - Rooted 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 6.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()) { - // 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 asyncGenObj( - cx, &asyncGenVal.toObject().as()); - - // Step 5 (reordered). - Rooted 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) diff --git a/js/src/builtin/Promise.h b/js/src/builtin/Promise.h index b9abb7a27fab..4985bc24d2d0 100644 --- a/js/src/builtin/Promise.h +++ b/js/src/builtin/Promise.h @@ -135,23 +135,6 @@ AsyncFunctionThrown(JSContext* cx, Handle resultPromise); MOZ_MUST_USE bool AsyncFunctionAwait(JSContext* cx, Handle resultPromise, HandleValue value); -class AsyncGeneratorObject; - -MOZ_MUST_USE bool -AsyncGeneratorAwait(JSContext* cx, Handle asyncGenObj, HandleValue value); - -MOZ_MUST_USE bool -AsyncGeneratorResolve(JSContext* cx, Handle asyncGenObj, - HandleValue value, bool done); - -MOZ_MUST_USE bool -AsyncGeneratorReject(JSContext* cx, Handle asyncGenObj, - HandleValue exception); - -MOZ_MUST_USE bool -AsyncGeneratorEnqueue(JSContext* cx, HandleValue asyncGenVal, CompletionKind completionKind, - HandleValue completionValue, MutableHandleValue result); - /** * 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/frontend/BytecodeCompiler.cpp b/js/src/frontend/BytecodeCompiler.cpp index c35ab2d8b8a0..5a2e89f1712e 100644 --- a/js/src/frontend/BytecodeCompiler.cpp +++ b/js/src/frontend/BytecodeCompiler.cpp @@ -778,15 +778,3 @@ frontend::CompileStandaloneAsyncFunction(JSContext* cx, MutableHandleFunction fu BytecodeCompiler compiler(cx, cx->tempLifoAlloc(), options, srcBuf, emptyGlobalScope); return compiler.compileStandaloneFunction(fun, NotGenerator, AsyncFunction, parameterListEnd); } - -bool -frontend::CompileStandaloneAsyncGenerator(JSContext* cx, MutableHandleFunction fun, - const ReadOnlyCompileOptions& options, - JS::SourceBufferHolder& srcBuf, - const Maybe& parameterListEnd) -{ - RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope()); - - BytecodeCompiler compiler(cx, cx->tempLifoAlloc(), options, srcBuf, emptyGlobalScope); - return compiler.compileStandaloneFunction(fun, StarGenerator, AsyncFunction, parameterListEnd); -} diff --git a/js/src/frontend/BytecodeCompiler.h b/js/src/frontend/BytecodeCompiler.h index 25c4cca52cea..ebfa6abe285b 100644 --- a/js/src/frontend/BytecodeCompiler.h +++ b/js/src/frontend/BytecodeCompiler.h @@ -89,12 +89,6 @@ CompileStandaloneAsyncFunction(JSContext* cx, MutableHandleFunction fun, JS::SourceBufferHolder& srcBuf, const mozilla::Maybe& parameterListEnd); -MOZ_MUST_USE bool -CompileStandaloneAsyncGenerator(JSContext* cx, MutableHandleFunction fun, - const ReadOnlyCompileOptions& options, - JS::SourceBufferHolder& srcBuf, - const mozilla::Maybe& parameterListEnd); - MOZ_MUST_USE bool CompileAsyncFunctionBody(JSContext* cx, MutableHandleFunction fun, const ReadOnlyCompileOptions& options, diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 1f980b240265..add7e2cf52d3 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -7841,8 +7841,7 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto) MOZ_ASSERT(fun->isArrow() == (pn->getOp() == JSOP_LAMBDA_ARROW)); if (funbox->isAsync()) { MOZ_ASSERT(!needsProto); - return emitAsyncWrapper(index, funbox->needsHomeObject(), fun->isArrow(), - fun->isStarGenerator()); + return emitAsyncWrapper(index, funbox->needsHomeObject(), fun->isArrow()); } if (fun->isArrow()) { @@ -7897,11 +7896,8 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto) MOZ_ASSERT(pn->getOp() == JSOP_NOP); switchToPrologue(); if (funbox->isAsync()) { - if (!emitAsyncWrapper(index, fun->isMethod(), fun->isArrow(), - fun->isStarGenerator())) - { + if (!emitAsyncWrapper(index, fun->isMethod(), fun->isArrow())) return false; - } } else { if (!emitIndex32(JSOP_LAMBDA, index)) return false; @@ -7917,12 +7913,10 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto) // initialize the binding name of the function in the current scope. bool isAsync = funbox->isAsync(); - bool isStarGenerator = funbox->isStarGenerator(); - auto emitLambda = [index, isAsync, isStarGenerator](BytecodeEmitter* bce, - const NameLocation&, bool) { + auto emitLambda = [index, isAsync](BytecodeEmitter* bce, const NameLocation&, bool) { if (isAsync) { return bce->emitAsyncWrapper(index, /* needsHomeObject = */ false, - /* isArrow = */ false, isStarGenerator); + /* isArrow = */ false); } return bce->emitIndexOp(JSOP_LAMBDA, index); }; @@ -7957,8 +7951,7 @@ BytecodeEmitter::emitAsyncWrapperLambda(unsigned index, bool isArrow) { } bool -BytecodeEmitter::emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isArrow, - bool isStarGenerator) +BytecodeEmitter::emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isArrow) { // needsHomeObject can be true for propertyList for extended class. // In that case push both unwrapped and wrapped function, in order to @@ -7990,13 +7983,8 @@ BytecodeEmitter::emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isA if (!emit1(JSOP_DUP)) return false; } - if (isStarGenerator) { - if (!emit1(JSOP_TOASYNCGEN)) - return false; - } else { - if (!emit1(JSOP_TOASYNC)) - return false; - } + if (!emit1(JSOP_TOASYNC)) + return false; return true; } diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h index 46019548530b..a24720adc025 100644 --- a/js/src/frontend/BytecodeEmitter.h +++ b/js/src/frontend/BytecodeEmitter.h @@ -619,8 +619,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter MOZ_MUST_USE bool emitPropIncDec(ParseNode* pn); MOZ_MUST_USE bool emitAsyncWrapperLambda(unsigned index, bool isArrow); - MOZ_MUST_USE bool emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isArrow, - bool isStarGenerator); + MOZ_MUST_USE bool emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isArrow); MOZ_MUST_USE bool emitComputedPropertyName(ParseNode* computedPropName); diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 77540ff9823e..38d3031bc1c5 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -3753,12 +3753,10 @@ Parser::functionStmt(uint32_t preludeStart, YieldHandling yieldHan GeneratorKind generatorKind = NotGenerator; if (tt == TOK_MUL) { -#ifdef RELEASE_OR_BETA if (asyncKind != SyncFunction) { error(JSMSG_ASYNC_GENERATOR); return null(); } -#endif generatorKind = StarGenerator; if (!tokenStream.getToken(&tt)) return null(); @@ -3827,12 +3825,10 @@ Parser::functionExpr(uint32_t preludeStart, InvokedPrediction invo return null(); if (tt == TOK_MUL) { -#ifdef RELEASE_OR_BETA if (asyncKind != SyncFunction) { error(JSMSG_ASYNC_GENERATOR); return null(); } -#endif generatorKind = StarGenerator; if (!tokenStream.getToken(&tt)) return null(); @@ -9292,6 +9288,11 @@ Parser::propertyName(YieldHandling yieldHandling, Node propList, bool isGenerator = false; bool isAsync = false; + if (ltok == TOK_MUL) { + isGenerator = true; + if (!tokenStream.getToken(<ok)) + return null(); + } if (ltok == TOK_ASYNC) { // AsyncMethod[Yield, Await]: @@ -9320,15 +9321,9 @@ Parser::propertyName(YieldHandling yieldHandling, Node propList, } } - if (ltok == TOK_MUL) { -#ifdef RELEASE_OR_BETA + if (isAsync && isGenerator) { error(JSMSG_ASYNC_GENERATOR); return null(); -#else - isGenerator = true; - if (!tokenStream.getToken(<ok)) - return null(); -#endif } propAtom.set(nullptr); diff --git a/js/src/js.msg b/js/src/js.msg index b191fdc60073..6e3eac5d4c40 100644 --- a/js/src/js.msg +++ b/js/src/js.msg @@ -591,6 +591,3 @@ MSG_DEF(JSMSG_PROMISE_ERROR_IN_WRAPPED_REJECTION_REASON,0, JSEXN_INTERNALERR, "P // Iterator MSG_DEF(JSMSG_RETURN_NOT_CALLABLE, 0, JSEXN_TYPEERR, "property 'return' of iterator is not callable") MSG_DEF(JSMSG_ITERATOR_NO_THROW, 0, JSEXN_TYPEERR, "iterator does not have a 'throw' method") - -// Async Iteration -MSG_DEF(JSMSG_NOT_AN_ASYNC_GENERATOR, 0, JSEXN_TYPEERR, "Not an async generator") diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 926da165dcc4..80484310e513 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -71,7 +71,6 @@ #include "js/StructuredClone.h" #include "js/Utility.h" #include "vm/AsyncFunction.h" -#include "vm/AsyncIteration.h" #include "vm/DateObject.h" #include "vm/Debugger.h" #include "vm/EnvironmentObject.h" @@ -3616,11 +3615,6 @@ CloneFunctionObject(JSContext* cx, HandleObject funobj, HandleObject env, Handle return nullptr; } - if (IsWrappedAsyncGenerator(fun)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_CLONE_OBJECT); - return nullptr; - } - if (CanReuseScriptForClone(cx->compartment(), fun, env)) { // If the script is to be reused, either the script can already handle // non-syntactic scopes, or there is only the standard global lexical diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 61bbc6284e33..5b57f77bc1e9 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -41,7 +41,6 @@ #include "js/CallNonGenericMethod.h" #include "js/Proxy.h" #include "vm/AsyncFunction.h" -#include "vm/AsyncIteration.h" #include "vm/Debugger.h" #include "vm/GlobalObject.h" #include "vm/Interpreter.h" @@ -307,8 +306,6 @@ CallerGetterImpl(JSContext* cx, const CallArgs& args) JSFunction* callerFun = &callerObj->as(); if (IsWrappedAsyncFunction(callerFun)) callerFun = GetUnwrappedAsyncFunction(callerFun); - else if (IsWrappedAsyncGenerator(callerFun)) - callerFun = GetUnwrappedAsyncGenerator(callerFun); MOZ_ASSERT(!callerFun->isBuiltin(), "non-builtin iterator returned a builtin?"); if (callerFun->strict()) { @@ -405,15 +402,13 @@ static const JSPropertySpec function_properties[] = { static bool ResolveInterpretedFunctionPrototype(JSContext* cx, HandleFunction fun, HandleId id) { - bool isAsyncGenerator = IsWrappedAsyncGenerator(fun); - - MOZ_ASSERT_IF(!isAsyncGenerator, fun->isInterpreted() || fun->isAsmJSNative()); + MOZ_ASSERT(fun->isInterpreted() || fun->isAsmJSNative()); MOZ_ASSERT(id == NameToId(cx->names().prototype)); // Assert that fun is not a compiler-created function object, which // must never leak to script or embedding code and then be mutated. // Also assert that fun is not bound, per the ES5 15.3.4.5 ref above. - MOZ_ASSERT_IF(!isAsyncGenerator, !IsInternalFunctionObject(*fun)); + MOZ_ASSERT(!IsInternalFunctionObject(*fun)); MOZ_ASSERT(!fun->isBoundFunction()); // Make the prototype object an instance of Object with the same parent as @@ -423,9 +418,7 @@ ResolveInterpretedFunctionPrototype(JSContext* cx, HandleFunction fun, HandleId bool isStarGenerator = fun->isStarGenerator(); Rooted global(cx, &fun->global()); RootedObject objProto(cx); - if (isAsyncGenerator) - objProto = GlobalObject::getOrCreateAsyncGeneratorPrototype(cx, global); - else if (isStarGenerator) + if (isStarGenerator) objProto = GlobalObject::getOrCreateStarGeneratorObjectPrototype(cx, global); else objProto = GlobalObject::getOrCreateObjectPrototype(cx, global); @@ -441,7 +434,7 @@ ResolveInterpretedFunctionPrototype(JSContext* cx, HandleFunction fun, HandleId // non-enumerable, and writable. However, per the 15 July 2013 ES6 draft, // section 15.19.3, the .prototype of a generator function does not link // back with a .constructor. - if (!isStarGenerator && !isAsyncGenerator) { + if (!isStarGenerator) { RootedValue objVal(cx, ObjectValue(*fun)); if (!DefineProperty(cx, proto, cx->names().constructor, objVal, nullptr, nullptr, 0)) return false; @@ -491,13 +484,11 @@ fun_resolve(JSContext* cx, HandleObject obj, HandleId id, bool* resolvedp) * - Arrow functions * - Function.prototype */ - if (!IsWrappedAsyncGenerator(fun)) { - if (fun->isBuiltin()) + if (fun->isBuiltin()) + return true; + if (!fun->isConstructor()) { + if (!fun->isStarGenerator() && !fun->isLegacyGenerator() && !fun->isAsync()) return true; - if (!fun->isConstructor()) { - if (!fun->isStarGenerator() && !fun->isLegacyGenerator() && !fun->isAsync()) - return true; - } } if (!ResolveInterpretedFunctionPrototype(cx, fun, id)) @@ -994,10 +985,6 @@ js::FunctionToString(JSContext* cx, HandleFunction fun, bool prettyPrint) RootedFunction unwrapped(cx, GetUnwrappedAsyncFunction(fun)); return FunctionToString(cx, unwrapped, prettyPrint); } - if (IsWrappedAsyncGenerator(fun)) { - RootedFunction unwrapped(cx, GetUnwrappedAsyncGenerator(fun)); - return FunctionToString(cx, unwrapped, prettyPrint); - } StringBuffer out(cx); RootedScript script(cx); @@ -1650,14 +1637,10 @@ FunctionConstructor(JSContext* cx, const CallArgs& args, GeneratorKind generator &mutedErrors); const char* introductionType = "Function"; - if (isAsync) { - if (isStarGenerator) - introductionType = "AsyncGenerator"; - else - introductionType = "AsyncFunction"; - } else if (generatorKind != NotGenerator) { + if (isAsync) + introductionType = "AsyncFunction"; + else if (generatorKind != NotGenerator) introductionType = "GeneratorFunction"; - } const char* introducerFilename = filename; if (maybeScript && maybeScript->scriptSource()->introducerFilename()) @@ -1784,20 +1767,12 @@ FunctionConstructor(JSContext* cx, const CallArgs& args, GeneratorKind generator : SourceBufferHolder::NoOwnership; bool ok; SourceBufferHolder srcBuf(chars.begin().get(), chars.length(), ownership); - if (isAsync) { - if (isStarGenerator) { - ok = frontend::CompileStandaloneAsyncGenerator(cx, &fun, options, srcBuf, - parameterListEnd); - } else { - ok = frontend::CompileStandaloneAsyncFunction(cx, &fun, options, srcBuf, - parameterListEnd); - } - } else { - if (isStarGenerator) - ok = frontend::CompileStandaloneGenerator(cx, &fun, options, srcBuf, parameterListEnd); - else - ok = frontend::CompileStandaloneFunction(cx, &fun, options, srcBuf, parameterListEnd); - } + if (isAsync) + ok = frontend::CompileStandaloneAsyncFunction(cx, &fun, options, srcBuf, parameterListEnd); + else if (isStarGenerator) + ok = frontend::CompileStandaloneGenerator(cx, &fun, options, srcBuf, parameterListEnd); + else + ok = frontend::CompileStandaloneFunction(cx, &fun, options, srcBuf, parameterListEnd); // Step 33. args.rval().setObject(*fun); @@ -1823,7 +1798,7 @@ js::AsyncFunctionConstructor(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); - // Save the callee before it's reset in FunctionConstructor(). + // Save the callee before its reset in FunctionConstructor(). RootedObject newTarget(cx); if (args.isConstructing()) newTarget = &args.newTarget().toObject(); @@ -1855,40 +1830,6 @@ js::AsyncFunctionConstructor(JSContext* cx, unsigned argc, Value* vp) return true; } -bool -js::AsyncGeneratorConstructor(JSContext* cx, unsigned argc, Value* vp) -{ - CallArgs args = CallArgsFromVp(argc, vp); - - // Save the callee before its reset in FunctionConstructor(). - RootedObject newTarget(cx); - if (args.isConstructing()) - newTarget = &args.newTarget().toObject(); - else - newTarget = &args.callee(); - - if (!FunctionConstructor(cx, args, StarGenerator, AsyncFunction)) - return false; - - RootedObject proto(cx); - if (!GetPrototypeFromConstructor(cx, newTarget, &proto)) - return false; - - if (!proto) { - proto = GlobalObject::getOrCreateAsyncGenerator(cx, cx->global()); - if (!proto) - return false; - } - - RootedFunction unwrapped(cx, &args.rval().toObject().as()); - RootedObject wrapped(cx, WrapAsyncGeneratorWithProto(cx, unwrapped, proto)); - if (!wrapped) - return false; - - args.rval().setObject(*wrapped); - return true; -} - bool JSFunction::isBuiltinFunctionConstructor() { diff --git a/js/src/jsfun.h b/js/src/jsfun.h index 4acb8c9ba1b8..2983bd8d6290 100644 --- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -647,9 +647,6 @@ Generator(JSContext* cx, unsigned argc, Value* vp); extern bool AsyncFunctionConstructor(JSContext* cx, unsigned argc, Value* vp); -extern bool -AsyncGeneratorConstructor(JSContext* cx, unsigned argc, Value* vp); - // Allocate a new function backed by a JSNative. Note that by default this // creates a singleton object. extern JSFunction* diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index b958bd992fb0..58e2bb6936f6 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -938,30 +938,28 @@ js::GetIteratorObject(JSContext* cx, HandleObject obj, uint32_t flags) return iterator; } -// ES 2017 draft 7.4.7. JSObject* -js::CreateIterResultObject(JSContext* cx, HandleValue value, bool done) +js::CreateItrResultObject(JSContext* cx, HandleValue value, bool done) { - // Step 1 (implicit). + // FIXME: We can cache the iterator result object shape somewhere. + AssertHeapIsIdle(); - // Step 2. - RootedObject resultObj(cx, NewBuiltinClassInstance(cx)); - if (!resultObj) + RootedObject proto(cx, GlobalObject::getOrCreateObjectPrototype(cx, cx->global())); + if (!proto) return nullptr; - // Step 3. - if (!DefineProperty(cx, resultObj, cx->names().value, value)) + RootedPlainObject obj(cx, NewObjectWithGivenProto(cx, proto)); + if (!obj) return nullptr; - // Step 4. - if (!DefineProperty(cx, resultObj, cx->names().done, - done ? TrueHandleValue : FalseHandleValue)) - { + if (!DefineProperty(cx, obj, cx->names().value, value)) return nullptr; - } - // Step 5. - return resultObj; + RootedValue doneBool(cx, BooleanValue(done)); + if (!DefineProperty(cx, obj, cx->names().done, doneBool)) + return nullptr; + + return obj; } bool diff --git a/js/src/jsiter.h b/js/src/jsiter.h index 350c758bb3a9..a3035ddd0f7a 100644 --- a/js/src/jsiter.h +++ b/js/src/jsiter.h @@ -210,10 +210,10 @@ ThrowStopIteration(JSContext* cx); /* * Create an object of the form { value: VALUE, done: DONE }. - * ES 2017 draft 7.4.7. + * ES6 draft from 2013-09-05, section 25.4.3.4. */ extern JSObject* -CreateIterResultObject(JSContext* cx, HandleValue value, bool done); +CreateItrResultObject(JSContext* cx, HandleValue value, bool done); extern JSObject* InitLegacyIteratorClass(JSContext* cx, HandleObject obj); diff --git a/js/src/moz.build b/js/src/moz.build index 20c06e3bc016..e88c5222bb63 100644 --- a/js/src/moz.build +++ b/js/src/moz.build @@ -311,7 +311,6 @@ UNIFIED_SOURCES += [ 'vm/ArgumentsObject.cpp', 'vm/ArrayBufferObject.cpp', 'vm/AsyncFunction.cpp', - 'vm/AsyncIteration.cpp', 'vm/Caches.cpp', 'vm/CallNonGenericMethod.cpp', 'vm/CharacterEncoding.cpp', @@ -754,7 +753,6 @@ selfhosted.inputs = [ 'builtin/SelfHostingDefines.h', 'builtin/Utilities.js', 'builtin/Array.js', - 'builtin/AsyncIteration.js', 'builtin/Classes.js', 'builtin/Date.js', 'builtin/Error.js', diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 4d548cecd745..7aefc2595ee5 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -86,7 +86,6 @@ #include "threading/Thread.h" #include "vm/ArgumentsObject.h" #include "vm/AsyncFunction.h" -#include "vm/AsyncIteration.h" #include "vm/Compression.h" #include "vm/Debugger.h" #include "vm/HelperThreads.h" @@ -2396,8 +2395,6 @@ ValueToScript(JSContext* cx, HandleValue v, JSFunction** funp = nullptr) // Get unwrapped async function. if (IsWrappedAsyncFunction(fun)) fun = GetUnwrappedAsyncFunction(fun); - if (IsWrappedAsyncGenerator(fun)) - fun = GetUnwrappedAsyncGenerator(fun); if (!fun->isInterpreted()) { JS_ReportErrorNumberASCII(cx, my_GetErrorMessage, nullptr, JSSMSG_SCRIPTS_ONLY); diff --git a/js/src/tests/ecma_2017/AsyncFunctions/syntax.js b/js/src/tests/ecma_2017/AsyncFunctions/syntax.js index 0b4b50af4f7a..28e5febc1b3b 100644 --- a/js/src/tests/ecma_2017/AsyncFunctions/syntax.js +++ b/js/src/tests/ecma_2017/AsyncFunctions/syntax.js @@ -9,6 +9,9 @@ if (typeof Reflect !== "undefined" && Reflect.parse) { assertEq(Reflect.parse("async function a() {}").body[0].async, true); assertEq(Reflect.parse("() => {}").body[0].async, undefined); + // Async generators are not allowed (with regards to spec) + assertThrows(() => Reflect.parse("async function* a() {}"), SyntaxError); + // No line terminator after async assertEq(Reflect.parse("async\nfunction a(){}").body[0].expression.name, "async"); diff --git a/js/src/vm/AsyncIteration.cpp b/js/src/vm/AsyncIteration.cpp deleted file mode 100644 index 04effe1b101f..000000000000 --- a/js/src/vm/AsyncIteration.cpp +++ /dev/null @@ -1,564 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sts=4 et sw=4 tw=99: - * 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/. */ - -#include "vm/AsyncIteration.h" - -#include "jsarray.h" -#include "jscompartment.h" - -#include "builtin/Promise.h" -#include "vm/GeneratorObject.h" -#include "vm/GlobalObject.h" -#include "vm/Interpreter.h" -#include "vm/SelfHosting.h" - -#include "jscntxtinlines.h" -#include "jsobjinlines.h" - -#include "vm/NativeObject-inl.h" - -using namespace js; -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. -static bool -WrappedAsyncGenerator(JSContext* cx, unsigned argc, Value* vp) -{ - CallArgs args = CallArgsFromVp(argc, vp); - - RootedFunction wrapped(cx, &args.callee().as()); - RootedValue unwrappedVal(cx, wrapped->getExtendedSlot(WRAPPED_ASYNC_UNWRAPPED_SLOT)); - RootedFunction unwrapped(cx, &unwrappedVal.toObject().as()); - RootedValue thisValue(cx, args.thisv()); - - // Step 1. - RootedValue generatorVal(cx); - InvokeArgs args2(cx); - if (!args2.init(cx, argc)) - return false; - for (size_t i = 0, len = argc; i < len; i++) - args2[i].set(args[i]); - if (!Call(cx, unwrappedVal, thisValue, args2, &generatorVal)) - return false; - - // Step 2. - Rooted asyncGenObj( - cx, AsyncGeneratorObject::create(cx, wrapped, generatorVal)); - if (!asyncGenObj) - return false; - - // Step 3 (skipped). - // Done in AsyncGeneratorObject::create and generator. - - // Step 4. - args.rval().setObject(*asyncGenObj); - return true; -} - -JSObject* -js::WrapAsyncGeneratorWithProto(JSContext* cx, HandleFunction unwrapped, HandleObject proto) -{ - MOZ_ASSERT(unwrapped->isAsync()); - MOZ_ASSERT(proto, "We need an explicit prototype to avoid the default" - "%FunctionPrototype% fallback in NewFunctionWithProto()."); - - // Create a new function with AsyncGeneratorPrototype, reusing the name and - // the length of `unwrapped`. - - RootedAtom funName(cx, unwrapped->explicitName()); - uint16_t length; - if (!JSFunction::getLength(cx, unwrapped, &length)) - return nullptr; - - RootedFunction wrapped(cx, NewFunctionWithProto(cx, WrappedAsyncGenerator, length, - JSFunction::NATIVE_FUN, nullptr, - funName, proto, - AllocKind::FUNCTION_EXTENDED, - TenuredObject)); - if (!wrapped) - return nullptr; - - if (unwrapped->hasCompileTimeName()) - wrapped->setCompileTimeName(unwrapped->compileTimeName()); - - // Link them to each other to make GetWrappedAsyncGenerator and - // GetUnwrappedAsyncGenerator work. - unwrapped->setExtendedSlot(UNWRAPPED_ASYNC_WRAPPED_SLOT, ObjectValue(*wrapped)); - wrapped->setExtendedSlot(WRAPPED_ASYNC_UNWRAPPED_SLOT, ObjectValue(*unwrapped)); - - return wrapped; -} - -JSObject* -js::WrapAsyncGenerator(JSContext* cx, HandleFunction unwrapped) -{ - RootedObject proto(cx, GlobalObject::getOrCreateAsyncGenerator(cx, cx->global())); - if (!proto) - return nullptr; - - return WrapAsyncGeneratorWithProto(cx, unwrapped, proto); -} - -bool -js::IsWrappedAsyncGenerator(JSFunction* fun) -{ - return fun->maybeNative() == WrappedAsyncGenerator; -} - -JSFunction* -js::GetWrappedAsyncGenerator(JSFunction* unwrapped) -{ - MOZ_ASSERT(unwrapped->isAsync()); - return &unwrapped->getExtendedSlot(UNWRAPPED_ASYNC_WRAPPED_SLOT).toObject().as(); -} - -JSFunction* -js::GetUnwrappedAsyncGenerator(JSFunction* wrapped) -{ - MOZ_ASSERT(IsWrappedAsyncGenerator(wrapped)); - JSFunction* unwrapped = &wrapped->getExtendedSlot(WRAPPED_ASYNC_UNWRAPPED_SLOT) - .toObject().as(); - MOZ_ASSERT(unwrapped->isAsync()); - return unwrapped; -} - -static MOZ_MUST_USE bool -AsyncGeneratorResume(JSContext* cx, Handle asyncGenObj, - CompletionKind completionKind, HandleValue argument); - -// Async Iteration proposal 5.1.1 Await Fulfilled Functions. -MOZ_MUST_USE bool -js::AsyncGeneratorAwaitedFulfilled(JSContext* cx, Handle asyncGenObj, - HandleValue value) -{ - return AsyncGeneratorResume(cx, asyncGenObj, CompletionKind::Normal, value); -} - -// Async Iteration proposal 5.1.2 Await Rejected Functions. -MOZ_MUST_USE bool -js::AsyncGeneratorAwaitedRejected(JSContext* cx, Handle asyncGenObj, - HandleValue reason) -{ - return AsyncGeneratorResume(cx, asyncGenObj, CompletionKind::Throw, reason); -} - -// Async Iteration proposal 6.4.1.2 AsyncGenerator.prototype.next. -static bool -AsyncGeneratorNext(JSContext* cx, unsigned argc, Value* vp) -{ - CallArgs args = CallArgsFromVp(argc, vp); - - // Steps 1-3. - return AsyncGeneratorEnqueue(cx, args.thisv(), CompletionKind::Normal, args.get(0), - args.rval()); -} - -// Async Iteration proposal 6.4.1.3 AsyncGenerator.prototype.return. -static bool -AsyncGeneratorReturn(JSContext* cx, unsigned argc, Value* vp) -{ - CallArgs args = CallArgsFromVp(argc, vp); - - // Steps 1-3. - return AsyncGeneratorEnqueue(cx, args.thisv(), CompletionKind::Return, args.get(0), - args.rval()); -} - -// Async Iteration proposal 6.4.1.4 AsyncGenerator.prototype.throw. -static bool -AsyncGeneratorThrow(JSContext* cx, unsigned argc, Value* vp) -{ - CallArgs args = CallArgsFromVp(argc, vp); - - // Steps 1-3. - return AsyncGeneratorEnqueue(cx, args.thisv(), CompletionKind::Throw, args.get(0), - args.rval()); -} - -const Class AsyncGeneratorObject::class_ = { - "AsyncGenerator", - JSCLASS_HAS_RESERVED_SLOTS(AsyncGeneratorObject::Slots) -}; - -// ES 2017 draft 9.1.13. -template -static JSObject* -OrdinaryCreateFromConstructor(JSContext* cx, HandleFunction fun, - ProtoGetter protoGetter, const Class* clasp) -{ - // Step 1 (skipped). - - // Step 2. - RootedValue protoVal(cx); - if (!GetProperty(cx, fun, fun, cx->names().prototype, &protoVal)) - return nullptr; - - RootedObject proto(cx, protoVal.isObject() ? &protoVal.toObject() : nullptr); - if (!proto) { - proto = protoGetter(cx, cx->global()); - if (!proto) - return nullptr; - } - - // Step 3. - return NewNativeObjectWithGivenProto(cx, clasp, proto); -} - -/* static */ AsyncGeneratorObject* -AsyncGeneratorObject::create(JSContext* cx, HandleFunction asyncGen, HandleValue generatorVal) -{ - MOZ_ASSERT(generatorVal.isObject()); - MOZ_ASSERT(generatorVal.toObject().is()); - - RootedObject obj( - cx, OrdinaryCreateFromConstructor(cx, asyncGen, - GlobalObject::getOrCreateAsyncGeneratorPrototype, - &class_)); - if (!obj) - return nullptr; - - Handle asyncGenObj = obj.as(); - - // Async Iteration proposal 6.4.3.2 AsyncGeneratorStart. - // Step 6. - asyncGenObj->setGenerator(generatorVal); - - // Step 7. - asyncGenObj->setSuspendedStart(); - - // Step 8. - asyncGenObj->clearSingleQueueRequest(); - - return asyncGenObj; -} - -/* static */ MOZ_MUST_USE bool -AsyncGeneratorObject::enqueueRequest(JSContext* cx, Handle asyncGenObj, - Handle request) -{ - if (asyncGenObj->isSingleQueue()) { - if (asyncGenObj->isSingleQueueEmpty()) { - asyncGenObj->setSingleQueueRequest(request); - return true; - } - - RootedArrayObject queue(cx, NewDenseEmptyArray(cx)); - if (!queue) - return false; - - if (!NewbornArrayPush(cx, queue, ObjectValue(*asyncGenObj->singleQueueRequest()))) - return false; - if (!NewbornArrayPush(cx, queue, ObjectValue(*request))) - return false; - - asyncGenObj->setQueue(queue); - return true; - } - - RootedArrayObject queue(cx, asyncGenObj->queue()); - - FixedInvokeArgs<1> args(cx); - args[0].setObject(*request); - args.setThis(ObjectValue(*queue)); - return CallJSNative(cx, array_push, args); -} - -/* static */ AsyncGeneratorRequest* -AsyncGeneratorObject::dequeueRequest(JSContext* cx, Handle asyncGenObj) -{ - if (asyncGenObj->isSingleQueue()) { - AsyncGeneratorRequest* request = asyncGenObj->singleQueueRequest(); - asyncGenObj->clearSingleQueueRequest(); - return request; - } - - RootedArrayObject queue(cx, asyncGenObj->queue()); - - FixedInvokeArgs<0> args(cx); - args.setThis(ObjectValue(*queue)); - if (!CallJSNative(cx, array_shift, args)) - return nullptr; - - return &args.rval().toObject().as(); -} - -/* static */ AsyncGeneratorRequest* -AsyncGeneratorObject::peekRequest(JSContext* cx, Handle asyncGenObj) -{ - if (asyncGenObj->isSingleQueue()) - return asyncGenObj->singleQueueRequest(); - - RootedArrayObject queue(cx, asyncGenObj->queue()); - - RootedValue requestVal(cx); - if (!GetElement(cx, queue, queue, 0, &requestVal)) - return nullptr; - - return &requestVal.toObject().as(); -} - -const Class AsyncGeneratorRequest::class_ = { - "AsyncGeneratorRequest", - JSCLASS_HAS_RESERVED_SLOTS(AsyncGeneratorRequest::Slots) -}; - -// Async Iteration proposal 6.4.3.1. -/* static */ AsyncGeneratorRequest* -AsyncGeneratorRequest::create(JSContext* cx, CompletionKind completionKind_, - HandleValue completionValue_, HandleObject promise_) -{ - RootedObject obj(cx, NewNativeObjectWithGivenProto(cx, &class_, nullptr)); - if (!obj) - return nullptr; - - Handle request = obj.as(); - request->setCompletionKind(completionKind_); - request->setCompletionValue(completionValue_); - request->setPromise(promise_); - return request; -} - -// Async Iteration proposal 6.4.3.2 steps 5.d-g. -static MOZ_MUST_USE bool -AsyncGeneratorReturned(JSContext* cx, Handle asyncGenObj, - HandleValue value) -{ - // Step 5.d. - asyncGenObj->setCompleted(); - - // Step 5.e (done in bytecode). - // Step 5.f.i (implicit). - - // Step 5.g. - return AsyncGeneratorResolve(cx, asyncGenObj, value, true); -} - -// Async Iteration proposal 6.4.3.2 steps 5.d, f. -static MOZ_MUST_USE bool -AsyncGeneratorThrown(JSContext* cx, Handle asyncGenObj) -{ - // Step 5.d. - asyncGenObj->setCompleted(); - - // Not much we can do about uncatchable exceptions, so just bail. - if (!cx->isExceptionPending()) - return false; - - // Step 5.f.i. - RootedValue value(cx); - if (!GetAndClearException(cx, &value)) - return false; - - // Step 5.f.ii. - return AsyncGeneratorReject(cx, asyncGenObj, value); -} - -// Async Iteration proposal 6.4.3.5. -MOZ_MUST_USE bool -js::AsyncGeneratorResumeNext(JSContext* cx, Handle asyncGenObj) -{ - // Step 1 (implicit). - - // Steps 2-3. - MOZ_ASSERT(!asyncGenObj->isExecuting()); - - // Steps 4-5. - if (asyncGenObj->isQueueEmpty()) - return true; - - // Steps 6-7. - Rooted 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.2 (partially). -// Most steps are done in generator. -static MOZ_MUST_USE bool -AsyncGeneratorYield(JSContext* cx, Handle asyncGenObj, - HandleValue value, bool done) -{ - // Step 6. - asyncGenObj->setSuspendedYield(); - - // Step 10.c. - return AsyncGeneratorResolve(cx, asyncGenObj, value, done); -} - -// 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. -// Execution context switching is handled in generator. -static MOZ_MUST_USE bool -AsyncGeneratorResume(JSContext* cx, Handle asyncGenObj, - CompletionKind completionKind, HandleValue argument) -{ - RootedValue generatorVal(cx, asyncGenObj->generatorVal()); - - // 6.4.3.5 steps 12-14, 16-20. - HandlePropertyName funName = completionKind == CompletionKind::Normal - ? cx->names().StarGeneratorNext - : completionKind == CompletionKind::Throw - ? cx->names().StarGeneratorThrow - : cx->names().StarGeneratorReturn; - FixedInvokeArgs<1> args(cx); - args[0].set(argument); - RootedValue result(cx); - if (!CallSelfHostedFunction(cx, funName, generatorVal, args, &result)) { - // 6.4.3.2 step 5.d, f. - return AsyncGeneratorThrown(cx, asyncGenObj); - } - - // The following code corresponds to the following 3 cases: - // * yield - // * await - // * return - // For await 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. - - 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)); - - // 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); -} - -static const JSFunctionSpec async_iterator_proto_methods[] = { - JS_SELF_HOSTED_SYM_FN(asyncIterator, "AsyncIteratorIdentity", 0, 0), - JS_FS_END -}; - -static const JSFunctionSpec async_generator_methods[] = { - JS_FN("next", AsyncGeneratorNext, 1, 0), - JS_FN("throw", AsyncGeneratorThrow, 1, 0), - JS_FN("return", AsyncGeneratorReturn, 1, 0), - JS_FS_END -}; - -/* static */ MOZ_MUST_USE bool -GlobalObject::initAsyncGenerators(JSContext* cx, Handle global) -{ - if (global->getReservedSlot(ASYNC_ITERATOR_PROTO).isObject()) - return true; - - // Async Iteration proposal 6.1.2 %AsyncIteratorPrototype%. - RootedObject asyncIterProto(cx, GlobalObject::createBlankPrototype(cx, global)); - if (!asyncIterProto) - return false; - if (!DefinePropertiesAndFunctions(cx, asyncIterProto, nullptr, async_iterator_proto_methods)) - return false; - - // Async Iteration proposal 6.4.1 %AsyncGeneratorPrototype%. - RootedObject asyncGenProto( - cx, GlobalObject::createBlankPrototypeInheriting(cx, global, &PlainObject::class_, - asyncIterProto)); - if (!asyncGenProto) - return false; - if (!DefinePropertiesAndFunctions(cx, asyncGenProto, nullptr, async_generator_methods) || - !DefineToStringTag(cx, asyncGenProto, cx->names().AsyncGenerator)) - { - return false; - } - - // Async Iteration proposal 6.3.3 %AsyncGenerator%. - RootedObject asyncGenerator(cx, NewSingletonObjectWithFunctionPrototype(cx, global)); - if (!asyncGenerator) - return false; - if (!JSObject::setDelegate(cx, asyncGenerator)) - return false; - if (!LinkConstructorAndPrototype(cx, asyncGenerator, asyncGenProto, JSPROP_READONLY, - JSPROP_READONLY) || - !DefineToStringTag(cx, asyncGenerator, cx->names().AsyncGeneratorFunction)) - { - return false; - } - - RootedValue function(cx, global->getConstructor(JSProto_Function)); - if (!function.toObjectOrNull()) - return false; - RootedObject proto(cx, &function.toObject()); - RootedAtom name(cx, cx->names().AsyncGeneratorFunction); - - // Async Iteration proposal 6.3.2 %AsyncGeneratorFunction%. - RootedObject asyncGenFunction( - cx, NewFunctionWithProto(cx, AsyncGeneratorConstructor, 1, JSFunction::NATIVE_CTOR, - nullptr, name, proto, gc::AllocKind::FUNCTION, SingletonObject)); - if (!asyncGenFunction) - return false; - if (!LinkConstructorAndPrototype(cx, asyncGenFunction, asyncGenerator, - JSPROP_PERMANENT | JSPROP_READONLY, JSPROP_READONLY)) - { - return false; - } - - global->setReservedSlot(ASYNC_ITERATOR_PROTO, ObjectValue(*asyncIterProto)); - global->setReservedSlot(ASYNC_GENERATOR, ObjectValue(*asyncGenerator)); - global->setReservedSlot(ASYNC_GENERATOR_FUNCTION, ObjectValue(*asyncGenFunction)); - global->setReservedSlot(ASYNC_GENERATOR_PROTO, ObjectValue(*asyncGenProto)); - return true; -} diff --git a/js/src/vm/AsyncIteration.h b/js/src/vm/AsyncIteration.h deleted file mode 100644 index c0135283fa6b..000000000000 --- a/js/src/vm/AsyncIteration.h +++ /dev/null @@ -1,204 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sts=4 et sw=4 tw=99: - * 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/. */ - -#ifndef vm_AsyncIteration_h -#define vm_AsyncIteration_h - -#include "jscntxt.h" -#include "jsobj.h" - -#include "builtin/Promise.h" -#include "vm/GeneratorObject.h" - -namespace js { - -// Async generator consists of 2 functions, |wrapped| and |unwrapped|. -// |unwrapped| is a generator function compiled from async generator script, -// |await| behaves just like |yield| there. |unwrapped| isn't exposed to user -// script. -// |wrapped| is a native function that is the value of async generator. - -JSObject* -WrapAsyncGeneratorWithProto(JSContext* cx, HandleFunction unwrapped, HandleObject proto); - -JSObject* -WrapAsyncGenerator(JSContext* cx, HandleFunction unwrapped); - -bool -IsWrappedAsyncGenerator(JSFunction* fun); - -JSFunction* -GetWrappedAsyncGenerator(JSFunction* unwrapped); - -JSFunction* -GetUnwrappedAsyncGenerator(JSFunction* wrapped); - -MOZ_MUST_USE bool -AsyncGeneratorAwaitedFulfilled(JSContext* cx, Handle asyncGenObj, - HandleValue value); - -MOZ_MUST_USE bool -AsyncGeneratorAwaitedRejected(JSContext* cx, Handle asyncGenObj, - HandleValue reason); - -class AsyncGeneratorRequest : public NativeObject -{ - private: - enum AsyncGeneratorRequestSlots { - Slot_CompletionKind = 0, - Slot_CompletionValue, - Slot_Promise, - Slots, - }; - - void setCompletionKind(CompletionKind completionKind_) { - setFixedSlot(Slot_CompletionKind, - Int32Value(static_cast(completionKind_))); - } - void setCompletionValue(HandleValue completionValue_) { - setFixedSlot(Slot_CompletionValue, completionValue_); - } - void setPromise(HandleObject promise_) { - setFixedSlot(Slot_Promise, ObjectValue(*promise_)); - } - - public: - static const Class class_; - - static AsyncGeneratorRequest* - create(JSContext* cx, CompletionKind completionKind, HandleValue completionValue, - HandleObject promise); - - CompletionKind completionKind() const { - return static_cast(getFixedSlot(Slot_CompletionKind).toInt32()); - } - JS::Value completionValue() const { - return getFixedSlot(Slot_CompletionValue); - } - JSObject* promise() const { - return &getFixedSlot(Slot_Promise).toObject(); - } -}; - -class AsyncGeneratorObject : public NativeObject -{ - private: - enum AsyncGeneratorObjectSlots { - Slot_State = 0, - Slot_Generator, - Slot_QueueOrRequest, - Slots - }; - - enum State { - State_SuspendedStart, - State_SuspendedYield, - State_Executing, - State_Completed - }; - - State state() const { - return static_cast(getFixedSlot(Slot_State).toInt32()); - } - void setState(State state_) { - setFixedSlot(Slot_State, Int32Value(state_)); - } - - void setGenerator(const Value& value) { - setFixedSlot(Slot_Generator, value); - } - - // Queue is implemented in 2 ways. If only one request is queued ever, - // request is stored directly to the slot. Once 2 requests are queued, an - // array is created and requests are pushed into it, and the array is - // stored to the slot. - - bool isSingleQueue() const { - return getFixedSlot(Slot_QueueOrRequest).isNull() || - getFixedSlot(Slot_QueueOrRequest).toObject().is(); - } - bool isSingleQueueEmpty() const { - return getFixedSlot(Slot_QueueOrRequest).isNull(); - } - void setSingleQueueRequest(AsyncGeneratorRequest* request) { - setFixedSlot(Slot_QueueOrRequest, ObjectValue(*request)); - } - void clearSingleQueueRequest() { - setFixedSlot(Slot_QueueOrRequest, NullHandleValue); - } - AsyncGeneratorRequest* singleQueueRequest() const { - return &getFixedSlot(Slot_QueueOrRequest).toObject().as(); - } - - ArrayObject* queue() const { - return &getFixedSlot(Slot_QueueOrRequest).toObject().as(); - } - void setQueue(JSObject* queue_) { - setFixedSlot(Slot_QueueOrRequest, ObjectValue(*queue_)); - } - - public: - static const Class class_; - - static AsyncGeneratorObject* - create(JSContext* cx, HandleFunction asyncGen, HandleValue generatorVal); - - bool isSuspendedStart() const { - return state() == State_SuspendedStart; - } - bool isSuspendedYield() const { - return state() == State_SuspendedYield; - } - bool isExecuting() const { - return state() == State_Executing; - } - bool isCompleted() const { - return state() == State_Completed; - } - - void setSuspendedStart() { - setState(State_SuspendedStart); - } - void setSuspendedYield() { - setState(State_SuspendedYield); - } - void setExecuting() { - setState(State_Executing); - } - void setCompleted() { - setState(State_Completed); - } - - JS::Value generatorVal() const { - return getFixedSlot(Slot_Generator); - } - GeneratorObject* generatorObj() const { - return &getFixedSlot(Slot_Generator).toObject().as(); - } - - static MOZ_MUST_USE bool - enqueueRequest(JSContext* cx, Handle asyncGenObj, - Handle request); - - static AsyncGeneratorRequest* - dequeueRequest(JSContext* cx, Handle asyncGenObj); - - static AsyncGeneratorRequest* - peekRequest(JSContext* cx, Handle asyncGenObj); - - bool isQueueEmpty() const { - if (isSingleQueue()) - return isSingleQueueEmpty(); - return queue()->length() == 0; - } -}; - -MOZ_MUST_USE bool -AsyncGeneratorResumeNext(JSContext* cx, Handle asyncGenObj); - -} // namespace js - -#endif /* vm_AsyncIteration_h */ diff --git a/js/src/vm/CommonPropertyNames.h b/js/src/vm/CommonPropertyNames.h index ffb4d5f25364..c74b4c1bbac6 100644 --- a/js/src/vm/CommonPropertyNames.h +++ b/js/src/vm/CommonPropertyNames.h @@ -31,8 +31,6 @@ macro(as, as, "as") \ macro(Async, Async, "Async") \ macro(AsyncFunction, AsyncFunction, "AsyncFunction") \ - macro(AsyncGenerator, AsyncGenerator, "AsyncGenerator") \ - macro(AsyncGeneratorFunction, AsyncGeneratorFunction, "AsyncGeneratorFunction") \ macro(AsyncWrapped, AsyncWrapped, "AsyncWrapped") \ macro(async, async, "async") \ macro(await, await, "await") \ @@ -321,7 +319,6 @@ macro(star, star, "*") \ macro(starDefaultStar, starDefaultStar, "*default*") \ macro(StarGeneratorNext, StarGeneratorNext, "StarGeneratorNext") \ - macro(StarGeneratorReturn, StarGeneratorReturn, "StarGeneratorReturn") \ macro(StarGeneratorThrow, StarGeneratorThrow, "StarGeneratorThrow") \ macro(startTimestamp, startTimestamp, "startTimestamp") \ macro(state, state, "state") \ diff --git a/js/src/vm/GlobalObject.h b/js/src/vm/GlobalObject.h index c9cbd94ccdb7..2e9711b636f7 100644 --- a/js/src/vm/GlobalObject.h +++ b/js/src/vm/GlobalObject.h @@ -98,10 +98,6 @@ class GlobalObject : public NativeObject STAR_GENERATOR_FUNCTION, ASYNC_FUNCTION_PROTO, ASYNC_FUNCTION, - ASYNC_ITERATOR_PROTO, - ASYNC_GENERATOR, - ASYNC_GENERATOR_FUNCTION, - ASYNC_GENERATOR_PROTO, MAP_ITERATOR_PROTO, SET_ITERATOR_PROTO, COLLATOR_PROTO, @@ -633,30 +629,6 @@ class GlobalObject : public NativeObject return getOrCreateObject(cx, global, ASYNC_FUNCTION, initAsyncFunction); } - static NativeObject* - getOrCreateAsyncIteratorPrototype(JSContext* cx, Handle global) - { - return MaybeNativeObject(getOrCreateObject(cx, global, ASYNC_ITERATOR_PROTO, - initAsyncGenerators)); - } - - static NativeObject* - getOrCreateAsyncGenerator(JSContext* cx, Handle global) { - return MaybeNativeObject(getOrCreateObject(cx, global, ASYNC_GENERATOR, - initAsyncGenerators)); - } - - static JSObject* - getOrCreateAsyncGeneratorFunction(JSContext* cx, Handle global) { - return getOrCreateObject(cx, global, ASYNC_GENERATOR_FUNCTION, initAsyncGenerators); - } - - static NativeObject* - getOrCreateAsyncGeneratorPrototype(JSContext* cx, Handle global) { - return MaybeNativeObject(getOrCreateObject(cx, global, ASYNC_GENERATOR_PROTO, - initAsyncGenerators)); - } - static JSObject* getOrCreateMapIteratorPrototype(JSContext* cx, Handle global) { return getOrCreateObject(cx, global, MAP_ITERATOR_PROTO, initMapIteratorProto); @@ -803,8 +775,6 @@ class GlobalObject : public NativeObject static bool initAsyncFunction(JSContext* cx, Handle global); - static bool initAsyncGenerators(JSContext* cx, Handle global); - // Implemented in builtin/MapObject.cpp. static bool initMapIteratorProto(JSContext* cx, Handle global); static bool initSetIteratorProto(JSContext* cx, Handle global); diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index c3899ab5d775..af76da23ac54 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -39,7 +39,6 @@ #include "jit/Ion.h" #include "jit/IonAnalysis.h" #include "vm/AsyncFunction.h" -#include "vm/AsyncIteration.h" #include "vm/Debugger.h" #include "vm/GeneratorObject.h" #include "vm/Opcodes.h" @@ -1923,6 +1922,7 @@ CASE(EnableInterruptsPseudoOpcode) /* Various 1-byte no-ops. */ CASE(JSOP_NOP) CASE(JSOP_NOP_DESTRUCTURING) +CASE(JSOP_UNUSED192) CASE(JSOP_UNUSED210) CASE(JSOP_UNUSED211) CASE(JSOP_UNUSED220) @@ -3566,18 +3566,6 @@ CASE(JSOP_TOASYNC) } END_CASE(JSOP_TOASYNC) -CASE(JSOP_TOASYNCGEN) -{ - ReservedRooted unwrapped(&rootFunction0, - ®S.sp[-1].toObject().as()); - JSObject* wrapped = WrapAsyncGenerator(cx, unwrapped); - if (!wrapped) - goto error; - - REGS.sp[-1].setObject(*wrapped); -} -END_CASE(JSOP_TOASYNCGEN) - CASE(JSOP_SETFUNNAME) { MOZ_ASSERT(REGS.stackDepth() >= 2); diff --git a/js/src/vm/Opcodes.h b/js/src/vm/Opcodes.h index 8896c4a9ec67..13ddd98f0475 100644 --- a/js/src/vm/Opcodes.h +++ b/js/src/vm/Opcodes.h @@ -1967,15 +1967,7 @@ * Stack: this => this */ \ macro(JSOP_CHECKTHISREINIT,191,"checkthisreinit",NULL,1, 1, 1, JOF_BYTE) \ - /* - * Pops the top of stack value as 'unwrapped', converts it to async - * generator 'wrapped', and pushes 'wrapped' back on the stack. - * Category: Statements - * Type: Generator - * Operands: - * Stack: unwrapped => wrapped - */ \ - macro(JSOP_TOASYNCGEN, 192, "toasyncgen", NULL, 1, 1, 1, JOF_BYTE) \ + macro(JSOP_UNUSED192, 192,"unused192", NULL, 1, 0, 0, JOF_BYTE) \ \ /* * Pops the top two values on the stack as 'propval' and 'obj', pushes