Skip to content

Commit

Permalink
spec: disable await binding identifier within static block
Browse files Browse the repository at this point in the history
  • Loading branch information
JLHwung committed Jan 20, 2021
1 parent 10978bb commit bd16c63
Show file tree
Hide file tree
Showing 10 changed files with 733 additions and 84 deletions.
2 changes: 2 additions & 0 deletions packages/babel-parser/src/parser/error-message.js
Expand Up @@ -14,6 +14,8 @@ export const ErrorMessages = Object.freeze({
"Async functions can only be declared at the top level or inside a block",
AwaitBindingIdentifier:
"Can not use 'await' as identifier inside an async function",
AwaitBindingIdentifierInStaticBlock:
"Can not use 'await' as identifier inside a static block",
AwaitExpressionFormalParameter:
"await is not allowed in async function parameters",
AwaitNotInAsyncContext:
Expand Down
3 changes: 3 additions & 0 deletions packages/babel-parser/src/parser/expression.js
Expand Up @@ -2297,6 +2297,9 @@ export default class ExpressionParser extends LValParser {
if (this.prodParam.hasAwait) {
this.raise(startLoc, Errors.AwaitBindingIdentifier);
return;
} else if (this.scope.inStaticBlock && !this.scope.inNonArrowFunction) {
this.raise(startLoc, Errors.AwaitBindingIdentifierInStaticBlock);
return;
} else {
this.expressionScope.recordAsyncArrowParametersError(
startLoc,
Expand Down
7 changes: 2 additions & 5 deletions packages/babel-parser/src/parser/statement.js
Expand Up @@ -20,6 +20,7 @@ import {
SCOPE_FUNCTION,
SCOPE_OTHER,
SCOPE_SIMPLE_CATCH,
SCOPE_STATIC_BLOCK,
SCOPE_SUPER,
CLASS_ELEMENT_OTHER,
CLASS_ELEMENT_INSTANCE_GETTER,
Expand Down Expand Up @@ -1519,10 +1520,7 @@ export default class StatementParser extends ExpressionParser {
) {
this.expectPlugin("classStaticBlock", member.start);
// Start a new lexical scope
this.scope.enter(SCOPE_CLASS | SCOPE_SUPER);
// Start a new expression scope, this is required for parsing edge cases like:
// async (x = class { static { await; } }) => {}
this.expressionScope.enter(newExpressionScope());
this.scope.enter(SCOPE_CLASS | SCOPE_STATIC_BLOCK | SCOPE_SUPER);
// Start a new scope with regard to loop labels
const oldLabels = this.state.labels;
this.state.labels = [];
Expand All @@ -1532,7 +1530,6 @@ export default class StatementParser extends ExpressionParser {
const body = (member.body = []);
this.parseBlockOrModuleBlockBody(body, undefined, false, tt.braceR);
this.prodParam.exit();
this.expressionScope.exit();
this.scope.exit();
this.state.labels = oldLabels;
classBody.body.push(this.finishNode<N.StaticBlock>(member, "StaticBlock"));
Expand Down
4 changes: 4 additions & 0 deletions packages/babel-parser/src/util/scope.js
Expand Up @@ -8,6 +8,7 @@ import {
SCOPE_PROGRAM,
SCOPE_VAR,
SCOPE_CLASS,
SCOPE_STATIC_BLOCK,
BIND_SCOPE_FUNCTION,
BIND_SCOPE_VAR,
BIND_SCOPE_LEXICAL,
Expand Down Expand Up @@ -61,6 +62,9 @@ export default class ScopeHandler<IScope: Scope = Scope> {
get inClass() {
return (this.currentThisScope().flags & SCOPE_CLASS) > 0;
}
get inStaticBlock() {
return (this.currentThisScope().flags & SCOPE_STATIC_BLOCK) > 0;
}
get inNonArrowFunction() {
return (this.currentThisScope().flags & SCOPE_FUNCTION) > 0;
}
Expand Down
22 changes: 12 additions & 10 deletions packages/babel-parser/src/util/scopeflags.js
Expand Up @@ -2,15 +2,16 @@

// Each scope gets a bitset that may contain these flags
// prettier-ignore
export const SCOPE_OTHER = 0b00000000,
SCOPE_PROGRAM = 0b00000001,
SCOPE_FUNCTION = 0b00000010,
SCOPE_ARROW = 0b00000100,
SCOPE_SIMPLE_CATCH = 0b00001000,
SCOPE_SUPER = 0b00010000,
SCOPE_DIRECT_SUPER = 0b00100000,
SCOPE_CLASS = 0b01000000,
SCOPE_TS_MODULE = 0b10000000,
export const SCOPE_OTHER = 0b000000000,
SCOPE_PROGRAM = 0b000000001,
SCOPE_FUNCTION = 0b000000010,
SCOPE_ARROW = 0b000000100,
SCOPE_SIMPLE_CATCH = 0b000001000,
SCOPE_SUPER = 0b000010000,
SCOPE_DIRECT_SUPER = 0b000100000,
SCOPE_CLASS = 0b001000000,
SCOPE_STATIC_BLOCK = 0b010000000,
SCOPE_TS_MODULE = 0b100000000,
SCOPE_VAR = SCOPE_PROGRAM | SCOPE_FUNCTION | SCOPE_TS_MODULE;

export type ScopeFlags =
Expand All @@ -22,7 +23,8 @@ export type ScopeFlags =
| typeof SCOPE_SIMPLE_CATCH
| typeof SCOPE_SUPER
| typeof SCOPE_DIRECT_SUPER
| typeof SCOPE_CLASS;
| typeof SCOPE_CLASS
| typeof SCOPE_STATIC_BLOCK;

// These flags are meant to be _only_ used inside the Scope class (or subclasses).
// prettier-ignore
Expand Down
@@ -0,0 +1,9 @@
var C;

C = class { static { function f() { await } } };

C = class { static { function f(await) {} } };

C = class { static { function f(x = await) {} } };

C = class { static { function f({ [await]: x }) {} } };
@@ -0,0 +1,23 @@
var C;

C = class { static { await } };

C = class { static { () => await } };

C = class { static { (await) => {} } };

C = class { static { (await) } };

C = class { static { async (await) => {} } };

C = class { static { async (await) } };

C = class { static { ({ [await]: x}) => {} } };

C = class { static { ({ [await]: x}) } };

C = class { static { async ({ [await]: x}) => {} } };

C = class { static { async ({ [await]: x}) } };

async (x = class { static { await } }) => {};

0 comments on commit bd16c63

Please sign in to comment.