Upgrade to https://github.com/acornjs/acorn.git commit 84eda6bf
[jst.git] / src / state.js
index a838742..c2e4111 100644 (file)
@@ -1,28 +1,24 @@
-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
@@ -69,11 +65,14 @@ export class Parser {
 
     // 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) === "#!")
@@ -85,6 +84,11 @@ export class Parser {
 
     // 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() {
@@ -94,13 +98,37 @@ export class Parser {
   }
 
   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