Skip to content

Commit 11b3621

Browse files
committed
2.0.1
1 parent b88000f commit 11b3621

File tree

7 files changed

+208
-56
lines changed

7 files changed

+208
-56
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file.
44

55
This project adheres to [Semantic Versioning](http://semver.org/).
66

7+
## 2.0.1
8+
* Fix crash on class methods named `static`:
9+
```js
10+
class X {
11+
static () {}
12+
}
13+
```
14+
15+
Thanks [@kumavis](https://github.com/kumavis)!
16+
717
## 2.0.0
818
* Use acorn's builtin dynamic `import()` parsing. This parses the `ImportExpression` node type instead of the `Import` node type from acorn-node 1.x.
919
* Reject escape sequences in `import.meta`.

lib/class-fields/index.js

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,12 @@
22

33
"use strict"
44

5-
var acorn = require("acorn")
6-
var tt = acorn.tokTypes
75
var privateClassElements = require("../private-class-elements")
86

9-
function maybeParseFieldValue(field) {
10-
if (this.eat(tt.eq)) {
11-
var oldInFieldValue = this._inFieldValue
12-
this._inFieldValue = true
13-
field.value = this.parseExpression()
14-
this._inFieldValue = oldInFieldValue
15-
} else { field.value = null }
16-
}
17-
187
module.exports = function(Parser) {
8+
var acorn = Parser.acorn || require("acorn")
9+
var tt = acorn.tokTypes
10+
1911
Parser = privateClassElements(Parser)
2012
return /*@__PURE__*/(function (Parser) {
2113
function anonymous () {
@@ -26,8 +18,18 @@ module.exports = function(Parser) {
2618
anonymous.prototype = Object.create( Parser && Parser.prototype );
2719
anonymous.prototype.constructor = anonymous;
2820

21+
anonymous.prototype._maybeParseFieldValue = function _maybeParseFieldValue (field) {
22+
if (this.eat(tt.eq)) {
23+
var oldInFieldValue = this._inFieldValue
24+
this._inFieldValue = true
25+
field.value = this.parseExpression()
26+
this._inFieldValue = oldInFieldValue
27+
} else { field.value = null }
28+
};
29+
30+
// Parse fields
2931
anonymous.prototype.parseClassElement = function parseClassElement (_constructorAllowsSuper) {
30-
if (this.options.ecmaVersion >= 8 && (this.type == tt.name || this.type == this.privateNameToken || this.type == tt.bracketL || this.type == tt.string)) {
32+
if (this.options.ecmaVersion >= 8 && (this.type == tt.name || this.type.keyword || this.type == this.privateNameToken || this.type == tt.bracketL || this.type == tt.string || this.type == tt.num)) {
3133
var branch = this._branch()
3234
if (branch.type == tt.bracketL) {
3335
var count = 0
@@ -48,7 +50,9 @@ module.exports = function(Parser) {
4850
(node.key.type === "Literal" && node.key.value === "constructor")) {
4951
this.raise(node.key.start, "Classes may not have a field called constructor")
5052
}
51-
maybeParseFieldValue.call(this, node)
53+
this.enterScope(64 | 2 | 1) // See acorn's scopeflags.js
54+
this._maybeParseFieldValue(node)
55+
this.exitScope()
5256
this.finishNode(node, "FieldDefinition")
5357
this.semicolon()
5458
return node

lib/export-ns-from/index.js

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44

55
var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g
66

7-
var tt = require("acorn").tokTypes
8-
97
module.exports = function(Parser) {
8+
var tt = (Parser.acorn || require("acorn")).tokTypes
9+
1010
return /*@__PURE__*/(function (Parser) {
1111
function anonymous () {
1212
Parser.apply(this, arguments);
@@ -23,19 +23,16 @@ module.exports = function(Parser) {
2323
if (next !== "*") { return Parser.prototype.parseExport.call(this, node, exports) }
2424

2525
this.next()
26-
var specifier = this.startNode()
2726
this.expect(tt.star)
2827
if (this.eatContextual("as")) {
29-
node.declaration = null
30-
specifier.exported = this.parseIdent(true)
31-
this.checkExport(exports, specifier.exported.name, this.lastTokStart)
32-
node.specifiers = [this.finishNode(specifier, "ExportNamespaceSpecifier")]
33-
}
28+
node.exported = this.parseIdent(true)
29+
this.checkExport(exports, node.exported.name, node.exported.start)
30+
} else { node.exported = null }
3431
this.expectContextual("from")
3532
if (this.type !== tt.string) { this.unexpected() }
3633
node.source = this.parseExprAtom()
3734
this.semicolon()
38-
return this.finishNode(node, node.specifiers ? "ExportNamedDeclaration" : "ExportAllDeclaration")
35+
return this.finishNode(node, "ExportAllDeclaration")
3936
};
4037

4138
return anonymous;

lib/import-meta/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ module.exports = function(Parser) {
3131
}
3232

3333
var node = this.startNode()
34+
if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword import") }
3435
node.meta = this.parseIdent(true)
3536
this.expect(tt.dot)
3637
node.property = this.parseIdent(true)

lib/numeric-separator/index.js

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
"use strict"
44

5-
module.exports = function(Parser) {
5+
function withoutAcornBigInt(acorn, Parser) {
66
return /*@__PURE__*/(function (Parser) {
77
function anonymous () {
88
Parser.apply(this, arguments);
@@ -59,3 +59,114 @@ module.exports = function(Parser) {
5959
return anonymous;
6060
}(Parser))
6161
}
62+
63+
function withAcornBigInt(acorn, Parser) {
64+
return /*@__PURE__*/(function (Parser) {
65+
function anonymous () {
66+
Parser.apply(this, arguments);
67+
}
68+
69+
if ( Parser ) anonymous.__proto__ = Parser;
70+
anonymous.prototype = Object.create( Parser && Parser.prototype );
71+
anonymous.prototype.constructor = anonymous;
72+
73+
anonymous.prototype.readInt = function readInt (radix, len) {
74+
// Hack: len is only != null for unicode escape sequences,
75+
// where numeric separators are not allowed
76+
if (len != null) { return Parser.prototype.readInt.call(this, radix, len) }
77+
78+
var start = this.pos, total = 0, acceptUnderscore = false
79+
for (;;) {
80+
var code = this.input.charCodeAt(this.pos), val = (void 0)
81+
if (code >= 97) { val = code - 97 + 10 } // a
82+
else if (code == 95) {
83+
if (!acceptUnderscore) { this.raise(this.pos, "Invalid numeric separator") }
84+
++this.pos
85+
acceptUnderscore = false
86+
continue
87+
} else if (code >= 65) { val = code - 65 + 10 } // A
88+
else if (code >= 48 && code <= 57) { val = code - 48 } // 0-9
89+
else { val = Infinity }
90+
if (val >= radix) { break }
91+
++this.pos
92+
total = total * radix + val
93+
acceptUnderscore = true
94+
}
95+
if (this.pos === start) { return null }
96+
if (!acceptUnderscore) { this.raise(this.pos - 1, "Invalid numeric separator") }
97+
98+
return total
99+
};
100+
101+
anonymous.prototype.readNumber = function readNumber (startsWithDot) {
102+
var start = this.pos
103+
if (!startsWithDot && this.readInt(10) === null) { this.raise(start, "Invalid number") }
104+
var octal = this.pos - start >= 2 && this.input.charCodeAt(start) === 48
105+
var octalLike = false
106+
if (octal && this.strict) { this.raise(start, "Invalid number") }
107+
var next = this.input.charCodeAt(this.pos)
108+
if (!octal && !startsWithDot && this.options.ecmaVersion >= 11 && next === 110) {
109+
var str$1 = this.getNumberInput(start, this.pos)
110+
var val$1 = typeof BigInt !== "undefined" ? BigInt(str$1) : null
111+
++this.pos
112+
if (acorn.isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number") }
113+
return this.finishToken(acorn.tokTypes.num, val$1)
114+
}
115+
if (octal && /[89]/.test(this.input.slice(start, this.pos))) {
116+
octal = false
117+
octalLike = true
118+
}
119+
if (next === 46 && !octal) { // '.'
120+
++this.pos
121+
this.readInt(10)
122+
next = this.input.charCodeAt(this.pos)
123+
}
124+
if ((next === 69 || next === 101) && !octal) { // 'eE'
125+
next = this.input.charCodeAt(++this.pos)
126+
if (next === 43 || next === 45) { ++this.pos } // '+-'
127+
if (this.readInt(10) === null) { this.raise(start, "Invalid number") }
128+
}
129+
if (acorn.isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number") }
130+
var str = this.getNumberInput(start, this.pos)
131+
if ((octal || octalLike) && str.length < this.pos - start) {
132+
this.raise(start, "Invalid number")
133+
}
134+
135+
var val = octal ? parseInt(str, 8) : parseFloat(str)
136+
return this.finishToken(acorn.tokTypes.num, val)
137+
};
138+
139+
anonymous.prototype.parseLiteral = function parseLiteral (value) {
140+
var ret = Parser.prototype.parseLiteral.call(this, value)
141+
if (ret.bigint) { ret.bigint = ret.bigint.replace(/_/g, "") }
142+
return ret
143+
};
144+
145+
anonymous.prototype.readRadixNumber = function readRadixNumber (radix) {
146+
var start = this.pos;
147+
this.pos += 2; // 0x
148+
var val = this.readInt(radix);
149+
if (val == null) { this.raise(this.start + 2, "Expected number in radix " + radix); }
150+
if (this.options.ecmaVersion >= 11 && this.input.charCodeAt(this.pos) === 110) {
151+
var str = this.getNumberInput(start, this.pos)
152+
val = typeof BigInt !== "undefined" ? BigInt(str) : null;
153+
++this.pos;
154+
} else if (acorn.isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }
155+
return this.finishToken(acorn.tokTypes.num, val)
156+
};
157+
158+
// This is used by acorn-bigint, which theoretically could be used with acorn@6.2 || acorn@7
159+
anonymous.prototype.getNumberInput = function getNumberInput (start, end) {
160+
return this.input.slice(start, end).replace(/_/g, "")
161+
};
162+
163+
return anonymous;
164+
}(Parser))
165+
}
166+
167+
module.exports = function(Parser) {
168+
var acorn = Parser.acorn || require("acorn")
169+
var withAcornBigIntSupport = (acorn.version.startsWith("6.") && !(acorn.version.startsWith("6.0.") || acorn.version.startsWith("6.1."))) || acorn.version.startsWith("7.")
170+
171+
return withAcornBigIntSupport ? withAcornBigInt(acorn, Parser) : withoutAcornBigInt(acorn, Parser)
172+
}

lib/private-class-elements/index.js

Lines changed: 59 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,34 @@
22

33
"use strict"
44

5-
var acorn = require("acorn")
6-
if (false) {
7-
throw new Error(("acorn-private-class-elements requires acorn@^6.1.0, not " + (acorn.version)))
5+
var getPrototype = Object.getPrototypeOf || (function (o) { return o.__proto__; })
6+
7+
var getAcorn = function (Parser) {
8+
if (Parser.acorn) { return Parser.acorn }
9+
10+
var acorn = require("acorn")
11+
12+
if (acorn.version.indexOf("6.") != 0 && acorn.version.indexOf("6.0.") == 0 && acorn.version.indexOf("7.") != 0) {
13+
throw new Error(("acorn-private-class-elements requires acorn@^6.1.0 or acorn@7.0.0, not " + (acorn.version)))
14+
}
15+
16+
// Make sure `Parser` comes from the same acorn as we `require`d,
17+
// otherwise the comparisons fail.
18+
for (var cur = Parser; cur && cur !== acorn.Parser; cur = getPrototype(cur)) {
19+
if (cur !== acorn.Parser) {
20+
throw new Error("acorn-private-class-elements does not support mixing different acorn copies")
21+
}
22+
}
23+
return acorn
824
}
9-
var tt = acorn.tokTypes
10-
var TokenType = acorn.TokenType
1125

1226
module.exports = function(Parser) {
1327
// Only load this plugin once.
1428
if (Parser.prototype.parsePrivateName) {
1529
return Parser
1630
}
1731

18-
// Make sure `Parser` comes from the same acorn as our `tt`,
19-
// otherwise the comparisons fail.
20-
var cur = Parser
21-
while (cur && cur !== acorn.Parser) {
22-
cur = cur.__proto__
23-
}
24-
if (cur !== acorn.Parser) {
25-
throw new Error("acorn-private-class-elements does not support mixing different acorn copies")
26-
}
32+
var acorn = getAcorn(Parser)
2733

2834
Parser = /*@__PURE__*/(function (Parser) {
2935
function Parser_ () {
@@ -49,12 +55,12 @@ module.exports = function(Parser) {
4955
element.key = this.parsePrivateName()
5056
if (element.key.name == "constructor") { this.raise(element.key.start, "Classes may not have a private element named constructor") }
5157
var accept = {get: "set", set: "get"}[element.kind]
52-
var privateBoundNames = this._privateBoundNamesStack[this._privateBoundNamesStack.length - 1]
58+
var privateBoundNames = this._privateBoundNames
5359
if (Object.prototype.hasOwnProperty.call(privateBoundNames, element.key.name) && privateBoundNames[element.key.name] !== accept) {
5460
this.raise(element.start, "Duplicate private element")
5561
}
5662
privateBoundNames[element.key.name] = element.kind || true
57-
delete this._unresolvedPrivateNamesStack[this._unresolvedPrivateNamesStack.length - 1][element.key.name]
63+
delete this._unresolvedPrivateNames[element.key.name]
5864
return element.key
5965
};
6066

@@ -79,37 +85,60 @@ module.exports = function(Parser) {
7985

8086
// Manage stacks and check for undeclared private names
8187
Parser_.prototype.parseClass = function parseClass (node, isStatement) {
82-
this._privateBoundNamesStack = this._privateBoundNamesStack || []
83-
var privateBoundNames = Object.create(this._privateBoundNamesStack[this._privateBoundNamesStack.length - 1] || null)
84-
this._privateBoundNamesStack.push(privateBoundNames)
85-
this._unresolvedPrivateNamesStack = this._unresolvedPrivateNamesStack || []
86-
var unresolvedPrivateNames = Object.create(null)
87-
this._unresolvedPrivateNamesStack.push(unresolvedPrivateNames)
88+
var oldOuterPrivateBoundNames = this._outerPrivateBoundNames
89+
this._outerPrivateBoundNames = this._privateBoundNames
90+
this._privateBoundNames = Object.create(this._privateBoundNames || null)
91+
var oldOuterUnresolvedPrivateNames = this._outerUnresolvedPrivateNames
92+
this._outerUnresolvedPrivateNames = this._unresolvedPrivateNames
93+
this._unresolvedPrivateNames = Object.create(null)
94+
8895
var _return = Parser.prototype.parseClass.call(this, node, isStatement)
89-
this._privateBoundNamesStack.pop()
90-
this._unresolvedPrivateNamesStack.pop()
91-
if (!this._unresolvedPrivateNamesStack.length) {
96+
97+
var unresolvedPrivateNames = this._unresolvedPrivateNames
98+
this._privateBoundNames = this._outerPrivateBoundNames
99+
this._outerPrivateBoundNames = oldOuterPrivateBoundNames
100+
this._unresolvedPrivateNames = this._outerUnresolvedPrivateNames
101+
this._outerUnresolvedPrivateNames = oldOuterUnresolvedPrivateNames
102+
if (!this._unresolvedPrivateNames) {
92103
var names = Object.keys(unresolvedPrivateNames)
93104
if (names.length) {
94105
names.sort(function (n1, n2) { return unresolvedPrivateNames[n1] - unresolvedPrivateNames[n2]; })
95106
this.raise(unresolvedPrivateNames[names[0]], "Usage of undeclared private name")
96107
}
97-
} else { Object.assign(this._unresolvedPrivateNamesStack[this._unresolvedPrivateNamesStack.length - 1], unresolvedPrivateNames) }
108+
} else { Object.assign(this._unresolvedPrivateNames, unresolvedPrivateNames) }
109+
return _return
110+
};
111+
112+
// Class heritage is evaluated with outer private environment
113+
Parser_.prototype.parseClassSuper = function parseClassSuper (node) {
114+
var privateBoundNames = this._privateBoundNames
115+
this._privateBoundNames = this._outerPrivateBoundNames
116+
var unresolvedPrivateNames = this._unresolvedPrivateNames
117+
this._unresolvedPrivateNames = this._outerUnresolvedPrivateNames
118+
var _return = Parser.prototype.parseClassSuper.call(this, node)
119+
this._privateBoundNames = privateBoundNames
120+
this._unresolvedPrivateNames = unresolvedPrivateNames
98121
return _return
99122
};
100123

101124
// Parse private element access
102125
Parser_.prototype.parseSubscript = function parseSubscript (base, startPos, startLoc, noCalls, maybeAsyncArrow) {
103-
if (!this.eat(tt.dot)) {
126+
if (!this.eat(acorn.tokTypes.dot)) {
104127
return Parser.prototype.parseSubscript.call(this, base, startPos, startLoc, noCalls, maybeAsyncArrow)
105128
}
106129
var node = this.startNodeAt(startPos, startLoc)
107130
node.object = base
108131
node.computed = false
109132
if (this.type == this.privateNameToken) {
133+
if (base.type == "Super") {
134+
this.raise(this.start, "Cannot access private element on super")
135+
}
110136
node.property = this.parsePrivateName()
111-
if (!this._privateBoundNamesStack.length || !this._privateBoundNamesStack[this._privateBoundNamesStack.length - 1][node.property.name]) {
112-
this._unresolvedPrivateNamesStack[this._unresolvedPrivateNamesStack.length - 1][node.property.name] = node.property.start
137+
if (!this._privateBoundNames || !this._privateBoundNames[node.property.name]) {
138+
if (!this._unresolvedPrivateNames) {
139+
this.raise(node.property.start, "Usage of undeclared private name")
140+
}
141+
this._unresolvedPrivateNames[node.property.name] = node.property.start
113142
}
114143
} else {
115144
node.property = this.parseIdent(true)
@@ -130,6 +159,6 @@ module.exports = function(Parser) {
130159

131160
return Parser_;
132161
}(Parser))
133-
Parser.prototype.privateNameToken = new TokenType("privateName")
162+
Parser.prototype.privateNameToken = new acorn.TokenType("privateName")
134163
return Parser
135164
}

0 commit comments

Comments
 (0)