Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit cc216ad

Browse files
author
Max Schaefer
committed
JavaScript: Buffer recoverable syntax errors during speculative parsing.
Analogous to how we buffer tokens, we need to delay reporting these errors until we have committed to a parse.
1 parent c7e428e commit cc216ad

4 files changed

Lines changed: 291 additions & 1 deletion

File tree

javascript/extractor/src/com/semmle/jcorn/flow/FlowParser.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import com.semmle.js.ast.ExpressionStatement;
2323
import com.semmle.js.ast.FieldDefinition;
2424
import com.semmle.js.ast.Identifier;
25-
import com.semmle.js.ast.ImportDeclaration;
2625
import com.semmle.js.ast.ImportSpecifier;
2726
import com.semmle.js.ast.Literal;
2827
import com.semmle.js.ast.MethodDefinition;
@@ -78,6 +77,8 @@ private class State {
7877
private Function<Token, Void> onToken;
7978
private boolean inType, noAnonFunctionType;
8079
private List<Token> tokens = new ArrayList<Token>();
80+
private Function<SyntaxError, ?> onRecoverableError;
81+
private List<SyntaxError> errors = new ArrayList<SyntaxError>();
8182

8283
private State() {
8384
this.exprAllowed = FlowParser.this.exprAllowed;
@@ -103,6 +104,10 @@ private State() {
103104
// buffer tokens while we are in speculative mode
104105
this.onToken = options.onToken();
105106
options.onToken((tk) -> { tokens.add(tk); return null; });
107+
108+
// buffer recoverable errors while we are in speculative mode
109+
this.onRecoverableError = options.onRecoverableError();
110+
options.onRecoverableError((err) -> { errors.add(err); return null; });
106111
}
107112

108113
private void reset() {
@@ -125,6 +130,7 @@ private void reset() {
125130
options.onToken(this.onToken);
126131
FlowParser.this.inType = this.inType;
127132
FlowParser.this.noAnonFunctionType = this.noAnonFunctionType;
133+
options.onRecoverableError(this.onRecoverableError);
128134
}
129135

130136
private void commit() {
@@ -133,6 +139,12 @@ private void commit() {
133139
if (this.onToken != null)
134140
for (Token tk : tokens)
135141
this.onToken.apply(tk);
142+
143+
// commit buffered syntax errors
144+
options.onRecoverableError(this.onRecoverableError);
145+
if (this.onRecoverableError != null)
146+
for (SyntaxError err : errors)
147+
this.onRecoverableError.apply(err);
136148
}
137149
}
138150

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
for (let i = 0; i < spec.switch.length; i++) {
2+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"experimental": true
3+
}
Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
#10000=@"/tst.js;sourcefile"
2+
files(#10000,"/tst.js","tst","js",0)
3+
#10001=@"/;folder"
4+
folders(#10001,"/","")
5+
containerparent(#10001,#10000)
6+
#10002=@"loc,{#10000},0,0,0,0"
7+
locations_default(#10002,#10000,0,0,0,0)
8+
hasLocation(#10000,#10002)
9+
#20000=@"global_scope"
10+
scopes(#20000,0)
11+
#20001=@"script;{#10000},1,1"
12+
#20002=*
13+
lines(#20002,#20001,"for (let i = 0; i < spec.switch.length; i++) {","
14+
")
15+
#20003=@"loc,{#10000},1,1,1,46"
16+
locations_default(#20003,#10000,1,1,1,46)
17+
hasLocation(#20002,#20003)
18+
#20004=*
19+
lines(#20004,#20001,"}","
20+
")
21+
#20005=@"loc,{#10000},2,1,2,1"
22+
locations_default(#20005,#10000,2,1,2,1)
23+
hasLocation(#20004,#20005)
24+
numlines(#20001,2,2,0)
25+
#20006=*
26+
tokeninfo(#20006,7,#20001,0,"for")
27+
#20007=@"loc,{#10000},1,1,1,3"
28+
locations_default(#20007,#10000,1,1,1,3)
29+
hasLocation(#20006,#20007)
30+
#20008=*
31+
tokeninfo(#20008,8,#20001,1,"(")
32+
#20009=@"loc,{#10000},1,5,1,5"
33+
locations_default(#20009,#10000,1,5,1,5)
34+
hasLocation(#20008,#20009)
35+
#20010=*
36+
tokeninfo(#20010,7,#20001,2,"let")
37+
#20011=@"loc,{#10000},1,6,1,8"
38+
locations_default(#20011,#10000,1,6,1,8)
39+
hasLocation(#20010,#20011)
40+
#20012=*
41+
tokeninfo(#20012,6,#20001,3,"i")
42+
#20013=@"loc,{#10000},1,10,1,10"
43+
locations_default(#20013,#10000,1,10,1,10)
44+
hasLocation(#20012,#20013)
45+
#20014=*
46+
tokeninfo(#20014,8,#20001,4,"=")
47+
#20015=@"loc,{#10000},1,12,1,12"
48+
locations_default(#20015,#10000,1,12,1,12)
49+
hasLocation(#20014,#20015)
50+
#20016=*
51+
tokeninfo(#20016,3,#20001,5,"0")
52+
#20017=@"loc,{#10000},1,14,1,14"
53+
locations_default(#20017,#10000,1,14,1,14)
54+
hasLocation(#20016,#20017)
55+
#20018=*
56+
tokeninfo(#20018,8,#20001,6,";")
57+
#20019=@"loc,{#10000},1,15,1,15"
58+
locations_default(#20019,#10000,1,15,1,15)
59+
hasLocation(#20018,#20019)
60+
#20020=*
61+
tokeninfo(#20020,6,#20001,7,"i")
62+
#20021=@"loc,{#10000},1,17,1,17"
63+
locations_default(#20021,#10000,1,17,1,17)
64+
hasLocation(#20020,#20021)
65+
#20022=*
66+
tokeninfo(#20022,8,#20001,8,"<")
67+
#20023=@"loc,{#10000},1,19,1,19"
68+
locations_default(#20023,#10000,1,19,1,19)
69+
hasLocation(#20022,#20023)
70+
#20024=*
71+
tokeninfo(#20024,6,#20001,9,"spec")
72+
#20025=@"loc,{#10000},1,21,1,24"
73+
locations_default(#20025,#10000,1,21,1,24)
74+
hasLocation(#20024,#20025)
75+
#20026=*
76+
tokeninfo(#20026,8,#20001,10,".")
77+
#20027=@"loc,{#10000},1,25,1,25"
78+
locations_default(#20027,#10000,1,25,1,25)
79+
hasLocation(#20026,#20027)
80+
#20028=*
81+
tokeninfo(#20028,7,#20001,11,"switch")
82+
#20029=@"loc,{#10000},1,26,1,31"
83+
locations_default(#20029,#10000,1,26,1,31)
84+
hasLocation(#20028,#20029)
85+
#20030=*
86+
tokeninfo(#20030,8,#20001,12,".")
87+
#20031=@"loc,{#10000},1,32,1,32"
88+
locations_default(#20031,#10000,1,32,1,32)
89+
hasLocation(#20030,#20031)
90+
#20032=*
91+
tokeninfo(#20032,6,#20001,13,"length")
92+
#20033=@"loc,{#10000},1,33,1,38"
93+
locations_default(#20033,#10000,1,33,1,38)
94+
hasLocation(#20032,#20033)
95+
#20034=*
96+
tokeninfo(#20034,8,#20001,14,";")
97+
#20035=@"loc,{#10000},1,39,1,39"
98+
locations_default(#20035,#10000,1,39,1,39)
99+
hasLocation(#20034,#20035)
100+
#20036=*
101+
tokeninfo(#20036,6,#20001,15,"i")
102+
#20037=@"loc,{#10000},1,41,1,41"
103+
locations_default(#20037,#10000,1,41,1,41)
104+
hasLocation(#20036,#20037)
105+
#20038=*
106+
tokeninfo(#20038,8,#20001,16,"++")
107+
#20039=@"loc,{#10000},1,42,1,43"
108+
locations_default(#20039,#10000,1,42,1,43)
109+
hasLocation(#20038,#20039)
110+
#20040=*
111+
tokeninfo(#20040,8,#20001,17,")")
112+
#20041=@"loc,{#10000},1,44,1,44"
113+
locations_default(#20041,#10000,1,44,1,44)
114+
hasLocation(#20040,#20041)
115+
#20042=*
116+
tokeninfo(#20042,8,#20001,18,"{")
117+
#20043=@"loc,{#10000},1,46,1,46"
118+
locations_default(#20043,#10000,1,46,1,46)
119+
hasLocation(#20042,#20043)
120+
#20044=*
121+
tokeninfo(#20044,8,#20001,19,"}")
122+
hasLocation(#20044,#20005)
123+
#20045=*
124+
tokeninfo(#20045,0,#20001,20,"")
125+
#20046=@"loc,{#10000},3,1,3,0"
126+
locations_default(#20046,#10000,3,1,3,0)
127+
hasLocation(#20045,#20046)
128+
toplevels(#20001,0)
129+
#20047=@"loc,{#10000},1,1,3,0"
130+
locations_default(#20047,#10000,1,1,3,0)
131+
hasLocation(#20001,#20047)
132+
#20048=*
133+
stmts(#20048,14,#20001,0,"for (le ... ++) {\n}")
134+
#20049=@"loc,{#10000},1,1,2,1"
135+
locations_default(#20049,#10000,1,1,2,1)
136+
hasLocation(#20048,#20049)
137+
stmtContainers(#20048,#20001)
138+
#20050=*
139+
scopes(#20050,5)
140+
scopenodes(#20048,#20050)
141+
scopenesting(#20050,#20000)
142+
#20051=@"var;{i};{#20050}"
143+
variables(#20051,"i",#20050)
144+
#20052=*
145+
exprs(#20052,27,#20048,1,"i < spe ... .length")
146+
#20053=@"loc,{#10000},1,17,1,38"
147+
locations_default(#20053,#10000,1,17,1,38)
148+
hasLocation(#20052,#20053)
149+
enclosingStmt(#20052,#20048)
150+
exprContainers(#20052,#20001)
151+
#20054=*
152+
exprs(#20054,79,#20052,0,"i")
153+
hasLocation(#20054,#20021)
154+
enclosingStmt(#20054,#20048)
155+
exprContainers(#20054,#20001)
156+
literals("i","i",#20054)
157+
bind(#20054,#20051)
158+
#20055=*
159+
exprs(#20055,14,#20052,1,"spec.switch.length")
160+
#20056=@"loc,{#10000},1,21,1,38"
161+
locations_default(#20056,#10000,1,21,1,38)
162+
hasLocation(#20055,#20056)
163+
enclosingStmt(#20055,#20048)
164+
exprContainers(#20055,#20001)
165+
#20057=*
166+
exprs(#20057,14,#20055,0,"spec.switch")
167+
#20058=@"loc,{#10000},1,21,1,31"
168+
locations_default(#20058,#10000,1,21,1,31)
169+
hasLocation(#20057,#20058)
170+
enclosingStmt(#20057,#20048)
171+
exprContainers(#20057,#20001)
172+
#20059=*
173+
exprs(#20059,79,#20057,0,"spec")
174+
hasLocation(#20059,#20025)
175+
enclosingStmt(#20059,#20048)
176+
exprContainers(#20059,#20001)
177+
literals("spec","spec",#20059)
178+
#20060=@"var;{spec};{#20000}"
179+
variables(#20060,"spec",#20000)
180+
bind(#20059,#20060)
181+
#20061=*
182+
exprs(#20061,0,#20057,1,"switch")
183+
hasLocation(#20061,#20029)
184+
enclosingStmt(#20061,#20048)
185+
exprContainers(#20061,#20001)
186+
literals("switch","switch",#20061)
187+
#20062=*
188+
exprs(#20062,0,#20055,1,"length")
189+
hasLocation(#20062,#20033)
190+
enclosingStmt(#20062,#20048)
191+
exprContainers(#20062,#20001)
192+
literals("length","length",#20062)
193+
#20063=*
194+
exprs(#20063,60,#20048,2,"i++")
195+
#20064=@"loc,{#10000},1,41,1,43"
196+
locations_default(#20064,#10000,1,41,1,43)
197+
hasLocation(#20063,#20064)
198+
enclosingStmt(#20063,#20048)
199+
exprContainers(#20063,#20001)
200+
#20065=*
201+
exprs(#20065,79,#20063,0,"i")
202+
hasLocation(#20065,#20037)
203+
enclosingStmt(#20065,#20048)
204+
exprContainers(#20065,#20001)
205+
literals("i","i",#20065)
206+
bind(#20065,#20051)
207+
#20066=*
208+
stmts(#20066,23,#20048,0,"let i = 0")
209+
#20067=@"loc,{#10000},1,6,1,14"
210+
locations_default(#20067,#10000,1,6,1,14)
211+
hasLocation(#20066,#20067)
212+
stmtContainers(#20066,#20001)
213+
#20068=*
214+
exprs(#20068,64,#20066,0,"i = 0")
215+
#20069=@"loc,{#10000},1,10,1,14"
216+
locations_default(#20069,#10000,1,10,1,14)
217+
hasLocation(#20068,#20069)
218+
enclosingStmt(#20068,#20066)
219+
exprContainers(#20068,#20001)
220+
#20070=*
221+
exprs(#20070,78,#20068,0,"i")
222+
hasLocation(#20070,#20013)
223+
enclosingStmt(#20070,#20066)
224+
exprContainers(#20070,#20001)
225+
literals("i","i",#20070)
226+
decl(#20070,#20051)
227+
#20071=*
228+
exprs(#20071,3,#20068,1,"0")
229+
hasLocation(#20071,#20017)
230+
enclosingStmt(#20071,#20066)
231+
exprContainers(#20071,#20001)
232+
literals("0","0",#20071)
233+
#20072=*
234+
stmts(#20072,1,#20048,3,"{\n}")
235+
#20073=@"loc,{#10000},1,46,2,1"
236+
locations_default(#20073,#10000,1,46,2,1)
237+
hasLocation(#20072,#20073)
238+
stmtContainers(#20072,#20001)
239+
#20074=*
240+
entry_cfg_node(#20074,#20001)
241+
#20075=@"loc,{#10000},1,1,1,0"
242+
locations_default(#20075,#10000,1,1,1,0)
243+
hasLocation(#20074,#20075)
244+
#20076=*
245+
exit_cfg_node(#20076,#20001)
246+
hasLocation(#20076,#20046)
247+
successor(#20048,#20066)
248+
successor(#20066,#20070)
249+
successor(#20071,#20068)
250+
successor(#20070,#20071)
251+
successor(#20068,#20054)
252+
successor(#20062,#20055)
253+
successor(#20061,#20057)
254+
successor(#20059,#20061)
255+
successor(#20057,#20062)
256+
successor(#20055,#20052)
257+
successor(#20054,#20059)
258+
#20077=*
259+
guard_node(#20077,1,#20052)
260+
hasLocation(#20077,#20053)
261+
successor(#20077,#20072)
262+
#20078=*
263+
guard_node(#20078,0,#20052)
264+
hasLocation(#20078,#20053)
265+
successor(#20078,#20076)
266+
successor(#20052,#20077)
267+
successor(#20052,#20078)
268+
successor(#20065,#20063)
269+
successor(#20063,#20054)
270+
successor(#20072,#20065)
271+
successor(#20074,#20048)
272+
numlines(#10000,2,2,0)
273+
filetype(#10000,"javascript")

0 commit comments

Comments
 (0)