-import {reservedWords, keywords} from "./identifier"
-import {types as tt} from "./tokentype"
-import {lineBreak} from "./whitespace"
-import {getOptions} from "./options"
-import {SCOPE_TOP, SCOPE_FUNCTION, SCOPE_ASYNC, SCOPE_GENERATOR, SCOPE_SUPER, SCOPE_DIRECT_SUPER} from "./scopeflags"
-
-function keywordRegexp(words) {
- return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$")
-}
+import {reservedWords, keywords} from "./identifier.js"
+import {types as tt} from "./tokentype.js"
+import {lineBreak} from "./whitespace.js"
+import {getOptions} from "./options.js"
+import {wordsRegexp} from "./util.js"
+import {SCOPE_TOP, SCOPE_FUNCTION, SCOPE_ASYNC, SCOPE_GENERATOR, SCOPE_SUPER, SCOPE_DIRECT_SUPER, SCOPE_CLASS_STATIC_BLOCK} from "./scopeflags.js"
export class Parser {
constructor(options, input, startPos) {
this.options = options = getOptions(options)
this.sourceFile = options.sourceFile
- this.keywords = keywordRegexp(keywords[options.ecmaVersion >= 6 ? 6 : 5])
+ this.keywords = wordsRegexp(keywords[options.ecmaVersion >= 6 ? 6 : options.sourceType === "module" ? "5module" : 5])
let reserved = ""
- if (!options.allowReserved) {
- for (let v = options.ecmaVersion;; v--)
- if (reserved = reservedWords[v]) break
+ if (options.allowReserved !== true) {
+ reserved = reservedWords[options.ecmaVersion >= 6 ? 6 : options.ecmaVersion === 5 ? 5 : 3]
if (options.sourceType === "module") reserved += " await"
}
- this.reservedWords = keywordRegexp(reserved)
+ this.reservedWords = wordsRegexp(reserved)
let reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict
- this.reservedWordsStrict = keywordRegexp(reservedStrict)
- this.reservedWordsStrictBind = keywordRegexp(reservedStrict + " " + reservedWords.strictBind)
+ this.reservedWordsStrict = wordsRegexp(reservedStrict)
+ this.reservedWordsStrictBind = wordsRegexp(reservedStrict + " " + reservedWords.strictBind)
this.input = String(input)
// Used to signal to callers of `readWord1` whether the word
// Used to signify the start of a potential arrow function
this.potentialArrowAt = -1
+ this.potentialArrowInForAwait = false
// Positions to delayed-check that yield/await does not exist in default parameters.
- this.yieldPos = this.awaitPos = 0
+ this.yieldPos = this.awaitPos = this.awaitIdentPos = 0
// Labels in scope.
this.labels = []
+ // Thus-far undefined exports.
+ this.undefinedExports = Object.create(null)
// If enabled, skip leading hashbang line.
if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!")
// For RegExp validation
this.regexpState = null
+
+ // The stack of private names.
+ // Each element has two properties: 'declared' and 'used'.
+ // When it exited from the outermost class definition, all used private names must be declared.
+ this.privateNameStack = []
}
parse() {
}
get inFunction() { return (this.currentVarScope().flags & SCOPE_FUNCTION) > 0 }
- get inGenerator() { return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0 }
- get inAsync() { return (this.currentVarScope().flags & SCOPE_ASYNC) > 0 }
- get allowSuper() { return (this.currentThisScope().flags & SCOPE_SUPER) > 0 }
+
+ get inGenerator() { return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0 && !this.currentVarScope().inClassFieldInit }
+
+ get inAsync() { return (this.currentVarScope().flags & SCOPE_ASYNC) > 0 && !this.currentVarScope().inClassFieldInit }
+
+ get canAwait() {
+ for (let i = this.scopeStack.length - 1; i >= 0; i--) {
+ let scope = this.scopeStack[i]
+ if (scope.inClassFieldInit || scope.flags & SCOPE_CLASS_STATIC_BLOCK) return false
+ if (scope.flags & SCOPE_FUNCTION) return (scope.flags & SCOPE_ASYNC) > 0
+ }
+ return (this.inModule && this.options.ecmaVersion >= 13) || this.options.allowAwaitOutsideFunction
+ }
+
+ get allowSuper() {
+ const {flags, inClassFieldInit} = this.currentThisScope()
+ return (flags & SCOPE_SUPER) > 0 || inClassFieldInit || this.options.allowSuperOutsideMethod
+ }
+
get allowDirectSuper() { return (this.currentThisScope().flags & SCOPE_DIRECT_SUPER) > 0 }
- // Switch to a getter for 7.0.0.
- inNonArrowFunction() { return (this.currentThisScope().flags & SCOPE_FUNCTION) > 0 }
+ get treatFunctionsAsVar() { return this.treatFunctionsAsVarInScope(this.currentScope()) }
+
+ get allowNewDotTarget() {
+ const {flags, inClassFieldInit} = this.currentThisScope()
+ return (flags & (SCOPE_FUNCTION | SCOPE_CLASS_STATIC_BLOCK)) > 0 || inClassFieldInit
+ }
+
+ get inClassStaticBlock() {
+ return (this.currentVarScope().flags & SCOPE_CLASS_STATIC_BLOCK) > 0
+ }
static extend(...plugins) {
let cls = this