Skip to content

Commit 671755e

Browse files
committed
Merge pull request #91 from eslint/issue86
Fix: Deeply nested template literals (fixes #86)
2 parents f12a54b + 6fd88d3 commit 671755e

File tree

3 files changed

+303
-12
lines changed

3 files changed

+303
-12
lines changed

espree.js

+23-12
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,14 @@ function scanPunctuator() {
442442
extra.openCurlyToken = extra.tokens.length;
443443
}
444444
}
445+
446+
// 123 is {, 125 is }
447+
if (code === 123) {
448+
state.curlyStack.push("{");
449+
} else if (code === 125) {
450+
state.curlyStack.pop();
451+
}
452+
445453
return {
446454
type: Token.Punctuator,
447455
value: String.fromCharCode(code),
@@ -993,6 +1001,14 @@ function scanTemplate() {
9931001
throwError({}, Messages.UnexpectedToken, "ILLEGAL");
9941002
}
9951003

1004+
if (!tail) {
1005+
state.curlyStack.push("template");
1006+
}
1007+
1008+
if (!head) {
1009+
state.curlyStack.pop();
1010+
}
1011+
9961012
return {
9971013
type: Token.Template,
9981014
value: {
@@ -1030,10 +1046,6 @@ function scanTemplateElement(options) {
10301046

10311047
template = scanTemplate();
10321048

1033-
if (!template.tail) {
1034-
extra.curlies.push("template");
1035-
}
1036-
10371049
peek();
10381050

10391051
return template;
@@ -1385,8 +1397,7 @@ function advance() {
13851397

13861398
// template strings start with backtick (96) or open curly (125) but only if the open
13871399
// curly closes a previously opened curly from a template.
1388-
if (ch === 96 || (ch === 125 && extra.curlies[extra.curlies.length - 1] === "template")) {
1389-
extra.curlies.pop();
1400+
if (ch === 96 || (ch === 125 && state.curlyStack[state.curlyStack.length - 1] === "template")) {
13901401
return scanTemplate();
13911402
}
13921403
}
@@ -1475,18 +1486,18 @@ function lex() {
14751486

14761487
if (token.type === Token.Template) {
14771488
if (token.tail) {
1478-
extra.curlies.pop();
1489+
state.curlyStack.pop();
14791490
} else {
1480-
extra.curlies.push("template");
1491+
state.curlyStack.push("template");
14811492
}
14821493
}
14831494

14841495
if (token.value === "{") {
1485-
extra.curlies.push("{");
1496+
state.curlyStack.push("{");
14861497
}
14871498

14881499
if (token.value === "}") {
1489-
extra.curlies.pop();
1500+
state.curlyStack.pop();
14901501
}
14911502

14921503
return token;
@@ -5235,7 +5246,7 @@ function tokenize(code, options) {
52355246
extra.openCurlyToken = -1;
52365247

52375248
// Needed when using template string tokenization
5238-
extra.curlies = [];
5249+
state.curlyStack = [];
52395250

52405251
extra.range = (typeof options.range === "boolean") && options.range;
52415252
extra.loc = (typeof options.loc === "boolean") && options.loc;
@@ -5328,7 +5339,7 @@ function parse(code, options) {
53285339
};
53295340

53305341
// for template strings
5331-
extra.curlies = [];
5342+
state.curlyStack = [];
53325343

53335344
if (typeof options !== "undefined") {
53345345
extra.range = (typeof options.range === "boolean") && options.range;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
module.exports = {
2+
"type": "Program",
3+
"body": [
4+
{
5+
"type": "ExpressionStatement",
6+
"expression": {
7+
"type": "TaggedTemplateExpression",
8+
"tag": {
9+
"type": "Identifier",
10+
"name": "raw",
11+
"range": [
12+
0,
13+
3
14+
],
15+
"loc": {
16+
"start": {
17+
"line": 1,
18+
"column": 0
19+
},
20+
"end": {
21+
"line": 1,
22+
"column": 3
23+
}
24+
}
25+
},
26+
"quasi": {
27+
"type": "TemplateLiteral",
28+
"quasis": [
29+
{
30+
"type": "TemplateElement",
31+
"value": {
32+
"raw": "hello ",
33+
"cooked": "hello "
34+
},
35+
"tail": false,
36+
"range": [
37+
3,
38+
12
39+
],
40+
"loc": {
41+
"start": {
42+
"line": 1,
43+
"column": 3
44+
},
45+
"end": {
46+
"line": 1,
47+
"column": 12
48+
}
49+
}
50+
},
51+
{
52+
"type": "TemplateElement",
53+
"value": {
54+
"raw": "",
55+
"cooked": ""
56+
},
57+
"tail": true,
58+
"range": [
59+
42,
60+
44
61+
],
62+
"loc": {
63+
"start": {
64+
"line": 1,
65+
"column": 42
66+
},
67+
"end": {
68+
"line": 1,
69+
"column": 44
70+
}
71+
}
72+
}
73+
],
74+
"expressions": [
75+
{
76+
"type": "TemplateLiteral",
77+
"quasis": [
78+
{
79+
"type": "TemplateElement",
80+
"value": {
81+
"raw": "nested ",
82+
"cooked": "nested "
83+
},
84+
"tail": false,
85+
"range": [
86+
12,
87+
22
88+
],
89+
"loc": {
90+
"start": {
91+
"line": 1,
92+
"column": 12
93+
},
94+
"end": {
95+
"line": 1,
96+
"column": 22
97+
}
98+
}
99+
},
100+
{
101+
"type": "TemplateElement",
102+
"value": {
103+
"raw": " blah",
104+
"cooked": " blah"
105+
},
106+
"tail": true,
107+
"range": [
108+
35,
109+
42
110+
],
111+
"loc": {
112+
"start": {
113+
"line": 1,
114+
"column": 35
115+
},
116+
"end": {
117+
"line": 1,
118+
"column": 42
119+
}
120+
}
121+
}
122+
],
123+
"expressions": [
124+
{
125+
"type": "BinaryExpression",
126+
"operator": "+",
127+
"left": {
128+
"type": "TemplateLiteral",
129+
"quasis": [
130+
{
131+
"type": "TemplateElement",
132+
"value": {
133+
"raw": "deeply",
134+
"cooked": "deeply"
135+
},
136+
"tail": true,
137+
"range": [
138+
22,
139+
30
140+
],
141+
"loc": {
142+
"start": {
143+
"line": 1,
144+
"column": 22
145+
},
146+
"end": {
147+
"line": 1,
148+
"column": 30
149+
}
150+
}
151+
}
152+
],
153+
"expressions": [],
154+
"range": [
155+
22,
156+
30
157+
],
158+
"loc": {
159+
"start": {
160+
"line": 1,
161+
"column": 22
162+
},
163+
"end": {
164+
"line": 1,
165+
"column": 30
166+
}
167+
}
168+
},
169+
"right": {
170+
"type": "ObjectExpression",
171+
"properties": [],
172+
"range": [
173+
33,
174+
35
175+
],
176+
"loc": {
177+
"start": {
178+
"line": 1,
179+
"column": 33
180+
},
181+
"end": {
182+
"line": 1,
183+
"column": 35
184+
}
185+
}
186+
},
187+
"range": [
188+
22,
189+
35
190+
],
191+
"loc": {
192+
"start": {
193+
"line": 1,
194+
"column": 22
195+
},
196+
"end": {
197+
"line": 1,
198+
"column": 35
199+
}
200+
}
201+
}
202+
],
203+
"range": [
204+
12,
205+
42
206+
],
207+
"loc": {
208+
"start": {
209+
"line": 1,
210+
"column": 12
211+
},
212+
"end": {
213+
"line": 1,
214+
"column": 42
215+
}
216+
}
217+
}
218+
],
219+
"range": [
220+
3,
221+
44
222+
],
223+
"loc": {
224+
"start": {
225+
"line": 1,
226+
"column": 3
227+
},
228+
"end": {
229+
"line": 1,
230+
"column": 44
231+
}
232+
}
233+
},
234+
"range": [
235+
0,
236+
44
237+
],
238+
"loc": {
239+
"start": {
240+
"line": 1,
241+
"column": 0
242+
},
243+
"end": {
244+
"line": 1,
245+
"column": 44
246+
}
247+
}
248+
},
249+
"range": [
250+
0,
251+
45
252+
],
253+
"loc": {
254+
"start": {
255+
"line": 1,
256+
"column": 0
257+
},
258+
"end": {
259+
"line": 1,
260+
"column": 45
261+
}
262+
}
263+
}
264+
],
265+
"range": [
266+
0,
267+
45
268+
],
269+
"loc": {
270+
"start": {
271+
"line": 1,
272+
"column": 0
273+
},
274+
"end": {
275+
"line": 1,
276+
"column": 45
277+
}
278+
}
279+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
raw`hello ${`nested ${`deeply` + {}} blah`}`;

0 commit comments

Comments
 (0)