Merge pull request #937 from xiemaisi/js/e4x

JavaScript: Add support for E4X.
This commit is contained in:
Esben Sparre Andreasen
2019-02-25 10:22:30 +01:00
committed by GitHub
50 changed files with 7205 additions and 1454 deletions

View File

@@ -19,6 +19,7 @@
## Changes to code extraction
* Extraction of JavaScript files (but not TypeScript files) on LGTM is now parallelized. By default, the extractor uses as many threads as there are processors, but this can be overridden by setting the `LGTM_INDEX_THREADS` environment variable. In particular, setting `LGTM_INDEX_THREADS` to 1 disables parallel extraction.
* The extractor now offers experimental support for [E4X](https://developer.mozilla.org/en-US/docs/Archive/Web/E4X), a legacy language extension developed by Mozilla.
* The extractor now supports additional [Flow](https://flow.org/) syntax.
* The extractor now supports [Nullish Coalescing](https://github.com/tc39/proposal-nullish-coalescing) expressions.
* The extractor now supports [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html).

View File

@@ -4,14 +4,17 @@ import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import com.semmle.jcorn.TokenType.Properties;
import com.semmle.jcorn.flow.FlowParser;
import com.semmle.js.ast.ArrayExpression;
import com.semmle.js.ast.AssignmentExpression;
import com.semmle.js.ast.BlockStatement;
import com.semmle.js.ast.CallExpression;
import com.semmle.js.ast.CatchClause;
import com.semmle.js.ast.ClassExpression;
import com.semmle.js.ast.ComprehensionBlock;
import com.semmle.js.ast.ComprehensionExpression;
import com.semmle.js.ast.Decorator;
import com.semmle.js.ast.Expression;
import com.semmle.js.ast.ExpressionStatement;
import com.semmle.js.ast.ForInStatement;
@@ -25,16 +28,23 @@ import com.semmle.js.ast.LetStatement;
import com.semmle.js.ast.MemberExpression;
import com.semmle.js.ast.NewExpression;
import com.semmle.js.ast.Node;
import com.semmle.js.ast.ParenthesizedExpression;
import com.semmle.js.ast.Position;
import com.semmle.js.ast.SourceLocation;
import com.semmle.js.ast.Statement;
import com.semmle.js.ast.Token;
import com.semmle.js.ast.TryStatement;
import com.semmle.js.ast.VariableDeclaration;
import com.semmle.js.ast.XMLAnyName;
import com.semmle.js.ast.XMLAttributeSelector;
import com.semmle.js.ast.XMLDotDotExpression;
import com.semmle.js.ast.XMLFilterExpression;
import com.semmle.util.data.Either;
import com.semmle.util.data.Pair;
/**
* An extension of the standard jcorn parser with support for Mozilla-specific
* language extension (most of JavaScript 1.8.5) and JScript language extensions.
* language extension (most of JavaScript 1.8.5 and E4X) and JScript language extensions.
*/
public class CustomParser extends FlowParser {
public CustomParser(Options options, String input, int startPos) {
@@ -128,7 +138,9 @@ public class CustomParser extends FlowParser {
this.next();
// check whether this is array comprehension or regular array
if (this.type == TokenType._for) {
return (Expression) this.parseComprehension(startLoc, false, null);
ComprehensionExpression c = this.parseComprehension(startLoc, false, null);
this.expect(TokenType.bracketR);
return this.finishNode(c);
}
List<Expression> elements;
if (this.type == TokenType.comma || this.type == TokenType.bracketR ||
@@ -138,7 +150,9 @@ public class CustomParser extends FlowParser {
Expression firstExpr = this.parseMaybeAssign(true, refDestructuringErrors, null);
// check whether this is a postfix array comprehension
if (this.type == TokenType._for || this.type == TokenType._if) {
return (Expression) this.parseComprehension(startLoc, false, firstExpr);
ComprehensionExpression c = this.parseComprehension(startLoc, false, firstExpr);
this.expect(TokenType.bracketR);
return this.finishNode(c);
} else {
this.eat(TokenType.comma);
elements = new ArrayList<Expression>();
@@ -155,6 +169,20 @@ public class CustomParser extends FlowParser {
List<Expression> args = this.parseExprList(TokenType.parenR, false, false, null);
CallExpression node = new CallExpression(new SourceLocation(startLoc), name, new ArrayList<>(), args, false, false);
return this.finishNode(node);
} else if (options.e4x() && this.type == at) {
// this could be either a decorator or an attribute selector; we first
// try parsing it as a decorator, and then convert it to an attribute selector
// if the next token turns out not to be `class`
List<Decorator> decorators = parseDecorators();
Expression attr = null;
if (decorators.size() > 1 ||
this.type == TokenType._class ||
((attr = decoratorToAttributeSelector(decorators.get(0))) == null)) {
ClassExpression ce = (ClassExpression) this.parseClass(startLoc, false);
ce.addDecorators(decorators);
return ce;
}
return attr;
} else {
return super.parseExprAtom(refDestructuringErrors);
}
@@ -167,8 +195,12 @@ public class CustomParser extends FlowParser {
this.expect(TokenType.parenR);
if (this.type == TokenType.braceL) {
if (!maybeStatement)
this.unexpected();
if (!maybeStatement) {
// must be the start of an object literal
Expression body = this.parseObj(false, null);
return this.finishNode(new LetExpression(new SourceLocation(startLoc), decl.getDeclarations(), body));
}
BlockStatement body = this.parseBlock(false);
return this.finishNode(new LetStatement(new SourceLocation(startLoc), decl.getDeclarations(), body));
} else if (maybeStatement) {
@@ -188,7 +220,7 @@ public class CustomParser extends FlowParser {
protected INode parseFunction(Position startLoc, boolean isStatement, boolean allowExpressionBody, boolean isAsync) {
if (isFunctionSent(isStatement))
return super.parseFunction(startLoc, isStatement, allowExpressionBody, isAsync);
allowExpressionBody = allowExpressionBody || options.mozExtensions() && !isStatement;
allowExpressionBody = allowExpressionBody || options.mozExtensions();
boolean oldInGen = this.inGenerator, oldInAsync = this.inAsync;
int oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos;
Pair<Boolean, Identifier> p = parseFunctionName(isStatement, isAsync);
@@ -242,20 +274,21 @@ public class CustomParser extends FlowParser {
}
// add parsing of comprehensions
protected Node parseComprehension(Position startLoc, boolean isGenerator, Expression body) {
protected ComprehensionExpression parseComprehension(Position startLoc, boolean isGenerator, Expression body) {
List<ComprehensionBlock> blocks = new ArrayList<ComprehensionBlock>();
while (this.type == TokenType._for) {
SourceLocation blockStart = new SourceLocation(this.startLoc);
boolean of = false;
this.next();
if (this.eatContextual("each"))
of = true;
this.expect(TokenType.parenL);
Expression left = this.parseBindingAtom();
this.checkLVal(left, true, null);
boolean of;
if (this.eatContextual("of")) {
of = true;
} else {
this.expect(TokenType._in);
of = false;
}
Expression right = this.parseExpression(false, null);
this.expect(TokenType.parenR);
@@ -264,9 +297,8 @@ public class CustomParser extends FlowParser {
Expression filter = this.eat(TokenType._if) ? this.parseParenExpression() : null;
if (body == null)
body = this.parseExpression(false, null);
this.expect(isGenerator ? TokenType.parenR : TokenType.bracketR);
return this.finishNode(new ComprehensionExpression(new SourceLocation(startLoc), body, blocks, filter, isGenerator));
return new ComprehensionExpression(new SourceLocation(startLoc), body, blocks, filter, isGenerator);
}
@Override
@@ -280,12 +312,36 @@ public class CustomParser extends FlowParser {
"for".equals(input.substring(m.end(), m.end()+3)) &&
!Identifiers.isIdentifierChar(input.charAt(m.end()+3), true)) {
next();
return (Expression) parseComprehension(startLoc, true, null);
ComprehensionExpression c = parseComprehension(startLoc, true, null);
this.expect(TokenType.parenR);
return this.finishNode(c);
}
}
}
return super.parseParenAndDistinguishExpression(canBeArrow);
Expression res = super.parseParenAndDistinguishExpression(canBeArrow);
if (res instanceof ParenthesizedExpression) {
ParenthesizedExpression p = (ParenthesizedExpression) res;
if (p.getExpression() instanceof ComprehensionExpression) {
ComprehensionExpression c = (ComprehensionExpression) p.getExpression();
if (c.isGenerator())
return new ComprehensionExpression(p.getLoc(), c.getBody(), c.getBlocks(), c.getFilter(), c.isGenerator());
}
}
return res;
}
@Override
protected boolean parseParenthesisedExpression(DestructuringErrors refDestructuringErrors,
boolean allowTrailingComma, ParenthesisedExpressions parenExprs, boolean first) {
boolean cont = super.parseParenthesisedExpression(refDestructuringErrors, allowTrailingComma, parenExprs, first);
if (options.mozExtensions() && parenExprs.exprList.size() == 1 && this.type == TokenType._for) {
Expression body = parenExprs.exprList.remove(0);
ComprehensionExpression c = parseComprehension(body.getLoc().getStart(), true, body);
parenExprs.exprList.add(this.finishNode(c));
return false;
}
return cont;
}
// add parsing of for-each loops
@@ -320,4 +376,222 @@ public class CustomParser extends FlowParser {
}
return res;
}
/*
* E4X
*
* PrimaryExpression :
* PropertyIdentifier
* XMLInitialiser
* XMLListInitialiser
*
* PropertyIdentifier :
* AttributeIdentifier
* QualifiedIdentifier
* WildcardIdent
*
* AttributeIdentifier :
* @ PropertySelector
* @ QualifiedIdentifier
* @ [ Expression ]
*
* PropertySelector :
* Identifier
* WildcardIdentifier
*
* QualifiedIdentifier :
* PropertySelector :: PropertySelector
* PropertySelector :: [ Expression ]
*
* WildcardIdentifier :
* *
*
* MemberExpression :
* MemberExpression . PropertyIdentifier
* MemberExpression .. Identifier
* MemberExpression .. PropertyIdentifier
* MemberExpression . ( Expression )
*
* DefaultXMLNamespaceStatement :
* default xml namespace = Expression
*/
protected TokenType doubleDot = new TokenType(new Properties(":").beforeExpr());
@Override
protected Token getTokenFromCode(int code) {
if (options.e4x() && code == '.' && charAt(this.pos+1) == '.' && charAt(this.pos+2) != '.') {
this.pos += 2;
return this.finishToken(doubleDot);
}
return super.getTokenFromCode(code);
}
// add parsing of E4X property, attribute and descendant accesses, as well as filter expressions
@Override
protected Pair<Expression, Boolean> parseSubscript(Expression base, Position startLoc, boolean noCalls) {
if (options.e4x() && this.eat(TokenType.dot)) {
SourceLocation start = new SourceLocation(startLoc);
if (this.eat(TokenType.parenL)) {
Expression filter = parseExpression(false, null);
this.expect(TokenType.parenR);
return Pair.make(this.finishNode(new XMLFilterExpression(start, base, filter)), true);
}
Expression property = this.parsePropertyIdentifierOrIdentifier();
MemberExpression node = new MemberExpression(start, base, property, false, false, isOnOptionalChain(false, base));
return Pair.make(this.finishNode(node), true);
} else if (this.eat(doubleDot)) {
SourceLocation start = new SourceLocation(startLoc);
Expression property = this.parsePropertyIdentifierOrIdentifier();
return Pair.make(this.finishNode(new XMLDotDotExpression(start, base, property)), true);
}
return super.parseSubscript(base, startLoc, noCalls);
}
/**
* Parse a an attribute identifier, a wildcard identifier, a qualified identifier,
* or a plain identifier.
*/
protected Expression parsePropertyIdentifierOrIdentifier() {
Position start = this.startLoc;
if (this.eat(at)) {
// attribute identifier
return parseAttributeIdentifier(new SourceLocation(start));
} else {
return parsePropertySelector(new SourceLocation(startLoc));
}
}
/**
* Parse a property selector, that is, either a wildcard identifier or a plain identifier.
*/
protected Expression parsePropertySelector(SourceLocation start) {
Expression res;
if (this.eat(TokenType.star)) {
// wildcard identifier
res = this.finishNode(new XMLAnyName(start));
} else {
res = this.parseIdent(true);
}
return res;
}
/**
* Parse an attribute identifier, either computed ({@code [ Expr ]}) or a possibly
* qualified identifier.
*/
protected Expression parseAttributeIdentifier(SourceLocation start) {
if (this.eat(TokenType.bracketL)) {
Expression idx = parseExpression(false, null);
this.expect(TokenType.bracketR);
return this.finishNode(new XMLAttributeSelector(start, idx, true));
} else {
return this.finishNode(new XMLAttributeSelector(start, parsePropertySelector(new SourceLocation(startLoc)), false));
}
}
@Override
protected Expression parseDecoratorBody() {
SourceLocation start = new SourceLocation(startLoc);
if (options.e4x() && this.eat(TokenType.bracketL)) {
// this must be an attribute selector, so only allow a single expression
// followed by a right bracket, which will later be converted by
// `decoratorToAttributeSelector` below
List<Expression> elements = new ArrayList<>();
elements.add(parseExpression(false, null));
this.expect(TokenType.bracketR);
return this.finishNode(new ArrayExpression(start, elements));
}
return super.parseDecoratorBody();
}
/**
* Convert a decorator that resulted from mis-parsing an attribute selector into
* an attribute selector.
*/
protected XMLAttributeSelector decoratorToAttributeSelector(Decorator d) {
Expression e = d.getExpression();
if (e instanceof ArrayExpression) {
ArrayExpression ae = (ArrayExpression) e;
if (ae.getElements().size() == 1)
return new XMLAttributeSelector(d.getLoc(), ae.getElements().get(0), true);
} else if (e instanceof Identifier) {
return new XMLAttributeSelector(d.getLoc(), e, false);
}
return null;
}
@Override
protected Token readToken(int code) {
// skip XML processing instructions (which are allowed in E4X, but not in JSX);
// there is a lexical ambiguity between an XML processing instruction starting a
// chunk of E4X content and a Flow type annotation (both can start with `<?`)
// hence if we can't find the closing `?>` of a putative XML processing instruction
// we backtrack and try lexing as something else
// to avoid frequent backtracking, we only consider `<?xml ...?>` processing instructions;
// while other processing instructions are technically possible, they are unlikely in practice
if (this.options.e4x()) {
while (code == '<') {
if (inputSubstring(this.pos+1, this.pos+5).equals("?xml")) {
int oldPos = this.pos;
this.pos += 5;
if (!jsx_readUntil("?>")) {
// didn't find a closing `?>`, so backtrack
this.pos = oldPos;
break;
}
} else {
break;
}
this.skipSpace();
code = this.fullCharCodeAtPos();
}
}
return super.readToken(code);
}
@Override
protected Either<Integer, Token> jsx_readChunk(StringBuilder out, int chunkStart, int ch) {
// skip XML comments, processing instructions and CDATA (which are allowed in E4X,
// but not in JSX)
// unlike in `readToken` above, we know that we're inside JSX/E4X code, so there is
// no ambiguity with Flow type annotations
if (this.options.e4x() && ch == '<') {
if (inputSubstring(this.pos+1, this.pos+4).equals("!--")) {
out.append(inputSubstring(chunkStart, this.pos));
this.pos += 4;
jsx_readUntil("-->");
return Either.left(this.pos);
} else if (charAt(this.pos+1) == '?') {
out.append(inputSubstring(chunkStart, this.pos));
this.pos += 2;
jsx_readUntil("?>");
return Either.left(this.pos);
} else if (inputSubstring(this.pos+1, this.pos+9).equals("![CDATA[")) {
out.append(inputSubstring(chunkStart, this.pos));
this.pos += 9;
int cdataStart = this.pos;
jsx_readUntil("]]>");
out.append(inputSubstring(cdataStart, this.pos-3));
return Either.left(this.pos);
}
}
return super.jsx_readChunk(out, chunkStart, ch);
}
private boolean jsx_readUntil(String terminator) {
char fst = terminator.charAt(0);
while (this.pos+terminator.length() <= this.input.length()) {
if (charAt(this.pos) == fst &&
inputSubstring(this.pos, this.pos+terminator.length()).equals(terminator)) {
this.pos += terminator.length();
return true;
}
++this.pos;
}
return false;
}
}

View File

@@ -257,7 +257,7 @@ public class ESNextParser extends JSXParser {
return member;
}
private List<Decorator> parseDecorators() {
public List<Decorator> parseDecorators() {
List<Decorator> result = new ArrayList<Decorator>();
while (this.type == at)
result.add(this.parseDecorator());
@@ -267,10 +267,23 @@ public class ESNextParser extends JSXParser {
private Decorator parseDecorator() {
Position start = startLoc;
this.next();
Decorator decorator = new Decorator(new SourceLocation(start), this.parseMaybeAssign(false, null, null));
Expression body = parseDecoratorBody();
Decorator decorator = new Decorator(new SourceLocation(start), body);
return this.finishNode(decorator);
}
protected Expression parseDecoratorBody() {
Expression base;
int startPos = this.start;
Position startLoc = this.startLoc;
if (this.type == TokenType.parenL) {
base = parseParenExpression();
} else {
base = parseIdent(true);
}
return parseSubscripts(base, startPos, startLoc, false);
}
/*
* Support for proposed extensions to `export`
* (http://leebyron.com/ecmascript-export-ns-from and http://leebyron.com/ecmascript-export-default-from)

View File

@@ -32,7 +32,7 @@ public class Options {
}
private boolean allowHashBang, allowReturnOutsideFunction, allowImportExportEverywhere;
private boolean preserveParens, mozExtensions, jscript, esnext, v8Extensions;
private boolean preserveParens, mozExtensions, jscript, esnext, v8Extensions, e4x;
private int ecmaVersion;
private AllowReserved allowReserved;
private String sourceType;
@@ -59,6 +59,7 @@ public class Options {
this.jscript = false;
this.esnext = false;
this.v8Extensions = false;
this.e4x = false;
this.onRecoverableError = null;
}
@@ -71,6 +72,7 @@ public class Options {
this.jscript = that.jscript;
this.esnext = that.esnext;
this.v8Extensions = that.v8Extensions;
this.e4x = that.e4x;
this.ecmaVersion = that.ecmaVersion;
this.allowReserved = that.allowReserved;
this.sourceType = that.sourceType;
@@ -114,6 +116,10 @@ public class Options {
return v8Extensions;
}
public boolean e4x() {
return e4x;
}
public Identifiers.Dialect getDialect() {
switch (ecmaVersion) {
case 3:
@@ -183,6 +189,10 @@ public class Options {
this.v8Extensions = v8Extensions;
}
public void e4x(boolean e4x) {
this.e4x = e4x;
}
public Options preserveParens(boolean preserveParens) {
this.preserveParens = preserveParens;
return this;

View File

@@ -1478,7 +1478,7 @@ public class Parser {
}
}
private boolean isOnOptionalChain(boolean optional, Expression base) {
protected boolean isOnOptionalChain(boolean optional, Expression base) {
return optional || base instanceof Chainable && ((Chainable)base).isOnOptionalChain();
}
@@ -1691,27 +1691,40 @@ public class Parser {
first = false;
else
this.expect(TokenType.comma);
if (allowTrailingComma && this.afterTrailingComma(TokenType.parenR, true)) {
parenExprs.lastIsComma = true;
if (!parseParenthesisedExpression(refDestructuringErrors, allowTrailingComma, parenExprs, first))
break;
} else if (this.type == TokenType.ellipsis) {
parenExprs.spreadStart = this.start;
parenExprs.exprList.add(this.parseParenItem(this.parseRest(false), -1, null));
if (this.type == TokenType.comma)
this.raise(this.startLoc, "Comma is not permitted after the rest element");
break;
} else {
if (this.type == TokenType.parenL && parenExprs.innerParenStart == 0) {
parenExprs.innerParenStart = this.start;
}
parenExprs.exprList.add(this.parseMaybeAssign(false, refDestructuringErrors, this::parseParenItem));
}
}
parenExprs.endLoc = this.startLoc;
this.expect(TokenType.parenR);
return parenExprs;
}
/**
* Parse an expression that forms part of a comma-separated list of expressions between parentheses, adding
* it to `parenExprs`.
*
* @return true if more expressions may follow this one, false if it must be the last one
*/
protected boolean parseParenthesisedExpression(DestructuringErrors refDestructuringErrors,
boolean allowTrailingComma, ParenthesisedExpressions parenExprs, boolean first) {
if (allowTrailingComma && this.afterTrailingComma(TokenType.parenR, true)) {
parenExprs.lastIsComma = true;
return false;
} else if (this.type == TokenType.ellipsis) {
parenExprs.spreadStart = this.start;
parenExprs.exprList.add(this.parseParenItem(this.parseRest(false), -1, null));
if (this.type == TokenType.comma)
this.raise(this.startLoc, "Comma is not permitted after the rest element");
return false;
} else {
if (this.type == TokenType.parenL && parenExprs.innerParenStart == 0) {
parenExprs.innerParenStart = this.start;
}
parenExprs.exprList.add(this.parseMaybeAssign(false, refDestructuringErrors, this::parseParenItem));
}
return true;
}
protected Expression parseParenItem(Expression left, int startPos, Position startLoc) {
return left;
}
@@ -2099,8 +2112,10 @@ public class Parser {
if (this.inAsync && this.value.equals("await"))
this.raiseRecoverable(this.start, "Can not use 'await' as identifier inside an async function");
name = String.valueOf(this.value);
} else if (liberal && this.type.keyword != null) {
} else if (this.type.keyword != null) {
name = this.type.keyword;
if (!liberal)
raiseRecoverable(this.start, "Cannot use keyword '" + name + "' as an identifier.");
} else {
this.unexpected();
}
@@ -2257,9 +2272,6 @@ public class Parser {
if (this.options.ecmaVersion() < 6)
return this.parseIdent(false);
if (this.type == TokenType.name)
return this.parseIdent(false);
if (this.type == TokenType.bracketL) {
Position start = this.startLoc;
this.next();
@@ -2271,8 +2283,7 @@ public class Parser {
if (this.type == TokenType.braceL)
return this.parseObj(true, null);
this.unexpected();
return null;
return this.parseIdent(false);
}
protected List<Expression> parseBindingList(TokenType close, boolean allowEmpty, boolean allowTrailingComma, boolean allowNonIdent) {
@@ -2914,9 +2925,9 @@ public class Parser {
if (this.eat(TokenType.eq)) {
init = this.parseMaybeAssign(isFor, null, null);
} else if (kind.equals("const") && !(this.type == TokenType._in || (this.options.ecmaVersion() >= 6 && this.isContextual("of")))) {
this.unexpected();
this.raiseRecoverable(this.lastTokEnd, "Constant declarations require an initialization value");
} else if (!(id instanceof Identifier) && !(isFor && (this.type == TokenType._in || this.isContextual("of")))) {
this.raise(this.lastTokEnd, "Complex binding patterns require an initialization value");
this.raiseRecoverable(this.lastTokEnd, "Complex binding patterns require an initialization value");
}
declarations.add(this.finishNode(
new VariableDeclarator(new SourceLocation(varDeclStart), (IPattern) id, init, noTypeAnnotation, DeclarationFlags.none)));
@@ -2984,7 +2995,7 @@ public class Parser {
IFunction node;
SourceLocation loc = new SourceLocation(startLoc);
if (isStatement && id != null)
node = new FunctionDeclaration(loc, id, params, (BlockStatement) body, generator, async);
node = new FunctionDeclaration(loc, id, params, body, generator, async);
else
node = new FunctionExpression(loc, id, params, body, generator, async);
return this.finishNode(node);

View File

@@ -22,7 +22,6 @@ import com.semmle.js.ast.Expression;
import com.semmle.js.ast.ExpressionStatement;
import com.semmle.js.ast.FieldDefinition;
import com.semmle.js.ast.Identifier;
import com.semmle.js.ast.ImportDeclaration;
import com.semmle.js.ast.ImportSpecifier;
import com.semmle.js.ast.Literal;
import com.semmle.js.ast.MethodDefinition;
@@ -78,6 +77,8 @@ public class FlowParser extends ESNextParser {
private Function<Token, Void> onToken;
private boolean inType, noAnonFunctionType;
private List<Token> tokens = new ArrayList<Token>();
private Function<SyntaxError, ?> onRecoverableError;
private List<SyntaxError> errors = new ArrayList<SyntaxError>();
private State() {
this.exprAllowed = FlowParser.this.exprAllowed;
@@ -103,6 +104,10 @@ public class FlowParser extends ESNextParser {
// buffer tokens while we are in speculative mode
this.onToken = options.onToken();
options.onToken((tk) -> { tokens.add(tk); return null; });
// buffer recoverable errors while we are in speculative mode
this.onRecoverableError = options.onRecoverableError();
options.onRecoverableError((err) -> { errors.add(err); return null; });
}
private void reset() {
@@ -125,6 +130,7 @@ public class FlowParser extends ESNextParser {
options.onToken(this.onToken);
FlowParser.this.inType = this.inType;
FlowParser.this.noAnonFunctionType = this.noAnonFunctionType;
options.onRecoverableError(this.onRecoverableError);
}
private void commit() {
@@ -133,6 +139,12 @@ public class FlowParser extends ESNextParser {
if (this.onToken != null)
for (Token tk : tokens)
this.onToken.apply(tk);
// commit buffered syntax errors
options.onRecoverableError(this.onRecoverableError);
if (this.onRecoverableError != null)
for (SyntaxError err : errors)
this.onRecoverableError.apply(err);
}
}

View File

@@ -40,6 +40,7 @@ import com.semmle.js.ast.jsx.JSXMemberExpression;
import com.semmle.js.ast.jsx.JSXNamespacedName;
import com.semmle.js.ast.jsx.JSXOpeningElement;
import com.semmle.js.ast.jsx.JSXSpreadAttribute;
import com.semmle.util.data.Either;
/**
* Java port of <a href="https://github.com/RReverser/acorn-jsx">Acorn-JSX</a> as of version
@@ -92,37 +93,47 @@ public class JSXParser extends Parser {
for (;;) {
if (this.pos >= this.input.length())
this.raise(this.start, "Unterminated JSX contents");
int ch = this.charAt(this.pos);
Either<Integer, Token> chunk = jsx_readChunk(out, chunkStart, this.charAt(this.pos));
if (chunk.isRight())
return chunk.getRight();
chunkStart = chunk.getLeft();
}
}
switch (ch) {
case 60: // '<'
case 123: // '{'
if (this.pos == this.start) {
if (ch == 60 && this.exprAllowed) {
++this.pos;
return this.finishToken(jsxTagStart);
}
return this.getTokenFromCode(ch);
}
out.append(inputSubstring(chunkStart, this.pos));
return this.finishToken(jsxText, out.toString());
case 38: // '&'
out.append(inputSubstring(chunkStart, this.pos));
out.append(this.jsx_readEntity());
chunkStart = this.pos;
break;
default:
if (isNewLine(ch)) {
out.append(inputSubstring(chunkStart, this.pos));
out.append(this.jsx_readNewLine(true));
chunkStart = this.pos;
} else {
/**
* Reads a chunk of inline JSX content, returning either the start of the next chunk
* or the completed content token.
*/
protected Either<Integer, Token> jsx_readChunk(StringBuilder out, int chunkStart, int ch) {
switch (ch) {
case 60: // '<'
case 123: // '{'
if (this.pos == this.start) {
if (ch == 60 && this.exprAllowed) {
++this.pos;
return Either.right(this.finishToken(jsxTagStart));
}
return Either.right(this.getTokenFromCode(ch));
}
out.append(inputSubstring(chunkStart, this.pos));
return Either.right(this.finishToken(jsxText, out.toString()));
case 38: // '&'
out.append(inputSubstring(chunkStart, this.pos));
out.append(this.jsx_readEntity());
chunkStart = this.pos;
break;
default:
if (isNewLine(ch)) {
out.append(inputSubstring(chunkStart, this.pos));
out.append(this.jsx_readNewLine(true));
chunkStart = this.pos;
} else {
++this.pos;
}
}
return Either.left(chunkStart);
}
private String jsx_readNewLine(boolean normalizeCRLF) {

View File

@@ -734,4 +734,29 @@ public class DefaultVisitor<C, R> implements Visitor<C, R> {
public R visit(RestTypeExpr nd, C c) {
return visit((TypeExpression) nd, c);
}
@Override
public R visit(XMLAnyName nd, C c) {
return visit((Expression) nd, c);
}
@Override
public R visit(XMLAttributeSelector nd, C c) {
return visit((Expression) nd, c);
}
@Override
public R visit(XMLFilterExpression nd, C c) {
return visit((Expression) nd, c);
}
@Override
public R visit(XMLQualifiedIdentifier nd, C c) {
return visit((Expression) nd, c);
}
@Override
public R visit(XMLDotDotExpression nd, C c) {
return visit((Expression) nd, c);
}
}

View File

@@ -17,26 +17,26 @@ import com.semmle.ts.ast.TypeParameter;
* </pre>
*/
public class FunctionDeclaration extends Statement implements IFunction {
private final AFunction<BlockStatement> fn;
private final AFunction<? extends Node> fn;
private final boolean hasDeclareKeyword;
private int symbol = -1;
public FunctionDeclaration(SourceLocation loc, Identifier id, List<Expression> params, BlockStatement body, boolean generator,
public FunctionDeclaration(SourceLocation loc, Identifier id, List<Expression> params, Node body, boolean generator,
boolean async) {
this(loc, new AFunction<BlockStatement>(id, params, body, generator, async, Collections.emptyList(), Collections.emptyList(),
this(loc, new AFunction<>(id, params, body, generator, async, Collections.emptyList(), Collections.emptyList(),
Collections.emptyList(), null, null),
false);
}
public FunctionDeclaration(SourceLocation loc, Identifier id,
List<Expression> params, BlockStatement body, boolean generator, boolean async, boolean hasDeclareKeyword,
List<Expression> params, Node body, boolean generator, boolean async, boolean hasDeclareKeyword,
List<TypeParameter> typeParameters, List<ITypeExpression> parameterTypes, ITypeExpression returnType,
ITypeExpression thisParameterType) {
this(loc, new AFunction<BlockStatement>(id, params, body, generator, async, typeParameters, parameterTypes, Collections.emptyList(),
this(loc, new AFunction<>(id, params, body, generator, async, typeParameters, parameterTypes, Collections.emptyList(),
returnType, thisParameterType), hasDeclareKeyword);
}
private FunctionDeclaration(SourceLocation loc, AFunction<BlockStatement> fn, boolean hasDeclareKeyword) {
private FunctionDeclaration(SourceLocation loc, AFunction<Node> fn, boolean hasDeclareKeyword) {
super("FunctionDeclaration", loc);
this.fn = fn;
this.hasDeclareKeyword = hasDeclareKeyword;
@@ -56,7 +56,7 @@ public class FunctionDeclaration extends Statement implements IFunction {
@Override public boolean hasDefault(int i) { return fn.hasDefault(i); }
@Override public Expression getDefault(int i) { return fn.getDefault(i); }
@Override public IPattern getRest() { return fn.getRest(); }
@Override public BlockStatement getBody() { return fn.getBody(); }
@Override public Node getBody() { return fn.getBody(); }
@Override public boolean hasRest() { return fn.hasRest(); }
public boolean hasId() { return fn.hasId(); }
public boolean isGenerator() { return fn.isGenerator(); }

View File

@@ -18,7 +18,7 @@ public abstract class MemberDefinition<V extends Expression> extends Node {
/**
* The name of the member.
*
* If {@link #isComputed} is false, this must be an {@link Identifier}, otherwise
* If {@link #isComputed()} is false, this must be an {@link Identifier}, otherwise
* it can be an arbitrary expression.
*/
private final Expression key;

View File

@@ -704,4 +704,29 @@ public class NodeCopier implements Visitor<Void, INode> {
public INode visit(RestTypeExpr nd, Void c) {
return new RestTypeExpr(visit(nd.getLoc()), copy(nd.getArrayType()));
}
@Override
public INode visit(XMLAnyName nd, Void c) {
return new XMLAnyName(visit(nd.getLoc()));
}
@Override
public INode visit(XMLAttributeSelector nd, Void c) {
return new XMLAttributeSelector(visit(nd.getLoc()), copy(nd.getAttribute()), nd.isComputed());
}
@Override
public INode visit(XMLFilterExpression nd, Void c) {
return new XMLFilterExpression(visit(nd.getLoc()), copy(nd.getLeft()), copy(nd.getRight()));
}
@Override
public INode visit(XMLQualifiedIdentifier nd, Void c) {
return new XMLQualifiedIdentifier(visit(nd.getLoc()), copy(nd.getLeft()), copy(nd.getRight()), nd.isComputed());
}
@Override
public INode visit(XMLDotDotExpression nd, Void c) {
return new XMLDotDotExpression(visit(nd.getLoc()), copy(nd.getLeft()), copy(nd.getRight()));
}
}

View File

@@ -174,4 +174,9 @@ public interface Visitor<C, R> {
public R visit(ImportTypeExpr nd, C c);
public R visit(OptionalTypeExpr nd, C c);
public R visit(RestTypeExpr nd, C c);
public R visit(XMLAnyName nd, C c);
public R visit(XMLAttributeSelector nd, C c);
public R visit(XMLFilterExpression nd, C c);
public R visit(XMLQualifiedIdentifier nd, C c);
public R visit(XMLDotDotExpression nd, C c);
}

View File

@@ -0,0 +1,13 @@
package com.semmle.js.ast;
public class XMLAnyName extends Expression {
public XMLAnyName(SourceLocation loc) {
super("XMLAnyName", loc);
}
@Override
public <C, R> R accept(Visitor<C, R> v, C c) {
return v.visit(this, c);
}
}

View File

@@ -0,0 +1,26 @@
package com.semmle.js.ast;
public class XMLAttributeSelector extends Expression {
final Expression attribute;
final boolean computed;
public XMLAttributeSelector(SourceLocation loc, Expression attribute, boolean computed) {
super("XMLAttributeSelector", loc);
this.attribute = attribute;
this.computed = computed;
}
public Expression getAttribute() {
return attribute;
}
public boolean isComputed() {
return computed;
}
@Override
public <C, R> R accept(Visitor<C, R> v, C c) {
return v.visit(this, c);
}
}

View File

@@ -0,0 +1,25 @@
package com.semmle.js.ast;
public class XMLDotDotExpression extends Expression {
final Expression left, right;
public XMLDotDotExpression(SourceLocation loc, Expression left, Expression right) {
super("XMLDotDotExpression", loc);
this.left = left;
this.right = right;
}
public Expression getLeft() {
return left;
}
public Expression getRight() {
return right;
}
@Override
public <C, R> R accept(Visitor<C, R> v, C c) {
return v.visit(this, c);
}
}

View File

@@ -0,0 +1,25 @@
package com.semmle.js.ast;
public class XMLFilterExpression extends Expression {
final Expression left, right;
public XMLFilterExpression(SourceLocation loc, Expression left, Expression right) {
super("XMLFilterExpression", loc);
this.left = left;
this.right = right;
}
public Expression getLeft() {
return left;
}
public Expression getRight() {
return right;
}
@Override
public <C, R> R accept(Visitor<C, R> v, C c) {
return v.visit(this, c);
}
}

View File

@@ -0,0 +1,31 @@
package com.semmle.js.ast;
public class XMLQualifiedIdentifier extends Expression {
final Expression left, right;
final boolean computed;
public XMLQualifiedIdentifier(SourceLocation loc, Expression left, Expression right, boolean computed) {
super("XMLQualifiedIdentifier", loc);
this.left = left;
this.right = right;
this.computed = computed;
}
public Expression getLeft() {
return left;
}
public Expression getRight() {
return right;
}
public boolean isComputed() {
return computed;
}
@Override
public <C, R> R accept(Visitor<C, R> v, C c) {
return v.visit(this, c);
}
}

View File

@@ -90,6 +90,10 @@ import com.semmle.js.ast.VariableDeclaration;
import com.semmle.js.ast.VariableDeclarator;
import com.semmle.js.ast.WhileStatement;
import com.semmle.js.ast.WithStatement;
import com.semmle.js.ast.XMLAttributeSelector;
import com.semmle.js.ast.XMLDotDotExpression;
import com.semmle.js.ast.XMLFilterExpression;
import com.semmle.js.ast.XMLQualifiedIdentifier;
import com.semmle.js.ast.YieldExpression;
import com.semmle.js.ast.jsx.IJSXName;
import com.semmle.js.ast.jsx.JSXAttribute;
@@ -1878,6 +1882,37 @@ public class ASTExtractor {
visit(nd.getArrayType(), key, 0, IdContext.typeBind);
return key;
}
@Override
public Label visit(XMLAttributeSelector nd, Context c) {
Label key = super.visit(nd, c);
visit(nd.getAttribute(), key, 0, IdContext.label);
return key;
}
@Override
public Label visit(XMLFilterExpression nd, Context c) {
Label key = super.visit(nd, c);
visit(nd.getLeft(), key, 0);
visit(nd.getRight(), key, 1);
return key;
}
@Override
public Label visit(XMLQualifiedIdentifier nd, Context c) {
Label key = super.visit(nd, c);
visit(nd.getLeft(), key, 0);
visit(nd.getRight(), key, 1, nd.isComputed() ? IdContext.varBind : IdContext.label);
return key;
}
@Override
public Label visit(XMLDotDotExpression nd, Context c) {
Label key = super.visit(nd, c);
visit(nd.getLeft(), key, 0);
visit(nd.getRight(), key, 1, IdContext.label);
return key;
}
}
public void extract(Node root, Platform platform, SourceType sourceType, int toplevelKind) {

View File

@@ -91,6 +91,11 @@ import com.semmle.js.ast.VariableDeclarator;
import com.semmle.js.ast.Visitor;
import com.semmle.js.ast.WhileStatement;
import com.semmle.js.ast.WithStatement;
import com.semmle.js.ast.XMLAnyName;
import com.semmle.js.ast.XMLAttributeSelector;
import com.semmle.js.ast.XMLDotDotExpression;
import com.semmle.js.ast.XMLFilterExpression;
import com.semmle.js.ast.XMLQualifiedIdentifier;
import com.semmle.js.ast.YieldExpression;
import com.semmle.js.ast.jsx.IJSXName;
import com.semmle.js.ast.jsx.JSXAttribute;
@@ -508,6 +513,26 @@ public class CFGExtractor {
return nd.getRight().accept(this, null);
}
@Override
public Node visit(XMLAttributeSelector nd, Void c) {
return nd.getAttribute().accept(this, c);
}
@Override
public Node visit(XMLFilterExpression nd, Void c) {
return nd.getLeft().accept(this, c);
}
@Override
public Node visit(XMLQualifiedIdentifier nd, Void c) {
return nd.getLeft().accept(this, c);
}
@Override
public Node visit(XMLDotDotExpression nd, Void c) {
return nd.getLeft().accept(this, c);
}
public static Node of(Node nd) {
return nd.accept(new First(), null);
}
@@ -1965,6 +1990,40 @@ public class CFGExtractor {
succ(nd, c.getAllSuccessors());
return null;
}
@Override
public Void visit(XMLAnyName nd, SuccessorInfo c) {
succ(nd, c.getAllSuccessors());
return null;
}
@Override
public Void visit(XMLAttributeSelector nd, SuccessorInfo c) {
seq(nd.getAttribute(), nd);
succ(nd, c.getAllSuccessors());
return null;
}
@Override
public Void visit(XMLFilterExpression nd, SuccessorInfo c) {
seq(nd.getLeft(), nd.getRight(), nd);
succ(nd, c.getAllSuccessors());
return null;
}
@Override
public Void visit(XMLQualifiedIdentifier nd, SuccessorInfo c) {
seq(nd.getLeft(), nd.getRight(), nd);
succ(nd, c.getAllSuccessors());
return null;
}
@Override
public Void visit(XMLDotDotExpression nd, SuccessorInfo c) {
seq(nd.getLeft(), nd.getRight(), nd);
succ(nd, c.getAllSuccessors());
return null;
}
}
public void extract(Node nd) {

View File

@@ -20,6 +20,11 @@ import com.semmle.js.ast.MemberExpression;
import com.semmle.js.ast.MetaProperty;
import com.semmle.js.ast.UnaryExpression;
import com.semmle.js.ast.UpdateExpression;
import com.semmle.js.ast.XMLAnyName;
import com.semmle.js.ast.XMLAttributeSelector;
import com.semmle.js.ast.XMLDotDotExpression;
import com.semmle.js.ast.XMLFilterExpression;
import com.semmle.js.ast.XMLQualifiedIdentifier;
import com.semmle.js.ast.jsx.JSXIdentifier;
import com.semmle.js.ast.jsx.JSXMemberExpression;
import com.semmle.js.ast.jsx.JSXSpreadAttribute;
@@ -266,6 +271,31 @@ public class ExprKinds {
public Integer visit(DecoratorList nd, Void c) {
return 104;
}
@Override
public Integer visit(XMLAnyName nd, Void c) {
return 108;
}
@Override
public Integer visit(XMLAttributeSelector nd, Void c) {
return nd.isComputed() ? 110 : 109;
}
@Override
public Integer visit(XMLFilterExpression nd, Void c) {
return 111;
}
@Override
public Integer visit(XMLQualifiedIdentifier nd, Void c) {
return nd.isComputed() ? 113 : 112;
}
@Override
public Integer visit(XMLDotDotExpression nd, Void c) {
return 114;
}
}, null);
if (kind == null)
throw new CatastrophicError("Unsupported expression kind: " + expr.getClass());

View File

@@ -207,6 +207,9 @@ public class ExtractorConfig {
/** Should v8-specific language extensions be supported? */
private boolean v8Extensions;
/** Should E4X syntax be supported? */
private boolean e4x;
/** Should parse errors be reported as violations instead of aborting extraction? */
private boolean tolerateParseErrors;
@@ -248,6 +251,7 @@ public class ExtractorConfig {
this.v8Extensions = true;
}
this.typescriptMode = TypeScriptMode.NONE;
this.e4x = experimental;
this.defaultEncoding = StandardCharsets.UTF_8.name();
}
@@ -260,6 +264,7 @@ public class ExtractorConfig {
this.jsx = that.jsx;
this.esnext = that.esnext;
this.v8Extensions = that.v8Extensions;
this.e4x = that.e4x;
this.tolerateParseErrors = that.tolerateParseErrors;
this.fileType = that.fileType;
this.sourceType = that.sourceType;
@@ -340,6 +345,16 @@ public class ExtractorConfig {
return res;
}
public boolean isE4X() {
return e4x;
}
public ExtractorConfig withE4X(boolean e4x) {
ExtractorConfig res = new ExtractorConfig(this);
res.e4x = e4x;
return res;
}
public boolean isTolerateParseErrors() {
return tolerateParseErrors;
}
@@ -440,14 +455,11 @@ public class ExtractorConfig {
@Override
public String toString() {
return "ExtractorConfig [ecmaVersion=" + ecmaVersion + ", externs="
+ externs + ", platform=" + platform + ", mozExtensions="
+ mozExtensions + ", jscript=" + jscript + ", jsx=" + jsx
+ ", esnext=" + esnext + ", v8Extensions=" + v8Extensions
+ ", tolerateParseErrors=" + tolerateParseErrors
+ ", htmlHandling=" + htmlHandling + ", fileType=" + fileType
+ ", sourceType=" + sourceType + ", extractLines="
+ extractLines + ", typescript=" + typescriptMode
+ ", defaultEncoding=" + defaultEncoding + "]";
return "ExtractorConfig [ecmaVersion=" + ecmaVersion + ", externs=" + externs + ", platform=" + platform
+ ", mozExtensions=" + mozExtensions + ", jscript=" + jscript + ", jsx=" + jsx + ", esnext=" + esnext
+ ", v8Extensions=" + v8Extensions + ", e4x=" + e4x + ", tolerateParseErrors=" + tolerateParseErrors
+ ", htmlHandling=" + htmlHandling + ", fileType=" + fileType + ", sourceType=" + sourceType
+ ", extractLines=" + extractLines + ", typescriptMode=" + typescriptMode + ", defaultEncoding="
+ defaultEncoding + "]";
}
}

View File

@@ -332,7 +332,7 @@ public class Main {
argsParser.addFlag(P_EXPERIMENTAL, 0, "Enable experimental support for pending ECMAScript proposals "
+ "(public class fields, function.sent, decorators, export extensions, function bind, "
+ "parameter-less catch, dynamic import, numeric separators, bigints), "
+ "as well as other language extensions (JScript, Mozilla and v8-specific extensions) and full HTML extraction.");
+ "as well as other language extensions (E4X, JScript, Mozilla and v8-specific extensions) and full HTML extraction.");
argsParser.addFlag(P_EXTERNS, 0, "Extract the given JavaScript files as Closure-style externs.");
argsParser.addFlag(P_EXTRACT_PROGRAM_TEXT, 0, "Extract a representation of the textual content of the program "
+ "(in addition to its syntactic structure).");

View File

@@ -37,6 +37,8 @@ public class JcornWrapper {
options.esnext(true);
if (config.isV8Extensions())
options.v8Extensions(true);
if (config.isE4X())
options.e4x(true);
Program program = null;
List<ParseError> errors = new ArrayList<>();

View File

@@ -0,0 +1,13 @@
items.@id;
items.*[1];
order.@*;
e..employee.(@id == 0 || @id == 1);
message.@soap::encodingStyle;
message.soap::Body;
items.@[f()];
message.soap::[g()];
var e = <?xml version="1.0" encoding="UTF-8"?> <elt>
<!-- comment -->
<![CDATA[ some <cdata> ]]>
</elt>;

View File

@@ -0,0 +1,3 @@
{
"experimental": true
}

View File

@@ -0,0 +1,996 @@
#10000=@"/tst.js;sourcefile"
files(#10000,"/tst.js","tst","js",0)
#10001=@"/;folder"
folders(#10001,"/","")
containerparent(#10001,#10000)
#10002=@"loc,{#10000},0,0,0,0"
locations_default(#10002,#10000,0,0,0,0)
hasLocation(#10000,#10002)
#20000=@"global_scope"
scopes(#20000,0)
#20001=@"script;{#10000},1,1"
#20002=*
lines(#20002,#20001,"items.@id;","
")
#20003=@"loc,{#10000},1,1,1,10"
locations_default(#20003,#10000,1,1,1,10)
hasLocation(#20002,#20003)
#20004=*
lines(#20004,#20001,"items.*[1];","
")
#20005=@"loc,{#10000},2,1,2,11"
locations_default(#20005,#10000,2,1,2,11)
hasLocation(#20004,#20005)
#20006=*
lines(#20006,#20001,"order.@*;","
")
#20007=@"loc,{#10000},3,1,3,9"
locations_default(#20007,#10000,3,1,3,9)
hasLocation(#20006,#20007)
#20008=*
lines(#20008,#20001,"e..employee.(@id == 0 || @id == 1);","
")
#20009=@"loc,{#10000},4,1,4,35"
locations_default(#20009,#10000,4,1,4,35)
hasLocation(#20008,#20009)
#20010=*
lines(#20010,#20001,"message.@soap::encodingStyle;","
")
#20011=@"loc,{#10000},5,1,5,29"
locations_default(#20011,#10000,5,1,5,29)
hasLocation(#20010,#20011)
#20012=*
lines(#20012,#20001,"message.soap::Body;","
")
#20013=@"loc,{#10000},6,1,6,19"
locations_default(#20013,#10000,6,1,6,19)
hasLocation(#20012,#20013)
#20014=*
lines(#20014,#20001,"items.@[f()];","
")
#20015=@"loc,{#10000},7,1,7,13"
locations_default(#20015,#10000,7,1,7,13)
hasLocation(#20014,#20015)
#20016=*
lines(#20016,#20001,"message.soap::[g()];","
")
#20017=@"loc,{#10000},8,1,8,20"
locations_default(#20017,#10000,8,1,8,20)
hasLocation(#20016,#20017)
#20018=*
lines(#20018,#20001,"","
")
#20019=@"loc,{#10000},9,1,9,0"
locations_default(#20019,#10000,9,1,9,0)
hasLocation(#20018,#20019)
#20020=*
lines(#20020,#20001,"var e = <?xml version=""1.0"" encoding=""UTF-8""?> <elt>","
")
#20021=@"loc,{#10000},10,1,10,52"
locations_default(#20021,#10000,10,1,10,52)
hasLocation(#20020,#20021)
#20022=*
lines(#20022,#20001," <!-- comment -->","
")
#20023=@"loc,{#10000},11,1,11,18"
locations_default(#20023,#10000,11,1,11,18)
hasLocation(#20022,#20023)
indentation(#10000,11," ",2)
#20024=*
lines(#20024,#20001," <![CDATA[ some <cdata> ]]>","
")
#20025=@"loc,{#10000},12,1,12,28"
locations_default(#20025,#10000,12,1,12,28)
hasLocation(#20024,#20025)
indentation(#10000,12," ",2)
#20026=*
lines(#20026,#20001," </elt>;","
")
#20027=@"loc,{#10000},13,1,13,9"
locations_default(#20027,#10000,13,1,13,9)
hasLocation(#20026,#20027)
indentation(#10000,13," ",2)
numlines(#20001,13,12,0)
#20028=*
tokeninfo(#20028,6,#20001,0,"items")
#20029=@"loc,{#10000},1,1,1,5"
locations_default(#20029,#10000,1,1,1,5)
hasLocation(#20028,#20029)
#20030=*
tokeninfo(#20030,8,#20001,1,".")
#20031=@"loc,{#10000},1,6,1,6"
locations_default(#20031,#10000,1,6,1,6)
hasLocation(#20030,#20031)
#20032=*
tokeninfo(#20032,8,#20001,2,"@")
#20033=@"loc,{#10000},1,7,1,7"
locations_default(#20033,#10000,1,7,1,7)
hasLocation(#20032,#20033)
#20034=*
tokeninfo(#20034,6,#20001,3,"id")
#20035=@"loc,{#10000},1,8,1,9"
locations_default(#20035,#10000,1,8,1,9)
hasLocation(#20034,#20035)
#20036=*
tokeninfo(#20036,8,#20001,4,";")
#20037=@"loc,{#10000},1,10,1,10"
locations_default(#20037,#10000,1,10,1,10)
hasLocation(#20036,#20037)
#20038=*
tokeninfo(#20038,6,#20001,5,"items")
#20039=@"loc,{#10000},2,1,2,5"
locations_default(#20039,#10000,2,1,2,5)
hasLocation(#20038,#20039)
#20040=*
tokeninfo(#20040,8,#20001,6,".")
#20041=@"loc,{#10000},2,6,2,6"
locations_default(#20041,#10000,2,6,2,6)
hasLocation(#20040,#20041)
#20042=*
tokeninfo(#20042,8,#20001,7,"*")
#20043=@"loc,{#10000},2,7,2,7"
locations_default(#20043,#10000,2,7,2,7)
hasLocation(#20042,#20043)
#20044=*
tokeninfo(#20044,8,#20001,8,"[")
#20045=@"loc,{#10000},2,8,2,8"
locations_default(#20045,#10000,2,8,2,8)
hasLocation(#20044,#20045)
#20046=*
tokeninfo(#20046,3,#20001,9,"1")
#20047=@"loc,{#10000},2,9,2,9"
locations_default(#20047,#10000,2,9,2,9)
hasLocation(#20046,#20047)
#20048=*
tokeninfo(#20048,8,#20001,10,"]")
#20049=@"loc,{#10000},2,10,2,10"
locations_default(#20049,#10000,2,10,2,10)
hasLocation(#20048,#20049)
#20050=*
tokeninfo(#20050,8,#20001,11,";")
#20051=@"loc,{#10000},2,11,2,11"
locations_default(#20051,#10000,2,11,2,11)
hasLocation(#20050,#20051)
#20052=*
tokeninfo(#20052,6,#20001,12,"order")
#20053=@"loc,{#10000},3,1,3,5"
locations_default(#20053,#10000,3,1,3,5)
hasLocation(#20052,#20053)
#20054=*
tokeninfo(#20054,8,#20001,13,".")
#20055=@"loc,{#10000},3,6,3,6"
locations_default(#20055,#10000,3,6,3,6)
hasLocation(#20054,#20055)
#20056=*
tokeninfo(#20056,8,#20001,14,"@")
#20057=@"loc,{#10000},3,7,3,7"
locations_default(#20057,#10000,3,7,3,7)
hasLocation(#20056,#20057)
#20058=*
tokeninfo(#20058,8,#20001,15,"*")
#20059=@"loc,{#10000},3,8,3,8"
locations_default(#20059,#10000,3,8,3,8)
hasLocation(#20058,#20059)
#20060=*
tokeninfo(#20060,8,#20001,16,";")
#20061=@"loc,{#10000},3,9,3,9"
locations_default(#20061,#10000,3,9,3,9)
hasLocation(#20060,#20061)
#20062=*
tokeninfo(#20062,6,#20001,17,"e")
#20063=@"loc,{#10000},4,1,4,1"
locations_default(#20063,#10000,4,1,4,1)
hasLocation(#20062,#20063)
#20064=*
tokeninfo(#20064,8,#20001,18,"..")
#20065=@"loc,{#10000},4,2,4,3"
locations_default(#20065,#10000,4,2,4,3)
hasLocation(#20064,#20065)
#20066=*
tokeninfo(#20066,6,#20001,19,"employee")
#20067=@"loc,{#10000},4,4,4,11"
locations_default(#20067,#10000,4,4,4,11)
hasLocation(#20066,#20067)
#20068=*
tokeninfo(#20068,8,#20001,20,".")
#20069=@"loc,{#10000},4,12,4,12"
locations_default(#20069,#10000,4,12,4,12)
hasLocation(#20068,#20069)
#20070=*
tokeninfo(#20070,8,#20001,21,"(")
#20071=@"loc,{#10000},4,13,4,13"
locations_default(#20071,#10000,4,13,4,13)
hasLocation(#20070,#20071)
#20072=*
tokeninfo(#20072,8,#20001,22,"@")
#20073=@"loc,{#10000},4,14,4,14"
locations_default(#20073,#10000,4,14,4,14)
hasLocation(#20072,#20073)
#20074=*
tokeninfo(#20074,6,#20001,23,"id")
#20075=@"loc,{#10000},4,15,4,16"
locations_default(#20075,#10000,4,15,4,16)
hasLocation(#20074,#20075)
#20076=*
tokeninfo(#20076,8,#20001,24,"==")
#20077=@"loc,{#10000},4,18,4,19"
locations_default(#20077,#10000,4,18,4,19)
hasLocation(#20076,#20077)
#20078=*
tokeninfo(#20078,3,#20001,25,"0")
#20079=@"loc,{#10000},4,21,4,21"
locations_default(#20079,#10000,4,21,4,21)
hasLocation(#20078,#20079)
#20080=*
tokeninfo(#20080,8,#20001,26,"||")
#20081=@"loc,{#10000},4,23,4,24"
locations_default(#20081,#10000,4,23,4,24)
hasLocation(#20080,#20081)
#20082=*
tokeninfo(#20082,8,#20001,27,"@")
#20083=@"loc,{#10000},4,26,4,26"
locations_default(#20083,#10000,4,26,4,26)
hasLocation(#20082,#20083)
#20084=*
tokeninfo(#20084,6,#20001,28,"id")
#20085=@"loc,{#10000},4,27,4,28"
locations_default(#20085,#10000,4,27,4,28)
hasLocation(#20084,#20085)
#20086=*
tokeninfo(#20086,8,#20001,29,"==")
#20087=@"loc,{#10000},4,30,4,31"
locations_default(#20087,#10000,4,30,4,31)
hasLocation(#20086,#20087)
#20088=*
tokeninfo(#20088,3,#20001,30,"1")
#20089=@"loc,{#10000},4,33,4,33"
locations_default(#20089,#10000,4,33,4,33)
hasLocation(#20088,#20089)
#20090=*
tokeninfo(#20090,8,#20001,31,")")
#20091=@"loc,{#10000},4,34,4,34"
locations_default(#20091,#10000,4,34,4,34)
hasLocation(#20090,#20091)
#20092=*
tokeninfo(#20092,8,#20001,32,";")
#20093=@"loc,{#10000},4,35,4,35"
locations_default(#20093,#10000,4,35,4,35)
hasLocation(#20092,#20093)
#20094=*
tokeninfo(#20094,6,#20001,33,"message")
#20095=@"loc,{#10000},5,1,5,7"
locations_default(#20095,#10000,5,1,5,7)
hasLocation(#20094,#20095)
#20096=*
tokeninfo(#20096,8,#20001,34,".")
#20097=@"loc,{#10000},5,8,5,8"
locations_default(#20097,#10000,5,8,5,8)
hasLocation(#20096,#20097)
#20098=*
tokeninfo(#20098,8,#20001,35,"@")
#20099=@"loc,{#10000},5,9,5,9"
locations_default(#20099,#10000,5,9,5,9)
hasLocation(#20098,#20099)
#20100=*
tokeninfo(#20100,6,#20001,36,"soap")
#20101=@"loc,{#10000},5,10,5,13"
locations_default(#20101,#10000,5,10,5,13)
hasLocation(#20100,#20101)
#20102=*
tokeninfo(#20102,8,#20001,37,"::")
#20103=@"loc,{#10000},5,14,5,15"
locations_default(#20103,#10000,5,14,5,15)
hasLocation(#20102,#20103)
#20104=*
tokeninfo(#20104,6,#20001,38,"encodingStyle")
#20105=@"loc,{#10000},5,16,5,28"
locations_default(#20105,#10000,5,16,5,28)
hasLocation(#20104,#20105)
#20106=*
tokeninfo(#20106,8,#20001,39,";")
#20107=@"loc,{#10000},5,29,5,29"
locations_default(#20107,#10000,5,29,5,29)
hasLocation(#20106,#20107)
#20108=*
tokeninfo(#20108,6,#20001,40,"message")
#20109=@"loc,{#10000},6,1,6,7"
locations_default(#20109,#10000,6,1,6,7)
hasLocation(#20108,#20109)
#20110=*
tokeninfo(#20110,8,#20001,41,".")
#20111=@"loc,{#10000},6,8,6,8"
locations_default(#20111,#10000,6,8,6,8)
hasLocation(#20110,#20111)
#20112=*
tokeninfo(#20112,6,#20001,42,"soap")
#20113=@"loc,{#10000},6,9,6,12"
locations_default(#20113,#10000,6,9,6,12)
hasLocation(#20112,#20113)
#20114=*
tokeninfo(#20114,8,#20001,43,"::")
#20115=@"loc,{#10000},6,13,6,14"
locations_default(#20115,#10000,6,13,6,14)
hasLocation(#20114,#20115)
#20116=*
tokeninfo(#20116,6,#20001,44,"Body")
#20117=@"loc,{#10000},6,15,6,18"
locations_default(#20117,#10000,6,15,6,18)
hasLocation(#20116,#20117)
#20118=*
tokeninfo(#20118,8,#20001,45,";")
#20119=@"loc,{#10000},6,19,6,19"
locations_default(#20119,#10000,6,19,6,19)
hasLocation(#20118,#20119)
#20120=*
tokeninfo(#20120,6,#20001,46,"items")
#20121=@"loc,{#10000},7,1,7,5"
locations_default(#20121,#10000,7,1,7,5)
hasLocation(#20120,#20121)
#20122=*
tokeninfo(#20122,8,#20001,47,".")
#20123=@"loc,{#10000},7,6,7,6"
locations_default(#20123,#10000,7,6,7,6)
hasLocation(#20122,#20123)
#20124=*
tokeninfo(#20124,8,#20001,48,"@")
#20125=@"loc,{#10000},7,7,7,7"
locations_default(#20125,#10000,7,7,7,7)
hasLocation(#20124,#20125)
#20126=*
tokeninfo(#20126,8,#20001,49,"[")
#20127=@"loc,{#10000},7,8,7,8"
locations_default(#20127,#10000,7,8,7,8)
hasLocation(#20126,#20127)
#20128=*
tokeninfo(#20128,6,#20001,50,"f")
#20129=@"loc,{#10000},7,9,7,9"
locations_default(#20129,#10000,7,9,7,9)
hasLocation(#20128,#20129)
#20130=*
tokeninfo(#20130,8,#20001,51,"(")
#20131=@"loc,{#10000},7,10,7,10"
locations_default(#20131,#10000,7,10,7,10)
hasLocation(#20130,#20131)
#20132=*
tokeninfo(#20132,8,#20001,52,")")
#20133=@"loc,{#10000},7,11,7,11"
locations_default(#20133,#10000,7,11,7,11)
hasLocation(#20132,#20133)
#20134=*
tokeninfo(#20134,8,#20001,53,"]")
#20135=@"loc,{#10000},7,12,7,12"
locations_default(#20135,#10000,7,12,7,12)
hasLocation(#20134,#20135)
#20136=*
tokeninfo(#20136,8,#20001,54,";")
#20137=@"loc,{#10000},7,13,7,13"
locations_default(#20137,#10000,7,13,7,13)
hasLocation(#20136,#20137)
#20138=*
tokeninfo(#20138,6,#20001,55,"message")
#20139=@"loc,{#10000},8,1,8,7"
locations_default(#20139,#10000,8,1,8,7)
hasLocation(#20138,#20139)
#20140=*
tokeninfo(#20140,8,#20001,56,".")
#20141=@"loc,{#10000},8,8,8,8"
locations_default(#20141,#10000,8,8,8,8)
hasLocation(#20140,#20141)
#20142=*
tokeninfo(#20142,6,#20001,57,"soap")
#20143=@"loc,{#10000},8,9,8,12"
locations_default(#20143,#10000,8,9,8,12)
hasLocation(#20142,#20143)
#20144=*
tokeninfo(#20144,8,#20001,58,"::")
#20145=@"loc,{#10000},8,13,8,14"
locations_default(#20145,#10000,8,13,8,14)
hasLocation(#20144,#20145)
#20146=*
tokeninfo(#20146,8,#20001,59,"[")
#20147=@"loc,{#10000},8,15,8,15"
locations_default(#20147,#10000,8,15,8,15)
hasLocation(#20146,#20147)
#20148=*
tokeninfo(#20148,6,#20001,60,"g")
#20149=@"loc,{#10000},8,16,8,16"
locations_default(#20149,#10000,8,16,8,16)
hasLocation(#20148,#20149)
#20150=*
tokeninfo(#20150,8,#20001,61,"(")
#20151=@"loc,{#10000},8,17,8,17"
locations_default(#20151,#10000,8,17,8,17)
hasLocation(#20150,#20151)
#20152=*
tokeninfo(#20152,8,#20001,62,")")
#20153=@"loc,{#10000},8,18,8,18"
locations_default(#20153,#10000,8,18,8,18)
hasLocation(#20152,#20153)
#20154=*
tokeninfo(#20154,8,#20001,63,"]")
#20155=@"loc,{#10000},8,19,8,19"
locations_default(#20155,#10000,8,19,8,19)
hasLocation(#20154,#20155)
#20156=*
tokeninfo(#20156,8,#20001,64,";")
#20157=@"loc,{#10000},8,20,8,20"
locations_default(#20157,#10000,8,20,8,20)
hasLocation(#20156,#20157)
#20158=*
tokeninfo(#20158,7,#20001,65,"var")
#20159=@"loc,{#10000},10,1,10,3"
locations_default(#20159,#10000,10,1,10,3)
hasLocation(#20158,#20159)
#20160=*
tokeninfo(#20160,6,#20001,66,"e")
#20161=@"loc,{#10000},10,5,10,5"
locations_default(#20161,#10000,10,5,10,5)
hasLocation(#20160,#20161)
#20162=*
tokeninfo(#20162,8,#20001,67,"=")
#20163=@"loc,{#10000},10,7,10,7"
locations_default(#20163,#10000,10,7,10,7)
hasLocation(#20162,#20163)
#20164=*
tokeninfo(#20164,8,#20001,68,"<?xml version=""1.0"" encoding=""UTF-8""?> <")
#20165=@"loc,{#10000},10,9,10,48"
locations_default(#20165,#10000,10,9,10,48)
hasLocation(#20164,#20165)
#20166=*
tokeninfo(#20166,6,#20001,69,"elt")
#20167=@"loc,{#10000},10,49,10,51"
locations_default(#20167,#10000,10,49,10,51)
hasLocation(#20166,#20167)
#20168=*
tokeninfo(#20168,8,#20001,70,">")
#20169=@"loc,{#10000},10,52,10,52"
locations_default(#20169,#10000,10,52,10,52)
hasLocation(#20168,#20169)
#20170=*
tokeninfo(#20170,4,#20001,71,"
<!-- comment -->
<![CDATA[ some <cdata> ]]>
")
#20171=@"loc,{#10000},10,53,13,2"
locations_default(#20171,#10000,10,53,13,2)
hasLocation(#20170,#20171)
#20172=*
tokeninfo(#20172,8,#20001,72,"<")
#20173=@"loc,{#10000},13,3,13,3"
locations_default(#20173,#10000,13,3,13,3)
hasLocation(#20172,#20173)
#20174=*
tokeninfo(#20174,8,#20001,73,"/")
#20175=@"loc,{#10000},13,4,13,4"
locations_default(#20175,#10000,13,4,13,4)
hasLocation(#20174,#20175)
#20176=*
tokeninfo(#20176,6,#20001,74,"elt")
#20177=@"loc,{#10000},13,5,13,7"
locations_default(#20177,#10000,13,5,13,7)
hasLocation(#20176,#20177)
#20178=*
tokeninfo(#20178,8,#20001,75,">")
#20179=@"loc,{#10000},13,8,13,8"
locations_default(#20179,#10000,13,8,13,8)
hasLocation(#20178,#20179)
#20180=*
tokeninfo(#20180,8,#20001,76,";")
#20181=@"loc,{#10000},13,9,13,9"
locations_default(#20181,#10000,13,9,13,9)
hasLocation(#20180,#20181)
#20182=*
tokeninfo(#20182,0,#20001,77,"")
#20183=@"loc,{#10000},14,1,14,0"
locations_default(#20183,#10000,14,1,14,0)
hasLocation(#20182,#20183)
toplevels(#20001,0)
#20184=@"loc,{#10000},1,1,14,0"
locations_default(#20184,#10000,1,1,14,0)
hasLocation(#20001,#20184)
#20185=@"var;{e};{#20000}"
variables(#20185,"e",#20000)
#20186=*
stmts(#20186,2,#20001,0,"items.@id;")
hasLocation(#20186,#20003)
stmtContainers(#20186,#20001)
#20187=*
exprs(#20187,14,#20186,0,"items.@id")
#20188=@"loc,{#10000},1,1,1,9"
locations_default(#20188,#10000,1,1,1,9)
hasLocation(#20187,#20188)
enclosingStmt(#20187,#20186)
exprContainers(#20187,#20001)
#20189=*
exprs(#20189,79,#20187,0,"items")
hasLocation(#20189,#20029)
enclosingStmt(#20189,#20186)
exprContainers(#20189,#20001)
literals("items","items",#20189)
#20190=@"var;{items};{#20000}"
variables(#20190,"items",#20000)
bind(#20189,#20190)
#20191=*
exprs(#20191,109,#20187,1,"@id")
#20192=@"loc,{#10000},1,7,1,9"
locations_default(#20192,#10000,1,7,1,9)
hasLocation(#20191,#20192)
enclosingStmt(#20191,#20186)
exprContainers(#20191,#20001)
#20193=*
exprs(#20193,0,#20191,0,"id")
hasLocation(#20193,#20035)
enclosingStmt(#20193,#20186)
exprContainers(#20193,#20001)
literals("id","id",#20193)
#20194=*
stmts(#20194,2,#20001,1,"items.*[1];")
hasLocation(#20194,#20005)
stmtContainers(#20194,#20001)
#20195=*
exprs(#20195,15,#20194,0,"items.*[1]")
#20196=@"loc,{#10000},2,1,2,10"
locations_default(#20196,#10000,2,1,2,10)
hasLocation(#20195,#20196)
enclosingStmt(#20195,#20194)
exprContainers(#20195,#20001)
#20197=*
exprs(#20197,14,#20195,0,"items.*")
#20198=@"loc,{#10000},2,1,2,7"
locations_default(#20198,#10000,2,1,2,7)
hasLocation(#20197,#20198)
enclosingStmt(#20197,#20194)
exprContainers(#20197,#20001)
#20199=*
exprs(#20199,79,#20197,0,"items")
hasLocation(#20199,#20039)
enclosingStmt(#20199,#20194)
exprContainers(#20199,#20001)
literals("items","items",#20199)
bind(#20199,#20190)
#20200=*
exprs(#20200,108,#20197,1,"*")
hasLocation(#20200,#20043)
enclosingStmt(#20200,#20194)
exprContainers(#20200,#20001)
#20201=*
exprs(#20201,3,#20195,1,"1")
hasLocation(#20201,#20047)
enclosingStmt(#20201,#20194)
exprContainers(#20201,#20001)
literals("1","1",#20201)
#20202=*
stmts(#20202,2,#20001,2,"order.@*;")
hasLocation(#20202,#20007)
stmtContainers(#20202,#20001)
#20203=*
exprs(#20203,14,#20202,0,"order.@*")
#20204=@"loc,{#10000},3,1,3,8"
locations_default(#20204,#10000,3,1,3,8)
hasLocation(#20203,#20204)
enclosingStmt(#20203,#20202)
exprContainers(#20203,#20001)
#20205=*
exprs(#20205,79,#20203,0,"order")
hasLocation(#20205,#20053)
enclosingStmt(#20205,#20202)
exprContainers(#20205,#20001)
literals("order","order",#20205)
#20206=@"var;{order};{#20000}"
variables(#20206,"order",#20000)
bind(#20205,#20206)
#20207=*
exprs(#20207,109,#20203,1,"@*")
#20208=@"loc,{#10000},3,7,3,8"
locations_default(#20208,#10000,3,7,3,8)
hasLocation(#20207,#20208)
enclosingStmt(#20207,#20202)
exprContainers(#20207,#20001)
#20209=*
exprs(#20209,108,#20207,0,"*")
hasLocation(#20209,#20059)
enclosingStmt(#20209,#20202)
exprContainers(#20209,#20001)
#20210=*
stmts(#20210,2,#20001,3,"e..empl ... == 1);")
hasLocation(#20210,#20009)
stmtContainers(#20210,#20001)
#20211=*
exprs(#20211,111,#20210,0,"e..empl ... d == 1)")
#20212=@"loc,{#10000},4,1,4,34"
locations_default(#20212,#10000,4,1,4,34)
hasLocation(#20211,#20212)
enclosingStmt(#20211,#20210)
exprContainers(#20211,#20001)
#20213=*
exprs(#20213,114,#20211,0,"e..employee")
#20214=@"loc,{#10000},4,1,4,11"
locations_default(#20214,#10000,4,1,4,11)
hasLocation(#20213,#20214)
enclosingStmt(#20213,#20210)
exprContainers(#20213,#20001)
#20215=*
exprs(#20215,79,#20213,0,"e")
hasLocation(#20215,#20063)
enclosingStmt(#20215,#20210)
exprContainers(#20215,#20001)
literals("e","e",#20215)
bind(#20215,#20185)
#20216=*
exprs(#20216,0,#20213,1,"employee")
hasLocation(#20216,#20067)
enclosingStmt(#20216,#20210)
exprContainers(#20216,#20001)
literals("employee","employee",#20216)
#20217=*
exprs(#20217,45,#20211,1,"@id == 0 || @id == 1")
#20218=@"loc,{#10000},4,14,4,33"
locations_default(#20218,#10000,4,14,4,33)
hasLocation(#20217,#20218)
enclosingStmt(#20217,#20210)
exprContainers(#20217,#20001)
#20219=*
exprs(#20219,23,#20217,0,"@id == 0")
#20220=@"loc,{#10000},4,14,4,21"
locations_default(#20220,#10000,4,14,4,21)
hasLocation(#20219,#20220)
enclosingStmt(#20219,#20210)
exprContainers(#20219,#20001)
#20221=*
exprs(#20221,109,#20219,0,"@id")
#20222=@"loc,{#10000},4,14,4,16"
locations_default(#20222,#10000,4,14,4,16)
hasLocation(#20221,#20222)
enclosingStmt(#20221,#20210)
exprContainers(#20221,#20001)
#20223=*
exprs(#20223,0,#20221,0,"id")
hasLocation(#20223,#20075)
enclosingStmt(#20223,#20210)
exprContainers(#20223,#20001)
literals("id","id",#20223)
#20224=*
exprs(#20224,3,#20219,1,"0")
hasLocation(#20224,#20079)
enclosingStmt(#20224,#20210)
exprContainers(#20224,#20001)
literals("0","0",#20224)
#20225=*
exprs(#20225,23,#20217,1,"@id == 1")
#20226=@"loc,{#10000},4,26,4,33"
locations_default(#20226,#10000,4,26,4,33)
hasLocation(#20225,#20226)
enclosingStmt(#20225,#20210)
exprContainers(#20225,#20001)
#20227=*
exprs(#20227,109,#20225,0,"@id")
#20228=@"loc,{#10000},4,26,4,28"
locations_default(#20228,#10000,4,26,4,28)
hasLocation(#20227,#20228)
enclosingStmt(#20227,#20210)
exprContainers(#20227,#20001)
#20229=*
exprs(#20229,0,#20227,0,"id")
hasLocation(#20229,#20085)
enclosingStmt(#20229,#20210)
exprContainers(#20229,#20001)
literals("id","id",#20229)
#20230=*
exprs(#20230,3,#20225,1,"1")
hasLocation(#20230,#20089)
enclosingStmt(#20230,#20210)
exprContainers(#20230,#20001)
literals("1","1",#20230)
#20231=*
stmts(#20231,2,#20001,4,"message ... gStyle;")
hasLocation(#20231,#20011)
stmtContainers(#20231,#20001)
#20232=*
exprs(#20232,97,#20231,0,"message ... ngStyle")
#20233=@"loc,{#10000},5,1,5,28"
locations_default(#20233,#10000,5,1,5,28)
hasLocation(#20232,#20233)
enclosingStmt(#20232,#20231)
exprContainers(#20232,#20001)
#20234=*
exprs(#20234,14,#20232,0,"message.@soap")
#20235=@"loc,{#10000},5,1,5,13"
locations_default(#20235,#10000,5,1,5,13)
hasLocation(#20234,#20235)
enclosingStmt(#20234,#20231)
exprContainers(#20234,#20001)
#20236=*
exprs(#20236,79,#20234,0,"message")
hasLocation(#20236,#20095)
enclosingStmt(#20236,#20231)
exprContainers(#20236,#20001)
literals("message","message",#20236)
#20237=@"var;{message};{#20000}"
variables(#20237,"message",#20000)
bind(#20236,#20237)
#20238=*
exprs(#20238,109,#20234,1,"@soap")
#20239=@"loc,{#10000},5,9,5,13"
locations_default(#20239,#10000,5,9,5,13)
hasLocation(#20238,#20239)
enclosingStmt(#20238,#20231)
exprContainers(#20238,#20001)
#20240=*
exprs(#20240,0,#20238,0,"soap")
hasLocation(#20240,#20101)
enclosingStmt(#20240,#20231)
exprContainers(#20240,#20001)
literals("soap","soap",#20240)
#20241=*
exprs(#20241,79,#20232,1,"encodingStyle")
hasLocation(#20241,#20105)
enclosingStmt(#20241,#20231)
exprContainers(#20241,#20001)
literals("encodingStyle","encodingStyle",#20241)
#20242=@"var;{encodingStyle};{#20000}"
variables(#20242,"encodingStyle",#20000)
bind(#20241,#20242)
#20243=*
stmts(#20243,2,#20001,5,"message.soap::Body;")
hasLocation(#20243,#20013)
stmtContainers(#20243,#20001)
#20244=*
exprs(#20244,97,#20243,0,"message.soap::Body")
#20245=@"loc,{#10000},6,1,6,18"
locations_default(#20245,#10000,6,1,6,18)
hasLocation(#20244,#20245)
enclosingStmt(#20244,#20243)
exprContainers(#20244,#20001)
#20246=*
exprs(#20246,14,#20244,0,"message.soap")
#20247=@"loc,{#10000},6,1,6,12"
locations_default(#20247,#10000,6,1,6,12)
hasLocation(#20246,#20247)
enclosingStmt(#20246,#20243)
exprContainers(#20246,#20001)
#20248=*
exprs(#20248,79,#20246,0,"message")
hasLocation(#20248,#20109)
enclosingStmt(#20248,#20243)
exprContainers(#20248,#20001)
literals("message","message",#20248)
bind(#20248,#20237)
#20249=*
exprs(#20249,0,#20246,1,"soap")
hasLocation(#20249,#20113)
enclosingStmt(#20249,#20243)
exprContainers(#20249,#20001)
literals("soap","soap",#20249)
#20250=*
exprs(#20250,79,#20244,1,"Body")
hasLocation(#20250,#20117)
enclosingStmt(#20250,#20243)
exprContainers(#20250,#20001)
literals("Body","Body",#20250)
#20251=@"var;{Body};{#20000}"
variables(#20251,"Body",#20000)
bind(#20250,#20251)
#20252=*
stmts(#20252,2,#20001,6,"items.@[f()];")
hasLocation(#20252,#20015)
stmtContainers(#20252,#20001)
#20253=*
exprs(#20253,14,#20252,0,"items.@[f()]")
#20254=@"loc,{#10000},7,1,7,12"
locations_default(#20254,#10000,7,1,7,12)
hasLocation(#20253,#20254)
enclosingStmt(#20253,#20252)
exprContainers(#20253,#20001)
#20255=*
exprs(#20255,79,#20253,0,"items")
hasLocation(#20255,#20121)
enclosingStmt(#20255,#20252)
exprContainers(#20255,#20001)
literals("items","items",#20255)
bind(#20255,#20190)
#20256=*
exprs(#20256,110,#20253,1,"@[f()]")
#20257=@"loc,{#10000},7,7,7,12"
locations_default(#20257,#10000,7,7,7,12)
hasLocation(#20256,#20257)
enclosingStmt(#20256,#20252)
exprContainers(#20256,#20001)
#20258=*
exprs(#20258,13,#20256,0,"f()")
#20259=@"loc,{#10000},7,9,7,11"
locations_default(#20259,#10000,7,9,7,11)
hasLocation(#20258,#20259)
enclosingStmt(#20258,#20252)
exprContainers(#20258,#20001)
#20260=*
exprs(#20260,79,#20258,-1,"f")
hasLocation(#20260,#20129)
enclosingStmt(#20260,#20252)
exprContainers(#20260,#20001)
literals("f","f",#20260)
#20261=@"var;{f};{#20000}"
variables(#20261,"f",#20000)
bind(#20260,#20261)
#20262=*
stmts(#20262,2,#20001,7,"message.soap::[g()];")
hasLocation(#20262,#20017)
stmtContainers(#20262,#20001)
#20263=*
exprs(#20263,97,#20262,0,"message.soap::[g()]")
#20264=@"loc,{#10000},8,1,8,19"
locations_default(#20264,#10000,8,1,8,19)
hasLocation(#20263,#20264)
enclosingStmt(#20263,#20262)
exprContainers(#20263,#20001)
#20265=*
exprs(#20265,14,#20263,0,"message.soap")
#20266=@"loc,{#10000},8,1,8,12"
locations_default(#20266,#10000,8,1,8,12)
hasLocation(#20265,#20266)
enclosingStmt(#20265,#20262)
exprContainers(#20265,#20001)
#20267=*
exprs(#20267,79,#20265,0,"message")
hasLocation(#20267,#20139)
enclosingStmt(#20267,#20262)
exprContainers(#20267,#20001)
literals("message","message",#20267)
bind(#20267,#20237)
#20268=*
exprs(#20268,0,#20265,1,"soap")
hasLocation(#20268,#20143)
enclosingStmt(#20268,#20262)
exprContainers(#20268,#20001)
literals("soap","soap",#20268)
#20269=*
exprs(#20269,7,#20263,1,"[g()]")
#20270=@"loc,{#10000},8,15,8,19"
locations_default(#20270,#10000,8,15,8,19)
hasLocation(#20269,#20270)
enclosingStmt(#20269,#20262)
exprContainers(#20269,#20001)
#20271=*
exprs(#20271,13,#20269,0,"g()")
#20272=@"loc,{#10000},8,16,8,18"
locations_default(#20272,#10000,8,16,8,18)
hasLocation(#20271,#20272)
enclosingStmt(#20271,#20262)
exprContainers(#20271,#20001)
#20273=*
exprs(#20273,79,#20271,-1,"g")
hasLocation(#20273,#20149)
enclosingStmt(#20273,#20262)
exprContainers(#20273,#20001)
literals("g","g",#20273)
#20274=@"var;{g};{#20000}"
variables(#20274,"g",#20000)
bind(#20273,#20274)
arraySize(#20269,1)
#20275=*
stmts(#20275,18,#20001,8,"var e = ... </elt>;")
#20276=@"loc,{#10000},10,1,13,9"
locations_default(#20276,#10000,10,1,13,9)
hasLocation(#20275,#20276)
stmtContainers(#20275,#20001)
#20277=*
exprs(#20277,64,#20275,0,"e = <?x ... </elt>")
#20278=@"loc,{#10000},10,5,13,8"
locations_default(#20278,#10000,10,5,13,8)
hasLocation(#20277,#20278)
enclosingStmt(#20277,#20275)
exprContainers(#20277,#20001)
#20279=*
exprs(#20279,78,#20277,0,"e")
hasLocation(#20279,#20161)
enclosingStmt(#20279,#20275)
exprContainers(#20279,#20001)
literals("e","e",#20279)
decl(#20279,#20185)
#20280=*
exprs(#20280,89,#20277,1,"<?xml v ... </elt>")
#20281=@"loc,{#10000},10,9,13,8"
locations_default(#20281,#10000,10,9,13,8)
hasLocation(#20280,#20281)
enclosingStmt(#20280,#20275)
exprContainers(#20280,#20001)
#20282=*
exprs(#20282,0,#20280,-1,"elt")
hasLocation(#20282,#20167)
enclosingStmt(#20282,#20275)
exprContainers(#20282,#20001)
literals("elt","elt",#20282)
#20283=*
exprs(#20283,4,#20280,-2,"\n <!-- ... ]]>\n ")
hasLocation(#20283,#20171)
enclosingStmt(#20283,#20275)
exprContainers(#20283,#20001)
literals("
some <cdata>
","
<!-- comment -->
<![CDATA[ some <cdata> ]]>
",#20283)
#20284=*
entry_cfg_node(#20284,#20001)
#20285=@"loc,{#10000},1,1,1,0"
locations_default(#20285,#10000,1,1,1,0)
hasLocation(#20284,#20285)
#20286=*
exit_cfg_node(#20286,#20001)
hasLocation(#20286,#20183)
successor(#20275,#20279)
successor(#20283,#20280)
successor(#20282,#20283)
successor(#20280,#20277)
successor(#20279,#20282)
successor(#20277,#20286)
successor(#20262,#20267)
successor(#20269,#20273)
successor(#20273,#20271)
successor(#20271,#20263)
successor(#20268,#20265)
successor(#20267,#20268)
successor(#20265,#20269)
successor(#20263,#20275)
successor(#20252,#20255)
successor(#20260,#20258)
successor(#20258,#20256)
successor(#20256,#20253)
successor(#20255,#20260)
successor(#20253,#20262)
successor(#20243,#20248)
successor(#20250,#20244)
successor(#20249,#20246)
successor(#20248,#20249)
successor(#20246,#20250)
successor(#20244,#20252)
successor(#20231,#20236)
successor(#20241,#20232)
successor(#20240,#20238)
successor(#20238,#20234)
successor(#20236,#20240)
successor(#20234,#20241)
successor(#20232,#20243)
successor(#20210,#20215)
successor(#20217,#20223)
successor(#20224,#20219)
successor(#20223,#20221)
successor(#20221,#20224)
#20287=*
guard_node(#20287,1,#20219)
hasLocation(#20287,#20220)
successor(#20287,#20211)
#20288=*
guard_node(#20288,0,#20219)
hasLocation(#20288,#20220)
successor(#20288,#20229)
successor(#20219,#20287)
successor(#20219,#20288)
successor(#20230,#20225)
successor(#20229,#20227)
successor(#20227,#20230)
successor(#20225,#20211)
successor(#20216,#20213)
successor(#20215,#20216)
successor(#20213,#20217)
successor(#20211,#20231)
successor(#20202,#20205)
successor(#20209,#20207)
successor(#20207,#20203)
successor(#20205,#20209)
successor(#20203,#20210)
successor(#20194,#20199)
successor(#20201,#20195)
successor(#20200,#20197)
successor(#20199,#20200)
successor(#20197,#20201)
successor(#20195,#20202)
successor(#20186,#20189)
successor(#20193,#20191)
successor(#20191,#20187)
successor(#20189,#20193)
successor(#20187,#20194)
successor(#20284,#20186)
numlines(#10000,13,12,0)
filetype(#10000,"javascript")

View File

@@ -0,0 +1 @@
var class = 23;

View File

@@ -0,0 +1,104 @@
#10000=@"/kwident.js;sourcefile"
files(#10000,"/kwident.js","kwident","js",0)
#10001=@"/;folder"
folders(#10001,"/","")
containerparent(#10001,#10000)
#10002=@"loc,{#10000},0,0,0,0"
locations_default(#10002,#10000,0,0,0,0)
hasLocation(#10000,#10002)
#20000=@"global_scope"
scopes(#20000,0)
#20001=@"script;{#10000},1,1"
#20002=*
lines(#20002,#20001,"var class = 23;","
")
#20003=@"loc,{#10000},1,1,1,15"
locations_default(#20003,#10000,1,1,1,15)
hasLocation(#20002,#20003)
numlines(#20001,1,1,0)
#20004=*
tokeninfo(#20004,7,#20001,0,"var")
#20005=@"loc,{#10000},1,1,1,3"
locations_default(#20005,#10000,1,1,1,3)
hasLocation(#20004,#20005)
#20006=*
tokeninfo(#20006,7,#20001,1,"class")
#20007=@"loc,{#10000},1,5,1,9"
locations_default(#20007,#10000,1,5,1,9)
hasLocation(#20006,#20007)
#20008=*
tokeninfo(#20008,8,#20001,2,"=")
#20009=@"loc,{#10000},1,11,1,11"
locations_default(#20009,#10000,1,11,1,11)
hasLocation(#20008,#20009)
#20010=*
tokeninfo(#20010,3,#20001,3,"23")
#20011=@"loc,{#10000},1,13,1,14"
locations_default(#20011,#10000,1,13,1,14)
hasLocation(#20010,#20011)
#20012=*
tokeninfo(#20012,8,#20001,4,";")
#20013=@"loc,{#10000},1,15,1,15"
locations_default(#20013,#10000,1,15,1,15)
hasLocation(#20012,#20013)
#20014=*
tokeninfo(#20014,0,#20001,5,"")
#20015=@"loc,{#10000},2,1,2,0"
locations_default(#20015,#10000,2,1,2,0)
hasLocation(#20014,#20015)
toplevels(#20001,0)
#20016=@"loc,{#10000},1,1,2,0"
locations_default(#20016,#10000,1,1,2,0)
hasLocation(#20001,#20016)
#20017=@"var;{class};{#20000}"
variables(#20017,"class",#20000)
#20018=*
stmts(#20018,18,#20001,0,"var class = 23;")
hasLocation(#20018,#20003)
stmtContainers(#20018,#20001)
#20019=*
exprs(#20019,64,#20018,0,"class = 23")
#20020=@"loc,{#10000},1,5,1,14"
locations_default(#20020,#10000,1,5,1,14)
hasLocation(#20019,#20020)
enclosingStmt(#20019,#20018)
exprContainers(#20019,#20001)
#20021=*
exprs(#20021,78,#20019,0,"class")
hasLocation(#20021,#20007)
enclosingStmt(#20021,#20018)
exprContainers(#20021,#20001)
literals("class","class",#20021)
decl(#20021,#20017)
#20022=*
exprs(#20022,3,#20019,1,"23")
hasLocation(#20022,#20011)
enclosingStmt(#20022,#20018)
exprContainers(#20022,#20001)
literals("23","23",#20022)
#20023=*
entry_cfg_node(#20023,#20001)
#20024=@"loc,{#10000},1,1,1,0"
locations_default(#20024,#10000,1,1,1,0)
hasLocation(#20023,#20024)
#20025=*
exit_cfg_node(#20025,#20001)
hasLocation(#20025,#20015)
successor(#20018,#20021)
successor(#20022,#20019)
successor(#20021,#20022)
successor(#20019,#20025)
successor(#20023,#20018)
#20026=*
jsParseErrors(#20026,#20001,"Error: Cannot use keyword 'class' as an identifier.","var class = 23;
")
#20027=@"loc,{#10000},1,5,1,5"
locations_default(#20027,#10000,1,5,1,5)
hasLocation(#20026,#20027)
#20028=*
lines(#20028,#20001,"var class = 23;","
")
hasLocation(#20028,#20003)
numlines(#20001,1,0,0)
numlines(#10000,1,1,0)
filetype(#10000,"javascript")

View File

@@ -0,0 +1,8 @@
declare module "test" {
declare type Foo = {|
|};
declare type Bar = {|
baz: () => Promise<?Foo>
|};
}

View File

@@ -0,0 +1,228 @@
#10000=@"/ambig.js;sourcefile"
files(#10000,"/ambig.js","ambig","js",0)
#10001=@"/;folder"
folders(#10001,"/","")
containerparent(#10001,#10000)
#10002=@"loc,{#10000},0,0,0,0"
locations_default(#10002,#10000,0,0,0,0)
hasLocation(#10000,#10002)
#20000=@"global_scope"
scopes(#20000,0)
#20001=@"script;{#10000},1,1"
#20002=*
lines(#20002,#20001,"declare module ""test"" {","
")
#20003=@"loc,{#10000},1,1,1,23"
locations_default(#20003,#10000,1,1,1,23)
hasLocation(#20002,#20003)
#20004=*
lines(#20004,#20001," declare type Foo = {|","
")
#20005=@"loc,{#10000},2,1,2,23"
locations_default(#20005,#10000,2,1,2,23)
hasLocation(#20004,#20005)
indentation(#10000,2," ",2)
#20006=*
lines(#20006,#20001," |};","
")
#20007=@"loc,{#10000},3,1,3,5"
locations_default(#20007,#10000,3,1,3,5)
hasLocation(#20006,#20007)
indentation(#10000,3," ",2)
#20008=*
lines(#20008,#20001,"","
")
#20009=@"loc,{#10000},4,1,4,0"
locations_default(#20009,#10000,4,1,4,0)
hasLocation(#20008,#20009)
#20010=*
lines(#20010,#20001," declare type Bar = {|","
")
#20011=@"loc,{#10000},5,1,5,23"
locations_default(#20011,#10000,5,1,5,23)
hasLocation(#20010,#20011)
indentation(#10000,5," ",2)
#20012=*
lines(#20012,#20001," baz: () => Promise<?Foo>","
")
#20013=@"loc,{#10000},6,1,6,28"
locations_default(#20013,#10000,6,1,6,28)
hasLocation(#20012,#20013)
indentation(#10000,6," ",4)
#20014=*
lines(#20014,#20001," |};","
")
#20015=@"loc,{#10000},7,1,7,5"
locations_default(#20015,#10000,7,1,7,5)
hasLocation(#20014,#20015)
indentation(#10000,7," ",2)
#20016=*
lines(#20016,#20001,"}","
")
#20017=@"loc,{#10000},8,1,8,1"
locations_default(#20017,#10000,8,1,8,1)
hasLocation(#20016,#20017)
numlines(#20001,8,7,0)
#20018=*
tokeninfo(#20018,6,#20001,0,"declare")
#20019=@"loc,{#10000},1,1,1,7"
locations_default(#20019,#10000,1,1,1,7)
hasLocation(#20018,#20019)
#20020=*
tokeninfo(#20020,6,#20001,1,"module")
#20021=@"loc,{#10000},1,9,1,14"
locations_default(#20021,#10000,1,9,1,14)
hasLocation(#20020,#20021)
#20022=*
tokeninfo(#20022,4,#20001,2,"""test""")
#20023=@"loc,{#10000},1,16,1,21"
locations_default(#20023,#10000,1,16,1,21)
hasLocation(#20022,#20023)
#20024=*
tokeninfo(#20024,8,#20001,3,"{")
#20025=@"loc,{#10000},1,23,1,23"
locations_default(#20025,#10000,1,23,1,23)
hasLocation(#20024,#20025)
#20026=*
tokeninfo(#20026,6,#20001,4,"declare")
#20027=@"loc,{#10000},2,3,2,9"
locations_default(#20027,#10000,2,3,2,9)
hasLocation(#20026,#20027)
#20028=*
tokeninfo(#20028,6,#20001,5,"type")
#20029=@"loc,{#10000},2,11,2,14"
locations_default(#20029,#10000,2,11,2,14)
hasLocation(#20028,#20029)
#20030=*
tokeninfo(#20030,6,#20001,6,"Foo")
#20031=@"loc,{#10000},2,16,2,18"
locations_default(#20031,#10000,2,16,2,18)
hasLocation(#20030,#20031)
#20032=*
tokeninfo(#20032,8,#20001,7,"=")
#20033=@"loc,{#10000},2,20,2,20"
locations_default(#20033,#10000,2,20,2,20)
hasLocation(#20032,#20033)
#20034=*
tokeninfo(#20034,8,#20001,8,"{|")
#20035=@"loc,{#10000},2,22,2,23"
locations_default(#20035,#10000,2,22,2,23)
hasLocation(#20034,#20035)
#20036=*
tokeninfo(#20036,8,#20001,9,"|}")
#20037=@"loc,{#10000},3,3,3,4"
locations_default(#20037,#10000,3,3,3,4)
hasLocation(#20036,#20037)
#20038=*
tokeninfo(#20038,8,#20001,10,";")
#20039=@"loc,{#10000},3,5,3,5"
locations_default(#20039,#10000,3,5,3,5)
hasLocation(#20038,#20039)
#20040=*
tokeninfo(#20040,6,#20001,11,"declare")
#20041=@"loc,{#10000},5,3,5,9"
locations_default(#20041,#10000,5,3,5,9)
hasLocation(#20040,#20041)
#20042=*
tokeninfo(#20042,6,#20001,12,"type")
#20043=@"loc,{#10000},5,11,5,14"
locations_default(#20043,#10000,5,11,5,14)
hasLocation(#20042,#20043)
#20044=*
tokeninfo(#20044,6,#20001,13,"Bar")
#20045=@"loc,{#10000},5,16,5,18"
locations_default(#20045,#10000,5,16,5,18)
hasLocation(#20044,#20045)
#20046=*
tokeninfo(#20046,8,#20001,14,"=")
#20047=@"loc,{#10000},5,20,5,20"
locations_default(#20047,#10000,5,20,5,20)
hasLocation(#20046,#20047)
#20048=*
tokeninfo(#20048,8,#20001,15,"{|")
#20049=@"loc,{#10000},5,22,5,23"
locations_default(#20049,#10000,5,22,5,23)
hasLocation(#20048,#20049)
#20050=*
tokeninfo(#20050,6,#20001,16,"baz")
#20051=@"loc,{#10000},6,5,6,7"
locations_default(#20051,#10000,6,5,6,7)
hasLocation(#20050,#20051)
#20052=*
tokeninfo(#20052,8,#20001,17,":")
#20053=@"loc,{#10000},6,8,6,8"
locations_default(#20053,#10000,6,8,6,8)
hasLocation(#20052,#20053)
#20054=*
tokeninfo(#20054,8,#20001,18,"(")
#20055=@"loc,{#10000},6,10,6,10"
locations_default(#20055,#10000,6,10,6,10)
hasLocation(#20054,#20055)
#20056=*
tokeninfo(#20056,8,#20001,19,")")
#20057=@"loc,{#10000},6,11,6,11"
locations_default(#20057,#10000,6,11,6,11)
hasLocation(#20056,#20057)
#20058=*
tokeninfo(#20058,8,#20001,20,"=>")
#20059=@"loc,{#10000},6,13,6,14"
locations_default(#20059,#10000,6,13,6,14)
hasLocation(#20058,#20059)
#20060=*
tokeninfo(#20060,6,#20001,21,"Promise")
#20061=@"loc,{#10000},6,16,6,22"
locations_default(#20061,#10000,6,16,6,22)
hasLocation(#20060,#20061)
#20062=*
tokeninfo(#20062,8,#20001,22,"<")
#20063=@"loc,{#10000},6,23,6,23"
locations_default(#20063,#10000,6,23,6,23)
hasLocation(#20062,#20063)
#20064=*
tokeninfo(#20064,8,#20001,23,"?")
#20065=@"loc,{#10000},6,24,6,24"
locations_default(#20065,#10000,6,24,6,24)
hasLocation(#20064,#20065)
#20066=*
tokeninfo(#20066,6,#20001,24,"Foo")
#20067=@"loc,{#10000},6,25,6,27"
locations_default(#20067,#10000,6,25,6,27)
hasLocation(#20066,#20067)
#20068=*
tokeninfo(#20068,8,#20001,25,">")
#20069=@"loc,{#10000},6,28,6,28"
locations_default(#20069,#10000,6,28,6,28)
hasLocation(#20068,#20069)
#20070=*
tokeninfo(#20070,8,#20001,26,"|}")
#20071=@"loc,{#10000},7,3,7,4"
locations_default(#20071,#10000,7,3,7,4)
hasLocation(#20070,#20071)
#20072=*
tokeninfo(#20072,8,#20001,27,";")
#20073=@"loc,{#10000},7,5,7,5"
locations_default(#20073,#10000,7,5,7,5)
hasLocation(#20072,#20073)
#20074=*
tokeninfo(#20074,8,#20001,28,"}")
hasLocation(#20074,#20017)
#20075=*
tokeninfo(#20075,0,#20001,29,"")
#20076=@"loc,{#10000},9,1,9,0"
locations_default(#20076,#10000,9,1,9,0)
hasLocation(#20075,#20076)
toplevels(#20001,0)
#20077=@"loc,{#10000},1,1,9,0"
locations_default(#20077,#10000,1,1,9,0)
hasLocation(#20001,#20077)
#20078=*
entry_cfg_node(#20078,#20001)
#20079=@"loc,{#10000},1,1,1,0"
locations_default(#20079,#10000,1,1,1,0)
hasLocation(#20078,#20079)
#20080=*
exit_cfg_node(#20080,#20001)
hasLocation(#20080,#20076)
successor(#20078,#20080)
numlines(#10000,8,7,0)
filetype(#10000,"javascript")

View File

@@ -0,0 +1,2 @@
for (let i = 0; i < spec.switch.length; i++) {
}

View File

@@ -0,0 +1,3 @@
{
"experimental": true
}

View File

@@ -0,0 +1,273 @@
#10000=@"/tst.js;sourcefile"
files(#10000,"/tst.js","tst","js",0)
#10001=@"/;folder"
folders(#10001,"/","")
containerparent(#10001,#10000)
#10002=@"loc,{#10000},0,0,0,0"
locations_default(#10002,#10000,0,0,0,0)
hasLocation(#10000,#10002)
#20000=@"global_scope"
scopes(#20000,0)
#20001=@"script;{#10000},1,1"
#20002=*
lines(#20002,#20001,"for (let i = 0; i < spec.switch.length; i++) {","
")
#20003=@"loc,{#10000},1,1,1,46"
locations_default(#20003,#10000,1,1,1,46)
hasLocation(#20002,#20003)
#20004=*
lines(#20004,#20001,"}","
")
#20005=@"loc,{#10000},2,1,2,1"
locations_default(#20005,#10000,2,1,2,1)
hasLocation(#20004,#20005)
numlines(#20001,2,2,0)
#20006=*
tokeninfo(#20006,7,#20001,0,"for")
#20007=@"loc,{#10000},1,1,1,3"
locations_default(#20007,#10000,1,1,1,3)
hasLocation(#20006,#20007)
#20008=*
tokeninfo(#20008,8,#20001,1,"(")
#20009=@"loc,{#10000},1,5,1,5"
locations_default(#20009,#10000,1,5,1,5)
hasLocation(#20008,#20009)
#20010=*
tokeninfo(#20010,7,#20001,2,"let")
#20011=@"loc,{#10000},1,6,1,8"
locations_default(#20011,#10000,1,6,1,8)
hasLocation(#20010,#20011)
#20012=*
tokeninfo(#20012,6,#20001,3,"i")
#20013=@"loc,{#10000},1,10,1,10"
locations_default(#20013,#10000,1,10,1,10)
hasLocation(#20012,#20013)
#20014=*
tokeninfo(#20014,8,#20001,4,"=")
#20015=@"loc,{#10000},1,12,1,12"
locations_default(#20015,#10000,1,12,1,12)
hasLocation(#20014,#20015)
#20016=*
tokeninfo(#20016,3,#20001,5,"0")
#20017=@"loc,{#10000},1,14,1,14"
locations_default(#20017,#10000,1,14,1,14)
hasLocation(#20016,#20017)
#20018=*
tokeninfo(#20018,8,#20001,6,";")
#20019=@"loc,{#10000},1,15,1,15"
locations_default(#20019,#10000,1,15,1,15)
hasLocation(#20018,#20019)
#20020=*
tokeninfo(#20020,6,#20001,7,"i")
#20021=@"loc,{#10000},1,17,1,17"
locations_default(#20021,#10000,1,17,1,17)
hasLocation(#20020,#20021)
#20022=*
tokeninfo(#20022,8,#20001,8,"<")
#20023=@"loc,{#10000},1,19,1,19"
locations_default(#20023,#10000,1,19,1,19)
hasLocation(#20022,#20023)
#20024=*
tokeninfo(#20024,6,#20001,9,"spec")
#20025=@"loc,{#10000},1,21,1,24"
locations_default(#20025,#10000,1,21,1,24)
hasLocation(#20024,#20025)
#20026=*
tokeninfo(#20026,8,#20001,10,".")
#20027=@"loc,{#10000},1,25,1,25"
locations_default(#20027,#10000,1,25,1,25)
hasLocation(#20026,#20027)
#20028=*
tokeninfo(#20028,7,#20001,11,"switch")
#20029=@"loc,{#10000},1,26,1,31"
locations_default(#20029,#10000,1,26,1,31)
hasLocation(#20028,#20029)
#20030=*
tokeninfo(#20030,8,#20001,12,".")
#20031=@"loc,{#10000},1,32,1,32"
locations_default(#20031,#10000,1,32,1,32)
hasLocation(#20030,#20031)
#20032=*
tokeninfo(#20032,6,#20001,13,"length")
#20033=@"loc,{#10000},1,33,1,38"
locations_default(#20033,#10000,1,33,1,38)
hasLocation(#20032,#20033)
#20034=*
tokeninfo(#20034,8,#20001,14,";")
#20035=@"loc,{#10000},1,39,1,39"
locations_default(#20035,#10000,1,39,1,39)
hasLocation(#20034,#20035)
#20036=*
tokeninfo(#20036,6,#20001,15,"i")
#20037=@"loc,{#10000},1,41,1,41"
locations_default(#20037,#10000,1,41,1,41)
hasLocation(#20036,#20037)
#20038=*
tokeninfo(#20038,8,#20001,16,"++")
#20039=@"loc,{#10000},1,42,1,43"
locations_default(#20039,#10000,1,42,1,43)
hasLocation(#20038,#20039)
#20040=*
tokeninfo(#20040,8,#20001,17,")")
#20041=@"loc,{#10000},1,44,1,44"
locations_default(#20041,#10000,1,44,1,44)
hasLocation(#20040,#20041)
#20042=*
tokeninfo(#20042,8,#20001,18,"{")
#20043=@"loc,{#10000},1,46,1,46"
locations_default(#20043,#10000,1,46,1,46)
hasLocation(#20042,#20043)
#20044=*
tokeninfo(#20044,8,#20001,19,"}")
hasLocation(#20044,#20005)
#20045=*
tokeninfo(#20045,0,#20001,20,"")
#20046=@"loc,{#10000},3,1,3,0"
locations_default(#20046,#10000,3,1,3,0)
hasLocation(#20045,#20046)
toplevels(#20001,0)
#20047=@"loc,{#10000},1,1,3,0"
locations_default(#20047,#10000,1,1,3,0)
hasLocation(#20001,#20047)
#20048=*
stmts(#20048,14,#20001,0,"for (le ... ++) {\n}")
#20049=@"loc,{#10000},1,1,2,1"
locations_default(#20049,#10000,1,1,2,1)
hasLocation(#20048,#20049)
stmtContainers(#20048,#20001)
#20050=*
scopes(#20050,5)
scopenodes(#20048,#20050)
scopenesting(#20050,#20000)
#20051=@"var;{i};{#20050}"
variables(#20051,"i",#20050)
#20052=*
exprs(#20052,27,#20048,1,"i < spe ... .length")
#20053=@"loc,{#10000},1,17,1,38"
locations_default(#20053,#10000,1,17,1,38)
hasLocation(#20052,#20053)
enclosingStmt(#20052,#20048)
exprContainers(#20052,#20001)
#20054=*
exprs(#20054,79,#20052,0,"i")
hasLocation(#20054,#20021)
enclosingStmt(#20054,#20048)
exprContainers(#20054,#20001)
literals("i","i",#20054)
bind(#20054,#20051)
#20055=*
exprs(#20055,14,#20052,1,"spec.switch.length")
#20056=@"loc,{#10000},1,21,1,38"
locations_default(#20056,#10000,1,21,1,38)
hasLocation(#20055,#20056)
enclosingStmt(#20055,#20048)
exprContainers(#20055,#20001)
#20057=*
exprs(#20057,14,#20055,0,"spec.switch")
#20058=@"loc,{#10000},1,21,1,31"
locations_default(#20058,#10000,1,21,1,31)
hasLocation(#20057,#20058)
enclosingStmt(#20057,#20048)
exprContainers(#20057,#20001)
#20059=*
exprs(#20059,79,#20057,0,"spec")
hasLocation(#20059,#20025)
enclosingStmt(#20059,#20048)
exprContainers(#20059,#20001)
literals("spec","spec",#20059)
#20060=@"var;{spec};{#20000}"
variables(#20060,"spec",#20000)
bind(#20059,#20060)
#20061=*
exprs(#20061,0,#20057,1,"switch")
hasLocation(#20061,#20029)
enclosingStmt(#20061,#20048)
exprContainers(#20061,#20001)
literals("switch","switch",#20061)
#20062=*
exprs(#20062,0,#20055,1,"length")
hasLocation(#20062,#20033)
enclosingStmt(#20062,#20048)
exprContainers(#20062,#20001)
literals("length","length",#20062)
#20063=*
exprs(#20063,60,#20048,2,"i++")
#20064=@"loc,{#10000},1,41,1,43"
locations_default(#20064,#10000,1,41,1,43)
hasLocation(#20063,#20064)
enclosingStmt(#20063,#20048)
exprContainers(#20063,#20001)
#20065=*
exprs(#20065,79,#20063,0,"i")
hasLocation(#20065,#20037)
enclosingStmt(#20065,#20048)
exprContainers(#20065,#20001)
literals("i","i",#20065)
bind(#20065,#20051)
#20066=*
stmts(#20066,23,#20048,0,"let i = 0")
#20067=@"loc,{#10000},1,6,1,14"
locations_default(#20067,#10000,1,6,1,14)
hasLocation(#20066,#20067)
stmtContainers(#20066,#20001)
#20068=*
exprs(#20068,64,#20066,0,"i = 0")
#20069=@"loc,{#10000},1,10,1,14"
locations_default(#20069,#10000,1,10,1,14)
hasLocation(#20068,#20069)
enclosingStmt(#20068,#20066)
exprContainers(#20068,#20001)
#20070=*
exprs(#20070,78,#20068,0,"i")
hasLocation(#20070,#20013)
enclosingStmt(#20070,#20066)
exprContainers(#20070,#20001)
literals("i","i",#20070)
decl(#20070,#20051)
#20071=*
exprs(#20071,3,#20068,1,"0")
hasLocation(#20071,#20017)
enclosingStmt(#20071,#20066)
exprContainers(#20071,#20001)
literals("0","0",#20071)
#20072=*
stmts(#20072,1,#20048,3,"{\n}")
#20073=@"loc,{#10000},1,46,2,1"
locations_default(#20073,#10000,1,46,2,1)
hasLocation(#20072,#20073)
stmtContainers(#20072,#20001)
#20074=*
entry_cfg_node(#20074,#20001)
#20075=@"loc,{#10000},1,1,1,0"
locations_default(#20075,#10000,1,1,1,0)
hasLocation(#20074,#20075)
#20076=*
exit_cfg_node(#20076,#20001)
hasLocation(#20076,#20046)
successor(#20048,#20066)
successor(#20066,#20070)
successor(#20071,#20068)
successor(#20070,#20071)
successor(#20068,#20054)
successor(#20062,#20055)
successor(#20061,#20057)
successor(#20059,#20061)
successor(#20057,#20062)
successor(#20055,#20052)
successor(#20054,#20059)
#20077=*
guard_node(#20077,1,#20052)
hasLocation(#20077,#20053)
successor(#20077,#20072)
#20078=*
guard_node(#20078,0,#20052)
hasLocation(#20078,#20053)
successor(#20078,#20076)
successor(#20052,#20077)
successor(#20052,#20078)
successor(#20065,#20063)
successor(#20063,#20054)
successor(#20072,#20065)
successor(#20074,#20048)
numlines(#10000,2,2,0)
filetype(#10000,"javascript")

View File

@@ -1,4 +1,5 @@
[for (year of years) if (year > 2000) year];
year;
[for (i of numbers) for (j of letters) i+j];
[for (i of numbers) for (j of letters) if (i<j) i+j];
[for (i of numbers) for (j of letters) if (i<j) i+j];
[for each (i in numbers) i];

View File

@@ -0,0 +1,7 @@
function f(x)("result")
function(b) {
if (b) {
function g(y)("other result")
}
}

View File

@@ -1,4 +1,6 @@
(for (year of years) if (year > 2000) year);
year;
(for (i of numbers) for (j of letters) i+j);
(for (i of numbers) for (j of letters) if (i<j) i+j);
(for (i of numbers) for (j of letters) if (i<j) i+j);
(x.p for (x in xs));
(x.p for each (x in xs));

View File

@@ -2,4 +2,6 @@ var x = 42, y = 19;
console.log(let (x = 23, y = 19) x + y);
console.log(x - y);
console.log(x - y);
JSON.stringify(let (x = 23, y = 19) { x: x, y: y});

View File

@@ -0,0 +1,437 @@
#10000=@"/exprfns.js;sourcefile"
files(#10000,"/exprfns.js","exprfns","js",0)
#10001=@"/;folder"
folders(#10001,"/","")
containerparent(#10001,#10000)
#10002=@"loc,{#10000},0,0,0,0"
locations_default(#10002,#10000,0,0,0,0)
hasLocation(#10000,#10002)
#20000=@"global_scope"
scopes(#20000,0)
#20001=@"script;{#10000},1,1"
#20002=*
lines(#20002,#20001,"function f(x)(""result"")","
")
#20003=@"loc,{#10000},1,1,1,23"
locations_default(#20003,#10000,1,1,1,23)
hasLocation(#20002,#20003)
#20004=*
lines(#20004,#20001,"","
")
#20005=@"loc,{#10000},2,1,2,0"
locations_default(#20005,#10000,2,1,2,0)
hasLocation(#20004,#20005)
#20006=*
lines(#20006,#20001,"function(b) {","
")
#20007=@"loc,{#10000},3,1,3,13"
locations_default(#20007,#10000,3,1,3,13)
hasLocation(#20006,#20007)
#20008=*
lines(#20008,#20001," if (b) {","
")
#20009=@"loc,{#10000},4,1,4,10"
locations_default(#20009,#10000,4,1,4,10)
hasLocation(#20008,#20009)
indentation(#10000,4," ",2)
#20010=*
lines(#20010,#20001," function g(y)(""other result"")","
")
#20011=@"loc,{#10000},5,1,5,33"
locations_default(#20011,#10000,5,1,5,33)
hasLocation(#20010,#20011)
indentation(#10000,5," ",4)
#20012=*
lines(#20012,#20001," }","
")
#20013=@"loc,{#10000},6,1,6,3"
locations_default(#20013,#10000,6,1,6,3)
hasLocation(#20012,#20013)
indentation(#10000,6," ",2)
#20014=*
lines(#20014,#20001,"}","
")
#20015=@"loc,{#10000},7,1,7,1"
locations_default(#20015,#10000,7,1,7,1)
hasLocation(#20014,#20015)
numlines(#20001,7,6,0)
#20016=*
tokeninfo(#20016,7,#20001,0,"function")
#20017=@"loc,{#10000},1,1,1,8"
locations_default(#20017,#10000,1,1,1,8)
hasLocation(#20016,#20017)
#20018=*
tokeninfo(#20018,6,#20001,1,"f")
#20019=@"loc,{#10000},1,10,1,10"
locations_default(#20019,#10000,1,10,1,10)
hasLocation(#20018,#20019)
#20020=*
tokeninfo(#20020,8,#20001,2,"(")
#20021=@"loc,{#10000},1,11,1,11"
locations_default(#20021,#10000,1,11,1,11)
hasLocation(#20020,#20021)
#20022=*
tokeninfo(#20022,6,#20001,3,"x")
#20023=@"loc,{#10000},1,12,1,12"
locations_default(#20023,#10000,1,12,1,12)
hasLocation(#20022,#20023)
#20024=*
tokeninfo(#20024,8,#20001,4,")")
#20025=@"loc,{#10000},1,13,1,13"
locations_default(#20025,#10000,1,13,1,13)
hasLocation(#20024,#20025)
#20026=*
tokeninfo(#20026,8,#20001,5,"(")
#20027=@"loc,{#10000},1,14,1,14"
locations_default(#20027,#10000,1,14,1,14)
hasLocation(#20026,#20027)
#20028=*
tokeninfo(#20028,4,#20001,6,"""result""")
#20029=@"loc,{#10000},1,15,1,22"
locations_default(#20029,#10000,1,15,1,22)
hasLocation(#20028,#20029)
#20030=*
tokeninfo(#20030,8,#20001,7,")")
#20031=@"loc,{#10000},1,23,1,23"
locations_default(#20031,#10000,1,23,1,23)
hasLocation(#20030,#20031)
#20032=*
tokeninfo(#20032,7,#20001,8,"function")
#20033=@"loc,{#10000},3,1,3,8"
locations_default(#20033,#10000,3,1,3,8)
hasLocation(#20032,#20033)
#20034=*
tokeninfo(#20034,8,#20001,9,"(")
#20035=@"loc,{#10000},3,9,3,9"
locations_default(#20035,#10000,3,9,3,9)
hasLocation(#20034,#20035)
#20036=*
tokeninfo(#20036,6,#20001,10,"b")
#20037=@"loc,{#10000},3,10,3,10"
locations_default(#20037,#10000,3,10,3,10)
hasLocation(#20036,#20037)
#20038=*
tokeninfo(#20038,8,#20001,11,")")
#20039=@"loc,{#10000},3,11,3,11"
locations_default(#20039,#10000,3,11,3,11)
hasLocation(#20038,#20039)
#20040=*
tokeninfo(#20040,8,#20001,12,"{")
#20041=@"loc,{#10000},3,13,3,13"
locations_default(#20041,#10000,3,13,3,13)
hasLocation(#20040,#20041)
#20042=*
tokeninfo(#20042,7,#20001,13,"if")
#20043=@"loc,{#10000},4,3,4,4"
locations_default(#20043,#10000,4,3,4,4)
hasLocation(#20042,#20043)
#20044=*
tokeninfo(#20044,8,#20001,14,"(")
#20045=@"loc,{#10000},4,6,4,6"
locations_default(#20045,#10000,4,6,4,6)
hasLocation(#20044,#20045)
#20046=*
tokeninfo(#20046,6,#20001,15,"b")
#20047=@"loc,{#10000},4,7,4,7"
locations_default(#20047,#10000,4,7,4,7)
hasLocation(#20046,#20047)
#20048=*
tokeninfo(#20048,8,#20001,16,")")
#20049=@"loc,{#10000},4,8,4,8"
locations_default(#20049,#10000,4,8,4,8)
hasLocation(#20048,#20049)
#20050=*
tokeninfo(#20050,8,#20001,17,"{")
#20051=@"loc,{#10000},4,10,4,10"
locations_default(#20051,#10000,4,10,4,10)
hasLocation(#20050,#20051)
#20052=*
tokeninfo(#20052,7,#20001,18,"function")
#20053=@"loc,{#10000},5,5,5,12"
locations_default(#20053,#10000,5,5,5,12)
hasLocation(#20052,#20053)
#20054=*
tokeninfo(#20054,6,#20001,19,"g")
#20055=@"loc,{#10000},5,14,5,14"
locations_default(#20055,#10000,5,14,5,14)
hasLocation(#20054,#20055)
#20056=*
tokeninfo(#20056,8,#20001,20,"(")
#20057=@"loc,{#10000},5,15,5,15"
locations_default(#20057,#10000,5,15,5,15)
hasLocation(#20056,#20057)
#20058=*
tokeninfo(#20058,6,#20001,21,"y")
#20059=@"loc,{#10000},5,16,5,16"
locations_default(#20059,#10000,5,16,5,16)
hasLocation(#20058,#20059)
#20060=*
tokeninfo(#20060,8,#20001,22,")")
#20061=@"loc,{#10000},5,17,5,17"
locations_default(#20061,#10000,5,17,5,17)
hasLocation(#20060,#20061)
#20062=*
tokeninfo(#20062,8,#20001,23,"(")
#20063=@"loc,{#10000},5,18,5,18"
locations_default(#20063,#10000,5,18,5,18)
hasLocation(#20062,#20063)
#20064=*
tokeninfo(#20064,4,#20001,24,"""other result""")
#20065=@"loc,{#10000},5,19,5,32"
locations_default(#20065,#10000,5,19,5,32)
hasLocation(#20064,#20065)
#20066=*
tokeninfo(#20066,8,#20001,25,")")
#20067=@"loc,{#10000},5,33,5,33"
locations_default(#20067,#10000,5,33,5,33)
hasLocation(#20066,#20067)
#20068=*
tokeninfo(#20068,8,#20001,26,"}")
#20069=@"loc,{#10000},6,3,6,3"
locations_default(#20069,#10000,6,3,6,3)
hasLocation(#20068,#20069)
#20070=*
tokeninfo(#20070,8,#20001,27,"}")
hasLocation(#20070,#20015)
#20071=*
tokeninfo(#20071,0,#20001,28,"")
#20072=@"loc,{#10000},8,1,8,0"
locations_default(#20072,#10000,8,1,8,0)
hasLocation(#20071,#20072)
toplevels(#20001,0)
#20073=@"loc,{#10000},1,1,8,0"
locations_default(#20073,#10000,1,1,8,0)
hasLocation(#20001,#20073)
#20074=@"var;{f};{#20000}"
variables(#20074,"f",#20000)
#20075=*
stmts(#20075,17,#20001,0,"functio ... esult"")")
hasLocation(#20075,#20003)
stmtContainers(#20075,#20001)
#20076=*
exprs(#20076,78,#20075,-1,"f")
hasLocation(#20076,#20019)
exprContainers(#20076,#20075)
literals("f","f",#20076)
decl(#20076,#20074)
#20077=*
scopes(#20077,1)
scopenodes(#20075,#20077)
scopenesting(#20077,#20000)
#20078=@"var;{x};{#20077}"
variables(#20078,"x",#20077)
#20079=*
exprs(#20079,78,#20075,0,"x")
hasLocation(#20079,#20023)
exprContainers(#20079,#20075)
literals("x","x",#20079)
decl(#20079,#20078)
#20080=@"var;{arguments};{#20077}"
variables(#20080,"arguments",#20077)
isArgumentsObject(#20080)
#20081=*
exprs(#20081,63,#20075,-2,"(""result"")")
#20082=@"loc,{#10000},1,14,1,23"
locations_default(#20082,#10000,1,14,1,23)
hasLocation(#20081,#20082)
exprContainers(#20081,#20075)
#20083=*
exprs(#20083,4,#20081,0,"""result""")
hasLocation(#20083,#20029)
exprContainers(#20083,#20075)
literals("result","""result""",#20083)
#20084=*
stmts(#20084,2,#20001,1,"functio ... )\n }\n}")
#20085=@"loc,{#10000},3,1,7,1"
locations_default(#20085,#10000,3,1,7,1)
hasLocation(#20084,#20085)
stmtContainers(#20084,#20001)
#20086=*
exprs(#20086,9,#20084,0,"functio ... )\n }\n}")
hasLocation(#20086,#20085)
enclosingStmt(#20086,#20084)
exprContainers(#20086,#20001)
#20087=*
scopes(#20087,1)
scopenodes(#20086,#20087)
scopenesting(#20087,#20000)
#20088=@"var;{g};{#20087}"
variables(#20088,"g",#20087)
#20089=@"var;{b};{#20087}"
variables(#20089,"b",#20087)
#20090=*
exprs(#20090,78,#20086,0,"b")
hasLocation(#20090,#20037)
exprContainers(#20090,#20086)
literals("b","b",#20090)
decl(#20090,#20089)
#20091=@"var;{arguments};{#20087}"
variables(#20091,"arguments",#20087)
isArgumentsObject(#20091)
#20092=*
stmts(#20092,1,#20086,-2,"{\n if ... )\n }\n}")
#20093=@"loc,{#10000},3,13,7,1"
locations_default(#20093,#10000,3,13,7,1)
hasLocation(#20092,#20093)
stmtContainers(#20092,#20086)
#20094=*
stmts(#20094,3,#20092,0,"if (b) ... t"")\n }")
#20095=@"loc,{#10000},4,3,6,3"
locations_default(#20095,#10000,4,3,6,3)
hasLocation(#20094,#20095)
stmtContainers(#20094,#20086)
#20096=*
exprs(#20096,79,#20094,0,"b")
hasLocation(#20096,#20047)
enclosingStmt(#20096,#20094)
exprContainers(#20096,#20086)
literals("b","b",#20096)
bind(#20096,#20089)
#20097=*
stmts(#20097,1,#20094,1,"{\n f ... t"")\n }")
#20098=@"loc,{#10000},4,10,6,3"
locations_default(#20098,#10000,4,10,6,3)
hasLocation(#20097,#20098)
stmtContainers(#20097,#20086)
#20099=*
stmts(#20099,17,#20097,0,"functio ... esult"")")
#20100=@"loc,{#10000},5,5,5,33"
locations_default(#20100,#10000,5,5,5,33)
hasLocation(#20099,#20100)
stmtContainers(#20099,#20086)
#20101=*
exprs(#20101,78,#20099,-1,"g")
hasLocation(#20101,#20055)
exprContainers(#20101,#20099)
literals("g","g",#20101)
decl(#20101,#20088)
#20102=*
scopes(#20102,1)
scopenodes(#20099,#20102)
scopenesting(#20102,#20087)
#20103=@"var;{y};{#20102}"
variables(#20103,"y",#20102)
#20104=*
exprs(#20104,78,#20099,0,"y")
hasLocation(#20104,#20059)
exprContainers(#20104,#20099)
literals("y","y",#20104)
decl(#20104,#20103)
#20105=@"var;{arguments};{#20102}"
variables(#20105,"arguments",#20102)
isArgumentsObject(#20105)
#20106=*
exprs(#20106,63,#20099,-2,"(""other result"")")
#20107=@"loc,{#10000},5,18,5,33"
locations_default(#20107,#10000,5,18,5,33)
hasLocation(#20106,#20107)
exprContainers(#20106,#20099)
#20108=*
exprs(#20108,4,#20106,0,"""other result""")
hasLocation(#20108,#20065)
exprContainers(#20108,#20099)
literals("other result","""other result""",#20108)
#20109=*
entry_cfg_node(#20109,#20001)
#20110=@"loc,{#10000},1,1,1,0"
locations_default(#20110,#10000,1,1,1,0)
hasLocation(#20109,#20110)
#20111=*
exit_cfg_node(#20111,#20001)
hasLocation(#20111,#20072)
successor(#20084,#20086)
successor(#20086,#20111)
#20112=*
entry_cfg_node(#20112,#20086)
#20113=@"loc,{#10000},3,1,3,0"
locations_default(#20113,#10000,3,1,3,0)
hasLocation(#20112,#20113)
#20114=*
exit_cfg_node(#20114,#20086)
#20115=@"loc,{#10000},7,2,7,1"
locations_default(#20115,#10000,7,2,7,1)
hasLocation(#20114,#20115)
successor(#20092,#20094)
successor(#20094,#20096)
#20116=*
guard_node(#20116,1,#20096)
hasLocation(#20116,#20047)
successor(#20116,#20097)
#20117=*
guard_node(#20117,0,#20096)
hasLocation(#20117,#20047)
successor(#20117,#20114)
successor(#20096,#20116)
successor(#20096,#20117)
successor(#20097,#20099)
successor(#20099,#20101)
successor(#20101,#20114)
#20118=*
entry_cfg_node(#20118,#20099)
#20119=@"loc,{#10000},5,5,5,4"
locations_default(#20119,#10000,5,5,5,4)
hasLocation(#20118,#20119)
#20120=*
exit_cfg_node(#20120,#20099)
#20121=@"loc,{#10000},5,34,5,33"
locations_default(#20121,#10000,5,34,5,33)
hasLocation(#20120,#20121)
successor(#20106,#20108)
successor(#20108,#20120)
successor(#20104,#20106)
successor(#20118,#20104)
successor(#20090,#20092)
successor(#20112,#20090)
successor(#20075,#20084)
#20122=*
entry_cfg_node(#20122,#20075)
hasLocation(#20122,#20110)
#20123=*
exit_cfg_node(#20123,#20075)
#20124=@"loc,{#10000},1,24,1,23"
locations_default(#20124,#10000,1,24,1,23)
hasLocation(#20123,#20124)
successor(#20081,#20083)
successor(#20083,#20123)
successor(#20079,#20081)
successor(#20122,#20079)
successor(#20076,#20075)
successor(#20109,#20076)
#20125=*
jsParseErrors(#20125,#20001,"Error: Missing function name","function(b) {
")
hasLocation(#20125,#20035)
#20126=*
lines(#20126,#20001,"function f(x)(""result"")","
")
hasLocation(#20126,#20003)
#20127=*
lines(#20127,#20001,"","
")
hasLocation(#20127,#20005)
#20128=*
lines(#20128,#20001,"function(b) {","
")
hasLocation(#20128,#20007)
#20129=*
lines(#20129,#20001," if (b) {","
")
hasLocation(#20129,#20009)
indentation(#10000,4," ",2)
#20130=*
lines(#20130,#20001," function g(y)(""other result"")","
")
hasLocation(#20130,#20011)
indentation(#10000,5," ",4)
#20131=*
lines(#20131,#20001," }","
")
hasLocation(#20131,#20013)
indentation(#10000,6," ",2)
#20132=*
lines(#20132,#20001,"}","
")
hasLocation(#20132,#20015)
numlines(#20001,7,0,0)
numlines(#10000,7,6,0)
filetype(#10000,"javascript")

View File

@@ -14,6 +14,7 @@ import semmle.javascript.Concepts
import semmle.javascript.Constants
import semmle.javascript.DefUse
import semmle.javascript.DOM
import semmle.javascript.E4X
import semmle.javascript.EmailClients
import semmle.javascript.Errors
import semmle.javascript.ES2015Modules

View File

@@ -0,0 +1,104 @@
/**
* Provides classes for working with E4X.
*/
import javascript
module E4X {
/**
* An E4X wildcard pseudo-identifier.
*/
class XMLAnyName extends Expr, @e4x_xml_anyname {
}
/**
* An E4X qualified identifier of the form `q::n` or `q::[expr]`.
*
* Note that qualified identifiers are not currently supported by the parser, so snapshots
* will not usually contain any.
*/
class XMLQualifiedIdentifier extends Expr, @e4x_xml_qualident {
/**
* Gets the left operand of this qualified identifier, which is either
* an identifier or a wildcard.
*/
Expr getLeft() { result = getChildExpr(0) }
/**
* Gets the right operand of this qualified identifer, which is either
* an identifier, or an arbitrary expression for computed qualified
* identifiers.
*/
Expr getRight() { result = getChildExpr(1) }
/**
* Holds if this is a qualified identifier with a computed name, as in
* `q::[expr]`.
*/
predicate isComputed() { this instanceof @e4x_xml_dynamic_qualident }
override ControlFlowNode getFirstControlFlowNode() {
result = getLeft().getFirstControlFlowNode()
}
}
/**
* An E4X attribute selector of the form `@name` or `@[expr]`.
*/
class XMLAttributeSelector extends Expr, @e4x_xml_attribute_selector {
/**
* Gets the selected attribute, which is either a static name (that is, a
* wildcard identifier or a possibly qualified name), or an arbitrary
* expression for computed attribute selectors.
*/
Expr getAttribute() { result = getChildExpr(0) }
/**
* Holds if this is an attribute selector with a computed name, as in
* `@[expr]`.
*/
predicate isComputed() { this instanceof @e4x_xml_dynamic_attribute_selector }
override ControlFlowNode getFirstControlFlowNode() {
result = getAttribute().getFirstControlFlowNode()
}
}
/**
* An E4X filter expression of the form `left.(right)`.
*/
class XMLFilterExpression extends Expr, @e4x_xml_filter_expression {
/**
* Gets the left operand of this filter expression.
*/
Expr getLeft() { result = getChildExpr(0) }
/**
* Gets the right operand of this filter expression.
*/
Expr getRight() { result = getChildExpr(1) }
override ControlFlowNode getFirstControlFlowNode() {
result = getLeft().getFirstControlFlowNode()
}
}
/**
* An E4X "dot-dot" expression of the form `e..id`.
*/
class XMLDotDotExpression extends Expr, @e4x_xml_dotdotexpr {
/**
* Gets the base expression of this dot-dot expression.
*/
Expr getBase() { result = getChildExpr(0) }
/**
* Gets the index expression of this dot-dot expression.
*/
Expr getIndex() { result = getChildExpr(1) }
override ControlFlowNode getFirstControlFlowNode() {
result = getBase().getFirstControlFlowNode()
}
}
}

View File

@@ -1078,8 +1078,14 @@ module DataFlow {
nd.asExpr() instanceof ExternalModuleReference and
cause = "import"
or
nd.asExpr() instanceof PropAccess and
cause = "heap"
exists (Expr e | e = nd.asExpr() and cause = "heap" |
e instanceof PropAccess or
e instanceof E4X::XMLAnyName or
e instanceof E4X::XMLAttributeSelector or
e instanceof E4X::XMLDotDotExpression or
e instanceof E4X::XMLFilterExpression or
e instanceof E4X::XMLQualifiedIdentifier
)
or
exists(Expr e | e = nd.asExpr() |
(e instanceof YieldExpr or e instanceof FunctionSentExpr) and

View File

@@ -341,6 +341,13 @@ case @expr.kind of
| 105 = @non_null_assertion
| 106 = @bigintliteral
| 107 = @nullishcoalescingexpr
| 108 = @e4x_xml_anyname
| 109 = @e4x_xml_static_attribute_selector
| 110 = @e4x_xml_dynamic_attribute_selector
| 111 = @e4x_xml_filter_expression
| 112 = @e4x_xml_static_qualident
| 113 = @e4x_xml_dynamic_qualident
| 114 = @e4x_xml_dotdotexpr
;
@varaccess = @proper_varaccess | @export_varaccess;
@@ -386,6 +393,9 @@ case @expr.kind of
@lexical_access = @varaccess | @localtypeaccess | @localvartypeaccess | @localnamespaceaccess;
@lexical_ref = @lexical_decl | @lexical_access;
@e4x_xml_attribute_selector = @e4x_xml_static_attribute_selector | @e4x_xml_dynamic_attribute_selector;
@e4x_xml_qualident = @e4x_xml_static_qualident | @e4x_xml_dynamic_qualident;
// scopes
scopes (unique int id: @scope,
int kind: int ref);

View File

@@ -1386,6 +1386,34 @@
<v>100</v>
</e>
<e>
<k>@e4x_xml_anyname</k>
<v>100</v>
</e>
<e>
<k>@e4x_xml_static_attribute_selector</k>
<v>100</v>
</e>
<e>
<k>@e4x_xml_dynamic_attribute_selector</k>
<v>100</v>
</e>
<e>
<k>@e4x_xml_filter_expression</k>
<v>100</v>
</e>
<e>
<k>@e4x_xml_static_qualident</k>
<v>100</v>
</e>
<e>
<k>@e4x_xml_dynamic_qualident</k>
<v>100</v>
</e>
<e>
<k>@e4x_xml_dotdotexpr</k>
<v>100</v>
</e>
<e>
<k>@xmldtd</k>
<v>1</v>
</e>

View File

@@ -0,0 +1,6 @@
function test(bar, e) {
let foo = bar;
e.target::foo::baz();
}
// semmle-extractor-options: --experimental

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: add E4X support
compatibility: backwards