Skip to content

Commit b04ee63

Browse files
committed
Fix parsing error in exponent expressions with unary left-hand sides.
Esprima (correctly) rejects expressions like -1**2. However, expressions like (-1)**2 are valid but still rejected. This commit fixes this issue by identifying when the left operand is parenthesized. Fixes jquery#1981
1 parent 70c0159 commit b04ee63

File tree

3 files changed

+250
-1
lines changed

3 files changed

+250
-1
lines changed

src/parser.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -1475,8 +1475,16 @@ export class Parser {
14751475
parseExponentiationExpression(): Node.Expression {
14761476
const startToken = this.lookahead;
14771477

1478+
// -1 ** 2 is not accepted, but (-1) ** 2
1479+
// However, the AST for both cases is identical
1480+
// We distinguish the two cases by explicitly checking for a parenthesis.
1481+
1482+
const isLeftParenthesized = this.match('(');
14781483
let expr = this.inheritCoverGrammar(this.parseUnaryExpression);
1479-
if (expr.type !== Syntax.UnaryExpression && this.match('**')) {
1484+
1485+
const exponentAllowed = expr.type !== Syntax.UnaryExpression || isLeftParenthesized;
1486+
1487+
if (exponentAllowed && this.match('**')) {
14801488
this.nextToken();
14811489
this.context.isAssignmentTarget = false;
14821490
this.context.isBindingElement = false;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
(-2) ** 1;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
{
2+
"type": "Program",
3+
"body": [
4+
{
5+
"type": "ExpressionStatement",
6+
"expression": {
7+
"type": "BinaryExpression",
8+
"operator": "**",
9+
"left": {
10+
"type": "UnaryExpression",
11+
"operator": "-",
12+
"argument": {
13+
"type": "Literal",
14+
"value": 2,
15+
"raw": "2",
16+
"range": [
17+
2,
18+
3
19+
],
20+
"loc": {
21+
"start": {
22+
"line": 1,
23+
"column": 2
24+
},
25+
"end": {
26+
"line": 1,
27+
"column": 3
28+
}
29+
}
30+
},
31+
"prefix": true,
32+
"range": [
33+
1,
34+
3
35+
],
36+
"loc": {
37+
"start": {
38+
"line": 1,
39+
"column": 1
40+
},
41+
"end": {
42+
"line": 1,
43+
"column": 3
44+
}
45+
}
46+
},
47+
"right": {
48+
"type": "Literal",
49+
"value": 1,
50+
"raw": "1",
51+
"range": [
52+
8,
53+
9
54+
],
55+
"loc": {
56+
"start": {
57+
"line": 1,
58+
"column": 8
59+
},
60+
"end": {
61+
"line": 1,
62+
"column": 9
63+
}
64+
}
65+
},
66+
"range": [
67+
0,
68+
9
69+
],
70+
"loc": {
71+
"start": {
72+
"line": 1,
73+
"column": 0
74+
},
75+
"end": {
76+
"line": 1,
77+
"column": 9
78+
}
79+
}
80+
},
81+
"range": [
82+
0,
83+
10
84+
],
85+
"loc": {
86+
"start": {
87+
"line": 1,
88+
"column": 0
89+
},
90+
"end": {
91+
"line": 1,
92+
"column": 10
93+
}
94+
}
95+
}
96+
],
97+
"sourceType": "script",
98+
"range": [
99+
0,
100+
10
101+
],
102+
"loc": {
103+
"start": {
104+
"line": 1,
105+
"column": 0
106+
},
107+
"end": {
108+
"line": 1,
109+
"column": 10
110+
}
111+
},
112+
"tokens": [
113+
{
114+
"type": "Punctuator",
115+
"value": "(",
116+
"range": [
117+
0,
118+
1
119+
],
120+
"loc": {
121+
"start": {
122+
"line": 1,
123+
"column": 0
124+
},
125+
"end": {
126+
"line": 1,
127+
"column": 1
128+
}
129+
}
130+
},
131+
{
132+
"type": "Punctuator",
133+
"value": "-",
134+
"range": [
135+
1,
136+
2
137+
],
138+
"loc": {
139+
"start": {
140+
"line": 1,
141+
"column": 1
142+
},
143+
"end": {
144+
"line": 1,
145+
"column": 2
146+
}
147+
}
148+
},
149+
{
150+
"type": "Numeric",
151+
"value": "2",
152+
"range": [
153+
2,
154+
3
155+
],
156+
"loc": {
157+
"start": {
158+
"line": 1,
159+
"column": 2
160+
},
161+
"end": {
162+
"line": 1,
163+
"column": 3
164+
}
165+
}
166+
},
167+
{
168+
"type": "Punctuator",
169+
"value": ")",
170+
"range": [
171+
3,
172+
4
173+
],
174+
"loc": {
175+
"start": {
176+
"line": 1,
177+
"column": 3
178+
},
179+
"end": {
180+
"line": 1,
181+
"column": 4
182+
}
183+
}
184+
},
185+
{
186+
"type": "Punctuator",
187+
"value": "**",
188+
"range": [
189+
5,
190+
7
191+
],
192+
"loc": {
193+
"start": {
194+
"line": 1,
195+
"column": 5
196+
},
197+
"end": {
198+
"line": 1,
199+
"column": 7
200+
}
201+
}
202+
},
203+
{
204+
"type": "Numeric",
205+
"value": "1",
206+
"range": [
207+
8,
208+
9
209+
],
210+
"loc": {
211+
"start": {
212+
"line": 1,
213+
"column": 8
214+
},
215+
"end": {
216+
"line": 1,
217+
"column": 9
218+
}
219+
}
220+
},
221+
{
222+
"type": "Punctuator",
223+
"value": ";",
224+
"range": [
225+
9,
226+
10
227+
],
228+
"loc": {
229+
"start": {
230+
"line": 1,
231+
"column": 9
232+
},
233+
"end": {
234+
"line": 1,
235+
"column": 10
236+
}
237+
}
238+
}
239+
]
240+
}

0 commit comments

Comments
 (0)