• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"use strict"
2
3const acorn = require('internal/deps/acorn/acorn/dist/acorn')
4const tt = acorn.tokTypes
5const privateClassElements = require('internal/deps/acorn-plugins/acorn-private-class-elements/index')
6
7function maybeParseFieldValue(field) {
8  if (this.eat(tt.eq)) {
9    const oldInFieldValue = this._inFieldValue
10    this._inFieldValue = true
11    field.value = this.parseExpression()
12    this._inFieldValue = oldInFieldValue
13  } else field.value = null
14}
15
16module.exports = function(Parser) {
17  Parser = privateClassElements(Parser)
18  return class extends Parser {
19    // Parse fields
20    parseClassElement(_constructorAllowsSuper) {
21      if (this.options.ecmaVersion >= 8 && (this.type == tt.name || this.type == this.privateNameToken || this.type == tt.bracketL || this.type == tt.string)) {
22        const branch = this._branch()
23        if (branch.type == tt.bracketL) {
24          let count = 0
25          do {
26            if (branch.eat(tt.bracketL)) ++count
27            else if (branch.eat(tt.bracketR)) --count
28            else branch.next()
29          } while (count > 0)
30        } else branch.next()
31        if (branch.type == tt.eq || branch.canInsertSemicolon() || branch.type == tt.semi) {
32          const node = this.startNode()
33          if (this.type == this.privateNameToken) {
34            this.parsePrivateClassElementName(node)
35          } else {
36            this.parsePropertyName(node)
37          }
38          if ((node.key.type === "Identifier" && node.key.name === "constructor") ||
39              (node.key.type === "Literal" && node.key.value === "constructor")) {
40            this.raise(node.key.start, "Classes may not have a field called constructor")
41          }
42          maybeParseFieldValue.call(this, node)
43          this.finishNode(node, "FieldDefinition")
44          this.semicolon()
45          return node
46        }
47      }
48
49      return super.parseClassElement.apply(this, arguments)
50    }
51
52    // Prohibit arguments in class field initializers
53    parseIdent(liberal, isBinding) {
54      const ident = super.parseIdent(liberal, isBinding)
55      if (this._inFieldValue && ident.name == "arguments") this.raise(ident.start, "A class field initializer may not contain arguments")
56      return ident
57    }
58  }
59}
60