|
| 1 | +"use strict" |
| 2 | + |
| 3 | +const acorn = require('internal/deps/acorn/acorn/dist/acorn') |
| 4 | +const tt = acorn.tokTypes |
| 5 | +const privateClassElements = require('internal/deps/acorn-plugins/acorn-private-class-elements/index') |
| 6 | + |
| 7 | +function 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 | + |
| 16 | +module.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 | +} |
0 commit comments