Skip to content

Commit 3221fa5

Browse files
committed
Change approach to field init scope tracking
1 parent 9e365f7 commit 3221fa5

File tree

5 files changed

+30
-22
lines changed

5 files changed

+30
-22
lines changed

Diff for: acorn/src/expression.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import {types as tokenCtxTypes} from "./tokencontext.js"
2121
import {Parser} from "./state.js"
2222
import {DestructuringErrors} from "./parseutil.js"
2323
import {lineBreak} from "./whitespace.js"
24-
import {functionFlags, SCOPE_ARROW, SCOPE_SUPER, SCOPE_DIRECT_SUPER, BIND_OUTSIDE, BIND_VAR} from "./scopeflags.js"
24+
import {functionFlags, SCOPE_ARROW, SCOPE_SUPER, SCOPE_DIRECT_SUPER, BIND_OUTSIDE, BIND_VAR, SCOPE_VAR} from "./scopeflags.js"
2525

2626
const pp = Parser.prototype
2727

@@ -1043,7 +1043,7 @@ pp.checkUnreserved = function({start, end, name}) {
10431043
this.raiseRecoverable(start, "Cannot use 'yield' as identifier inside a generator")
10441044
if (this.inAsync && name === "await")
10451045
this.raiseRecoverable(start, "Cannot use 'await' as identifier inside an async function")
1046-
if (this.currentScope().inClassFieldInit && name === "arguments")
1046+
if (!(this.currentThisScope().flags & SCOPE_VAR) && name === "arguments")
10471047
this.raiseRecoverable(start, "Cannot use 'arguments' in class field initializer")
10481048
if (this.inClassStaticBlock && (name === "arguments" || name === "await"))
10491049
this.raise(start, `Cannot use ${name} in class static initialization block`)

Diff for: acorn/src/scope.js

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import {Parser} from "./state.js"
2-
import {SCOPE_VAR, SCOPE_FUNCTION, SCOPE_TOP, SCOPE_ARROW, SCOPE_SIMPLE_CATCH, BIND_LEXICAL, BIND_SIMPLE_CATCH, BIND_FUNCTION} from "./scopeflags.js"
2+
import {
3+
SCOPE_VAR, SCOPE_FUNCTION, SCOPE_TOP, SCOPE_ARROW, SCOPE_SIMPLE_CATCH, BIND_LEXICAL,
4+
BIND_SIMPLE_CATCH, BIND_FUNCTION, SCOPE_CLASS_FIELD_INIT, SCOPE_CLASS_STATIC_BLOCK
5+
} from "./scopeflags.js"
36

47
const pp = Parser.prototype
58

@@ -12,8 +15,6 @@ class Scope {
1215
this.lexical = []
1316
// A list of lexically-declared FunctionDeclaration names in the current lexical scope
1417
this.functions = []
15-
// A switch to disallow the identifier reference 'arguments'
16-
this.inClassFieldInit = false
1718
}
1819
}
1920

