summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMoonchild <moonchild@palemoon.org>2022-06-21 15:14:23 +0000
committerMoonchild <moonchild@palemoon.org>2022-06-21 15:14:23 +0000
commit4af78849297dbe4735b5aad5880af16587042a28 (patch)
tree2367ef2a43fbdbd28728594b35c090bea4cad35c
parent27347bc82722fad7c2f4eac05dcde7b51f19cd2c (diff)
parent324f6a0ea30ff1b8fc1ada50abc9e0bad986958b (diff)
downloaduxp-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.cpp67
-rw-r--r--js/src/frontend/Parser.h1
-rw-r--r--js/src/tests/ecma_2017/AsyncFunctions/async-property-name-error.js21
-rw-r--r--js/src/tests/test262/local/let-newline-await-in-async-function.js18
-rw-r--r--js/src/tests/test262/local/let-newline-await-in-normal-function.js20
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;
+}