Skip to content

Commit 2fe6d1f

Browse files
authored
Merge pull request #10470 from erik-krogh/flowParse
JS: Try to parse files without using our parser extensions before enabling the extensions
2 parents 140458b + f404f1d commit 2fe6d1f

File tree

7 files changed

+90
-71
lines changed

7 files changed

+90
-71
lines changed

javascript/extractor/src/com/semmle/jcorn/Options.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public void call(
4040
}
4141

4242
private boolean allowHashBang, allowReturnOutsideFunction, allowImportExportEverywhere, allowGeneratedCodeExprs;
43-
private boolean preserveParens, mozExtensions, jscript, esnext, v8Extensions, e4x;
43+
private boolean preserveParens, mozExtensions, jscript, esnext, v8Extensions, e4x, allowFlowTypes;
4444
private int ecmaVersion;
4545
private AllowReserved allowReserved;
4646
private String sourceType;
@@ -70,6 +70,7 @@ public Options() {
7070
this.v8Extensions = false;
7171
this.e4x = false;
7272
this.onRecoverableError = null;
73+
this.allowFlowTypes = false;
7374
}
7475

7576
public Options(Options that) {
@@ -92,6 +93,7 @@ public Options(Options that) {
9293
this.onComment = that.onComment;
9394
this.program = that.program;
9495
this.onRecoverableError = that.onRecoverableError;
96+
this.allowFlowTypes = that.allowFlowTypes;
9597
}
9698

9799
public boolean allowHashBang() {
@@ -130,6 +132,10 @@ public boolean v8Extensions() {
130132
return v8Extensions;
131133
}
132134

135+
public boolean allowFlowTypes() {
136+
return allowFlowTypes;
137+
}
138+
133139
public boolean e4x() {
134140
return e4x;
135141
}
@@ -202,6 +208,10 @@ public void v8Extensions(boolean v8Extensions) {
202208
this.v8Extensions = v8Extensions;
203209
}
204210

211+
public void allowFlowTypes(boolean allowFlowTypes) {
212+
this.allowFlowTypes = allowFlowTypes;
213+
}
214+
205215
public void e4x(boolean e4x) {
206216
this.e4x = e4x;
207217
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -830,7 +830,7 @@ private void flowParseTypeAnnotatableIdentifier(
830830

831831
/** Should Flow syntax be allowed? */
832832
private boolean flow() {
833-
return options.esnext();
833+
return options.allowFlowTypes();
834834
}
835835

836836
@Override

javascript/extractor/src/com/semmle/js/extractor/Main.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public class Main {
4141
* A version identifier that should be updated every time the extractor changes in such a way that
4242
* it may produce different tuples for the same file under the same {@link ExtractorConfig}.
4343
*/
44-
public static final String EXTRACTOR_VERSION = "2022-08-25";
44+
public static final String EXTRACTOR_VERSION = "2022-09-19";
4545

4646
public static final Pattern NEWLINE = Pattern.compile("\n");
4747

javascript/extractor/src/com/semmle/js/parser/JcornWrapper.java

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,29 @@ public static JSParser.Result parse(
2828
.onToken(tokens)
2929
.preserveParens(true)
3030
.allowReturnOutsideFunction(true);
31-
if (config.isMozExtensions()) options.mozExtensions(true);
32-
if (config.isJscript()) options.jscript(true);
33-
if (config.isJsx()) options = new JSXOptions(options);
3431
if (config.isEsnext()) options.esnext(true);
35-
if (config.isV8Extensions()) options.v8Extensions(true);
36-
if (config.isE4X()) options.e4x(true);
3732

3833
Program program = null;
3934
List<ParseError> errors = new ArrayList<>();
35+
4036
try {
41-
if (config.isTolerateParseErrors())
42-
options.onRecoverableError((err) -> errors.add(mkParseError(err)));
43-
44-
program = sourceType.createParser(options, source, 0).parse();
37+
try {
38+
// First try to parse as a regular JavaScript program.
39+
program = sourceType.createParser(options, source, 0).parse();
40+
} catch (SyntaxError e) {
41+
// If that fails, try to enable all the extensions that we support.
42+
if (config.isTolerateParseErrors())
43+
options.onRecoverableError((err) -> errors.add(mkParseError(err)));
44+
comments.clear();
45+
tokens.clear();
46+
if (config.isMozExtensions()) options.mozExtensions(true);
47+
if (config.isJscript()) options.jscript(true);
48+
if (config.isJsx()) options = new JSXOptions(options);
49+
if (config.isV8Extensions()) options.v8Extensions(true);
50+
if (config.isE4X()) options.e4x(true);
51+
if (config.isEsnext()) options.allowFlowTypes(true); // allow the flow-parser to parse types.
52+
program = sourceType.createParser(options, source, 0).parse();
53+
}
4554
} catch (SyntaxError e) {
4655
errors.add(mkParseError(e));
4756
}

javascript/extractor/tests/mozilla/output/trap/odasa-2593.js.trap

Lines changed: 54 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -133,76 +133,71 @@ locations_default(#20044,#10000,1,17,4,1)
133133
hasLocation(#20043,#20044)
134134
stmt_containers(#20043,#20039)
135135
#20045=*
136-
scopes(#20045,4)
137-
scopenodes(#20043,#20045)
138-
scopenesting(#20045,#20041)
139-
#20046=@"var;{arguments};{#20045}"
140-
variables(#20046,"arguments",#20045)
136+
stmts(#20045,2,#20043,0,"arguments;")
137+
#20046=@"loc,{#10000},2,5,2,14"
138+
locations_default(#20046,#10000,2,5,2,14)
139+
hasLocation(#20045,#20046)
140+
stmt_containers(#20045,#20039)
141141
#20047=*
142-
stmts(#20047,2,#20043,0,"arguments;")
143-
#20048=@"loc,{#10000},2,5,2,14"
144-
locations_default(#20048,#10000,2,5,2,14)
145-
hasLocation(#20047,#20048)
146-
stmt_containers(#20047,#20039)
147-
#20049=*
148-
exprs(#20049,79,#20047,0,"arguments")
149-
hasLocation(#20049,#20021)
150-
enclosing_stmt(#20049,#20047)
151-
expr_containers(#20049,#20039)
152-
literals("arguments","arguments",#20049)
153-
bind(#20049,#20046)
142+
exprs(#20047,79,#20045,0,"arguments")
143+
hasLocation(#20047,#20021)
144+
enclosing_stmt(#20047,#20045)
145+
expr_containers(#20047,#20039)
146+
literals("arguments","arguments",#20047)
147+
bind(#20047,#20042)
148+
#20048=*
149+
stmts(#20048,2,#20043,1,"let (arguments);")
150+
#20049=@"loc,{#10000},3,5,3,20"
151+
locations_default(#20049,#10000,3,5,3,20)
152+
hasLocation(#20048,#20049)
153+
stmt_containers(#20048,#20039)
154154
#20050=*
155-
stmts(#20050,24,#20043,1,"let (arguments);")
156-
#20051=@"loc,{#10000},3,5,3,20"
157-
locations_default(#20051,#10000,3,5,3,20)
155+
exprs(#20050,13,#20048,0,"let (arguments)")
156+
#20051=@"loc,{#10000},3,5,3,19"
157+
locations_default(#20051,#10000,3,5,3,19)
158158
hasLocation(#20050,#20051)
159-
stmt_containers(#20050,#20039)
159+
enclosing_stmt(#20050,#20048)
160+
expr_containers(#20050,#20039)
160161
#20052=*
161-
scopes(#20052,4)
162-
scopenodes(#20050,#20052)
163-
scopenesting(#20052,#20045)
164-
#20053=@"var;{arguments};{#20052}"
165-
variables(#20053,"arguments",#20052)
162+
exprs(#20052,79,#20050,-1,"let")
163+
hasLocation(#20052,#20025)
164+
enclosing_stmt(#20052,#20048)
165+
expr_containers(#20052,#20039)
166+
literals("let","let",#20052)
167+
#20053=@"var;{let};{#20000}"
168+
variables(#20053,"let",#20000)
169+
bind(#20052,#20053)
166170
#20054=*
167-
exprs(#20054,64,#20050,0,"arguments")
171+
exprs(#20054,79,#20050,0,"arguments")
168172
hasLocation(#20054,#20029)
169-
enclosing_stmt(#20054,#20050)
173+
enclosing_stmt(#20054,#20048)
170174
expr_containers(#20054,#20039)
175+
literals("arguments","arguments",#20054)
176+
bind(#20054,#20042)
171177
#20055=*
172-
exprs(#20055,78,#20054,0,"arguments")
173-
hasLocation(#20055,#20029)
174-
enclosing_stmt(#20055,#20050)
175-
expr_containers(#20055,#20039)
176-
literals("arguments","arguments",#20055)
177-
decl(#20055,#20053)
178-
#20056=*
179-
stmts(#20056,0,#20050,-1,";")
180-
hasLocation(#20056,#20033)
181-
stmt_containers(#20056,#20039)
178+
entry_cfg_node(#20055,#20001)
179+
#20056=@"loc,{#10000},1,1,1,0"
180+
locations_default(#20056,#10000,1,1,1,0)
181+
hasLocation(#20055,#20056)
182182
#20057=*
183-
entry_cfg_node(#20057,#20001)
184-
#20058=@"loc,{#10000},1,1,1,0"
185-
locations_default(#20058,#10000,1,1,1,0)
186-
hasLocation(#20057,#20058)
183+
exit_cfg_node(#20057,#20001)
184+
hasLocation(#20057,#20036)
185+
successor(#20039,#20057)
186+
#20058=*
187+
entry_cfg_node(#20058,#20039)
188+
hasLocation(#20058,#20056)
187189
#20059=*
188-
exit_cfg_node(#20059,#20001)
190+
exit_cfg_node(#20059,#20039)
189191
hasLocation(#20059,#20036)
190-
successor(#20039,#20059)
191-
#20060=*
192-
entry_cfg_node(#20060,#20039)
193-
hasLocation(#20060,#20058)
194-
#20061=*
195-
exit_cfg_node(#20061,#20039)
196-
hasLocation(#20061,#20036)
197-
successor(#20043,#20047)
198-
successor(#20050,#20055)
199-
successor(#20056,#20061)
200-
successor(#20055,#20054)
201-
successor(#20054,#20056)
202-
successor(#20047,#20049)
203-
successor(#20049,#20050)
204-
successor(#20060,#20043)
192+
successor(#20043,#20045)
193+
successor(#20048,#20052)
194+
successor(#20054,#20050)
195+
successor(#20052,#20054)
196+
successor(#20050,#20059)
197+
successor(#20045,#20047)
198+
successor(#20047,#20048)
199+
successor(#20058,#20043)
205200
successor(#20040,#20039)
206-
successor(#20057,#20040)
201+
successor(#20055,#20040)
207202
numlines(#10000,4,4,0)
208203
filetype(#10000,"javascript")
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Improved how the JavaScript parser handles ambiguities between plain JavaScript and dialects such as Flow and E4X that use the same file extension. The parser now prefers plain JavaScript if possible, falling back to dialects only if the source code can not be parsed as plain JavaScript. Previously, there were rare cases where parsing would fail because the parser would erroneously attempt to parse dialect-specific syntax in a regular JavaScript file.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
foo ? () => ({}) : (name) => "foo";

0 commit comments

Comments
 (0)