Skip to content

Commit 64f066f

Browse files
committed
Fix for bang call subscripting issue across block boundaries
1 parent bda54e5 commit 64f066f

10 files changed

Lines changed: 345 additions & 6 deletions

File tree

src/parser/statement.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,8 @@ pp.parseBlockBody = function (node, allowDirectives, topLevel, end) {
608608
let oldStrict;
609609
let octalPosition;
610610

611+
this.state.nestedBlockLevel++;
612+
611613
let isEnd;
612614
if (this.hasPlugin("lightscript") && typeof end === "number") {
613615
isEnd = () => this.state.indentLevel <= end || this.match(tt.eof);
@@ -642,6 +644,8 @@ pp.parseBlockBody = function (node, allowDirectives, topLevel, end) {
642644
node.body.push(stmt);
643645
}
644646

647+
this.state.nestedBlockLevel--;
648+
645649
if (oldStrict === false) {
646650
this.setStrict(false);
647651
}

src/plugins/bangCall.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ export default function(parser) {
4343
// Read args
4444
let first = true;
4545
const oldBangUnwindLevel = this.state.bangUnwindLevel;
46+
const oldBangBlockLevel = this.state.bangBlockLevel;
47+
this.state.bangBlockLevel = this.state.nestedBlockLevel;
4648
this.state.bangUnwindLevel = bangIndentLevel + 1;
4749

4850
while (true) {
@@ -81,6 +83,7 @@ export default function(parser) {
8183
}
8284

8385
this.state.bangUnwindLevel = oldBangUnwindLevel;
86+
this.state.bangBlockLevel = oldBangBlockLevel;
8487

8588
node = this.finishNode(node, nodeType);
8689

@@ -93,6 +96,8 @@ export default function(parser) {
9396

9497
// Subscripts to a bang call must appear at the arg indent level
9598
pp.shouldUnwindBangSubscript = function() {
96-
return this.isLineBreak() && (this.state.indentLevel <= this.state.bangUnwindLevel);
99+
return this.isLineBreak() &&
100+
(this.state.bangBlockLevel == this.state.nestedBlockLevel) &&
101+
(this.state.indentLevel <= this.state.bangUnwindLevel);
97102
};
98103
}

src/plugins/lightscript.js

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,9 @@ pp.rethrowObjParseError = function(objParseResult, blockParseError) {
187187
pp.parseInlineWhiteBlock = function(node) {
188188
if (this.state.type.startsExpr) return this.parseMaybeAssign();
189189
// oneline statement case
190+
this.state.nestedBlockLevel++;
190191
node.body = [this.parseStatement(true)];
192+
this.state.nestedBlockLevel--;
191193
node.directives = [];
192194
this.addExtra(node, "curly", false);
193195
return this.finishNode(node, "BlockStatement");
@@ -198,15 +200,20 @@ pp.parseMultilineWhiteBlock = function(node, indentLevel) {
198200
if (this.match(tt.braceL) && this.hasPlugin("objectBlockAmbiguity_preferObject")) {
199201
objParseResult = this.tryParseObjectWhiteBlock(node, indentLevel);
200202
if (objParseResult[0]) return objParseResult[0];
201-
}
202203

203-
try {
204+
try {
205+
this.parseBlockBody(node, false, false, indentLevel);
206+
if (!node.body.length) {
207+
this.unexpected(node.start, "Expected an Indent or Statement");
208+
}
209+
} catch (err) {
210+
this.rethrowObjParseError(objParseResult, err);
211+
}
212+
} else {
204213
this.parseBlockBody(node, false, false, indentLevel);
205214
if (!node.body.length) {
206215
this.unexpected(node.start, "Expected an Indent or Statement");
207216
}
208-
} catch (err) {
209-
this.rethrowObjParseError(objParseResult, err);
210217
}
211218

212219
this.addExtra(node, "curly", false);
@@ -230,7 +237,10 @@ pp.parseWhiteBlock = function (isExpression?) {
230237
if (objParseResult[0]) return objParseResult[0];
231238
}
232239
try {
233-
return this.parseStatement(false);
240+
this.state.nestedBlockLevel++;
241+
const stmt = this.parseStatement(false);
242+
this.state.nestedBlockLevel--;
243+
return stmt;
234244
} catch (err) {
235245
this.rethrowObjParseError(objParseResult, err);
236246
}

src/tokenizer/state.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export default class State {
4040

4141
// for lightscript
4242
this.indentLevel = 0;
43+
this.nestedBlockLevel = 0;
4344
this.inMatchCaseTest = false;
4445

4546
this.type = tt.eof;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
a! ->
2+
b
3+
~c()
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
{
2+
"type": "File",
3+
"start": 0,
4+
"end": 16,
5+
"loc": {
6+
"start": {
7+
"line": 1,
8+
"column": 0
9+
},
10+
"end": {
11+
"line": 3,
12+
"column": 6
13+
}
14+
},
15+
"program": {
16+
"type": "Program",
17+
"start": 0,
18+
"end": 16,
19+
"loc": {
20+
"start": {
21+
"line": 1,
22+
"column": 0
23+
},
24+
"end": {
25+
"line": 3,
26+
"column": 6
27+
}
28+
},
29+
"sourceType": "script",
30+
"body": [
31+
{
32+
"type": "ExpressionStatement",
33+
"start": 0,
34+
"end": 16,
35+
"loc": {
36+
"start": {
37+
"line": 1,
38+
"column": 0
39+
},
40+
"end": {
41+
"line": 3,
42+
"column": 6
43+
}
44+
},
45+
"expression": {
46+
"type": "CallExpression",
47+
"start": 0,
48+
"end": 16,
49+
"loc": {
50+
"start": {
51+
"line": 1,
52+
"column": 0
53+
},
54+
"end": {
55+
"line": 3,
56+
"column": 6
57+
}
58+
},
59+
"callee": {
60+
"type": "Identifier",
61+
"start": 0,
62+
"end": 1,
63+
"loc": {
64+
"start": {
65+
"line": 1,
66+
"column": 0
67+
},
68+
"end": {
69+
"line": 1,
70+
"column": 1
71+
},
72+
"identifierName": "a"
73+
},
74+
"name": "a"
75+
},
76+
"arguments": [
77+
{
78+
"type": "ArrowFunctionExpression",
79+
"start": 3,
80+
"end": 16,
81+
"loc": {
82+
"start": {
83+
"line": 1,
84+
"column": 3
85+
},
86+
"end": {
87+
"line": 3,
88+
"column": 6
89+
}
90+
},
91+
"id": null,
92+
"generator": false,
93+
"expression": false,
94+
"async": false,
95+
"params": [],
96+
"skinny": true,
97+
"body": {
98+
"type": "BlockStatement",
99+
"start": 3,
100+
"end": 16,
101+
"loc": {
102+
"start": {
103+
"line": 1,
104+
"column": 3
105+
},
106+
"end": {
107+
"line": 3,
108+
"column": 6
109+
}
110+
},
111+
"body": [
112+
{
113+
"type": "ExpressionStatement",
114+
"start": 8,
115+
"end": 16,
116+
"loc": {
117+
"start": {
118+
"line": 2,
119+
"column": 2
120+
},
121+
"end": {
122+
"line": 3,
123+
"column": 6
124+
}
125+
},
126+
"expression": {
127+
"type": "TildeCallExpression",
128+
"start": 8,
129+
"end": 16,
130+
"loc": {
131+
"start": {
132+
"line": 2,
133+
"column": 2
134+
},
135+
"end": {
136+
"line": 3,
137+
"column": 6
138+
}
139+
},
140+
"left": {
141+
"type": "Identifier",
142+
"start": 8,
143+
"end": 9,
144+
"loc": {
145+
"start": {
146+
"line": 2,
147+
"column": 2
148+
},
149+
"end": {
150+
"line": 2,
151+
"column": 3
152+
},
153+
"identifierName": "b"
154+
},
155+
"name": "b"
156+
},
157+
"right": {
158+
"type": "Identifier",
159+
"start": 13,
160+
"end": 14,
161+
"loc": {
162+
"start": {
163+
"line": 3,
164+
"column": 3
165+
},
166+
"end": {
167+
"line": 3,
168+
"column": 4
169+
},
170+
"identifierName": "c"
171+
},
172+
"name": "c"
173+
},
174+
"arguments": []
175+
}
176+
}
177+
],
178+
"directives": [],
179+
"extra": {
180+
"curly": false
181+
}
182+
}
183+
}
184+
],
185+
"extra": {
186+
"bang": true
187+
}
188+
}
189+
}
190+
],
191+
"directives": []
192+
}
193+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"alternatives": {
3+
"default": {
4+
"throws": "Indentation required. (3:2)"
5+
},
6+
"noEnforcedSubscriptIndentation": {
7+
"allPlugins": true,
8+
"excludePlugins": ["enforceSubscriptIndentation"]
9+
}
10+
}
11+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
a
2+
~b()

0 commit comments

Comments
 (0)