diff options
author | Moonchild <moonchild@palemoon.org> | 2022-06-21 15:14:23 +0000 |
---|---|---|
committer | Moonchild <moonchild@palemoon.org> | 2022-06-21 15:14:23 +0000 |
commit | 4af78849297dbe4735b5aad5880af16587042a28 (patch) | |
tree | 2367ef2a43fbdbd28728594b35c090bea4cad35c | |
parent | 27347bc82722fad7c2f4eac05dcde7b51f19cd2c (diff) | |
parent | 324f6a0ea30ff1b8fc1ada50abc9e0bad986958b (diff) | |
download | uxp-4af78849297dbe4735b5aad5880af16587042a28.tar.gz |
Merge pull request 'Collected ports for async functions in the JS parser' (#1924) from martok/UXP-contrib:1918-asyncgenerator into master
Reviewed-on: https://repo.palemoon.org/MoonchildProductions/UXP/pulls/1924
-rw-r--r-- | js/src/frontend/Parser.cpp | 67 | ||||
-rw-r--r-- | js/src/frontend/Parser.h | 1 | ||||
-rw-r--r-- | js/src/tests/ecma_2017/AsyncFunctions/async-property-name-error.js | 21 | ||||
-rw-r--r-- | js/src/tests/test262/local/let-newline-await-in-async-function.js | 18 | ||||
-rw-r--r-- | js/src/tests/test262/local/let-newline-await-in-normal-function.js | 20 |
5 files changed, 101 insertions, 26 deletions
diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index a66183b4a8..cb84a939f6 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -7085,6 +7085,7 @@ JSOpFromPropertyType(PropertyType propType) case PropertyType::Method: case PropertyType::GeneratorMethod: case PropertyType::AsyncMethod: + case PropertyType::AsyncGeneratorMethod: case PropertyType::Constructor: case PropertyType::DerivedConstructor: return JSOP_INITPROP; @@ -7208,7 +7209,7 @@ Parser<ParseHandler>::classDefinition(YieldHandling yieldHandling, if (propType != PropertyType::Getter && propType != PropertyType::Setter && propType != PropertyType::Method && propType != PropertyType::GeneratorMethod && - propType != PropertyType::AsyncMethod && + propType != PropertyType::AsyncMethod && propType != PropertyType::AsyncGeneratorMethod && propType != PropertyType::Constructor && propType != PropertyType::DerivedConstructor) { errorAt(nameOffset, JSMSG_BAD_METHOD_DEF); @@ -7348,6 +7349,11 @@ Parser<ParseHandler>::nextTokenContinuesLetDeclaration(TokenKind next, YieldHand if (next == TOK_YIELD) return yieldHandling == YieldIsName; + // Somewhat similar logic applies for "await", except that it's not tracked + // with an AwaitHandling argument. + if (next == TOK_AWAIT) + return !awaitIsKeyword(); + // Otherwise a let declaration must have a name. if (TokenKindIsPossibleIdentifier(next)) { // A "let" edge case deserves special comment. Consider this: @@ -9731,6 +9737,9 @@ Parser<ParseHandler>::propertyName(YieldHandling yieldHandling, // AsyncMethod[Yield, Await]: // async [no LineTerminator here] PropertyName[?Yield, ?Await] ... // + // AsyncGeneratorMethod[Yield, Await]: + // async [no LineTerminator here] * PropertyName[?Yield, ?Await] ... + // // PropertyName: // LiteralPropertyName // ComputedPropertyName[?Yield, ?Await] @@ -9743,13 +9752,14 @@ Parser<ParseHandler>::propertyName(YieldHandling yieldHandling, // ComputedPropertyName[Yield, Await]: // [ ... TokenKind tt = TOK_EOF; - if (!tokenStream.getToken(&tt)) + if (!tokenStream.peekTokenSameLine(&tt)) return null(); - if (tt != TOK_LP && tt != TOK_COLON && tt != TOK_RC && tt != TOK_ASSIGN) { + if (tt == TOK_STRING || tt == TOK_NUMBER || tt == TOK_LB || + TokenKindIsPossibleIdentifierName(tt) || tt == TOK_MUL) + { isAsync = true; + tokenStream.consumeKnownToken(tt); ltok = tt; - } else { - tokenStream.ungetToken(); } } @@ -9771,6 +9781,21 @@ Parser<ParseHandler>::propertyName(YieldHandling yieldHandling, return null(); break; + case TOK_STRING: { + propAtom.set(tokenStream.currentToken().atom()); + uint32_t index; + if (propAtom->isIndex(&index)) { + propName = handler.newNumber(index, NoDecimal, pos()); + if (!propName) + return null(); + break; + } + propName = stringLiteral(); + if (!propName) + return null(); + break; + } + case TOK_LB: propName = computedPropertyName(yieldHandling, maybeDecl, propList); if (!propName) @@ -9784,7 +9809,7 @@ Parser<ParseHandler>::propertyName(YieldHandling yieldHandling, } propAtom.set(tokenStream.currentName()); - // Do not look for accessor syntax on generators + // Do not look for accessor syntax on generator or async methods. if (isGenerator || isAsync || !(ltok == TOK_GET || ltok == TOK_SET)) { propName = handler.newObjectLiteralPropertyName(propAtom, pos()); if (!propName) @@ -9839,21 +9864,6 @@ Parser<ParseHandler>::propertyName(YieldHandling yieldHandling, return null(); break; } - - case TOK_STRING: { - propAtom.set(tokenStream.currentToken().atom()); - uint32_t index; - if (propAtom->isIndex(&index)) { - propName = handler.newNumber(index, NoDecimal, pos()); - if (!propName) - return null(); - break; - } - propName = stringLiteral(); - if (!propName) - return null(); - break; - } } TokenKind tt; @@ -9861,7 +9871,7 @@ Parser<ParseHandler>::propertyName(YieldHandling yieldHandling, return null(); if (tt == TOK_COLON) { - if (isGenerator) { + if (isGenerator || isAsync) { error(JSMSG_BAD_PROP_ID); return null(); } @@ -9872,7 +9882,7 @@ Parser<ParseHandler>::propertyName(YieldHandling yieldHandling, if (TokenKindIsPossibleIdentifierName(ltok) && (tt == TOK_COMMA || tt == TOK_RC || tt == TOK_ASSIGN)) { - if (isGenerator) { + if (isGenerator || isAsync) { error(JSMSG_BAD_PROP_ID); return null(); } @@ -9885,7 +9895,9 @@ Parser<ParseHandler>::propertyName(YieldHandling yieldHandling, if (tt == TOK_LP) { tokenStream.ungetToken(); - if (isGenerator) + if (isGenerator && isAsync) + *propType = PropertyType::AsyncGeneratorMethod; + else if (isGenerator) *propType = PropertyType::GeneratorMethod; else if (isAsync) *propType = PropertyType::AsyncMethod; @@ -10163,6 +10175,7 @@ Parser<ParseHandler>::methodDefinition(uint32_t toStringStart, PropertyType prop case PropertyType::Method: case PropertyType::GeneratorMethod: case PropertyType::AsyncMethod: + case PropertyType::AsyncGeneratorMethod: kind = Method; break; @@ -10178,11 +10191,13 @@ Parser<ParseHandler>::methodDefinition(uint32_t toStringStart, PropertyType prop MOZ_CRASH("Parser: methodDefinition: unexpected property type"); } - GeneratorKind generatorKind = propType == PropertyType::GeneratorMethod + GeneratorKind generatorKind = (propType == PropertyType::GeneratorMethod || + propType == PropertyType::AsyncGeneratorMethod) ? StarGenerator : NotGenerator; - FunctionAsyncKind asyncKind = (propType == PropertyType::AsyncMethod) + FunctionAsyncKind asyncKind = (propType == PropertyType::AsyncMethod || + propType == PropertyType::AsyncGeneratorMethod) ? AsyncFunction : SyncFunction; diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index 97f6917bd6..1e9028cbee 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -579,6 +579,7 @@ enum class PropertyType { Method, GeneratorMethod, AsyncMethod, + AsyncGeneratorMethod, Constructor, DerivedConstructor }; diff --git a/js/src/tests/ecma_2017/AsyncFunctions/async-property-name-error.js b/js/src/tests/ecma_2017/AsyncFunctions/async-property-name-error.js new file mode 100644 index 0000000000..926794e5d0 --- /dev/null +++ b/js/src/tests/ecma_2017/AsyncFunctions/async-property-name-error.js @@ -0,0 +1,21 @@ +function assertSyntaxError(code) { + assertThrowsInstanceOf(() => { Function(code); }, SyntaxError, "Function:" + code); + assertThrowsInstanceOf(() => { eval(code); }, SyntaxError, "eval:" + code); + var ieval = eval; + assertThrowsInstanceOf(() => { ieval(code); }, SyntaxError, "indirect eval:" + code); +} + +assertSyntaxError(`({async async: 0})`); +assertSyntaxError(`({async async})`); +assertSyntaxError(`({async async, })`); +assertSyntaxError(`({async async = 0} = {})`); + +for (let decl of ["var", "let", "const"]) { + assertSyntaxError(`${decl} {async async: a} = {}`); + assertSyntaxError(`${decl} {async async} = {}`); + assertSyntaxError(`${decl} {async async, } = {}`); + assertSyntaxError(`${decl} {async async = 0} = {}`); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/test262/local/let-newline-await-in-async-function.js b/js/src/tests/test262/local/let-newline-await-in-async-function.js new file mode 100644 index 0000000000..c43a5b2745 --- /dev/null +++ b/js/src/tests/test262/local/let-newline-await-in-async-function.js @@ -0,0 +1,18 @@ +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Jeff Walden <jwalden+code@mit.edu> +esid: sec-let-and-const-declarations +description: > + |await| is excluded from LexicalDeclaration by grammar parameter, in + AsyncFunction. Therefore |let| followed by |await| inside AsyncFunction is + an ASI opportunity, and this code must parse without error. +---*/ + +async function f() { + let + await 0; +} + +reportCompare(true, f instanceof Function); diff --git a/js/src/tests/test262/local/let-newline-await-in-normal-function.js b/js/src/tests/test262/local/let-newline-await-in-normal-function.js new file mode 100644 index 0000000000..f49f9ea528 --- /dev/null +++ b/js/src/tests/test262/local/let-newline-await-in-normal-function.js @@ -0,0 +1,20 @@ +// |reftest| error:SyntaxError +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: Jeff Walden <jwalden+code@mit.edu> +esid: sec-let-and-const-declarations +description: > + Outside AsyncFunction, |await| is a perfectly cromulent LexicalDeclaration + variable name. Therefore ASI doesn't apply, and so the |0| where a |=| was + expected is a syntax error. +negative: + phase: early + type: SyntaxError +---*/ + +function f() { + let + await 0; +} |