Merge branch 'main' into henrymercer/polish-diagnostics

This commit is contained in:
Arthur Baars
2023-03-14 23:42:33 +01:00
committed by GitHub
824 changed files with 32300 additions and 2361 deletions

View File

@@ -224,6 +224,7 @@ const astProperties: string[] = [
"argument",
"argumentExpression",
"arguments",
"assertClause",
"assertsModifier",
"asteriskToken",
"attributes",

View File

@@ -314,7 +314,8 @@ public class ESNextParser extends JSXParser {
this.parseExportSpecifiersMaybe(specifiers, exports);
}
Literal source = (Literal) this.parseExportFrom(specifiers, null, true);
return this.finishNode(new ExportNamedDeclaration(exportStart, null, specifiers, source));
Expression assertion = this.parseImportOrExportAssertionAndSemicolon();
return this.finishNode(new ExportNamedDeclaration(exportStart, null, specifiers, source, assertion));
}
return super.parseExportRest(exportStart, exports);
@@ -330,7 +331,8 @@ public class ESNextParser extends JSXParser {
List<ExportSpecifier> specifiers = CollectionUtil.makeList(nsSpec);
this.parseExportSpecifiersMaybe(specifiers, exports);
Literal source = (Literal) this.parseExportFrom(specifiers, null, true);
return this.finishNode(new ExportNamedDeclaration(exportStart, null, specifiers, source));
Expression assertion = this.parseImportOrExportAssertionAndSemicolon();
return this.finishNode(new ExportNamedDeclaration(exportStart, null, specifiers, source, assertion));
}
return super.parseExportAll(exportStart, starLoc, exports);
@@ -435,8 +437,15 @@ public class ESNextParser extends JSXParser {
*/
private DynamicImport parseDynamicImport(Position startLoc) {
Expression source = parseMaybeAssign(false, null, null);
Expression attributes = null;
if (this.eat(TokenType.comma)) {
if (this.type != TokenType.parenR) { // Skip if the comma was a trailing comma
attributes = this.parseMaybeAssign(false, null, null);
this.eat(TokenType.comma); // Allow trailing comma
}
}
this.expect(TokenType.parenR);
DynamicImport di = this.finishNode(new DynamicImport(new SourceLocation(startLoc), source));
DynamicImport di = this.finishNode(new DynamicImport(new SourceLocation(startLoc), source, attributes));
return di;
}

View File

@@ -1648,13 +1648,13 @@ public class Parser {
return this.finishNode(node);
} else if (this.type == TokenType.pound) {
Position startLoc = this.startLoc;
// there is only one case where this is valid, and that is "Ergonomic brand checks for Private Fields", i.e. `#name in obj`.
// there is only one case where this is valid, and that is "Ergonomic brand checks for Private Fields", i.e. `#name in obj`.
Identifier id = parseIdent(true);
String op = String.valueOf(this.value);
if (!op.equals("in")) {
this.unexpected(startLoc);
}
return this.parseExprOp(id, this.start, startLoc, -1, false);
return this.parseExprOp(id, this.start, startLoc, -1, false);
} else if (this.type == TokenType.name) {
Position startLoc = this.startLoc;
Identifier id = this.parseIdent(this.type != TokenType.name);
@@ -2783,7 +2783,7 @@ public class Parser {
boolean isBreak = keyword.equals("break");
this.next();
Identifier label = null;
if (this.eat(TokenType.semi) || this.insertSemicolon()) {
if (this.eagerlyTrySemicolon()) {
label = null;
} else if (this.type != TokenType.name) {
this.unexpected();
@@ -2893,6 +2893,15 @@ public class Parser {
new IfStatement(new SourceLocation(startLoc), test, consequent, alternate));
}
/**
* Consumes or inserts a semicolon if possible, and returns true if a semicolon was consumed or inserted.
*
* Returns false if there was no semicolon and insertion was not possible.
*/
protected boolean eagerlyTrySemicolon() {
return this.eat(TokenType.semi) || this.insertSemicolon();
}
protected ReturnStatement parseReturnStatement(Position startLoc) {
if (!this.inFunction && !this.options.allowReturnOutsideFunction())
this.raise(this.start, "'return' outside of function");
@@ -2902,7 +2911,7 @@ public class Parser {
// optional arguments, we eagerly look for a semicolon or the
// possibility to insert one.
Expression argument;
if (this.eat(TokenType.semi) || this.insertSemicolon()) {
if (this.eagerlyTrySemicolon()) {
argument = null;
} else {
argument = this.parseExpression(false, null);
@@ -3404,6 +3413,7 @@ public class Parser {
Statement declaration;
List<ExportSpecifier> specifiers;
Expression source = null;
Expression assertion = null;
if (this.shouldParseExportStatement()) {
declaration = this.parseStatement(true, false);
if (declaration == null) return null;
@@ -3419,11 +3429,13 @@ public class Parser {
declaration = null;
specifiers = this.parseExportSpecifiers(exports);
source = parseExportFrom(specifiers, source, false);
assertion = parseImportOrExportAssertionAndSemicolon();
}
return this.finishNode(
new ExportNamedDeclaration(loc, declaration, specifiers, (Literal) source));
new ExportNamedDeclaration(loc, declaration, specifiers, (Literal) source, assertion));
}
/** Parses the 'from' clause of an export, not including the assertion or semicolon. */
protected Expression parseExportFrom(
List<ExportSpecifier> specifiers, Expression source, boolean expectFrom) {
if (this.eatContextual("from")) {
@@ -3442,14 +3454,14 @@ public class Parser {
source = null;
}
this.semicolon();
return source;
}
protected ExportDeclaration parseExportAll(
SourceLocation loc, Position starLoc, Set<String> exports) {
Expression source = parseExportFrom(null, null, true);
return this.finishNode(new ExportAllDeclaration(loc, (Literal) source));
Expression assertion = parseImportOrExportAssertionAndSemicolon();
return this.finishNode(new ExportAllDeclaration(loc, (Literal) source, assertion));
}
private void checkExport(Set<String> exports, String name, Position pos) {
@@ -3514,6 +3526,16 @@ public class Parser {
return parseImportRest(loc);
}
protected Expression parseImportOrExportAssertionAndSemicolon() {
Expression result = null;
if (!this.eagerlyTrySemicolon()) {
this.expectContextual("assert");
result = this.parseObj(false, null);
this.semicolon();
}
return result;
}
protected ImportDeclaration parseImportRest(SourceLocation loc) {
List<ImportSpecifier> specifiers;
Literal source;
@@ -3527,9 +3549,9 @@ public class Parser {
if (this.type != TokenType.string) this.unexpected();
source = (Literal) this.parseExprAtom(null);
}
this.semicolon();
Expression assertion = this.parseImportOrExportAssertionAndSemicolon();
if (specifiers == null) return null;
return this.finishNode(new ImportDeclaration(loc, specifiers, source));
return this.finishNode(new ImportDeclaration(loc, specifiers, source, assertion));
}
// Parses a comma-separated list of module imports.

View File

@@ -943,10 +943,12 @@ public class FlowParser extends ESNextParser {
// `export type { foo, bar };`
List<ExportSpecifier> specifiers = this.parseExportSpecifiers(exports);
this.parseExportFrom(specifiers, null, false);
this.parseImportOrExportAssertionAndSemicolon();
return null;
} else if (this.eat(TokenType.star)) {
if (this.eatContextual("as")) this.parseIdent(true);
this.parseExportFrom(null, null, true);
this.parseImportOrExportAssertionAndSemicolon();
return null;
} else {
// `export type Foo = Bar;`

View File

@@ -2,16 +2,23 @@ package com.semmle.js.ast;
public class DynamicImport extends Expression {
private final Expression source;
private final Expression attributes;
public DynamicImport(SourceLocation loc, Expression source) {
public DynamicImport(SourceLocation loc, Expression source, Expression attributes) {
super("DynamicImport", loc);
this.source = source;
this.attributes = attributes;
}
public Expression getSource() {
return source;
}
/** Returns the second "argument" provided to the import, such as <code>{ assert: { type: "json" }}</code>. */
public Expression getAttributes() {
return attributes;
}
@Override
public <C, R> R accept(Visitor<C, R> v, C c) {
return v.visit(this, c);

View File

@@ -9,16 +9,22 @@ package com.semmle.js.ast;
*/
public class ExportAllDeclaration extends ExportDeclaration {
private final Literal source;
private final Expression assertion;
public ExportAllDeclaration(SourceLocation loc, Literal source) {
public ExportAllDeclaration(SourceLocation loc, Literal source, Expression assertion) {
super("ExportAllDeclaration", loc);
this.source = source;
this.assertion = assertion;
}
public Literal getSource() {
return source;
}
public Expression getAssertion() {
return assertion;
}
@Override
public <C, R> R accept(Visitor<C, R> v, C c) {
return v.visit(this, c);

View File

@@ -15,20 +15,22 @@ public class ExportNamedDeclaration extends ExportDeclaration {
private final Statement declaration;
private final List<ExportSpecifier> specifiers;
private final Literal source;
private final Expression assertion;
private final boolean hasTypeKeyword;
public ExportNamedDeclaration(
SourceLocation loc, Statement declaration, List<ExportSpecifier> specifiers, Literal source) {
this(loc, declaration, specifiers, source, false);
SourceLocation loc, Statement declaration, List<ExportSpecifier> specifiers, Literal source, Expression assertion) {
this(loc, declaration, specifiers, source, assertion, false);
}
public ExportNamedDeclaration(
SourceLocation loc, Statement declaration, List<ExportSpecifier> specifiers, Literal source,
boolean hasTypeKeyword) {
Expression assertion, boolean hasTypeKeyword) {
super("ExportNamedDeclaration", loc);
this.declaration = declaration;
this.specifiers = specifiers;
this.source = source;
this.assertion = assertion;
this.hasTypeKeyword = hasTypeKeyword;
}
@@ -57,6 +59,11 @@ public class ExportNamedDeclaration extends ExportDeclaration {
return v.visit(this, c);
}
/** Returns the expression after the <code>assert</code> keyword, if any, such as <code>{ type: "json" }</code>. */
public Expression getAssertion() {
return assertion;
}
/** Returns true if this is an <code>export type</code> declaration. */
public boolean hasTypeKeyword() {
return hasTypeKeyword;

View File

@@ -23,18 +23,21 @@ public class ImportDeclaration extends Statement implements INodeWithSymbol {
/** The module from which declarations are imported. */
private final Literal source;
private final Expression assertion;
private int symbol = -1;
private boolean hasTypeKeyword;
public ImportDeclaration(SourceLocation loc, List<ImportSpecifier> specifiers, Literal source) {
this(loc, specifiers, source, false);
public ImportDeclaration(SourceLocation loc, List<ImportSpecifier> specifiers, Literal source, Expression assertion) {
this(loc, specifiers, source, assertion, false);
}
public ImportDeclaration(SourceLocation loc, List<ImportSpecifier> specifiers, Literal source, boolean hasTypeKeyword) {
public ImportDeclaration(SourceLocation loc, List<ImportSpecifier> specifiers, Literal source, Expression assertion, boolean hasTypeKeyword) {
super("ImportDeclaration", loc);
this.specifiers = specifiers;
this.source = source;
this.assertion = assertion;
this.hasTypeKeyword = hasTypeKeyword;
}
@@ -46,6 +49,11 @@ public class ImportDeclaration extends Statement implements INodeWithSymbol {
return specifiers;
}
/** Returns the expression after the <code>assert</code> keyword, if any, such as <code>{ type: "json" }</code>. */
public Expression getAssertion() {
return assertion;
}
@Override
public <C, R> R accept(Visitor<C, R> v, C c) {
return v.visit(this, c);

View File

@@ -523,7 +523,7 @@ public class NodeCopier implements Visitor<Void, INode> {
@Override
public ExportAllDeclaration visit(ExportAllDeclaration nd, Void c) {
return new ExportAllDeclaration(visit(nd.getLoc()), copy(nd.getSource()));
return new ExportAllDeclaration(visit(nd.getLoc()), copy(nd.getSource()), copy(nd.getAssertion()));
}
@Override
@@ -537,7 +537,8 @@ public class NodeCopier implements Visitor<Void, INode> {
visit(nd.getLoc()),
copy(nd.getDeclaration()),
copy(nd.getSpecifiers()),
copy(nd.getSource()));
copy(nd.getSource()),
copy(nd.getAssertion()));
}
@Override
@@ -558,7 +559,7 @@ public class NodeCopier implements Visitor<Void, INode> {
@Override
public ImportDeclaration visit(ImportDeclaration nd, Void c) {
return new ImportDeclaration(
visit(nd.getLoc()), copy(nd.getSpecifiers()), copy(nd.getSource()));
visit(nd.getLoc()), copy(nd.getSpecifiers()), copy(nd.getSource()), copy(nd.getAssertion()), nd.hasTypeKeyword());
}
@Override
@@ -678,7 +679,7 @@ public class NodeCopier implements Visitor<Void, INode> {
@Override
public INode visit(DynamicImport nd, Void c) {
return new DynamicImport(visit(nd.getLoc()), copy(nd.getSource()));
return new DynamicImport(visit(nd.getLoc()), copy(nd.getSource()), copy(nd.getAttributes()));
}
@Override

View File

@@ -1759,6 +1759,7 @@ public class ASTExtractor {
public Label visit(ExportAllDeclaration nd, Context c) {
Label lbl = super.visit(nd, c);
visit(nd.getSource(), lbl, 0);
visit(nd.getAssertion(), lbl, -10);
return lbl;
}
@@ -1774,6 +1775,7 @@ public class ASTExtractor {
Label lbl = super.visit(nd, c);
visit(nd.getDeclaration(), lbl, -1);
visit(nd.getSource(), lbl, -2);
visit(nd.getAssertion(), lbl, -10);
IdContext childContext =
nd.hasSource()
? IdContext.LABEL
@@ -1797,6 +1799,7 @@ public class ASTExtractor {
public Label visit(ImportDeclaration nd, Context c) {
Label lbl = super.visit(nd, c);
visit(nd.getSource(), lbl, -1);
visit(nd.getAssertion(), lbl, -10);
IdContext childContext =
nd.hasTypeKeyword()
? IdContext.TYPE_ONLY_IMPORT
@@ -1972,6 +1975,7 @@ public class ASTExtractor {
public Label visit(DynamicImport nd, Context c) {
Label key = super.visit(nd, c);
visit(nd.getSource(), key, 0);
visit(nd.getAttributes(), key, 1);
return key;
}

View File

@@ -177,6 +177,7 @@ public class TypeScriptASTConverter {
private static final Pattern EXPORT_DECL_START =
Pattern.compile("^export" + "(" + WHITESPACE_CHAR + "+default)?" + WHITESPACE_CHAR + "+");
private static final Pattern TYPEOF_START = Pattern.compile("^typeof" + WHITESPACE_CHAR + "+");
private static final Pattern ASSERT_START = Pattern.compile("^assert" + WHITESPACE_CHAR + "+");
private static final Pattern WHITESPACE_END_PAREN =
Pattern.compile("^" + WHITESPACE_CHAR + "*\\)");
@@ -342,7 +343,11 @@ public class TypeScriptASTConverter {
return convertArrowFunction(node, loc);
case "AsExpression":
return convertTypeAssertionExpression(node, loc);
case "SatisfiesExpression":
case "AssertClause":
return convertAssertClause(node, loc);
case "AssertEntry":
return convertAssertEntry(node, loc);
case "SatisfiesExpression":
return convertSatisfiesExpression(node, loc);
case "AwaitExpression":
return convertAwaitExpression(node, loc);
@@ -887,8 +892,8 @@ public class TypeScriptASTConverter {
private Node convertCallExpression(JsonObject node, SourceLocation loc) throws ParseError {
List<Expression> arguments = convertChildren(node, "arguments");
if (arguments.size() == 1 && hasKind(node.get("expression"), "ImportKeyword")) {
return new DynamicImport(loc, arguments.get(0));
if (arguments.size() >= 1 && hasKind(node.get("expression"), "ImportKeyword")) {
return new DynamicImport(loc, arguments.get(0), arguments.size() > 1 ? arguments.get(1) : null);
}
Expression callee = convertChild(node, "expression");
List<ITypeExpression> typeArguments = convertChildrenAsTypes(node, "typeArguments");
@@ -1193,15 +1198,16 @@ public class TypeScriptASTConverter {
private Node convertExportDeclaration(JsonObject node, SourceLocation loc) throws ParseError {
Literal source = tryConvertChild(node, "moduleSpecifier", Literal.class);
Expression assertion = convertChild(node, "assertClause");
if (hasChild(node, "exportClause")) {
boolean hasTypeKeyword = node.get("isTypeOnly").getAsBoolean();
List<ExportSpecifier> specifiers =
hasKind(node.get("exportClause"), "NamespaceExport")
? Collections.singletonList(convertChild(node, "exportClause"))
: convertChildren(node.get("exportClause").getAsJsonObject(), "elements");
return new ExportNamedDeclaration(loc, null, specifiers, source, hasTypeKeyword);
return new ExportNamedDeclaration(loc, null, specifiers, source, assertion, hasTypeKeyword);
} else {
return new ExportAllDeclaration(loc, source);
return new ExportAllDeclaration(loc, source, assertion);
}
}
@@ -1383,6 +1389,7 @@ public class TypeScriptASTConverter {
private Node convertImportDeclaration(JsonObject node, SourceLocation loc) throws ParseError {
Literal src = tryConvertChild(node, "moduleSpecifier", Literal.class);
Expression assertion = convertChild(node, "assertClause");
List<ImportSpecifier> specifiers = new ArrayList<>();
boolean hasTypeKeyword = false;
if (hasChild(node, "importClause")) {
@@ -1400,7 +1407,7 @@ public class TypeScriptASTConverter {
}
hasTypeKeyword = importClause.get("isTypeOnly").getAsBoolean();
}
ImportDeclaration importDecl = new ImportDeclaration(loc, specifiers, src, hasTypeKeyword);
ImportDeclaration importDecl = new ImportDeclaration(loc, specifiers, src, assertion, hasTypeKeyword);
attachSymbolInformation(importDecl, node);
return importDecl;
}
@@ -1746,7 +1753,7 @@ public class TypeScriptASTConverter {
if (hasFlag(node, "NestedNamespace")) {
// In a nested namespace declaration `namespace A.B`, the nested namespace `B`
// is implicitly exported.
return new ExportNamedDeclaration(loc, decl, new ArrayList<>(), null);
return new ExportNamedDeclaration(loc, decl, new ArrayList<>(), null, null);
} else {
return fixExports(loc, decl);
}
@@ -2276,6 +2283,29 @@ public class TypeScriptASTConverter {
return new TypeAssertion(loc, convertChild(node, "expression"), type, false);
}
private Node convertAssertClause(JsonObject node, SourceLocation loc) throws ParseError {
List<Property> properties = new ArrayList<>();
for (INode child : convertChildren(node, "elements")) {
properties.add((Property)child);
}
// Adjust location to skip over the `assert` keyword.
Matcher m = ASSERT_START.matcher(loc.getSource());
if (m.find()) {
advance(loc, m.group(0));
}
return new ObjectExpression(loc, properties);
}
private Node convertAssertEntry(JsonObject node, SourceLocation loc) throws ParseError {
return new Property(
loc,
convertChild(node, "key"),
convertChild(node, "value"),
"init",
false,
false);
}
private Node convertSatisfiesExpression(JsonObject node, SourceLocation loc) throws ParseError {
ITypeExpression type = convertChildAsType(node, "type");
return new SatisfiesExpr(loc, convertChild(node, "expression"), type);
@@ -2455,7 +2485,7 @@ public class TypeScriptASTConverter {
advance(loc, skipped);
// capture group 1 is `default`, if present
if (m.group(1) == null)
return new ExportNamedDeclaration(outerLoc, (Statement) decl, new ArrayList<>(), null);
return new ExportNamedDeclaration(outerLoc, (Statement) decl, new ArrayList<>(), null, null);
return new ExportDefaultDeclaration(outerLoc, decl);
}
return decl;

View File

@@ -1,3 +1,6 @@
import("m");
b ? import("n") : {};
import("o").then((o) => {});
import("m",);
import("m",{},);

View File

@@ -0,0 +1,13 @@
import "module" assert { type: "json" };
import * as v1 from "module" assert { type: "json" };
import { v2 } from "module" assert { type: "json" };
import v3 from "module" assert { type: "json" };
export { v4 } from "module" assert { type: "json" };
export * from "module" assert { type: "json" };
export * as v5 from "module" assert { type: "json" };
const v6 = import("module", { assert: { type: "json" } });
import "module" // missing semicolon
assert({type: "json"}); // function call, not import assertion

View File

@@ -27,355 +27,507 @@ lines(#20006,#20001,"import(""o"").then((o) => {});","
#20007=@"loc,{#10000},3,1,3,28"
locations_default(#20007,#10000,3,1,3,28)
hasLocation(#20006,#20007)
numlines(#20001,3,3,0)
#20008=*
tokeninfo(#20008,7,#20001,0,"import")
#20009=@"loc,{#10000},1,1,1,6"
locations_default(#20009,#10000,1,1,1,6)
lines(#20008,#20001,"","
")
#20009=@"loc,{#10000},4,1,4,0"
locations_default(#20009,#10000,4,1,4,0)
hasLocation(#20008,#20009)
#20010=*
tokeninfo(#20010,8,#20001,1,"(")
#20011=@"loc,{#10000},1,7,1,7"
locations_default(#20011,#10000,1,7,1,7)
lines(#20010,#20001,"import(""m"",);","
")
#20011=@"loc,{#10000},5,1,5,13"
locations_default(#20011,#10000,5,1,5,13)
hasLocation(#20010,#20011)
#20012=*
tokeninfo(#20012,4,#20001,2,"""m""")
#20013=@"loc,{#10000},1,8,1,10"
locations_default(#20013,#10000,1,8,1,10)
lines(#20012,#20001,"import(""m"",{},);","
")
#20013=@"loc,{#10000},6,1,6,16"
locations_default(#20013,#10000,6,1,6,16)
hasLocation(#20012,#20013)
numlines(#20001,6,5,0)
#20014=*
tokeninfo(#20014,8,#20001,3,")")
#20015=@"loc,{#10000},1,11,1,11"
locations_default(#20015,#10000,1,11,1,11)
tokeninfo(#20014,7,#20001,0,"import")
#20015=@"loc,{#10000},1,1,1,6"
locations_default(#20015,#10000,1,1,1,6)
hasLocation(#20014,#20015)
#20016=*
tokeninfo(#20016,8,#20001,4,";")
#20017=@"loc,{#10000},1,12,1,12"
locations_default(#20017,#10000,1,12,1,12)
tokeninfo(#20016,8,#20001,1,"(")
#20017=@"loc,{#10000},1,7,1,7"
locations_default(#20017,#10000,1,7,1,7)
hasLocation(#20016,#20017)
#20018=*
tokeninfo(#20018,6,#20001,5,"b")
#20019=@"loc,{#10000},2,1,2,1"
locations_default(#20019,#10000,2,1,2,1)
tokeninfo(#20018,4,#20001,2,"""m""")
#20019=@"loc,{#10000},1,8,1,10"
locations_default(#20019,#10000,1,8,1,10)
hasLocation(#20018,#20019)
#20020=*
tokeninfo(#20020,8,#20001,6,"?")
#20021=@"loc,{#10000},2,3,2,3"
locations_default(#20021,#10000,2,3,2,3)
tokeninfo(#20020,8,#20001,3,")")
#20021=@"loc,{#10000},1,11,1,11"
locations_default(#20021,#10000,1,11,1,11)
hasLocation(#20020,#20021)
#20022=*
tokeninfo(#20022,7,#20001,7,"import")
#20023=@"loc,{#10000},2,5,2,10"
locations_default(#20023,#10000,2,5,2,10)
tokeninfo(#20022,8,#20001,4,";")
#20023=@"loc,{#10000},1,12,1,12"
locations_default(#20023,#10000,1,12,1,12)
hasLocation(#20022,#20023)
#20024=*
tokeninfo(#20024,8,#20001,8,"(")
#20025=@"loc,{#10000},2,11,2,11"
locations_default(#20025,#10000,2,11,2,11)
tokeninfo(#20024,6,#20001,5,"b")
#20025=@"loc,{#10000},2,1,2,1"
locations_default(#20025,#10000,2,1,2,1)
hasLocation(#20024,#20025)
#20026=*
tokeninfo(#20026,4,#20001,9,"""n""")
#20027=@"loc,{#10000},2,12,2,14"
locations_default(#20027,#10000,2,12,2,14)
tokeninfo(#20026,8,#20001,6,"?")
#20027=@"loc,{#10000},2,3,2,3"
locations_default(#20027,#10000,2,3,2,3)
hasLocation(#20026,#20027)
#20028=*
tokeninfo(#20028,8,#20001,10,")")
#20029=@"loc,{#10000},2,15,2,15"
locations_default(#20029,#10000,2,15,2,15)
tokeninfo(#20028,7,#20001,7,"import")
#20029=@"loc,{#10000},2,5,2,10"
locations_default(#20029,#10000,2,5,2,10)
hasLocation(#20028,#20029)
#20030=*
tokeninfo(#20030,8,#20001,11,":")
#20031=@"loc,{#10000},2,17,2,17"
locations_default(#20031,#10000,2,17,2,17)
tokeninfo(#20030,8,#20001,8,"(")
#20031=@"loc,{#10000},2,11,2,11"
locations_default(#20031,#10000,2,11,2,11)
hasLocation(#20030,#20031)
#20032=*
tokeninfo(#20032,8,#20001,12,"{")
#20033=@"loc,{#10000},2,19,2,19"
locations_default(#20033,#10000,2,19,2,19)
tokeninfo(#20032,4,#20001,9,"""n""")
#20033=@"loc,{#10000},2,12,2,14"
locations_default(#20033,#10000,2,12,2,14)
hasLocation(#20032,#20033)
#20034=*
tokeninfo(#20034,8,#20001,13,"}")
#20035=@"loc,{#10000},2,20,2,20"
locations_default(#20035,#10000,2,20,2,20)
tokeninfo(#20034,8,#20001,10,")")
#20035=@"loc,{#10000},2,15,2,15"
locations_default(#20035,#10000,2,15,2,15)
hasLocation(#20034,#20035)
#20036=*
tokeninfo(#20036,8,#20001,14,";")
#20037=@"loc,{#10000},2,21,2,21"
locations_default(#20037,#10000,2,21,2,21)
tokeninfo(#20036,8,#20001,11,":")
#20037=@"loc,{#10000},2,17,2,17"
locations_default(#20037,#10000,2,17,2,17)
hasLocation(#20036,#20037)
#20038=*
tokeninfo(#20038,7,#20001,15,"import")
#20039=@"loc,{#10000},3,1,3,6"
locations_default(#20039,#10000,3,1,3,6)
tokeninfo(#20038,8,#20001,12,"{")
#20039=@"loc,{#10000},2,19,2,19"
locations_default(#20039,#10000,2,19,2,19)
hasLocation(#20038,#20039)
#20040=*
tokeninfo(#20040,8,#20001,16,"(")
#20041=@"loc,{#10000},3,7,3,7"
locations_default(#20041,#10000,3,7,3,7)
tokeninfo(#20040,8,#20001,13,"}")
#20041=@"loc,{#10000},2,20,2,20"
locations_default(#20041,#10000,2,20,2,20)
hasLocation(#20040,#20041)
#20042=*
tokeninfo(#20042,4,#20001,17,"""o""")
#20043=@"loc,{#10000},3,8,3,10"
locations_default(#20043,#10000,3,8,3,10)
tokeninfo(#20042,8,#20001,14,";")
#20043=@"loc,{#10000},2,21,2,21"
locations_default(#20043,#10000,2,21,2,21)
hasLocation(#20042,#20043)
#20044=*
tokeninfo(#20044,8,#20001,18,")")
#20045=@"loc,{#10000},3,11,3,11"
locations_default(#20045,#10000,3,11,3,11)
tokeninfo(#20044,7,#20001,15,"import")
#20045=@"loc,{#10000},3,1,3,6"
locations_default(#20045,#10000,3,1,3,6)
hasLocation(#20044,#20045)
#20046=*
tokeninfo(#20046,8,#20001,19,".")
#20047=@"loc,{#10000},3,12,3,12"
locations_default(#20047,#10000,3,12,3,12)
tokeninfo(#20046,8,#20001,16,"(")
#20047=@"loc,{#10000},3,7,3,7"
locations_default(#20047,#10000,3,7,3,7)
hasLocation(#20046,#20047)
#20048=*
tokeninfo(#20048,6,#20001,20,"then")
#20049=@"loc,{#10000},3,13,3,16"
locations_default(#20049,#10000,3,13,3,16)
tokeninfo(#20048,4,#20001,17,"""o""")
#20049=@"loc,{#10000},3,8,3,10"
locations_default(#20049,#10000,3,8,3,10)
hasLocation(#20048,#20049)
#20050=*
tokeninfo(#20050,8,#20001,21,"(")
#20051=@"loc,{#10000},3,17,3,17"
locations_default(#20051,#10000,3,17,3,17)
tokeninfo(#20050,8,#20001,18,")")
#20051=@"loc,{#10000},3,11,3,11"
locations_default(#20051,#10000,3,11,3,11)
hasLocation(#20050,#20051)
#20052=*
tokeninfo(#20052,8,#20001,22,"(")
#20053=@"loc,{#10000},3,18,3,18"
locations_default(#20053,#10000,3,18,3,18)
tokeninfo(#20052,8,#20001,19,".")
#20053=@"loc,{#10000},3,12,3,12"
locations_default(#20053,#10000,3,12,3,12)
hasLocation(#20052,#20053)
#20054=*
tokeninfo(#20054,6,#20001,23,"o")
#20055=@"loc,{#10000},3,19,3,19"
locations_default(#20055,#10000,3,19,3,19)
tokeninfo(#20054,6,#20001,20,"then")
#20055=@"loc,{#10000},3,13,3,16"
locations_default(#20055,#10000,3,13,3,16)
hasLocation(#20054,#20055)
#20056=*
tokeninfo(#20056,8,#20001,24,")")
#20057=@"loc,{#10000},3,20,3,20"
locations_default(#20057,#10000,3,20,3,20)
tokeninfo(#20056,8,#20001,21,"(")
#20057=@"loc,{#10000},3,17,3,17"
locations_default(#20057,#10000,3,17,3,17)
hasLocation(#20056,#20057)
#20058=*
tokeninfo(#20058,8,#20001,25,"=>")
#20059=@"loc,{#10000},3,22,3,23"
locations_default(#20059,#10000,3,22,3,23)
tokeninfo(#20058,8,#20001,22,"(")
#20059=@"loc,{#10000},3,18,3,18"
locations_default(#20059,#10000,3,18,3,18)
hasLocation(#20058,#20059)
#20060=*
tokeninfo(#20060,8,#20001,26,"{")
#20061=@"loc,{#10000},3,25,3,25"
locations_default(#20061,#10000,3,25,3,25)
tokeninfo(#20060,6,#20001,23,"o")
#20061=@"loc,{#10000},3,19,3,19"
locations_default(#20061,#10000,3,19,3,19)
hasLocation(#20060,#20061)
#20062=*
tokeninfo(#20062,8,#20001,27,"}")
#20063=@"loc,{#10000},3,26,3,26"
locations_default(#20063,#10000,3,26,3,26)
tokeninfo(#20062,8,#20001,24,")")
#20063=@"loc,{#10000},3,20,3,20"
locations_default(#20063,#10000,3,20,3,20)
hasLocation(#20062,#20063)
#20064=*
tokeninfo(#20064,8,#20001,28,")")
#20065=@"loc,{#10000},3,27,3,27"
locations_default(#20065,#10000,3,27,3,27)
tokeninfo(#20064,8,#20001,25,"=>")
#20065=@"loc,{#10000},3,22,3,23"
locations_default(#20065,#10000,3,22,3,23)
hasLocation(#20064,#20065)
#20066=*
tokeninfo(#20066,8,#20001,29,";")
#20067=@"loc,{#10000},3,28,3,28"
locations_default(#20067,#10000,3,28,3,28)
tokeninfo(#20066,8,#20001,26,"{")
#20067=@"loc,{#10000},3,25,3,25"
locations_default(#20067,#10000,3,25,3,25)
hasLocation(#20066,#20067)
#20068=*
tokeninfo(#20068,0,#20001,30,"")
#20069=@"loc,{#10000},4,1,4,0"
locations_default(#20069,#10000,4,1,4,0)
tokeninfo(#20068,8,#20001,27,"}")
#20069=@"loc,{#10000},3,26,3,26"
locations_default(#20069,#10000,3,26,3,26)
hasLocation(#20068,#20069)
#20070=*
tokeninfo(#20070,8,#20001,28,")")
#20071=@"loc,{#10000},3,27,3,27"
locations_default(#20071,#10000,3,27,3,27)
hasLocation(#20070,#20071)
#20072=*
tokeninfo(#20072,8,#20001,29,";")
#20073=@"loc,{#10000},3,28,3,28"
locations_default(#20073,#10000,3,28,3,28)
hasLocation(#20072,#20073)
#20074=*
tokeninfo(#20074,7,#20001,30,"import")
#20075=@"loc,{#10000},5,1,5,6"
locations_default(#20075,#10000,5,1,5,6)
hasLocation(#20074,#20075)
#20076=*
tokeninfo(#20076,8,#20001,31,"(")
#20077=@"loc,{#10000},5,7,5,7"
locations_default(#20077,#10000,5,7,5,7)
hasLocation(#20076,#20077)
#20078=*
tokeninfo(#20078,4,#20001,32,"""m""")
#20079=@"loc,{#10000},5,8,5,10"
locations_default(#20079,#10000,5,8,5,10)
hasLocation(#20078,#20079)
#20080=*
tokeninfo(#20080,8,#20001,33,",")
#20081=@"loc,{#10000},5,11,5,11"
locations_default(#20081,#10000,5,11,5,11)
hasLocation(#20080,#20081)
#20082=*
tokeninfo(#20082,8,#20001,34,")")
#20083=@"loc,{#10000},5,12,5,12"
locations_default(#20083,#10000,5,12,5,12)
hasLocation(#20082,#20083)
#20084=*
tokeninfo(#20084,8,#20001,35,";")
#20085=@"loc,{#10000},5,13,5,13"
locations_default(#20085,#10000,5,13,5,13)
hasLocation(#20084,#20085)
#20086=*
tokeninfo(#20086,7,#20001,36,"import")
#20087=@"loc,{#10000},6,1,6,6"
locations_default(#20087,#10000,6,1,6,6)
hasLocation(#20086,#20087)
#20088=*
tokeninfo(#20088,8,#20001,37,"(")
#20089=@"loc,{#10000},6,7,6,7"
locations_default(#20089,#10000,6,7,6,7)
hasLocation(#20088,#20089)
#20090=*
tokeninfo(#20090,4,#20001,38,"""m""")
#20091=@"loc,{#10000},6,8,6,10"
locations_default(#20091,#10000,6,8,6,10)
hasLocation(#20090,#20091)
#20092=*
tokeninfo(#20092,8,#20001,39,",")
#20093=@"loc,{#10000},6,11,6,11"
locations_default(#20093,#10000,6,11,6,11)
hasLocation(#20092,#20093)
#20094=*
tokeninfo(#20094,8,#20001,40,"{")
#20095=@"loc,{#10000},6,12,6,12"
locations_default(#20095,#10000,6,12,6,12)
hasLocation(#20094,#20095)
#20096=*
tokeninfo(#20096,8,#20001,41,"}")
#20097=@"loc,{#10000},6,13,6,13"
locations_default(#20097,#10000,6,13,6,13)
hasLocation(#20096,#20097)
#20098=*
tokeninfo(#20098,8,#20001,42,",")
#20099=@"loc,{#10000},6,14,6,14"
locations_default(#20099,#10000,6,14,6,14)
hasLocation(#20098,#20099)
#20100=*
tokeninfo(#20100,8,#20001,43,")")
#20101=@"loc,{#10000},6,15,6,15"
locations_default(#20101,#10000,6,15,6,15)
hasLocation(#20100,#20101)
#20102=*
tokeninfo(#20102,8,#20001,44,";")
#20103=@"loc,{#10000},6,16,6,16"
locations_default(#20103,#10000,6,16,6,16)
hasLocation(#20102,#20103)
#20104=*
tokeninfo(#20104,0,#20001,45,"")
#20105=@"loc,{#10000},7,1,7,0"
locations_default(#20105,#10000,7,1,7,0)
hasLocation(#20104,#20105)
toplevels(#20001,0)
#20070=@"loc,{#10000},1,1,4,0"
locations_default(#20070,#10000,1,1,4,0)
hasLocation(#20001,#20070)
#20071=@"module;{#10000},1,1"
scopes(#20071,3)
scopenodes(#20001,#20071)
scopenesting(#20071,#20000)
#20106=@"loc,{#10000},1,1,7,0"
locations_default(#20106,#10000,1,1,7,0)
hasLocation(#20001,#20106)
#20107=@"module;{#10000},1,1"
scopes(#20107,3)
scopenodes(#20001,#20107)
scopenesting(#20107,#20000)
is_module(#20001)
is_es2015_module(#20001)
#20072=*
stmts(#20072,2,#20001,0,"import(""m"");")
hasLocation(#20072,#20003)
stmt_containers(#20072,#20001)
#20073=*
exprs(#20073,99,#20072,0,"import(""m"")")
#20074=@"loc,{#10000},1,1,1,11"
locations_default(#20074,#10000,1,1,1,11)
hasLocation(#20073,#20074)
enclosing_stmt(#20073,#20072)
expr_containers(#20073,#20001)
#20075=*
exprs(#20075,4,#20073,0,"""m""")
hasLocation(#20075,#20013)
enclosing_stmt(#20075,#20072)
expr_containers(#20075,#20001)
literals("m","""m""",#20075)
#20076=*
regexpterm(#20076,14,#20075,0,"m")
#20077=@"loc,{#10000},1,9,1,9"
locations_default(#20077,#10000,1,9,1,9)
hasLocation(#20076,#20077)
regexp_const_value(#20076,"m")
#20078=*
stmts(#20078,2,#20001,1,"b ? imp ... ) : {};")
hasLocation(#20078,#20005)
stmt_containers(#20078,#20001)
#20079=*
exprs(#20079,11,#20078,0,"b ? import(""n"") : {}")
#20080=@"loc,{#10000},2,1,2,20"
locations_default(#20080,#10000,2,1,2,20)
hasLocation(#20079,#20080)
enclosing_stmt(#20079,#20078)
expr_containers(#20079,#20001)
#20081=*
exprs(#20081,79,#20079,0,"b")
hasLocation(#20081,#20019)
enclosing_stmt(#20081,#20078)
expr_containers(#20081,#20001)
literals("b","b",#20081)
#20082=@"var;{b};{#20000}"
variables(#20082,"b",#20000)
bind(#20081,#20082)
#20083=*
exprs(#20083,99,#20079,1,"import(""n"")")
#20084=@"loc,{#10000},2,5,2,15"
locations_default(#20084,#10000,2,5,2,15)
hasLocation(#20083,#20084)
enclosing_stmt(#20083,#20078)
expr_containers(#20083,#20001)
#20085=*
exprs(#20085,4,#20083,0,"""n""")
hasLocation(#20085,#20027)
enclosing_stmt(#20085,#20078)
expr_containers(#20085,#20001)
literals("n","""n""",#20085)
#20086=*
regexpterm(#20086,14,#20085,0,"n")
#20087=@"loc,{#10000},2,13,2,13"
locations_default(#20087,#10000,2,13,2,13)
hasLocation(#20086,#20087)
regexp_const_value(#20086,"n")
#20088=*
exprs(#20088,8,#20079,2,"{}")
#20089=@"loc,{#10000},2,19,2,20"
locations_default(#20089,#10000,2,19,2,20)
hasLocation(#20088,#20089)
enclosing_stmt(#20088,#20078)
expr_containers(#20088,#20001)
#20090=*
stmts(#20090,2,#20001,2,"import( ... => {});")
hasLocation(#20090,#20007)
stmt_containers(#20090,#20001)
#20091=*
exprs(#20091,13,#20090,0,"import( ... => {})")
#20092=@"loc,{#10000},3,1,3,27"
locations_default(#20092,#10000,3,1,3,27)
hasLocation(#20091,#20092)
enclosing_stmt(#20091,#20090)
expr_containers(#20091,#20001)
#20093=*
exprs(#20093,14,#20091,-1,"import(""o"").then")
#20094=@"loc,{#10000},3,1,3,16"
locations_default(#20094,#10000,3,1,3,16)
hasLocation(#20093,#20094)
enclosing_stmt(#20093,#20090)
expr_containers(#20093,#20001)
#20095=*
exprs(#20095,99,#20093,0,"import(""o"")")
#20096=@"loc,{#10000},3,1,3,11"
locations_default(#20096,#10000,3,1,3,11)
hasLocation(#20095,#20096)
enclosing_stmt(#20095,#20090)
expr_containers(#20095,#20001)
#20097=*
exprs(#20097,4,#20095,0,"""o""")
hasLocation(#20097,#20043)
enclosing_stmt(#20097,#20090)
expr_containers(#20097,#20001)
literals("o","""o""",#20097)
#20098=*
regexpterm(#20098,14,#20097,0,"o")
#20099=@"loc,{#10000},3,9,3,9"
locations_default(#20099,#10000,3,9,3,9)
hasLocation(#20098,#20099)
regexp_const_value(#20098,"o")
#20100=*
exprs(#20100,0,#20093,1,"then")
hasLocation(#20100,#20049)
enclosing_stmt(#20100,#20090)
expr_containers(#20100,#20001)
literals("then","then",#20100)
#20101=*
exprs(#20101,65,#20091,0,"(o) => {}")
#20102=@"loc,{#10000},3,18,3,26"
locations_default(#20102,#10000,3,18,3,26)
hasLocation(#20101,#20102)
enclosing_stmt(#20101,#20090)
expr_containers(#20101,#20001)
#20103=*
scopes(#20103,1)
scopenodes(#20101,#20103)
scopenesting(#20103,#20071)
#20104=@"var;{o};{#20103}"
variables(#20104,"o",#20103)
#20105=*
exprs(#20105,78,#20101,0,"o")
hasLocation(#20105,#20055)
expr_containers(#20105,#20101)
literals("o","o",#20105)
decl(#20105,#20104)
#20106=*
stmts(#20106,1,#20101,-2,"{}")
#20107=@"loc,{#10000},3,25,3,26"
locations_default(#20107,#10000,3,25,3,26)
hasLocation(#20106,#20107)
stmt_containers(#20106,#20101)
#20108=*
entry_cfg_node(#20108,#20001)
#20109=@"loc,{#10000},1,1,1,0"
locations_default(#20109,#10000,1,1,1,0)
hasLocation(#20108,#20109)
#20110=*
exit_cfg_node(#20110,#20001)
hasLocation(#20110,#20069)
successor(#20090,#20097)
successor(#20101,#20091)
stmts(#20108,2,#20001,0,"import(""m"");")
hasLocation(#20108,#20003)
stmt_containers(#20108,#20001)
#20109=*
exprs(#20109,99,#20108,0,"import(""m"")")
#20110=@"loc,{#10000},1,1,1,11"
locations_default(#20110,#10000,1,1,1,11)
hasLocation(#20109,#20110)
enclosing_stmt(#20109,#20108)
expr_containers(#20109,#20001)
#20111=*
entry_cfg_node(#20111,#20101)
#20112=@"loc,{#10000},3,18,3,17"
locations_default(#20112,#10000,3,18,3,17)
hasLocation(#20111,#20112)
#20113=*
exit_cfg_node(#20113,#20101)
#20114=@"loc,{#10000},3,27,3,26"
locations_default(#20114,#10000,3,27,3,26)
hasLocation(#20113,#20114)
successor(#20106,#20113)
successor(#20105,#20106)
successor(#20111,#20105)
successor(#20100,#20093)
successor(#20097,#20095)
successor(#20095,#20100)
successor(#20093,#20101)
successor(#20091,#20110)
successor(#20078,#20079)
successor(#20079,#20081)
exprs(#20111,4,#20109,0,"""m""")
hasLocation(#20111,#20019)
enclosing_stmt(#20111,#20108)
expr_containers(#20111,#20001)
literals("m","""m""",#20111)
#20112=*
regexpterm(#20112,14,#20111,0,"m")
#20113=@"loc,{#10000},1,9,1,9"
locations_default(#20113,#10000,1,9,1,9)
hasLocation(#20112,#20113)
regexp_const_value(#20112,"m")
#20114=*
stmts(#20114,2,#20001,1,"b ? imp ... ) : {};")
hasLocation(#20114,#20005)
stmt_containers(#20114,#20001)
#20115=*
guard_node(#20115,1,#20081)
hasLocation(#20115,#20019)
successor(#20115,#20085)
#20116=*
guard_node(#20116,0,#20081)
hasLocation(#20116,#20019)
successor(#20116,#20088)
successor(#20081,#20115)
successor(#20081,#20116)
successor(#20085,#20083)
successor(#20083,#20090)
successor(#20088,#20090)
successor(#20072,#20075)
successor(#20075,#20073)
successor(#20073,#20078)
successor(#20108,#20072)
numlines(#10000,3,3,0)
exprs(#20115,11,#20114,0,"b ? import(""n"") : {}")
#20116=@"loc,{#10000},2,1,2,20"
locations_default(#20116,#10000,2,1,2,20)
hasLocation(#20115,#20116)
enclosing_stmt(#20115,#20114)
expr_containers(#20115,#20001)
#20117=*
exprs(#20117,79,#20115,0,"b")
hasLocation(#20117,#20025)
enclosing_stmt(#20117,#20114)
expr_containers(#20117,#20001)
literals("b","b",#20117)
#20118=@"var;{b};{#20000}"
variables(#20118,"b",#20000)
bind(#20117,#20118)
#20119=*
exprs(#20119,99,#20115,1,"import(""n"")")
#20120=@"loc,{#10000},2,5,2,15"
locations_default(#20120,#10000,2,5,2,15)
hasLocation(#20119,#20120)
enclosing_stmt(#20119,#20114)
expr_containers(#20119,#20001)
#20121=*
exprs(#20121,4,#20119,0,"""n""")
hasLocation(#20121,#20033)
enclosing_stmt(#20121,#20114)
expr_containers(#20121,#20001)
literals("n","""n""",#20121)
#20122=*
regexpterm(#20122,14,#20121,0,"n")
#20123=@"loc,{#10000},2,13,2,13"
locations_default(#20123,#10000,2,13,2,13)
hasLocation(#20122,#20123)
regexp_const_value(#20122,"n")
#20124=*
exprs(#20124,8,#20115,2,"{}")
#20125=@"loc,{#10000},2,19,2,20"
locations_default(#20125,#10000,2,19,2,20)
hasLocation(#20124,#20125)
enclosing_stmt(#20124,#20114)
expr_containers(#20124,#20001)
#20126=*
stmts(#20126,2,#20001,2,"import( ... => {});")
hasLocation(#20126,#20007)
stmt_containers(#20126,#20001)
#20127=*
exprs(#20127,13,#20126,0,"import( ... => {})")
#20128=@"loc,{#10000},3,1,3,27"
locations_default(#20128,#10000,3,1,3,27)
hasLocation(#20127,#20128)
enclosing_stmt(#20127,#20126)
expr_containers(#20127,#20001)
#20129=*
exprs(#20129,14,#20127,-1,"import(""o"").then")
#20130=@"loc,{#10000},3,1,3,16"
locations_default(#20130,#10000,3,1,3,16)
hasLocation(#20129,#20130)
enclosing_stmt(#20129,#20126)
expr_containers(#20129,#20001)
#20131=*
exprs(#20131,99,#20129,0,"import(""o"")")
#20132=@"loc,{#10000},3,1,3,11"
locations_default(#20132,#10000,3,1,3,11)
hasLocation(#20131,#20132)
enclosing_stmt(#20131,#20126)
expr_containers(#20131,#20001)
#20133=*
exprs(#20133,4,#20131,0,"""o""")
hasLocation(#20133,#20049)
enclosing_stmt(#20133,#20126)
expr_containers(#20133,#20001)
literals("o","""o""",#20133)
#20134=*
regexpterm(#20134,14,#20133,0,"o")
#20135=@"loc,{#10000},3,9,3,9"
locations_default(#20135,#10000,3,9,3,9)
hasLocation(#20134,#20135)
regexp_const_value(#20134,"o")
#20136=*
exprs(#20136,0,#20129,1,"then")
hasLocation(#20136,#20055)
enclosing_stmt(#20136,#20126)
expr_containers(#20136,#20001)
literals("then","then",#20136)
#20137=*
exprs(#20137,65,#20127,0,"(o) => {}")
#20138=@"loc,{#10000},3,18,3,26"
locations_default(#20138,#10000,3,18,3,26)
hasLocation(#20137,#20138)
enclosing_stmt(#20137,#20126)
expr_containers(#20137,#20001)
#20139=*
scopes(#20139,1)
scopenodes(#20137,#20139)
scopenesting(#20139,#20107)
#20140=@"var;{o};{#20139}"
variables(#20140,"o",#20139)
#20141=*
exprs(#20141,78,#20137,0,"o")
hasLocation(#20141,#20061)
expr_containers(#20141,#20137)
literals("o","o",#20141)
decl(#20141,#20140)
#20142=*
stmts(#20142,1,#20137,-2,"{}")
#20143=@"loc,{#10000},3,25,3,26"
locations_default(#20143,#10000,3,25,3,26)
hasLocation(#20142,#20143)
stmt_containers(#20142,#20137)
#20144=*
stmts(#20144,2,#20001,3,"import(""m"",);")
hasLocation(#20144,#20011)
stmt_containers(#20144,#20001)
#20145=*
exprs(#20145,99,#20144,0,"import(""m"",)")
#20146=@"loc,{#10000},5,1,5,12"
locations_default(#20146,#10000,5,1,5,12)
hasLocation(#20145,#20146)
enclosing_stmt(#20145,#20144)
expr_containers(#20145,#20001)
#20147=*
exprs(#20147,4,#20145,0,"""m""")
hasLocation(#20147,#20079)
enclosing_stmt(#20147,#20144)
expr_containers(#20147,#20001)
literals("m","""m""",#20147)
#20148=*
regexpterm(#20148,14,#20147,0,"m")
#20149=@"loc,{#10000},5,9,5,9"
locations_default(#20149,#10000,5,9,5,9)
hasLocation(#20148,#20149)
regexp_const_value(#20148,"m")
#20150=*
stmts(#20150,2,#20001,4,"import(""m"",{},);")
hasLocation(#20150,#20013)
stmt_containers(#20150,#20001)
#20151=*
exprs(#20151,99,#20150,0,"import(""m"",{},)")
#20152=@"loc,{#10000},6,1,6,15"
locations_default(#20152,#10000,6,1,6,15)
hasLocation(#20151,#20152)
enclosing_stmt(#20151,#20150)
expr_containers(#20151,#20001)
#20153=*
exprs(#20153,4,#20151,0,"""m""")
hasLocation(#20153,#20091)
enclosing_stmt(#20153,#20150)
expr_containers(#20153,#20001)
literals("m","""m""",#20153)
#20154=*
regexpterm(#20154,14,#20153,0,"m")
#20155=@"loc,{#10000},6,9,6,9"
locations_default(#20155,#10000,6,9,6,9)
hasLocation(#20154,#20155)
regexp_const_value(#20154,"m")
#20156=*
exprs(#20156,8,#20151,1,"{}")
#20157=@"loc,{#10000},6,12,6,13"
locations_default(#20157,#10000,6,12,6,13)
hasLocation(#20156,#20157)
enclosing_stmt(#20156,#20150)
expr_containers(#20156,#20001)
#20158=*
entry_cfg_node(#20158,#20001)
#20159=@"loc,{#10000},1,1,1,0"
locations_default(#20159,#10000,1,1,1,0)
hasLocation(#20158,#20159)
#20160=*
exit_cfg_node(#20160,#20001)
hasLocation(#20160,#20105)
successor(#20150,#20153)
successor(#20153,#20151)
successor(#20151,#20160)
successor(#20144,#20147)
successor(#20147,#20145)
successor(#20145,#20150)
successor(#20126,#20133)
successor(#20137,#20127)
#20161=*
entry_cfg_node(#20161,#20137)
#20162=@"loc,{#10000},3,18,3,17"
locations_default(#20162,#10000,3,18,3,17)
hasLocation(#20161,#20162)
#20163=*
exit_cfg_node(#20163,#20137)
#20164=@"loc,{#10000},3,27,3,26"
locations_default(#20164,#10000,3,27,3,26)
hasLocation(#20163,#20164)
successor(#20142,#20163)
successor(#20141,#20142)
successor(#20161,#20141)
successor(#20136,#20129)
successor(#20133,#20131)
successor(#20131,#20136)
successor(#20129,#20137)
successor(#20127,#20144)
successor(#20114,#20115)
successor(#20115,#20117)
#20165=*
guard_node(#20165,1,#20117)
hasLocation(#20165,#20025)
successor(#20165,#20121)
#20166=*
guard_node(#20166,0,#20117)
hasLocation(#20166,#20025)
successor(#20166,#20124)
successor(#20117,#20165)
successor(#20117,#20166)
successor(#20121,#20119)
successor(#20119,#20126)
successor(#20124,#20126)
successor(#20108,#20111)
successor(#20111,#20109)
successor(#20109,#20114)
successor(#20158,#20108)
numlines(#10000,6,5,0)
filetype(#10000,"javascript")

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
import "module" assert { type: "json" };
import * as v1 from "module" assert { type: "json" };
import { v2 } from "module" assert { type: "json" };
import v3 from "module" assert { type: "json" };
export { v4 } from "module" assert { type: "json" };
export * from "module" assert { type: "json" };
export * as v5 from "module" assert { type: "json" };
const v6 = import("module", { assert: { type: "json" } });
import "module"; // missing semicolon
assert({ type: "json" }); // function call, not import assertion

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
---
category: minorAnalysis
---
* Deleted the deprecated `getPath` and `getFolder` predicates from the `XmlFile` class.
* Deleted the deprecated `getId` from the `Function`, `NamespaceDefinition`, and `ImportEqualsDeclaration` classes.
* Deleted the deprecated `flowsTo` predicate from the `HTTP::Servers::RequestSource` and `HTTP::Servers::ResponseSource` class.
* Deleted the deprecated `getEventName` predicate from the `SocketIO::ReceiveNode`, `SocketIO::SendNode`, `SocketIOClient::SendNode` classes.
* Deleted the deprecated `RateLimitedRouteHandlerExpr` and `RouteHandlerExpressionWithRateLimiter` classes.

View File

@@ -0,0 +1,5 @@
---
category: minorAnalysis
---
* [Import assertions](https://github.com/tc39/proposal-import-assertions) are now supported.
Previously this feature was only supported in TypeScript code, but is now supported for plain JavaScript as well and is also accessible in the AST.

View File

@@ -90,6 +90,16 @@ class ImportDeclaration extends Stmt, Import, @import_declaration {
override PathExpr getImportedPath() { result = getChildExpr(-1) }
/**
* Gets the object literal passed as part of the `assert` clause in this import declaration.
*
* For example, this gets the `{ type: "json" }` object literal in the following:
* ```js
* import foo from "foo" assert { type: "json" };
* ```
*/
ObjectExpr getImportAssertion() { result = this.getChildExpr(-10) }
/** Gets the `i`th import specifier of this import declaration. */
ImportSpecifier getSpecifier(int i) { result = getChildExpr(i) }
@@ -310,6 +320,19 @@ abstract class ExportDeclaration extends Stmt, @export_declaration {
predicate isTypeOnly() { has_type_keyword(this) }
override string getAPrimaryQlClass() { result = "ExportDeclaration" }
/**
* Gets the object literal passed as part of the `assert` clause, if this is
* a re-export declaration.
*
* For example, this gets the `{ type: "json" }` expression in each of the following:
* ```js
* export { x } from 'foo' assert { type: "json" };
* export * from 'foo' assert { type: "json" };
* export * as x from 'foo' assert { type: "json" };
* ```
*/
ObjectExpr getImportAssertion() { result = this.getChildExpr(-10) }
}
/**

View File

@@ -2807,6 +2807,7 @@ class FunctionBindExpr extends @bind_expr, Expr {
*
* ```
* import("fs")
* import("foo", { assert: { type: "json" }})
* ```
*/
class DynamicImportExpr extends @dynamic_import, Expr, Import {
@@ -2819,6 +2820,16 @@ class DynamicImportExpr extends @dynamic_import, Expr, Import {
override PathExpr getImportedPath() { result = this.getSource() }
/**
* Gets the second "argument" to the import expression, that is, the `Y` in `import(X, Y)`.
*
* For example, gets the `{ assert: { type: "json" }}` expression in the following:
* ```js
* import('foo', { assert: { type: "json" }})
* ```
*/
Expr getImportAttributes() { result = this.getChildExpr(1) }
override Module getEnclosingModule() { result = this.getTopLevel() }
override DataFlow::Node getImportedModuleNode() { result = DataFlow::valueNode(this) }

View File

@@ -83,13 +83,6 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
result = this.getDocumentation().getATagByTitle("this").getType()
}
/**
* DEPRECATED: Use `getIdentifier()` instead.
*
* Gets the identifier specifying the name of this function, if any.
*/
deprecated VarDecl getId() { result = this.getIdentifier() }
/** Gets the identifier specifying the name of this function, if any. */
VarDecl getIdentifier() { result = this.getChildExpr(-1) }

View File

@@ -7,13 +7,6 @@ import javascript
* considered to be namespace definitions.
*/
class NamespaceDefinition extends Stmt, @namespace_definition, AST::ValueNode {
/**
* DEPRECATED: Use `getIdentifier()` instead.
*
* Gets the identifier naming the namespace.
*/
deprecated Identifier getId() { result = this.getIdentifier() }
/**
* Gets the identifier naming the namespace.
*/
@@ -189,13 +182,6 @@ class GlobalAugmentationDeclaration extends Stmt, StmtContainer, @global_augment
/** A TypeScript "import-equals" declaration. */
class ImportEqualsDeclaration extends Stmt, @import_equals_declaration {
/**
* DEPRECATED: Use `getIdentifier()` instead.
*
* Gets the name under which the imported entity is imported.
*/
deprecated Identifier getId() { result = this.getIdentifier() }
/** Gets the name under which the imported entity is imported. */
Identifier getIdentifier() { result = this.getChildExpr(0) }

View File

@@ -108,20 +108,6 @@ class XmlFile extends XmlParent, File {
/** Gets the name of this XML file. */
override string getName() { result = File.super.getAbsolutePath() }
/**
* DEPRECATED: Use `getAbsolutePath()` instead.
*
* Gets the path of this XML file.
*/
deprecated string getPath() { result = this.getAbsolutePath() }
/**
* DEPRECATED: Use `getParentContainer().getAbsolutePath()` instead.
*
* Gets the path of the folder that contains this XML file.
*/
deprecated string getFolder() { result = this.getParentContainer().getAbsolutePath() }
/** Gets the encoding of this XML file. */
string getEncoding() { xmlEncoding(this, result) }

View File

@@ -347,9 +347,6 @@ module Http {
*/
abstract RouteHandler getRouteHandler();
/** DEPRECATED. Use `ref().flowsTo()` instead. */
deprecated predicate flowsTo(DataFlow::Node nd) { this.ref().flowsTo(nd) }
private DataFlow::SourceNode ref(DataFlow::TypeTracker t) {
t.start() and
result = this
@@ -372,9 +369,6 @@ module Http {
*/
abstract RouteHandler getRouteHandler();
/** DEPRECATED. Use `ref().flowsTo()` instead. */
deprecated predicate flowsTo(DataFlow::Node nd) { this.ref().flowsTo(nd) }
private DataFlow::SourceNode ref(DataFlow::TypeTracker t) {
t.start() and
result = this

View File

@@ -775,7 +775,7 @@ private class ReactRouterLocationSource extends DOM::LocationSource::Range {
private DataFlow::SourceNode higherOrderComponentBuilder() {
// `memo(f)` returns a function that behaves as `f` but caches results
// It is sometimes used to wrap an entire functional component.
result = react().getAPropertyRead("memo")
result = react().getAPropertyRead(["memo", "forwardRef"])
or
result = DataFlow::moduleMember("react-redux", "connect").getACall()
or

View File

@@ -269,9 +269,6 @@ module SocketIO {
/** Gets the acknowledgment callback, if any. */
ReceiveCallback getAck() { result.getReceiveNode() = this }
/** DEPRECATED. Use `getChannel()` instead. */
deprecated string getEventName() { result = this.getChannel() }
}
/** An acknowledgment callback when receiving a message. */
@@ -360,9 +357,6 @@ module SocketIO {
/** Gets the acknowledgment callback, if any. */
SendCallback getAck() { result.getSendNode() = this }
/** DEPRECATED. Use `getChannel()` instead. */
deprecated string getEventName() { result = this.getChannel() }
}
/** A socket.io namespace, identified by its server and its path. */
@@ -646,9 +640,6 @@ module SocketIOClient {
/** Gets the acknowledgment callback, if any. */
DataFlow::FunctionNode getAck() { result.(SendCallback).getSendNode() = this }
/** DEPRECATED. Use `getChannel()` instead. */
deprecated string getEventName() { result = this.getChannel() }
}
/**

View File

@@ -25,8 +25,7 @@ module TrustedTypes {
/** Gets the function passed as the given option. */
DataFlow::FunctionNode getPolicyCallback(string method) {
// Require local callback to avoid potential call/return mismatch in the uses below
result = getOptionArgument(1, method).getALocalSource()
result = getParameter(1).getMember(method).getAValueReachingSink()
}
}

View File

@@ -40,17 +40,6 @@ abstract class ExpensiveRouteHandler extends DataFlow::Node {
abstract predicate explain(string explanation, DataFlow::Node reference, string referenceLabel);
}
/**
* DEPRECATED. Use `RateLimitingMiddleware` instead.
*
* A route handler expression that is guarded by a rate limiter.
*/
deprecated class RateLimitedRouteHandlerExpr extends Express::RouteHandlerExpr {
RateLimitedRouteHandlerExpr() {
Routing::getNode(this.flow()).isGuardedBy(any(RateLimitingMiddleware m))
}
}
// default implementations
/**
* A route handler that performs an expensive action, and hence should be rate-limited.
@@ -100,17 +89,6 @@ class DatabaseAccessAsExpensiveAction extends ExpensiveAction instanceof Databas
override string describe() { result = "a database access" }
}
/**
* DEPRECATED. Use the `Routing::Node` API instead.
*
* A route handler expression that is rate-limited by a rate-limiting middleware.
*/
deprecated class RouteHandlerExpressionWithRateLimiter extends Expr {
RouteHandlerExpressionWithRateLimiter() {
Routing::getNode(this.flow()).isGuardedBy(any(RateLimitingMiddleware m))
}
}
/**
* The creation of a middleware function that acts as a rate limiter.
*/

View File

@@ -0,0 +1,13 @@
import "module" assert { type: "json" };
import * as v1 from "module" assert { type: "json" };
import { v2 } from "module" assert { type: "json" };
import v3 from "module" assert { type: "json" };
export { v4 } from "module" assert { type: "json" };
export * from "module" assert { type: "json" };
export * as v5 from "module" assert { type: "json" };
const v6 = import("module", { assert: { type: "json" } });
import "module" // missing semicolon
assert({type: "json"}); // function call, not import assertion

View File

@@ -0,0 +1,20 @@
getImportAssertionFromImport
| js-import-assertions.js:1:1:1:40 | import ... son" }; | js-import-assertions.js:1:24:1:39 | { type: "json" } |
| js-import-assertions.js:2:1:2:53 | import ... son" }; | js-import-assertions.js:2:37:2:52 | { type: "json" } |
| js-import-assertions.js:3:1:3:52 | import ... son" }; | js-import-assertions.js:3:36:3:51 | { type: "json" } |
| js-import-assertions.js:4:1:4:48 | import ... son" }; | js-import-assertions.js:4:32:4:47 | { type: "json" } |
| ts-import-assertions.ts:3:1:3:40 | import ... son" }; | ts-import-assertions.ts:3:24:3:39 | { type: "json" } |
| ts-import-assertions.ts:4:1:4:53 | import ... son" }; | ts-import-assertions.ts:4:37:4:52 | { type: "json" } |
| ts-import-assertions.ts:5:1:5:52 | import ... son" }; | ts-import-assertions.ts:5:36:5:51 | { type: "json" } |
| ts-import-assertions.ts:6:1:6:48 | import ... son" }; | ts-import-assertions.ts:6:32:6:47 | { type: "json" } |
getImportAssertionFromExport
| js-import-assertions.js:6:1:6:52 | export ... son" }; | js-import-assertions.js:6:36:6:51 | { type: "json" } |
| js-import-assertions.js:7:1:7:47 | export ... son" }; | js-import-assertions.js:7:31:7:46 | { type: "json" } |
| js-import-assertions.js:8:1:8:53 | export ... son" }; | js-import-assertions.js:8:37:8:52 | { type: "json" } |
| ts-import-assertions.ts:8:1:8:52 | export ... son" }; | ts-import-assertions.ts:8:36:8:51 | { type: "json" } |
| ts-import-assertions.ts:9:1:9:47 | export ... son" }; | ts-import-assertions.ts:9:31:9:46 | { type: "json" } |
| ts-import-assertions.ts:10:1:10:53 | export ... son" }; | ts-import-assertions.ts:10:37:10:52 | { type: "json" } |
getImportAttributes
| js-import-assertions.js:10:12:10:57 | import( ... n" } }) | js-import-assertions.js:10:29:10:56 | { asser ... on" } } |
| ts-import-assertions.ts:12:12:12:57 | import( ... n" } }) | ts-import-assertions.ts:12:29:12:56 | { asser ... on" } } |
errors

View File

@@ -0,0 +1,13 @@
import javascript
query Expr getImportAssertionFromImport(ImportDeclaration decl) {
result = decl.getImportAssertion()
}
query Expr getImportAssertionFromExport(ExportDeclaration decl) {
result = decl.getImportAssertion()
}
query Expr getImportAttributes(DynamicImportExpr imprt) { result = imprt.getImportAttributes() }
query JSParseError errors() { any() }

View File

@@ -0,0 +1,15 @@
// TypeScript
import "module" assert { type: "json" };
import * as v1 from "module" assert { type: "json" };
import { v2 } from "module" assert { type: "json" };
import v3 from "module" assert { type: "json" };
export { v4 } from "module" assert { type: "json" };
export * from "module" assert { type: "json" };
export * as v5 from "module" assert { type: "json" };
const v6 = import("module", { assert: { type: "json" } });
import "module" // missing semicolon
assert({ type: "json" }); // function call, not import assertion

View File

@@ -949,6 +949,8 @@ nodes
| tst.ts:237:8:237:16 | [ImportSpecifier] * as Foo3 | semmle.label | [ImportSpecifier] * as Foo3 |
| tst.ts:237:13:237:16 | [VarDecl] Foo3 | semmle.label | [VarDecl] Foo3 |
| tst.ts:237:23:237:40 | [Literal] "./something.json" | semmle.label | [Literal] "./something.json" |
| tst.ts:237:49:237:64 | [ObjectExpr] { type: "json" } | semmle.label | [ObjectExpr] { type: "json" } |
| tst.ts:237:51:237:62 | [Property] type: "json" | semmle.label | [Property] type: "json" |
| tst.ts:238:1:238:19 | [DeclStmt] var foo = ... | semmle.label | [DeclStmt] var foo = ... |
| tst.ts:238:1:238:19 | [DeclStmt] var foo = ... | semmle.order | 59 |
| tst.ts:238:5:238:7 | [VarDecl] foo | semmle.label | [VarDecl] foo |
@@ -3461,8 +3463,12 @@ edges
| tst.ts:237:1:237:65 | [ImportDeclaration] import ... son" }; | tst.ts:237:8:237:16 | [ImportSpecifier] * as Foo3 | semmle.order | 1 |
| tst.ts:237:1:237:65 | [ImportDeclaration] import ... son" }; | tst.ts:237:23:237:40 | [Literal] "./something.json" | semmle.label | 2 |
| tst.ts:237:1:237:65 | [ImportDeclaration] import ... son" }; | tst.ts:237:23:237:40 | [Literal] "./something.json" | semmle.order | 2 |
| tst.ts:237:1:237:65 | [ImportDeclaration] import ... son" }; | tst.ts:237:49:237:64 | [ObjectExpr] { type: "json" } | semmle.label | 3 |
| tst.ts:237:1:237:65 | [ImportDeclaration] import ... son" }; | tst.ts:237:49:237:64 | [ObjectExpr] { type: "json" } | semmle.order | 3 |
| tst.ts:237:8:237:16 | [ImportSpecifier] * as Foo3 | tst.ts:237:13:237:16 | [VarDecl] Foo3 | semmle.label | 1 |
| tst.ts:237:8:237:16 | [ImportSpecifier] * as Foo3 | tst.ts:237:13:237:16 | [VarDecl] Foo3 | semmle.order | 1 |
| tst.ts:237:49:237:64 | [ObjectExpr] { type: "json" } | tst.ts:237:51:237:62 | [Property] type: "json" | semmle.label | 1 |
| tst.ts:237:49:237:64 | [ObjectExpr] { type: "json" } | tst.ts:237:51:237:62 | [Property] type: "json" | semmle.order | 1 |
| tst.ts:238:1:238:19 | [DeclStmt] var foo = ... | tst.ts:238:5:238:18 | [VariableDeclarator] foo = Foo3.foo | semmle.label | 1 |
| tst.ts:238:1:238:19 | [DeclStmt] var foo = ... | tst.ts:238:5:238:18 | [VariableDeclarator] foo = Foo3.foo | semmle.order | 1 |
| tst.ts:238:5:238:18 | [VariableDeclarator] foo = Foo3.foo | tst.ts:238:5:238:7 | [VarDecl] foo | semmle.label | 1 |

View File

@@ -1,4 +1,4 @@
import { memo } from 'react';
import { memo, forwardRef } from 'react';
import { connect } from 'react-redux';
import { compose } from 'redux';
import styled from 'styled-components';
@@ -25,4 +25,4 @@ const ConnectedComponent = compose(withConnect, unknownFunction)(StyledComponent
const ConnectedComponent2 = withState('counter', 'setCounter', 0)(ConnectedComponent);
export default hot(module)(memo(ConnectedComponent2));
export default hot(module)(memo(forwardRef(ConnectedComponent2)));

View File

@@ -689,14 +689,22 @@ nodes
| translate.js:9:27:9:50 | searchP ... 'term') |
| translate.js:9:27:9:50 | searchP ... 'term') |
| translate.js:9:27:9:50 | searchP ... 'term') |
| trusted-types.js:2:66:2:66 | x |
| trusted-types.js:2:66:2:66 | x |
| trusted-types.js:2:71:2:71 | x |
| trusted-types.js:2:71:2:71 | x |
| trusted-types.js:2:71:2:71 | x |
| trusted-types.js:3:24:3:34 | window.name |
| trusted-types.js:3:24:3:34 | window.name |
| trusted-types.js:3:24:3:34 | window.name |
| trusted-types-lib.js:1:28:1:28 | x |
| trusted-types-lib.js:1:28:1:28 | x |
| trusted-types-lib.js:2:12:2:12 | x |
| trusted-types-lib.js:2:12:2:12 | x |
| trusted-types-lib.js:2:12:2:12 | x |
| trusted-types.js:3:62:3:62 | x |
| trusted-types.js:3:62:3:62 | x |
| trusted-types.js:3:67:3:67 | x |
| trusted-types.js:3:67:3:67 | x |
| trusted-types.js:3:67:3:67 | x |
| trusted-types.js:4:20:4:30 | window.name |
| trusted-types.js:4:20:4:30 | window.name |
| trusted-types.js:4:20:4:30 | window.name |
| trusted-types.js:13:20:13:30 | window.name |
| trusted-types.js:13:20:13:30 | window.name |
| trusted-types.js:13:20:13:30 | window.name |
| tst3.js:2:12:2:75 | JSON.pa ... tr(1))) |
| tst3.js:2:23:2:74 | decodeU ... str(1)) |
| tst3.js:2:42:2:63 | window. ... .search |
@@ -1818,14 +1826,22 @@ edges
| translate.js:9:27:9:38 | searchParams | translate.js:9:27:9:50 | searchP ... 'term') |
| translate.js:9:27:9:38 | searchParams | translate.js:9:27:9:50 | searchP ... 'term') |
| translate.js:9:27:9:38 | searchParams | translate.js:9:27:9:50 | searchP ... 'term') |
| trusted-types.js:2:66:2:66 | x | trusted-types.js:2:71:2:71 | x |
| trusted-types.js:2:66:2:66 | x | trusted-types.js:2:71:2:71 | x |
| trusted-types.js:2:66:2:66 | x | trusted-types.js:2:71:2:71 | x |
| trusted-types.js:2:66:2:66 | x | trusted-types.js:2:71:2:71 | x |
| trusted-types.js:3:24:3:34 | window.name | trusted-types.js:2:66:2:66 | x |
| trusted-types.js:3:24:3:34 | window.name | trusted-types.js:2:66:2:66 | x |
| trusted-types.js:3:24:3:34 | window.name | trusted-types.js:2:66:2:66 | x |
| trusted-types.js:3:24:3:34 | window.name | trusted-types.js:2:66:2:66 | x |
| trusted-types-lib.js:1:28:1:28 | x | trusted-types-lib.js:2:12:2:12 | x |
| trusted-types-lib.js:1:28:1:28 | x | trusted-types-lib.js:2:12:2:12 | x |
| trusted-types-lib.js:1:28:1:28 | x | trusted-types-lib.js:2:12:2:12 | x |
| trusted-types-lib.js:1:28:1:28 | x | trusted-types-lib.js:2:12:2:12 | x |
| trusted-types.js:3:62:3:62 | x | trusted-types.js:3:67:3:67 | x |
| trusted-types.js:3:62:3:62 | x | trusted-types.js:3:67:3:67 | x |
| trusted-types.js:3:62:3:62 | x | trusted-types.js:3:67:3:67 | x |
| trusted-types.js:3:62:3:62 | x | trusted-types.js:3:67:3:67 | x |
| trusted-types.js:4:20:4:30 | window.name | trusted-types.js:3:62:3:62 | x |
| trusted-types.js:4:20:4:30 | window.name | trusted-types.js:3:62:3:62 | x |
| trusted-types.js:4:20:4:30 | window.name | trusted-types.js:3:62:3:62 | x |
| trusted-types.js:4:20:4:30 | window.name | trusted-types.js:3:62:3:62 | x |
| trusted-types.js:13:20:13:30 | window.name | trusted-types-lib.js:1:28:1:28 | x |
| trusted-types.js:13:20:13:30 | window.name | trusted-types-lib.js:1:28:1:28 | x |
| trusted-types.js:13:20:13:30 | window.name | trusted-types-lib.js:1:28:1:28 | x |
| trusted-types.js:13:20:13:30 | window.name | trusted-types-lib.js:1:28:1:28 | x |
| tst3.js:2:12:2:75 | JSON.pa ... tr(1))) | tst3.js:4:25:4:28 | data |
| tst3.js:2:12:2:75 | JSON.pa ... tr(1))) | tst3.js:5:26:5:29 | data |
| tst3.js:2:12:2:75 | JSON.pa ... tr(1))) | tst3.js:7:32:7:35 | data |
@@ -2382,7 +2398,8 @@ edges
| tooltip.jsx:10:25:10:30 | source | tooltip.jsx:6:20:6:30 | window.name | tooltip.jsx:10:25:10:30 | source | Cross-site scripting vulnerability due to $@. | tooltip.jsx:6:20:6:30 | window.name | user-provided value |
| tooltip.jsx:11:25:11:30 | source | tooltip.jsx:6:20:6:30 | window.name | tooltip.jsx:11:25:11:30 | source | Cross-site scripting vulnerability due to $@. | tooltip.jsx:6:20:6:30 | window.name | user-provided value |
| translate.js:9:27:9:50 | searchP ... 'term') | translate.js:6:16:6:39 | documen ... .search | translate.js:9:27:9:50 | searchP ... 'term') | Cross-site scripting vulnerability due to $@. | translate.js:6:16:6:39 | documen ... .search | user-provided value |
| trusted-types.js:2:71:2:71 | x | trusted-types.js:3:24:3:34 | window.name | trusted-types.js:2:71:2:71 | x | Cross-site scripting vulnerability due to $@. | trusted-types.js:3:24:3:34 | window.name | user-provided value |
| trusted-types-lib.js:2:12:2:12 | x | trusted-types.js:13:20:13:30 | window.name | trusted-types-lib.js:2:12:2:12 | x | Cross-site scripting vulnerability due to $@. | trusted-types.js:13:20:13:30 | window.name | user-provided value |
| trusted-types.js:3:67:3:67 | x | trusted-types.js:4:20:4:30 | window.name | trusted-types.js:3:67:3:67 | x | Cross-site scripting vulnerability due to $@. | trusted-types.js:4:20:4:30 | window.name | user-provided value |
| tst3.js:4:25:4:32 | data.src | tst3.js:2:42:2:63 | window. ... .search | tst3.js:4:25:4:32 | data.src | Cross-site scripting vulnerability due to $@. | tst3.js:2:42:2:63 | window. ... .search | user-provided value |
| tst3.js:5:26:5:31 | data.p | tst3.js:2:42:2:63 | window. ... .search | tst3.js:5:26:5:31 | data.p | Cross-site scripting vulnerability due to $@. | tst3.js:2:42:2:63 | window. ... .search | user-provided value |
| tst3.js:7:32:7:37 | data.p | tst3.js:2:42:2:63 | window. ... .search | tst3.js:7:32:7:37 | data.p | Cross-site scripting vulnerability due to $@. | tst3.js:2:42:2:63 | window. ... .search | user-provided value |

View File

@@ -701,14 +701,22 @@ nodes
| translate.js:9:27:9:50 | searchP ... 'term') |
| translate.js:9:27:9:50 | searchP ... 'term') |
| translate.js:9:27:9:50 | searchP ... 'term') |
| trusted-types.js:2:66:2:66 | x |
| trusted-types.js:2:66:2:66 | x |
| trusted-types.js:2:71:2:71 | x |
| trusted-types.js:2:71:2:71 | x |
| trusted-types.js:2:71:2:71 | x |
| trusted-types.js:3:24:3:34 | window.name |
| trusted-types.js:3:24:3:34 | window.name |
| trusted-types.js:3:24:3:34 | window.name |
| trusted-types-lib.js:1:28:1:28 | x |
| trusted-types-lib.js:1:28:1:28 | x |
| trusted-types-lib.js:2:12:2:12 | x |
| trusted-types-lib.js:2:12:2:12 | x |
| trusted-types-lib.js:2:12:2:12 | x |
| trusted-types.js:3:62:3:62 | x |
| trusted-types.js:3:62:3:62 | x |
| trusted-types.js:3:67:3:67 | x |
| trusted-types.js:3:67:3:67 | x |
| trusted-types.js:3:67:3:67 | x |
| trusted-types.js:4:20:4:30 | window.name |
| trusted-types.js:4:20:4:30 | window.name |
| trusted-types.js:4:20:4:30 | window.name |
| trusted-types.js:13:20:13:30 | window.name |
| trusted-types.js:13:20:13:30 | window.name |
| trusted-types.js:13:20:13:30 | window.name |
| tst3.js:2:12:2:75 | JSON.pa ... tr(1))) |
| tst3.js:2:23:2:74 | decodeU ... str(1)) |
| tst3.js:2:42:2:63 | window. ... .search |
@@ -1880,14 +1888,22 @@ edges
| translate.js:9:27:9:38 | searchParams | translate.js:9:27:9:50 | searchP ... 'term') |
| translate.js:9:27:9:38 | searchParams | translate.js:9:27:9:50 | searchP ... 'term') |
| translate.js:9:27:9:38 | searchParams | translate.js:9:27:9:50 | searchP ... 'term') |
| trusted-types.js:2:66:2:66 | x | trusted-types.js:2:71:2:71 | x |
| trusted-types.js:2:66:2:66 | x | trusted-types.js:2:71:2:71 | x |
| trusted-types.js:2:66:2:66 | x | trusted-types.js:2:71:2:71 | x |
| trusted-types.js:2:66:2:66 | x | trusted-types.js:2:71:2:71 | x |
| trusted-types.js:3:24:3:34 | window.name | trusted-types.js:2:66:2:66 | x |
| trusted-types.js:3:24:3:34 | window.name | trusted-types.js:2:66:2:66 | x |
| trusted-types.js:3:24:3:34 | window.name | trusted-types.js:2:66:2:66 | x |
| trusted-types.js:3:24:3:34 | window.name | trusted-types.js:2:66:2:66 | x |
| trusted-types-lib.js:1:28:1:28 | x | trusted-types-lib.js:2:12:2:12 | x |
| trusted-types-lib.js:1:28:1:28 | x | trusted-types-lib.js:2:12:2:12 | x |
| trusted-types-lib.js:1:28:1:28 | x | trusted-types-lib.js:2:12:2:12 | x |
| trusted-types-lib.js:1:28:1:28 | x | trusted-types-lib.js:2:12:2:12 | x |
| trusted-types.js:3:62:3:62 | x | trusted-types.js:3:67:3:67 | x |
| trusted-types.js:3:62:3:62 | x | trusted-types.js:3:67:3:67 | x |
| trusted-types.js:3:62:3:62 | x | trusted-types.js:3:67:3:67 | x |
| trusted-types.js:3:62:3:62 | x | trusted-types.js:3:67:3:67 | x |
| trusted-types.js:4:20:4:30 | window.name | trusted-types.js:3:62:3:62 | x |
| trusted-types.js:4:20:4:30 | window.name | trusted-types.js:3:62:3:62 | x |
| trusted-types.js:4:20:4:30 | window.name | trusted-types.js:3:62:3:62 | x |
| trusted-types.js:4:20:4:30 | window.name | trusted-types.js:3:62:3:62 | x |
| trusted-types.js:13:20:13:30 | window.name | trusted-types-lib.js:1:28:1:28 | x |
| trusted-types.js:13:20:13:30 | window.name | trusted-types-lib.js:1:28:1:28 | x |
| trusted-types.js:13:20:13:30 | window.name | trusted-types-lib.js:1:28:1:28 | x |
| trusted-types.js:13:20:13:30 | window.name | trusted-types-lib.js:1:28:1:28 | x |
| tst3.js:2:12:2:75 | JSON.pa ... tr(1))) | tst3.js:4:25:4:28 | data |
| tst3.js:2:12:2:75 | JSON.pa ... tr(1))) | tst3.js:5:26:5:29 | data |
| tst3.js:2:12:2:75 | JSON.pa ... tr(1))) | tst3.js:7:32:7:35 | data |

View File

@@ -0,0 +1,3 @@
export function createHtml(x) {
return x;
}

View File

@@ -1,10 +1,13 @@
(function() {
const policy1 = trustedTypes.createPolicy('x', { createHTML: x => x }); // NOT OK
policy1.createHTML(window.name);
import * as lib from './trusted-types-lib';
const policy2 = trustedTypes.createPolicy('x', { createHTML: x => 'safe' }); // OK
policy2.createHTML(window.name);
const policy1 = trustedTypes.createPolicy('x', { createHTML: x => x }); // NOT OK
policy1.createHTML(window.name);
const policy3 = trustedTypes.createPolicy('x', { createHTML: x => x }); // OK
policy3.createHTML('safe');
})();
const policy2 = trustedTypes.createPolicy('x', { createHTML: x => 'safe' }); // OK
policy2.createHTML(window.name);
const policy3 = trustedTypes.createPolicy('x', { createHTML: x => x }); // OK
policy3.createHTML('safe');
const policy4 = trustedTypes.createPolicy('x', { createHTML: lib.createHtml });
policy4.createHTML(window.name);