Skip to content

Commit bab2a79

Browse files
committed
JS: Add parsing support in JS parser
1 parent 215602c commit bab2a79

File tree

4 files changed

+21
-9
lines changed

4 files changed

+21
-9
lines changed

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

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
import com.semmle.js.ast.ImportDeclaration;
6262
import com.semmle.js.ast.ImportDefaultSpecifier;
6363
import com.semmle.js.ast.ImportNamespaceSpecifier;
64+
import com.semmle.js.ast.ImportPhaseModifier;
6465
import com.semmle.js.ast.ImportSpecifier;
6566
import com.semmle.js.ast.LabeledStatement;
6667
import com.semmle.js.ast.Literal;
@@ -3587,34 +3588,40 @@ protected Expression parseImportOrExportAttributesAndSemicolon() {
35873588
}
35883589

35893590
protected ImportDeclaration parseImportRest(SourceLocation loc) {
3591+
ImportPhaseModifier[] phaseModifier = { ImportPhaseModifier.NONE };
35903592
List<ImportSpecifier> specifiers;
35913593
Literal source;
35923594
// import '...'
35933595
if (this.type == TokenType.string) {
35943596
specifiers = new ArrayList<ImportSpecifier>();
35953597
source = (Literal) this.parseExprAtom(null);
35963598
} else {
3597-
specifiers = this.parseImportSpecifiers();
3599+
specifiers = this.parseImportSpecifiers(phaseModifier);
35983600
this.expectContextual("from");
35993601
if (this.type != TokenType.string) this.unexpected();
36003602
source = (Literal) this.parseExprAtom(null);
36013603
}
36023604
Expression attributes = this.parseImportOrExportAttributesAndSemicolon();
36033605
if (specifiers == null) return null;
3604-
return this.finishNode(new ImportDeclaration(loc, specifiers, source, attributes));
3606+
return this.finishNode(new ImportDeclaration(loc, specifiers, source, attributes, phaseModifier[0]));
36053607
}
36063608

36073609
// Parses a comma-separated list of module imports.
3608-
protected List<ImportSpecifier> parseImportSpecifiers() {
3610+
protected List<ImportSpecifier> parseImportSpecifiers(ImportPhaseModifier[] phaseModifier) {
36093611
List<ImportSpecifier> nodes = new ArrayList<ImportSpecifier>();
36103612
boolean first = true;
36113613
if (this.type == TokenType.name) {
36123614
// import defaultObj, { x, y as z } from '...'
36133615
SourceLocation loc = new SourceLocation(this.startLoc);
36143616
Identifier local = this.parseIdent(false);
3615-
this.checkLVal(local, true, null);
3616-
nodes.add(this.finishNode(new ImportDefaultSpecifier(loc, local)));
3617-
if (!this.eat(TokenType.comma)) return nodes;
3617+
// Parse `import defer *` as the beginning of a deferred import, instead of a default import specifier
3618+
if (this.type == TokenType.star && local.getName().equals("defer")) {
3619+
phaseModifier[0] = ImportPhaseModifier.DEFER;
3620+
} else {
3621+
this.checkLVal(local, true, null);
3622+
nodes.add(this.finishNode(new ImportDefaultSpecifier(loc, local)));
3623+
if (!this.eat(TokenType.comma)) return nodes;
3624+
}
36183625
}
36193626
if (this.type == TokenType.star) {
36203627
SourceLocation loc = new SourceLocation(this.startLoc);
@@ -3647,7 +3654,7 @@ protected ImportSpecifier parseImportSpecifier() {
36473654
if (this.type == TokenType.string) {
36483655
// Arbitrary Module Namespace Identifiers
36493656
// e.g. `import { "Foo::new" as Foo_new } from "./foo.wasm"`
3650-
Expression string = this.parseExprAtom(null);
3657+
Expression string = this.parseExprAtom(null);
36513658
String str = ((Literal)string).getStringValue();
36523659
imported = this.finishNode(new Identifier(loc, str));
36533660
// only makes sense if there is a local identifier

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import com.semmle.js.ast.ExpressionStatement;
1515
import com.semmle.js.ast.FieldDefinition;
1616
import com.semmle.js.ast.Identifier;
17+
import com.semmle.js.ast.ImportPhaseModifier;
1718
import com.semmle.js.ast.ImportSpecifier;
1819
import com.semmle.js.ast.Literal;
1920
import com.semmle.js.ast.MethodDefinition;
@@ -1064,13 +1065,13 @@ private String peekAtSpecialFlowImportSpecifier() {
10641065
}
10651066

10661067
@Override
1067-
protected List<ImportSpecifier> parseImportSpecifiers() {
1068+
protected List<ImportSpecifier> parseImportSpecifiers(ImportPhaseModifier[] phaseModifier) {
10681069
String kind = null;
10691070
if (flow()) {
10701071
kind = flowParseImportSpecifiers();
10711072
}
10721073

1073-
List<ImportSpecifier> specs = super.parseImportSpecifiers();
1074+
List<ImportSpecifier> specs = super.parseImportSpecifiers(phaseModifier);
10741075
if (kind != null || specs.isEmpty()) return null;
10751076
return specs;
10761077
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import defer * as deferred from "somewhere";
2+
import * as normal from "somewhere";
3+
import defer from "somewhere";
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
| test-js.js:1:1:1:44 | import ... where"; |
12
| tst.ts:1:1:1:44 | import ... where"; |

0 commit comments

Comments
 (0)