Skip to content

Commit e678c16

Browse files
committed
JS: Parse EJS-style template tags
1 parent a7cdf53 commit e678c16

5 files changed

Lines changed: 435 additions & 3 deletions

File tree

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,15 @@ private Token readToken_lt_gt(int code) { // '<>'
618618
this.skipSpace();
619619
return this.nextToken();
620620
}
621+
if (next == '%' && code == '<' && this.options.allowGeneratedCodeExprs()) {
622+
// `<%`, the beginning of an EJS-style template tag
623+
size = 2;
624+
int nextNext = charAt(this.pos + 2);
625+
if (nextNext == '=' || nextNext == '-') {
626+
++size;
627+
}
628+
return this.finishOp(TokenType.generatedCodeDelimiterEJS, size);
629+
}
621630
if (next == 61) size = 2;
622631
return this.finishOp(TokenType.relational, size);
623632
}
@@ -1689,6 +1698,9 @@ protected Expression parseExprAtom(DestructuringErrors refDestructuringErrors) {
16891698
return this.parseNew();
16901699
} else if (this.type == TokenType.backQuote) {
16911700
return this.parseTemplate(false);
1701+
} else if (this.type == TokenType.generatedCodeDelimiterEJS) {
1702+
String openingDelimiter = (String) this.value;
1703+
return this.parseGeneratedCodeExpr(this.startLoc, openingDelimiter, "%>");
16921704
} else {
16931705
this.unexpected();
16941706
return null;

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
package com.semmle.jcorn;
22

3-
import com.semmle.jcorn.Parser.TokContext;
43
import java.util.LinkedHashMap;
54
import java.util.Map;
65

6+
import com.semmle.jcorn.Parser.TokContext;
7+
78
/// tokentype.js
89

910
// ## Token types
@@ -91,6 +92,7 @@ public void updateContext(Parser parser, TokenType prevType) {
9192
invalidTemplate = new TokenType(new Properties("invalidTemplate")),
9293
generatedCodeExpr = new TokenType(new Properties("generatedCodeExpr")),
9394
generatedCodeDelimiter = new TokenType(new Properties("generatedCodeDelimiter")),
95+
generatedCodeDelimiterEJS = new TokenType(new Properties("<%/%>")),
9496
ellipsis = new TokenType(new Properties("...").beforeExpr()),
9597
backQuote =
9698
new TokenType(new Properties("`").startsExpr()) {

javascript/extractor/src/com/semmle/jcorn/jsx/JSXParser.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -420,8 +420,9 @@ protected Token readToken(int code) {
420420
&& code == 60
421421
&& this.exprAllowed
422422
&&
423-
// avoid getting confused on HTML comments
424-
this.charAt(this.pos + 1) != '!') {
423+
// avoid getting confused on HTML comments or EJS-style template tags
424+
this.charAt(this.pos + 1) != '!' &&
425+
this.charAt(this.pos + 1) != '%') {
425426
++this.pos;
426427
return this.finishToken(jsxTagStart);
427428
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
let data1 = <%= user_data1 %>;
2+
let data2 = <%- user_data2 %>;
3+
if (<%something%>) {}
4+
foo(<%bar%>, <%baz%>);
5+
6+
<% generated_code %>
7+
let string = "<%= not_generated_code %>"; // parse as string literal

0 commit comments

Comments
 (0)