@@ -84,14 +85,15 @@ pp.currentScope = function() {
8485
pp.currentVarScope = function() {
8586
for (let i = this.scopeStack.length - 1;; i--) {
8687
let scope = this.scopeStack[i]
87-
if (scope.flags & SCOPE_VAR) return scope
88+
if (scope.flags & (SCOPE_VAR | SCOPE_CLASS_FIELD_INIT | SCOPE_CLASS_STATIC_BLOCK)) return scope
8889
}
8990
}
9091

9192
// Could be useful for `this`, `new.target`, `super()`, `super.property`, and `super[property]`.
9293
pp.currentThisScope = function() {
9394
for (let i = this.scopeStack.length - 1;; i--) {
9495
let scope = this.scopeStack[i]
95-
if (scope.flags & SCOPE_VAR && !(scope.flags & SCOPE_ARROW)) return scope
96+
if (scope.flags & (SCOPE_VAR | SCOPE_CLASS_FIELD_INIT | SCOPE_CLASS_STATIC_BLOCK) &&
97+
!(scope.flags & SCOPE_ARROW)) return scope
9698
}
9799
}

Diff for: acorn/src/scopeflags.js

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export const
99
SCOPE_SUPER = 64,
1010
SCOPE_DIRECT_SUPER = 128,
1111
SCOPE_CLASS_STATIC_BLOCK = 256,
12+
SCOPE_CLASS_FIELD_INIT = 512,
1213
SCOPE_VAR = SCOPE_TOP | SCOPE_FUNCTION | SCOPE_CLASS_STATIC_BLOCK
1314

1415
export function functionFlags(async, generator) {

Diff for: acorn/src/state.js

+17-10
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ import {types as tt} from "./tokentype.js"
33
import {lineBreak} from "./whitespace.js"
44
import {getOptions} from "./options.js"
55
import {wordsRegexp} from "./util.js"
6-
import {SCOPE_TOP, SCOPE_FUNCTION, SCOPE_ASYNC, SCOPE_GENERATOR, SCOPE_SUPER, SCOPE_DIRECT_SUPER, SCOPE_CLASS_STATIC_BLOCK} from "./scopeflags.js"
6+
import {
7+
SCOPE_TOP, SCOPE_FUNCTION, SCOPE_ASYNC, SCOPE_GENERATOR, SCOPE_SUPER, SCOPE_DIRECT_SUPER,
8+
SCOPE_ARROW, SCOPE_CLASS_STATIC_BLOCK, SCOPE_CLASS_FIELD_INIT
9+
} from "./scopeflags.js"
710

811
export class Parser {
912
constructor(options, input, startPos) {
@@ -99,31 +102,35 @@ export class Parser {
99102

100103
get inFunction() { return (this.currentVarScope().flags & SCOPE_FUNCTION) > 0 }
101104

102-
get inGenerator() { return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0 && !this.currentScope().inClassFieldInit }
105+
get inGenerator() { return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0 }
103106

104-
get inAsync() { return (this.currentScope().flags & SCOPE_ASYNC) > 0 && !this.currentScope().inClassFieldInit }
107+
get inAsync() { return (this.currentVarScope().flags & SCOPE_ASYNC) > 0 }
105108

106109
get canAwait() {
107110
for (let i = this.scopeStack.length - 1; i >= 0; i--) {
108-
let scope = this.scopeStack[i]
109-
if (scope.flags & SCOPE_CLASS_STATIC_BLOCK || scope.inClassFieldInit) return false
110-
if (scope.flags & SCOPE_FUNCTION) return (scope.flags & SCOPE_ASYNC) > 0
111+
let {flags} = this.scopeStack[i]
112+
if (flags & (SCOPE_CLASS_STATIC_BLOCK | SCOPE_CLASS_FIELD_INIT)) return false
113+
if (flags & SCOPE_FUNCTION) return (flags & SCOPE_ASYNC) > 0
111114
}
112115
return (this.inModule && this.options.ecmaVersion >= 13) || this.options.allowAwaitOutsideFunction
113116
}
114117

115118
get allowSuper() {
116-
const {flags, inClassFieldInit} = this.currentThisScope()
117-
return (flags & SCOPE_SUPER) > 0 || inClassFieldInit || this.options.allowSuperOutsideMethod
119+
const {flags} = this.currentThisScope()
120+
return (flags & SCOPE_SUPER) > 0 || this.options.allowSuperOutsideMethod
118121
}
119122

120123
get allowDirectSuper() { return (this.currentThisScope().flags & SCOPE_DIRECT_SUPER) > 0 }
121124

122125
get treatFunctionsAsVar() { return this.treatFunctionsAsVarInScope(this.currentScope()) }
123126

124127
get allowNewDotTarget() {
125-
const {flags} = this.currentThisScope()
126-
return (flags & (SCOPE_FUNCTION | SCOPE_CLASS_STATIC_BLOCK)) > 0 || this.currentScope().inClassFieldInit
128+
for (let i = this.scopeStack.length - 1; i >= 0; i--) {
129+
let {flags} = this.scopeStack[i]
130+
if (flags & (SCOPE_CLASS_STATIC_BLOCK | SCOPE_CLASS_FIELD_INIT) ||
131+
((flags & SCOPE_FUNCTION) && !(flags & SCOPE_ARROW))) return true
132+
}
133+
return false
127134
}
128135

129136
get inClassStaticBlock() {

Diff for: acorn/src/statement.js

+3-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {lineBreak, skipWhiteSpace} from "./whitespace.js"
44
import {isIdentifierStart, isIdentifierChar, keywordRelationalOperator} from "./identifier.js"
55
import {hasOwn, loneSurrogate} from "./util.js"
66
import {DestructuringErrors} from "./parseutil.js"
7-
import {functionFlags, SCOPE_SIMPLE_CATCH, BIND_SIMPLE_CATCH, BIND_LEXICAL, BIND_VAR, BIND_FUNCTION, SCOPE_CLASS_STATIC_BLOCK, SCOPE_SUPER} from "./scopeflags.js"
7+
import {functionFlags, SCOPE_SIMPLE_CATCH, BIND_SIMPLE_CATCH, BIND_LEXICAL, BIND_VAR, BIND_FUNCTION, SCOPE_CLASS_STATIC_BLOCK, SCOPE_SUPER, SCOPE_CLASS_FIELD_INIT} from "./scopeflags.js"
88

99
const pp = Parser.prototype
1010

@@ -742,11 +742,9 @@ pp.parseClassField = function(field) {
742742

743743
if (this.eat(tt.eq)) {
744744
// To raise SyntaxError if 'arguments' exists in the initializer.
745-
const scope = this.currentScope()
746-
const inClassFieldInit = scope.inClassFieldInit
747-
scope.inClassFieldInit = true
745+
this.enterScope(SCOPE_CLASS_FIELD_INIT | SCOPE_SUPER)
748746
field.value = this.parseMaybeAssign()
749-
scope.inClassFieldInit = inClassFieldInit
747+
this.exitScope()
750748
} else {
751749
field.value = null
752750
}

0 commit comments

Comments
 (0)