From d5086ac3aa308bb1ef177834366eeaf7b39bb17e Mon Sep 17 00:00:00 2001 From: Gaming4JC Date: Fri, 13 Dec 2019 21:29:23 -0500 Subject: Bug 1331092 - Part 2: Implement Async Generator except yield*. Tag #1287 --- js/src/frontend/BytecodeCompiler.cpp | 13 +++++++++++++ js/src/frontend/BytecodeCompiler.h | 6 ++++++ js/src/frontend/BytecodeEmitter.cpp | 26 +++++++++++++++++++------- js/src/frontend/BytecodeEmitter.h | 3 ++- js/src/frontend/Parser.cpp | 22 ++++++++++++++-------- 5 files changed, 54 insertions(+), 16 deletions(-) (limited to 'js/src/frontend') diff --git a/js/src/frontend/BytecodeCompiler.cpp b/js/src/frontend/BytecodeCompiler.cpp index 7760c4b2e..ccfe3cd2e 100644 --- a/js/src/frontend/BytecodeCompiler.cpp +++ b/js/src/frontend/BytecodeCompiler.cpp @@ -729,3 +729,16 @@ frontend::CompileStandaloneAsyncFunction(JSContext* cx, MutableHandleFunction fu TraceLogger_ParserCompileFunction); return compiler.compileStandaloneFunction(fun, NotGenerator, AsyncFunction, parameterListEnd); } + +bool +frontend::CompileStandaloneAsyncGenerator(JSContext* cx, MutableHandleFunction fun, + const ReadOnlyCompileOptions& options, + JS::SourceBufferHolder& srcBuf, + Maybe parameterListEnd) +{ + RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope()); + + BytecodeCompiler compiler(cx, cx->tempLifoAlloc(), options, srcBuf, emptyGlobalScope, + TraceLogger_ParserCompileFunction); + return compiler.compileStandaloneFunction(fun, StarGenerator, AsyncFunction, parameterListEnd); +} diff --git a/js/src/frontend/BytecodeCompiler.h b/js/src/frontend/BytecodeCompiler.h index 0bc1ab2ab..029fbe632 100644 --- a/js/src/frontend/BytecodeCompiler.h +++ b/js/src/frontend/BytecodeCompiler.h @@ -84,6 +84,12 @@ CompileStandaloneAsyncFunction(JSContext* cx, MutableHandleFunction fun, JS::SourceBufferHolder& srcBuf, mozilla::Maybe parameterListEnd); +MOZ_MUST_USE bool +CompileStandaloneAsyncGenerator(JSContext* cx, MutableHandleFunction fun, + const ReadOnlyCompileOptions& options, + JS::SourceBufferHolder& srcBuf, + 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 a98016d63..9d6a68609 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -8067,7 +8067,8 @@ 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()); + return emitAsyncWrapper(index, funbox->needsHomeObject(), fun->isArrow(), + fun->isStarGenerator()); } if (fun->isArrow()) { @@ -8122,8 +8123,11 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto) MOZ_ASSERT(pn->getOp() == JSOP_NOP); switchToPrologue(); if (funbox->isAsync()) { - if (!emitAsyncWrapper(index, fun->isMethod(), fun->isArrow())) + if (!emitAsyncWrapper(index, fun->isMethod(), fun->isArrow(), + fun->isStarGenerator())) + { return false; + } } else { if (!emitIndex32(JSOP_LAMBDA, index)) return false; @@ -8139,10 +8143,12 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto) // initialize the binding name of the function in the current scope. bool isAsync = funbox->isAsync(); - auto emitLambda = [index, isAsync](BytecodeEmitter* bce, const NameLocation&, bool) { + bool isStarGenerator = funbox->isStarGenerator(); + auto emitLambda = [index, isAsync, isStarGenerator](BytecodeEmitter* bce, + const NameLocation&, bool) { if (isAsync) { return bce->emitAsyncWrapper(index, /* needsHomeObject = */ false, - /* isArrow = */ false); + /* isArrow = */ false, isStarGenerator); } return bce->emitIndexOp(JSOP_LAMBDA, index); }; @@ -8177,7 +8183,8 @@ BytecodeEmitter::emitAsyncWrapperLambda(unsigned index, bool isArrow) { } bool -BytecodeEmitter::emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isArrow) +BytecodeEmitter::emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isArrow, + bool isStarGenerator) { // needsHomeObject can be true for propertyList for extended class. // In that case push both unwrapped and wrapped function, in order to @@ -8209,8 +8216,13 @@ BytecodeEmitter::emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isA if (!emit1(JSOP_DUP)) return false; } - if (!emit1(JSOP_TOASYNC)) - return false; + if (isStarGenerator) { + if (!emit1(JSOP_TOASYNCGEN)) + return false; + } else { + if (!emit1(JSOP_TOASYNC)) + return false; + } return true; } diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h index f3f78df16..67e329489 100644 --- a/js/src/frontend/BytecodeEmitter.h +++ b/js/src/frontend/BytecodeEmitter.h @@ -620,7 +620,8 @@ 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); + MOZ_MUST_USE bool emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isArrow, + bool isStarGenerator); MOZ_MUST_USE bool emitComputedPropertyName(ParseNode* computedPropName); diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 3ae5890ac..7704cf65a 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -3785,10 +3785,12 @@ Parser::functionStmt(uint32_t toStringStart, YieldHandling yieldHa 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(); @@ -3857,10 +3859,12 @@ Parser::functionExpr(uint32_t toStringStart, InvokedPrediction inv 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(); @@ -9468,11 +9472,6 @@ Parser::propertyName(YieldHandling yieldHandling, 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]: @@ -9500,9 +9499,16 @@ Parser::propertyName(YieldHandling yieldHandling, } } - if (isAsync && isGenerator) { - error(JSMSG_ASYNC_GENERATOR); - return null(); + if (ltok == TOK_MUL) { +#ifdef RELEASE_OR_BETA + if (isAsync) { + error(JSMSG_ASYNC_GENERATOR); + return null(); + } +#endif + isGenerator = true; + if (!tokenStream.getToken(<ok)) + return null(); } propAtom.set(nullptr); -- cgit v1.2.3