Merge branch 'development'

Conflicts:
	VERSION
	packages/babel-cli/package.json
	packages/babel-generator/src/buffer.js
	packages/babel-runtime/package.json
	packages/babel-traverse/src/scope/index.js
	packages/babel-types/src/validators.js
	packages/babel/package.json
	packages/babel/src/generation/generators/expressions.js
	packages/babel/src/generation/generators/statements.js
	packages/babel/src/transformation/transformers/es6/tail-call.js
	packages/babel/src/transformation/transformers/es7/async-functions.js
	packages/babel/src/transformation/transformers/es7/exponentiation-operator.js
	packages/babel/src/types/retrievers.js
	packages/babel/test/fixtures/transformation/es6.tail-call/default-parameters/expected.js
	packages/babel/test/fixtures/transformation/es6.tail-call/factorial/expected.js
	packages/babel/test/fixtures/transformation/es6.tail-call/max-args/expected.js
	packages/babel/test/fixtures/transformation/es6.tail-call/recursion/expected.js
	packages/babylon/package.json
This commit is contained in:
Sebastian McKenzie 2015-10-30 00:48:36 +00:00
commit 470d5738e1
2897 changed files with 115810 additions and 10027 deletions

View File

@ -6,10 +6,68 @@
Babylon is a JavaScript parser used in <a href="https://github.com/babel/babel">Babel</a>.
</p>
- ES6 enabled by default.
- Comment attachment.
- Support for JSX and Flow.
- Support for experimental language proposals.
## Credits
Heavily based on [acorn](https://github.com/marijnh/acorn) and [acorn-jsx](https://github.com/RReverser/acorn-jsx),
thanks to the awesome work of [@RReverser](https://github.com/RReverser) and [@marijnh](https://github.com/marijnh).
Significant diversions are expected to occur in the future such as streaming, EBNF definitions, sweet.js integration,
interspacial parsing, comment attachment and more.
Significant diversions are expected to occur in the future such as streaming, EBNF definitions, sweet.js integration, interspacial parsing and more.
## API
### `babylon.parse(code, [options])`
## Options
- **allowImportExportEverywhere**: By default, `import` and `export`
declarations can only appear at a program's top level. Setting this
option to `true` allows them anywhere where a statement is allowed.
- **allowReturnOutsideFunction**: By default, a return statement at
the top level raises an error. Set this to `true` to accept such
code.
- **allowSuperOutsideMethod** TODO
- **sourceType**: Indicate the mode the code should be parsed in. Can be
either `"script"` or `"module"`.
- **plugins**: Array containing the plugins that you want to enable.
### Example
```javascript
require("babylon").parse("code", {
// parse in strict mode and allow module declarations
sourceType: "module",
features: [
// enable experimental async functions
"asyncFunctions",
// enable jsx and flow syntax
"jsx",
"flow"
]
});
```
### Plugins
- `jsx`
- `flow`
- `asyncFunctions`
- `classConstructorCall`
- `doExpressions`
- `trailingFunctionCommas`
- `objectRestSpread`
- `decorators`
- `classProperties`
- `exportExtensions`
- `exponentiationOperator`
- `asyncGenerators`

15
bin/babylon.js Executable file
View File

@ -0,0 +1,15 @@
#!/usr/bin/env node
var babylon = require("../lib/index");
var fs = require("fs");
var filename = process.argv[2];
if (!filename) {
console.error("no filename specified");
process.exit(0);
}
var file = fs.readFileSync(filename, "utf8");
var ast = babylon.parse(file);
console.log(JSON.stringify(ast, null, " "));

View File

@ -1,10 +1,16 @@
{
"name": "babylon",
"version": "5.8.29",
"description": "",
"version": "6.0.2",
"description": "A JavaScript parser",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://babeljs.io/",
"license": "MIT",
"repository": "babel/babel",
"main": "lib/index.js"
"main": "lib/index.js",
"dependencies": {
"babel-runtime": "^6.0.2"
},
"bin": {
"babylon": "./bin/babylon.js"
}
}

View File

@ -1,3 +1,5 @@
/* @flow */
import Parser, { plugins } from "./parser";
import "./parser/util";
import "./parser/statement";

View File

@ -1,29 +1,28 @@
/* @flow */
// A second optional argument can be given to further configure
// the parser process. These options are recognized:
export const defaultOptions = {
// Source type ("script" or "module") for different semantics
sourceType: "script",
// By default, reserved words are not enforced. Disable
// `allowReserved` to enforce them. When this option has the
// value "never", reserved words and keywords can also not be
// used as property names.
allowReserved: true,
// When enabled, a return at the top level is not considered an
// error.
allowReturnOutsideFunction: false,
// When enabled, import/export statements are not constrained to
// appearing at the top of the program.
allowImportExportEverywhere: false,
plugins: {},
// Babel-specific options
features: {},
strictMode: null
// TODO
allowSuperOutsideMethod: false,
// An array of plugins to enable
plugins: [],
// TODO
strictMode: null,
};
// Interpret and default an options object
export function getOptions(opts) {
export function getOptions(opts?: Object): Object {
let options = {};
for (let key in defaultOptions) {
options[key] = opts && key in opts ? opts[key] : defaultOptions[key];

View File

@ -1,3 +1,5 @@
/* @flow */
/**
* Based on the comment attachment algorithm used in espree and estraverse.
*
@ -38,9 +40,9 @@ pp.addComment = function (comment) {
pp.processComment = function (node) {
if (node.type === "Program" && node.body.length > 0) return;
var stack = this.state.commentStack;
let stack = this.state.commentStack;
var lastChild, trailingComments, i;
let lastChild, trailingComments, i;
if (this.state.trailingComments.length > 0) {
// If the first comment in trailingComments comes after the
@ -60,7 +62,7 @@ pp.processComment = function (node) {
this.state.trailingComments.length = 0;
}
} else {
var lastInStack = last(stack);
let lastInStack = last(stack);
if (stack.length > 0 && lastInStack.trailingComments && lastInStack.trailingComments[0].start >= node.end) {
trailingComments = lastInStack.trailingComments;
lastInStack.trailingComments = null;
@ -78,7 +80,7 @@ pp.processComment = function (node) {
node.leadingComments = lastChild.leadingComments;
lastChild.leadingComments = null;
} else {
// A leading comment for an anonymous class had been stolen by its first MethodDefinition,
// A leading comment for an anonymous class had been stolen by its first ClassMethod,
// so this takes back the leading comment.
// See also: https://github.com/eslint/espree/issues/158
for (i = lastChild.leadingComments.length - 2; i >= 0; --i) {

View File

@ -1,3 +1,5 @@
/* @flow */
// A recursive descent parser operates by defining functions for all
// syntactic elements, and recursively calling those, each function
// advancing the input stream and returning an AST node. Precedence
@ -28,17 +30,25 @@ const pp = Parser.prototype;
// strict mode, init properties are also not allowed to be repeated.
pp.checkPropClash = function (prop, propHash) {
if (prop.computed || prop.method || prop.shorthand) return;
if (prop.computed || prop.method) return;
let key = prop.key, name;
let key = prop.key;
let name;
switch (key.type) {
case "Identifier": name = key.name; break;
case "Literal": name = String(key.value); break;
default: return;
case "Identifier":
name = key.name;
break;
case "StringLiteral":
case "NumberLiteral":
name = String(key.value);
break;
default:
return;
}
let kind = prop.kind;
if (name === "__proto__" && kind === "init") {
if (name === "__proto__" && prop.kind === "init") {
if (propHash.proto) this.raise(key.start, "Redefinition of __proto__ property");
propHash.proto = true;
}
@ -101,7 +111,7 @@ pp.parseMaybeAssign = function (noIn, refShorthandDefaultPos, afterLeftParse) {
node.left = this.match(tt.eq) ? this.toAssignable(left) : left;
refShorthandDefaultPos.start = 0; // reset because shorthand default was used correctly
this.checkLVal(left);
if (left.parenthesizedExpression) {
if (left.extra && left.extra.parenthesized) {
let errorMsg;
if (left.type === "ObjectPattern") {
errorMsg = "`({a}) = 0` use `({a} = 0)`";
@ -186,7 +196,7 @@ pp.parseMaybeUnary = function (refShorthandDefaultPos) {
if (refShorthandDefaultPos && refShorthandDefaultPos.start) this.unexpected(refShorthandDefaultPos.start);
if (update) {
this.checkLVal(node.argument);
} else if (this.strict && node.operator === "delete" && node.argument.type === "Identifier") {
} else if (this.state.strict && node.operator === "delete" && node.argument.type === "Identifier") {
this.raise(node.start, "Deleting local variable in strict mode");
}
return this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
@ -215,11 +225,11 @@ pp.parseExprSubscripts = function (refShorthandDefaultPos) {
if (refShorthandDefaultPos && refShorthandDefaultPos.start) {
return expr;
} else {
return this.parseSubscripts(expr, startPos, startLoc);
return this.parseSubscripts(expr, startPos, startLoc);
}
};
pp.parseSubscripts = function(base, startPos, startLoc, noCalls) {
pp.parseSubscripts = function (base, startPos, startLoc, noCalls) {
for (;;) {
if (!noCalls && this.eat(tt.doubleColon)) {
let node = this.startNodeAt(startPos, startLoc);
@ -229,7 +239,7 @@ pp.parseSubscripts = function(base, startPos, startLoc, noCalls) {
} else if (this.eat(tt.dot)) {
let node = this.startNodeAt(startPos, startLoc);
node.object = base;
node.property = this.parseIdent(true);
node.property = this.parseIdentifier(true);
node.computed = false;
base = this.finishNode(node, "MemberExpression");
} else if (this.eat(tt.bracketL)) {
@ -245,11 +255,11 @@ pp.parseSubscripts = function(base, startPos, startLoc, noCalls) {
let node = this.startNodeAt(startPos, startLoc);
node.callee = base;
node.arguments = this.parseExprList(tt.parenR, this.options.features["es7.trailingFunctionCommas"]);
node.arguments = this.parseCallExpressionArguments(tt.parenR, this.hasPlugin("trailingFunctionCommas"), possibleAsync);
base = this.finishNode(node, "CallExpression");
if (possibleAsync && (this.match(tt.colon) || this.match(tt.arrow))) {
base = this.parseAsyncArrowFromCallExpression(this.startNodeAt(startPos, startLoc), node);
if (possibleAsync && this.shouldParseAsyncArrow()) {
return this.parseAsyncArrowFromCallExpression(this.startNodeAt(startPos, startLoc), node);
} else {
this.toReferencedList(node.arguments);
}
@ -264,8 +274,40 @@ pp.parseSubscripts = function(base, startPos, startLoc, noCalls) {
}
};
pp.parseCallExpressionArguments = function (close, allowTrailingComma, possibleAsyncArrow) {
let innerParenStart;
let elts = [], first = true;
while (!this.eat(close)) {
if (first) {
first = false;
} else {
this.expect(tt.comma);
if (allowTrailingComma && this.eat(close)) break;
}
// we need to make sure that if this is an async arrow functions, that we don't allow inner parens inside the params
if (this.match(tt.parenL) && !innerParenStart) {
innerParenStart = this.state.start;
}
elts.push(this.parseExprListItem());
}
// we found an async arrow function so let's not allow any inner parens
if (possibleAsyncArrow && innerParenStart && this.shouldParseAsyncArrow()) {
this.unexpected();
}
return elts;
};
pp.shouldParseAsyncArrow = function () {
return this.match(tt.arrow);
};
pp.parseAsyncArrowFromCallExpression = function (node, call) {
if (!this.options.features["es7.asyncFunctions"]) this.unexpected();
if (!this.hasPlugin("asyncFunctions")) this.unexpected();
this.expect(tt.arrow);
return this.parseArrowExpression(node, call.arguments, true);
};
@ -286,45 +328,46 @@ pp.parseExprAtom = function (refShorthandDefaultPos) {
let node, canBeArrow = this.state.potentialArrowAt === this.state.start;
switch (this.state.type) {
case tt._super:
if (!this.state.inFunction)
if (!this.state.inMethod && !this.options.allowSuperOutsideMethod) {
this.raise(this.state.start, "'super' outside of function or class");
case tt._this:
let type = this.match(tt._this) ? "ThisExpression" : "Super";
}
node = this.startNode();
this.next();
return this.finishNode(node, type);
if (!this.match(tt.parenL) && !this.match(tt.bracketL) && !this.match(tt.dot)) {
this.unexpected();
}
if (this.match(tt.parenL) && this.state.inMethod !== "constructor" && !this.options.allowSuperOutsideMethod) {
this.raise(node.start, "super() outside of class constructor");
}
return this.finishNode(node, "Super");
case tt._this:
node = this.startNode();
this.next();
return this.finishNode(node, "ThisExpression");
case tt._yield:
if (this.state.inGenerator) this.unexpected();
case tt._do:
if (this.options.features["es7.doExpressions"]) {
let node = this.startNode();
this.next();
var oldInFunction = this.state.inFunction;
var oldLabels = this.state.labels;
this.state.labels = [];
this.state.inFunction = false;
node.body = this.parseBlock();
this.state.inFunction = oldInFunction;
this.state.labels = oldLabels;
return this.finishNode(node, "DoExpression");
}
case tt.name:
node = this.startNode();
let id = this.parseIdent(true);
let allowAwait = this.hasPlugin("asyncFunctions") && this.state.value === "await" && this.state.inAsync;
let allowYield = this.shouldAllowYieldIdentifier();
let id = this.parseIdentifier(allowAwait || allowYield);
if (this.options.features["es7.asyncFunctions"]) {
if (this.hasPlugin("asyncFunctions")) {
if (id.name === "await") {
if (this.inAsync) return this.parseAwait(node);
if (this.state.inAsync || this.inModule) {
return this.parseAwait(node);
}
} else if (id.name === "async" && this.match(tt._function) && !this.canInsertSemicolon()) {
this.next();
return this.parseFunction(node, false, false, true);
} else if (canBeArrow && id.name === "async" && this.match(tt.name)) {
var params = [this.parseIdent()];
let params = [this.parseIdentifier()];
this.expect(tt.arrow);
// var foo = bar => {};
// let foo = bar => {};
return this.parseArrowExpression(node, params, true);
}
}
@ -335,21 +378,43 @@ pp.parseExprAtom = function (refShorthandDefaultPos) {
return id;
case tt._do:
if (this.hasPlugin("doExpressions")) {
let node = this.startNode();
this.next();
let oldInFunction = this.state.inFunction;
let oldLabels = this.state.labels;
this.state.labels = [];
this.state.inFunction = false;
node.body = this.parseBlock(false, true);
this.state.inFunction = oldInFunction;
this.state.labels = oldLabels;
return this.finishNode(node, "DoExpression");
}
case tt.regexp:
let value = this.state.value;
node = this.parseLiteral(value.value);
node.regex = {pattern: value.pattern, flags: value.flags};
node = this.parseLiteral(value.value, "RegexLiteral");
node.pattern = value.pattern;
node.flags = value.flags;
return node;
case tt.num: case tt.string:
return this.parseLiteral(this.state.value);
case tt.num:
return this.parseLiteral(this.state.value, "NumberLiteral");
case tt._null: case tt._true: case tt._false:
case tt.string:
return this.parseLiteral(this.state.value, "StringLiteral");
case tt._null:
node = this.startNode();
node.rawValue = node.value = this.match(tt._null) ? null : this.match(tt._true);
node.raw = this.state.type.keyword;
this.next();
return this.finishNode(node, "Literal");
return this.finishNode(node, "NullLiteral");
case tt._true: case tt._false:
node = this.startNode();
node.value = this.match(tt._true);
this.next();
return this.finishNode(node, "BooleanLiteral");
case tt.parenL:
return this.parseParenAndDistinguishExpression(null, null, canBeArrow);
@ -357,10 +422,6 @@ pp.parseExprAtom = function (refShorthandDefaultPos) {
case tt.bracketL:
node = this.startNode();
this.next();
// check whether this is array comprehension or regular array
if (this.options.features["es7.comprehensions"] && this.match(tt._for)) {
return this.parseComprehension(node, false);
}
node.elements = this.parseExprList(tt.bracketR, true, true, refShorthandDefaultPos);
this.toReferencedList(node.elements);
return this.finishNode(node, "ArrayExpression");
@ -403,12 +464,13 @@ pp.parseExprAtom = function (refShorthandDefaultPos) {
}
};
pp.parseLiteral = function (value) {
pp.parseLiteral = function (value, type) {
let node = this.startNode();
node.rawValue = node.value = value;
node.raw = this.input.slice(this.state.start, this.state.end);
this.addExtra(node, "rawValue", value);
this.addExtra(node, "raw", this.input.slice(this.state.start, this.state.end));
node.value = value;
this.next();
return this.finishNode(node, "Literal");
return this.finishNode(node, type);
};
pp.parseParenExpression = function () {
@ -424,19 +486,15 @@ pp.parseParenAndDistinguishExpression = function (startPos, startLoc, canBeArrow
let val;
this.next();
if (this.options.features["es7.comprehensions"] && this.match(tt._for)) {
return this.parseComprehension(this.startNodeAt(startPos, startLoc), true);
}
let innerStartPos = this.state.start, innerStartLoc = this.state.startLoc;
let exprList = [], first = true;
let refShorthandDefaultPos = {start: 0}, spreadStart, innerParenStart, optionalCommaStart;
let refShorthandDefaultPos = { start: 0 }, spreadStart, innerParenStart, optionalCommaStart;
while (!this.match(tt.parenR)) {
if (first) {
first = false;
} else {
this.expect(tt.comma);
if (this.match(tt.parenR) && this.options.features["es7.trailingFunctionCommas"]) {
if (this.match(tt.parenR) && this.hasPlugin("trailingFunctionCommas")) {
optionalCommaStart = this.state.start;
break;
}
@ -454,6 +512,7 @@ pp.parseParenAndDistinguishExpression = function (startPos, startLoc, canBeArrow
exprList.push(this.parseMaybeAssign(false, refShorthandDefaultPos, this.parseParenItem));
}
}
let innerEndPos = this.state.start;
let innerEndLoc = this.state.startLoc;
this.expect(tt.parenR);
@ -482,8 +541,7 @@ pp.parseParenAndDistinguishExpression = function (startPos, startLoc, canBeArrow
} else {
val = exprList[0];
}
val.parenthesizedExpression = true;
this.addExtra(val, "parenthesized", true);
return val;
};
@ -497,11 +555,11 @@ pp.parseParenItem = function (node) {
pp.parseNew = function () {
let node = this.startNode();
let meta = this.parseIdent(true);
let meta = this.parseIdentifier(true);
if (this.eat(tt.dot)) {
node.meta = meta;
node.property = this.parseIdent(true);
node.property = this.parseIdentifier(true);
if (node.property.name !== "target") {
this.raise(node.property.start, "The only valid meta property for new is new.target");
@ -513,7 +571,7 @@ pp.parseNew = function () {
node.callee = this.parseNoCallExpr();
if (this.eat(tt.parenL)) {
node.arguments = this.parseExprList(tt.parenR, this.options.features["es7.trailingFunctionCommas"]);
node.arguments = this.parseExprList(tt.parenR, this.hasPlugin("trailingFunctionCommas"));
this.toReferencedList(node.arguments);
} else {
node.arguments = [];
@ -554,10 +612,14 @@ pp.parseTemplate = function () {
// Parse an object literal or binding pattern.
pp.parseObj = function (isPattern, refShorthandDefaultPos) {
let node = this.startNode(), first = true, propHash = Object.create(null);
node.properties = [];
let decorators = [];
let propHash = Object.create(null);
let first = true;
let node = this.startNode();
node.properties = [];
this.next();
while (!this.eat(tt.braceR)) {
if (first) {
first = false;
@ -575,24 +637,30 @@ pp.parseObj = function (isPattern, refShorthandDefaultPos) {
prop.decorators = decorators;
decorators = [];
}
if (this.options.features["es7.objectRestSpread"] && this.match(tt.ellipsis)) {
if (this.hasPlugin("objectRestSpread") && this.match(tt.ellipsis)) {
prop = this.parseSpread();
prop.type = "SpreadProperty";
prop.type = isPattern ? "RestProperty" : "SpreadProperty";
node.properties.push(prop);
continue;
}
prop.method = false;
prop.shorthand = false;
if (isPattern || refShorthandDefaultPos) {
startPos = this.state.start;
startLoc = this.state.startLoc;
}
if (!isPattern) {
isGenerator = this.eat(tt.star);
}
if (!isPattern && this.options.features["es7.asyncFunctions"] && this.isContextual("async")) {
if (!isPattern && this.hasPlugin("asyncFunctions") && this.isContextual("async")) {
if (isGenerator) this.unexpected();
var asyncId = this.parseIdent();
let asyncId = this.parseIdentifier();
if (this.match(tt.colon) || this.match(tt.parenL) || this.match(tt.braceR)) {
prop.key = asyncId;
} else {
@ -602,57 +670,78 @@ pp.parseObj = function (isPattern, refShorthandDefaultPos) {
} else {
this.parsePropertyName(prop);
}
this.parseObjPropValue(prop, startPos, startLoc, isGenerator, isAsync, isPattern, refShorthandDefaultPos);
this.checkPropClash(prop, propHash);
node.properties.push(this.finishNode(prop, "Property"));
if (prop.shorthand) {
this.addExtra(prop, "shorthand", true);
}
node.properties.push(prop);
}
if (decorators.length) {
this.raise(this.state.start, "You have trailing decorators with no property");
}
return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression");
};
pp.parseObjPropValue = function (prop, startPos, startLoc, isGenerator, isAsync, isPattern, refShorthandDefaultPos) {
if (this.eat(tt.colon)) {
prop.value = isPattern ? this.parseMaybeDefault(this.state.start, this.state.startLoc) : this.parseMaybeAssign(false, refShorthandDefaultPos);
prop.kind = "init";
} else if (this.match(tt.parenL)) {
return this.finishNode(prop, "ObjectProperty");
}
if (this.match(tt.parenL)) {
if (isPattern) this.unexpected();
prop.kind = "init";
prop.kind = "method";
prop.method = true;
prop.value = this.parseMethod(isGenerator, isAsync);
} else if (!prop.computed && prop.key.type === "Identifier" && (prop.key.name === "get" || prop.key.name === "set") && (!this.match(tt.comma) && !this.match(tt.braceR))) {
this.parseMethod(prop, isGenerator, isAsync);
return this.finishNode(prop, "ObjectMethod");
}
if (!prop.computed && prop.key.type === "Identifier" && (prop.key.name === "get" || prop.key.name === "set") && (!this.match(tt.comma) && !this.match(tt.braceR))) {
if (isGenerator || isAsync || isPattern) this.unexpected();
prop.kind = prop.key.name;
this.parsePropertyName(prop);
prop.value = this.parseMethod(false);
this.parseMethod(prop, false);
let paramCount = prop.kind === "get" ? 0 : 1;
if (prop.value.params.length !== paramCount) {
let start = prop.value.start;
if (prop.kind === "get")
if (prop.params.length !== paramCount) {
let start = prop.start;
if (prop.kind === "get") {
this.raise(start, "getter should have no params");
else
} else {
this.raise(start, "setter should have exactly one param");
}
}
} else if (!prop.computed && prop.key.type === "Identifier") {
prop.kind = "init";
return this.finishNode(prop, "ObjectMethod");
}
if (!prop.computed && prop.key.type === "Identifier") {
if (isPattern) {
if (this.isKeyword(prop.key.name) ||
(this.strict && (reservedWords.strictBind(prop.key.name) || reservedWords.strict(prop.key.name))) ||
(!this.options.allowReserved && this.isReservedWord(prop.key.name)))
this.raise(prop.key.start, "Binding " + prop.key.name);
let illegalBinding = this.isKeyword(prop.key.name);
if (!illegalBinding && this.state.strict) {
illegalBinding = reservedWords.strictBind(prop.key.name) || reservedWords.strict(prop.key.name);
}
if (illegalBinding) {
this.raise(prop.key.start, "Binding " + prop.key.name);
}
prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key.__clone());
} else if (this.match(tt.eq) && refShorthandDefaultPos) {
if (!refShorthandDefaultPos.start)
if (!refShorthandDefaultPos.start) {
refShorthandDefaultPos.start = this.state.start;
}
prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key.__clone());
} else {
prop.value = prop.key.__clone();
}
prop.shorthand = true;
} else {
this.unexpected();
return this.finishNode(prop, "ObjectProperty");
}
this.unexpected();
};
pp.parsePropertyName = function (prop) {
@ -663,7 +752,7 @@ pp.parsePropertyName = function (prop) {
return prop.key;
} else {
prop.computed = false;
return prop.key = (this.match(tt.num) || this.match(tt.string)) ? this.parseExprAtom() : this.parseIdent(true);
return prop.key = (this.match(tt.num) || this.match(tt.string)) ? this.parseExprAtom() : this.parseIdentifier(true);
}
};
@ -673,21 +762,23 @@ pp.initFunction = function (node, isAsync) {
node.id = null;
node.generator = false;
node.expression = false;
if (this.options.features["es7.asyncFunctions"]) {
if (this.hasPlugin("asyncFunctions")) {
node.async = !!isAsync;
}
};
// Parse object or class method.
pp.parseMethod = function (isGenerator, isAsync) {
let node = this.startNode();
pp.parseMethod = function (node, isGenerator, isAsync) {
let oldInMethod = this.state.inMethod;
this.state.inMethod = node.kind || true;
this.initFunction(node, isAsync);
this.expect(tt.parenL);
node.params = this.parseBindingList(tt.parenR, false, this.options.features["es7.trailingFunctionCommas"]);
node.params = this.parseBindingList(tt.parenR, false, this.hasPlugin("trailingFunctionCommas"));
node.generator = isGenerator;
this.parseFunctionBody(node);
return this.finishNode(node, "FunctionExpression");
this.state.inMethod = oldInMethod;
return node;
};
// Parse arrow function expression with given parameters.
@ -704,8 +795,8 @@ pp.parseArrowExpression = function (node, params, isAsync) {
pp.parseFunctionBody = function (node, allowExpression) {
let isExpression = allowExpression && !this.match(tt.braceL);
var oldInAsync = this.inAsync;
this.inAsync = node.async;
let oldInAsync = this.state.inAsync;
this.state.inAsync = node.async;
if (isExpression) {
node.body = this.parseMaybeAssign();
node.expression = true;
@ -718,21 +809,46 @@ pp.parseFunctionBody = function (node, allowExpression) {
node.expression = false;
this.state.inFunction = oldInFunc; this.state.inGenerator = oldInGen; this.state.labels = oldLabels;
}
this.inAsync = oldInAsync;
this.state.inAsync = oldInAsync;
// If this is a strict mode function, verify that argument names
// are not repeated, and it does not try to bind the words `eval`
// or `arguments`.
if (this.strict || !isExpression && node.body.body.length && this.isUseStrict(node.body.body[0])) {
let nameHash = Object.create(null), oldStrict = this.strict;
this.strict = true;
let checkLVal = this.state.strict;
let checkLValStrict = false;
let isStrict = false;
// arrow function
if (allowExpression) checkLVal = true;
// normal function
if (!isExpression && node.body.directives.length) {
for (let directive of (node.body.directives: Array<Object>)) {
if (directive.value.value === "use strict") {
isStrict = true;
checkLVal = true;
checkLValStrict = true;
break;
}
}
}
//
if (isStrict && node.id && node.id.type === "Identifier" && node.id.name === "yield") {
this.raise(node.id.start, "Binding yield in strict mode");
}
if (checkLVal) {
let nameHash = Object.create(null);
let oldStrict = this.state.strict;
if (checkLValStrict) this.state.strict = true;
if (node.id) {
this.checkLVal(node.id, true);
}
for (let param of (node.params: Array)) {
for (let param of (node.params: Array<Object>)) {
this.checkLVal(param, true, nameHash);
}
this.strict = oldStrict;
this.state.strict = oldStrict;
}
};
@ -773,19 +889,25 @@ pp.parseExprListItem = function (allowEmpty, refShorthandDefaultPos) {
// when parsing properties), it will also convert keywords into
// identifiers.
pp.parseIdent = function (liberal) {
pp.parseIdentifier = function (liberal) {
let node = this.startNode();
if (this.match(tt.name)) {
if (!liberal &&
((!this.options.allowReserved && this.isReservedWord(this.state.value)) ||
(this.strict && reservedWords.strict(this.state.value))))
if (!liberal && this.state.strict && reservedWords.strict(this.state.value)) {
this.raise(this.state.start, "The keyword '" + this.state.value + "' is reserved");
}
node.name = this.state.value;
} else if (liberal && this.state.type.keyword) {
node.name = this.state.type.keyword;
} else {
this.unexpected();
}
if (!liberal && node.name === "await" && this.state.inAsync) {
this.raise(node.start, "invalid use of await inside of an async function");
}
this.next();
return this.finishNode(node, "Identifier");
};
@ -793,7 +915,7 @@ pp.parseIdent = function (liberal) {
// Parses await expression inside async function.
pp.parseAwait = function (node) {
if (this.eat(tt.semi) || this.canInsertSemicolon()) {
if (this.isLineTerminator()) {
this.unexpected();
}
node.all = this.eat(tt.star);
@ -815,25 +937,3 @@ pp.parseYield = function () {
}
return this.finishNode(node, "YieldExpression");
};
// Parses array and generator comprehensions.
pp.parseComprehension = function (node, isGenerator) {
node.blocks = [];
while (this.match(tt._for)) {
let block = this.startNode();
this.next();
this.expect(tt.parenL);
block.left = this.parseBindingAtom();
this.checkLVal(block.left, true);
this.expectContextual("of");
block.right = this.parseExpression();
this.expect(tt.parenR);
node.blocks.push(this.finishNode(block, "ComprehensionBlock"));
}
node.filter = this.eat(tt._if) ? this.parseParenExpression() : null;
node.body = this.parseExpression();
this.expect(isGenerator ? tt.parenR : tt.bracketR);
node.generator = isGenerator;
return this.finishNode(node, "ComprehensionExpression");
};

View File

@ -1,24 +1,21 @@
import { reservedWords, isKeyword } from "../util/identifier";
/* @flow */
import { reservedWords } from "../util/identifier";
import { getOptions } from "../options";
import Tokenizer from "../tokenizer";
// Registered plugins
export const plugins = {};
export default class Parser extends Tokenizer {
constructor(options, input) {
super(input);
constructor(options, input: string) {
options = getOptions(options);
super(options, input);
this.options = getOptions(options);
this.isKeyword = isKeyword;
this.options = options;
this.inModule = this.options.sourceType === "module";
this.isReservedWord = reservedWords[6];
this.input = input;
this.loadPlugins(this.options.plugins);
// Figure out if it's a module code.
this.inModule = this.options.sourceType === "module";
this.strict = this.options.strictMode === false ? false : this.inModule;
this.plugins = this.loadPlugins(this.options.plugins);
// If enabled, skip leading hashbang line.
if (this.state.pos === 0 && this.input[0] === "#" && this.input[1] === "!") {
@ -26,19 +23,40 @@ export default class Parser extends Tokenizer {
}
}
extend(name, f) {
hasPlugin(name: string): boolean {
return !!(this.plugins["*"] || this.plugins[name]);
}
extend(name: string, f: Function) {
this[name] = f(this[name]);
}
loadPlugins(plugins) {
for (let name in plugins) {
let plugin = exports.plugins[name];
if (!plugin) throw new Error(`Plugin '${name}' not found`);
plugin(this, plugins[name]);
loadPlugins(plugins: Array<string>) {
let pluginMap = {};
if (plugins.indexOf("flow") >= 0) {
// ensure flow plugin loads last
plugins.splice(plugins.indexOf("flow"), 1);
plugins.push("flow");
}
for (let name of plugins) {
pluginMap[name] = true;
let plugin = exports.plugins[name];
if (plugin) plugin(this);
}
return pluginMap;
}
parse() {
parse(): {
type: "File",
program: {
type: "Program",
body: Array<Object>
}
} {
let file = this.startNode();
let program = this.startNode();
this.nextToken();

View File

@ -1,3 +1,5 @@
/* @flow */
import { getLineInfo } from "../util/location";
import Parser from "./index";

View File

@ -1,3 +1,5 @@
/* @flow */
import { types as tt } from "../tokenizer/types";
import Parser from "./index";
import { reservedWords } from "../util/identifier";
@ -18,10 +20,20 @@ pp.toAssignable = function (node, isBinding) {
case "ObjectExpression":
node.type = "ObjectPattern";
for (let prop of (node.properties: Array)) {
for (let prop of (node.properties: Array<Object>)) {
if (prop.type === "SpreadProperty") continue;
if (prop.kind !== "init") this.raise(prop.key.start, "Object pattern can't contain getter or setter");
this.toAssignable(prop.value, isBinding);
if (prop.type === "ObjectMethod") {
if (prop.kind === "get" || prop.kind === "set") {
this.raise(prop.key.start, "Object pattern can't contain getter or setter");
} else {
this.raise(prop.key.start, "Object pattern can't contain methods");
}
}
if (prop.type === "ObjectProperty") {
this.toAssignable(prop.value, isBinding);
}
}
break;
@ -92,16 +104,27 @@ pp.parseSpread = function (refShorthandDefaultPos) {
pp.parseRest = function () {
let node = this.startNode();
this.next();
node.argument = this.match(tt.name) || this.match(tt.bracketL) ? this.parseBindingAtom() : this.unexpected();
node.argument = this.parseBindingIdentifier();
return this.finishNode(node, "RestElement");
};
pp.shouldAllowYieldIdentifier = function () {
return this.match(tt._yield) && !this.state.strict && !this.state.inGenerator;
};
pp.parseBindingIdentifier = function () {
return this.parseIdentifier(this.shouldAllowYieldIdentifier());
};
// Parses lvalue (assignable) atom.
pp.parseBindingAtom = function () {
switch (this.state.type) {
case tt._yield:
if (this.state.strict || this.state.inGenerator) this.unexpected();
case tt.name:
return this.parseIdent();
return this.parseIdentifier(true);
case tt.bracketL:
let node = this.startNode();
@ -118,10 +141,14 @@ pp.parseBindingAtom = function () {
};
pp.parseBindingList = function (close, allowEmpty, allowTrailingComma) {
var elts = [], first = true;
let elts = [];
let first = true;
while (!this.eat(close)) {
if (first) first = false;
else this.expect(tt.comma);
if (first) {
first = false;
} else {
this.expect(tt.comma);
}
if (allowEmpty && this.match(tt.comma)) {
elts.push(null);
} else if (allowTrailingComma && this.eat(close)) {
@ -131,7 +158,7 @@ pp.parseBindingList = function (close, allowEmpty, allowTrailingComma) {
this.expect(close);
break;
} else {
var left = this.parseMaybeDefault();
let left = this.parseMaybeDefault();
this.parseAssignableListItemTypes(left);
elts.push(this.parseMaybeDefault(null, null, left));
}
@ -163,8 +190,10 @@ pp.parseMaybeDefault = function (startPos, startLoc, left) {
pp.checkLVal = function (expr, isBinding, checkClashes) {
switch (expr.type) {
case "Identifier":
if (this.strict && (reservedWords.strictBind(expr.name) || reservedWords.strict(expr.name)))
if (this.state.strict && (reservedWords.strictBind(expr.name) || reservedWords.strict(expr.name))) {
this.raise(expr.start, (isBinding ? "Binding " : "Assigning to ") + expr.name + " in strict mode");
}
if (checkClashes) {
if (checkClashes[expr.name]) {
this.raise(expr.start, "Argument name clash in strict mode");
@ -179,14 +208,14 @@ pp.checkLVal = function (expr, isBinding, checkClashes) {
break;
case "ObjectPattern":
for (let prop of (expr.properties: Array)) {
if (prop.type === "Property") prop = prop.value;
for (let prop of (expr.properties: Array<Object>)) {
if (prop.type === "ObjectProperty") prop = prop.value;
this.checkLVal(prop, isBinding, checkClashes);
}
break;
case "ArrayPattern":
for (let elem of (expr.elements: Array)) {
for (let elem of (expr.elements: Array<Object>)) {
if (elem) this.checkLVal(elem, isBinding, checkClashes);
}
break;
@ -195,7 +224,7 @@ pp.checkLVal = function (expr, isBinding, checkClashes) {
this.checkLVal(expr.left, isBinding, checkClashes);
break;
case "SpreadProperty":
case "RestProperty":
case "RestElement":
this.checkLVal(expr.argument, isBinding, checkClashes);
break;

View File

@ -1,3 +1,5 @@
/* @flow */
import Parser from "./index";
import { SourceLocation } from "../util/location";
@ -5,27 +7,32 @@ import { SourceLocation } from "../util/location";
const pp = Parser.prototype;
export class Node {
constructor(parser, pos, loc) {
class Node {
constructor(pos?: number, loc?: SourceLocation) {
this.type = "";
this.start = pos;
this.end = 0;
this.loc = new SourceLocation(loc);
}
__clone() {
var node2 = new Node;
for (var key in this) node2[key] = this[key];
type: string;
start: ?number;
end: number;
loc: SourceLocation;
__clone(): Node {
let node2 = new Node;
for (let key in this) node2[key] = this[key];
return node2;
}
}
pp.startNode = function () {
return new Node(this, this.state.start, this.state.startLoc);
return new Node(this.state.start, this.state.startLoc);
};
pp.startNodeAt = function (pos, loc) {
return new Node(this, pos, loc);
return new Node(pos, loc);
};
function finishNodeAt(node, type, pos, loc) {

View File

@ -1,3 +1,5 @@
/* @flow */
import { types as tt } from "../tokenizer/types";
import Parser from "./index";
import { lineBreak } from "../util/whitespace";
@ -13,18 +15,8 @@ const pp = Parser.prototype;
pp.parseTopLevel = function (file, program) {
program.sourceType = this.options.sourceType;
program.body = [];
let first = true;
while (!this.match(tt.eof)) {
let stmt = this.parseStatement(true, true);
program.body.push(stmt);
if (first) {
if (this.isUseStrict(stmt)) this.setStrict(true);
first = false;
}
}
this.next();
this.parseBlockBody(program, true, true, tt.eof);
file.program = this.finishNode(program, "Program");
file.comments = this.state.comments;
@ -35,6 +27,26 @@ pp.parseTopLevel = function (file, program) {
const loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"};
// TODO
pp.parseDirective = function () {
let directiveLiteral = this.startNode();
let directive = this.startNode();
let raw = this.input.slice(this.state.start, this.state.end);
let val = directiveLiteral.value = raw.slice(1, -1); // remove quotes
this.addExtra(directiveLiteral, "raw", raw);
this.addExtra(directiveLiteral, "rawValue", val);
this.next();
directive.value = this.finishNode(directiveLiteral, "DirectiveLiteral");
this.semicolon();
return this.finishNode(directive, "Directive");
};
// Parse a single statement.
//
// If expecting a statement and finding a slash operator, parse a
@ -72,8 +84,14 @@ pp.parseStatement = function (declaration, topLevel) {
case tt._switch: return this.parseSwitchStatement(node);
case tt._throw: return this.parseThrowStatement(node);
case tt._try: return this.parseTryStatement(node);
case tt._let: case tt._const: if (!declaration) this.unexpected(); // NOTE: falls through to _var
case tt._var: return this.parseVarStatement(node, starttype);
case tt._let:
case tt._const:
if (!declaration) this.unexpected(); // NOTE: falls through to _var
case tt._var:
return this.parseVarStatement(node, starttype);
case tt._while: return this.parseWhileStatement(node);
case tt._with: return this.parseWithStatement(node);
case tt.braceL: return this.parseBlock();
@ -81,18 +99,20 @@ pp.parseStatement = function (declaration, topLevel) {
case tt._export:
case tt._import:
if (!this.options.allowImportExportEverywhere) {
if (!topLevel)
if (!topLevel) {
this.raise(this.state.start, "'import' and 'export' may only appear at the top level");
}
if (!this.inModule)
if (!this.inModule) {
this.raise(this.state.start, "'import' and 'export' may appear only with 'sourceType: module'");
}
}
return starttype === tt._import ? this.parseImport(node) : this.parseExport(node);
case tt.name:
if (this.options.features["es7.asyncFunctions"] && this.state.value === "async") {
if (this.hasPlugin("asyncFunctions") && this.state.value === "async") {
// peek ahead and see if next token is a function
var state = this.state.clone();
let state = this.state.clone();
this.next();
if (this.match(tt._function) && !this.canInsertSemicolon()) {
this.expect(tt._function);
@ -101,20 +121,19 @@ pp.parseStatement = function (declaration, topLevel) {
this.state = state;
}
}
}
// If the statement does not start with a statement keyword or a
// brace, it's an ExpressionStatement or LabeledStatement. We
// simply start parsing an expression, and afterwards, if the
// next token is a colon and the expression was a simple
// Identifier node, we switch to interpreting it as a label.
default:
let maybeName = this.state.value, expr = this.parseExpression();
// If the statement does not start with a statement keyword or a
// brace, it's an ExpressionStatement or LabeledStatement. We
// simply start parsing an expression, and afterwards, if the
// next token is a colon and the expression was a simple
// Identifier node, we switch to interpreting it as a label.
let maybeName = this.state.value, expr = this.parseExpression();
if (starttype === tt.name && expr.type === "Identifier" && this.eat(tt.colon)) {
return this.parseLabeledStatement(node, maybeName, expr);
} else {
return this.parseExpressionStatement(node, expr);
}
if (starttype === tt.name && expr.type === "Identifier" && this.eat(tt.colon)) {
return this.parseLabeledStatement(node, maybeName, expr);
} else {
return this.parseExpressionStatement(node, expr);
}
};
@ -140,7 +159,7 @@ pp.parseDecorators = function (allowExport) {
};
pp.parseDecorator = function () {
if (!this.options.features["es7.decorators"]) {
if (!this.hasPlugin("decorators")) {
this.unexpected();
}
let node = this.startNode();
@ -153,18 +172,19 @@ pp.parseBreakContinueStatement = function (node, keyword) {
let isBreak = keyword === "break";
this.next();
if (this.eat(tt.semi) || this.canInsertSemicolon()) {
if (this.isLineTerminator()) {
node.label = null;
} else if (!this.match(tt.name)) {
this.unexpected();
} else {
node.label = this.parseIdent();
node.label = this.parseIdentifier();
this.semicolon();
}
// Verify that there is an actual destination to break or
// continue to.
for (var i = 0; i < this.state.labels.length; ++i) {
let i;
for (i = 0; i < this.state.labels.length; ++i) {
let lab = this.state.labels[i];
if (node.label == null || lab.name === node.label.name) {
if (lab.kind != null && (isBreak || lab.kind === "loop")) break;
@ -214,9 +234,13 @@ pp.parseForStatement = function (node) {
this.next();
this.parseVar(init, true, varKind);
this.finishNode(init, "VariableDeclaration");
if ((this.match(tt._in) || this.isContextual("of")) && init.declarations.length === 1 &&
!(varKind !== tt._var && init.declarations[0].init))
return this.parseForIn(node, init);
if (this.match(tt._in) || this.isContextual("of")) {
if (init.declarations.length === 1 && !init.declarations[0].init) {
return this.parseForIn(node, init);
}
}
return this.parseFor(node, init);
}
@ -256,7 +280,7 @@ pp.parseReturnStatement = function (node) {
// optional arguments, we eagerly look for a semicolon or the
// possibility to insert one.
if (this.eat(tt.semi) || this.canInsertSemicolon()) {
if (this.isLineTerminator()) {
node.argument = null;
} else {
node.argument = this.parseExpression();
@ -277,7 +301,8 @@ pp.parseSwitchStatement = function (node) {
// nodes. `cur` is used to keep the node that we are currently
// adding statements to.
for (var cur, sawDefault; !this.match(tt.braceR); ) {
let cur;
for (let sawDefault; !this.match(tt.braceR); ) {
if (this.match(tt._case) || this.match(tt._default)) {
let isCase = this.match(tt._case);
if (cur) this.finishNode(cur, "SwitchCase");
@ -293,8 +318,11 @@ pp.parseSwitchStatement = function (node) {
}
this.expect(tt.colon);
} else {
if (!cur) this.unexpected();
cur.consequent.push(this.parseStatement(true));
if (cur) {
cur.consequent.push(this.parseStatement(true));
} else {
this.unexpected();
}
}
}
if (cur) this.finishNode(cur, "SwitchCase");
@ -314,19 +342,23 @@ pp.parseThrowStatement = function (node) {
// Reused empty array added for node fields that are always empty.
var empty = [];
let empty = [];
pp.parseTryStatement = function (node) {
this.next();
node.block = this.parseBlock();
node.handler = null;
if (this.match(tt._catch)) {
let clause = this.startNode();
this.next();
this.expect(tt.parenL);
clause.param = this.parseBindingAtom();
this.checkLVal(clause.param, true);
this.checkLVal(clause.param, true, Object.create(null));
this.expect(tt.parenR);
clause.body = this.parseBlock();
node.handler = this.finishNode(clause, "CatchClause");
}
@ -358,7 +390,7 @@ pp.parseWhileStatement = function (node) {
};
pp.parseWithStatement = function (node) {
if (this.strict) this.raise(this.state.start, "'with' in strict mode");
if (this.state.strict) this.raise(this.state.start, "'with' in strict mode");
this.next();
node.object = this.parseParenExpression();
node.body = this.parseStatement(false);
@ -371,7 +403,7 @@ pp.parseEmptyStatement = function (node) {
};
pp.parseLabeledStatement = function (node, maybeName, expr) {
for (let label of (this.state.labels: Array)){
for (let label of (this.state.labels: Array<Object>)){
if (label.name === maybeName) {
this.raise(expr.start, `Label '${maybeName}' is already declared`);
}
@ -405,23 +437,62 @@ pp.parseExpressionStatement = function (node, expr) {
// strict"` declarations when `allowStrict` is true (used for
// function bodies).
pp.parseBlock = function (allowStrict) {
let node = this.startNode(), first = true, oldStrict;
node.body = [];
pp.parseBlock = function (allowDirectives?) {
let node = this.startNode();
this.expect(tt.braceL);
while (!this.eat(tt.braceR)) {
let stmt = this.parseStatement(true);
node.body.push(stmt);
if (first && allowStrict && this.isUseStrict(stmt)) {
oldStrict = this.strict;
this.setStrict(this.strict = true);
}
first = false;
}
if (oldStrict === false) this.setStrict(false);
this.parseBlockBody(node, allowDirectives, false, tt.braceR);
return this.finishNode(node, "BlockStatement");
};
// TODO
pp.parseBlockBody = function (node, allowDirectives, topLevel, end) {
node.body = [];
node.directives = [];
let parsedNonDirective = false;
let oldStrict;
let octalPosition;
while (!this.eat(end)) {
if (allowDirectives && !parsedNonDirective && this.match(tt.string)) {
let oldState = this.state;
let lookahead = this.lookahead();
this.state = lookahead;
let isDirective = this.isLineTerminator();
this.state = oldState;
if (isDirective) {
if (this.state.containsOctal && !octalPosition) {
octalPosition = this.state.octalPosition;
}
let stmt = this.parseDirective();
node.directives.push(stmt);
if (allowDirectives && stmt.value.value === "use strict") {
oldStrict = this.state.strict;
this.state.strict = true;
this.setStrict(true);
if (octalPosition) {
this.raise(octalPosition, "Octal literal in strict mode");
}
}
continue;
}
}
parsedNonDirective = true;
node.body.push(this.parseStatement(true, topLevel));
}
if (oldStrict === false) {
this.setStrict(false);
}
};
// Parse a regular `for` loop. The disambiguation code in
// `parseStatement` will already have parsed the init statement or
// expression.
@ -483,76 +554,142 @@ pp.parseVarHead = function (decl) {
// Parse a function declaration or literal (depending on the
// `isStatement` parameter).
pp.parseFunction = function (node, isStatement, allowExpressionBody, isAsync) {
this.initFunction(node, isAsync);
node.generator = this.eat(tt.star);
pp.parseFunction = function (node, isStatement, allowExpressionBody, isAsync, optionalId) {
let oldInMethod = this.state.inMethod;
this.state.inMethod = false;
if (isStatement || this.match(tt.name)) {
node.id = this.parseIdent();
this.initFunction(node, isAsync);
if (this.match(tt.star)) {
if (node.async && !this.hasPlugin("asyncGenerators")) {
this.unexpected();
} else {
node.generator = true;
this.next();
}
}
if (isStatement && !optionalId && !this.match(tt.name) && !this.match(tt._yield)) {
this.unexpected();
}
if (this.match(tt.name) || this.match(tt._yield)) {
node.id = this.parseBindingIdentifier();
}
this.parseFunctionParams(node);
this.parseFunctionBody(node, allowExpressionBody);
this.state.inMethod = oldInMethod;
return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression");
};
pp.parseFunctionParams = function (node) {
this.expect(tt.parenL);
node.params = this.parseBindingList(tt.parenR, false, this.options.features["es7.trailingFunctionCommas"]);
node.params = this.parseBindingList(tt.parenR, false, this.hasPlugin("trailingFunctionCommas"));
};
// Parse a class declaration or literal (depending on the
// `isStatement` parameter).
pp.parseClass = function (node, isStatement) {
pp.parseClass = function (node, isStatement, optionalId) {
this.next();
this.parseClassId(node, isStatement);
this.parseClassId(node, isStatement, optionalId);
this.parseClassSuper(node);
var classBody = this.startNode();
this.parseClassBody(node);
return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression");
};
pp.isClassProperty = function () {
return this.match(tt.eq) || this.isLineTerminator();
};
pp.parseClassBody = function (node) {
// class bodies are implicitly strict
let oldStrict = this.state.strict;
this.state.strict = true;
let hadConstructorCall = false;
let hadConstructor = false;
classBody.body = [];
this.expect(tt.braceL);
let decorators = [];
let classBody = this.startNode();
classBody.body = [];
this.expect(tt.braceL);
while (!this.eat(tt.braceR)) {
if (this.eat(tt.semi)) continue;
if (this.eat(tt.semi)) {
continue;
}
if (this.match(tt.at)) {
decorators.push(this.parseDecorator());
continue;
}
var method = this.startNode();
let method = this.startNode();
// steal the decorators if there are any
if (decorators.length) {
method.decorators = decorators;
decorators = [];
}
let isConstructorCall = false;
let isMaybeStatic = this.match(tt.name) && this.state.value === "static";
var isGenerator = this.eat(tt.star), isAsync = false;
let isGenerator = this.eat(tt.star);
let isGetSet = false;
let isAsync = false;
this.parsePropertyName(method);
method.static = isMaybeStatic && !this.match(tt.parenL);
if (method.static) {
if (isGenerator) this.unexpected();
isGenerator = this.eat(tt.star);
this.parsePropertyName(method);
}
if (!isGenerator && method.key.type === "Identifier" && !method.computed && this.isClassProperty()) {
classBody.body.push(this.parseClassProperty(method));
continue;
if (!isGenerator && method.key.type === "Identifier" && !method.computed) {
if (this.isClassProperty()) {
classBody.body.push(this.parseClassProperty(method));
continue;
}
if (this.hasPlugin("classConstructorCall") && method.key.name === "call" && this.match(tt.name) && this.state.value === "constructor") {
isConstructorCall = true;
this.parsePropertyName(method);
}
}
if (this.options.features["es7.asyncFunctions"] && !this.match(tt.parenL) &&
!method.computed && method.key.type === "Identifier" && method.key.name === "async") {
let isAsyncMethod = this.hasPlugin("asyncFunctions") && !this.match(tt.parenL) && !method.computed && method.key.type === "Identifier" && method.key.name === "async";
if (isAsyncMethod) {
if (this.hasPlugin("asyncGenerators") && this.eat(tt.star)) isGenerator = true;
isAsync = true;
this.parsePropertyName(method);
}
let isGetSet = false;
method.kind = "method";
if (!method.computed) {
let {key} = method;
let { key } = method;
// handle get/set methods
// eg. class Foo { get bar() {} set bar() {} }
if (!isAsync && !isGenerator && key.type === "Identifier" && !this.match(tt.parenL) && (key.name === "get" || key.name === "set")) {
isGetSet = true;
method.kind = key.name;
key = this.parsePropertyName(method);
}
if (!method.static && (key.type === "Identifier" && key.name === "constructor" ||
key.type === "Literal" && key.value === "constructor")) {
// disallow invalid constructors
let isConstructor = !isConstructorCall && !method.static && (
(key.type === "Identifier" && key.name === "constructor") ||
(key.type === "StringLiteral" && key.value === "constructor")
);
if (isConstructor) {
if (hadConstructor) this.raise(key.start, "Duplicate constructor in the same class");
if (isGetSet) this.raise(key.start, "Constructor can't have get/set modifier");
if (isGenerator) this.raise(key.start, "Constructor can't be a generator");
@ -560,15 +697,37 @@ pp.parseClass = function (node, isStatement) {
method.kind = "constructor";
hadConstructor = true;
}
// disallow static prototype method
let isStaticPrototype = method.static && (
(key.type === "Identifier" && key.name === "prototype") ||
(key.type === "StringLiteral" && key.value === "prototype")
);
if (isStaticPrototype) {
this.raise(key.start, "Classes may not have static property named prototype");
}
}
if (method.kind === "constructor" && method.decorators) {
// convert constructor to a constructor call
if (isConstructorCall) {
if (hadConstructorCall) this.raise(method.start, "Duplicate constructor call in the same class");
method.kind = "constructorCall";
hadConstructorCall = true;
}
// disallow decorators on class constructors
if ((method.kind === "constructor" || method.kind === "constructorCall") && method.decorators) {
this.raise(method.start, "You can't attach decorators to a class constructor");
}
this.parseClassMethod(classBody, method, isGenerator, isAsync);
// get methods aren't allowed to have any parameters
// set methods must have exactly 1 parameter
if (isGetSet) {
let paramCount = method.kind === "get" ? 0 : 1;
if (method.value.params.length !== paramCount) {
let start = method.value.start;
if (method.params.length !== paramCount) {
let start = method.start;
if (method.kind === "get") {
this.raise(start, "getter should have no params");
} else {
@ -583,16 +742,13 @@ pp.parseClass = function (node, isStatement) {
}
node.body = this.finishNode(classBody, "ClassBody");
return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression");
};
pp.isClassProperty = function () {
return this.match(tt.eq) || (this.match(tt.semi) || this.canInsertSemicolon());
this.state.strict = oldStrict;
};
pp.parseClassProperty = function (node) {
if (this.match(tt.eq)) {
if (!this.options.features["es7.classProperties"]) this.unexpected();
if (!this.hasPlugin("classProperties")) this.unexpected();
this.next();
node.value = this.parseMaybeAssign();
} else {
@ -603,12 +759,20 @@ pp.parseClassProperty = function (node) {
};
pp.parseClassMethod = function (classBody, method, isGenerator, isAsync) {
method.value = this.parseMethod(isGenerator, isAsync);
classBody.body.push(this.finishNode(method, "MethodDefinition"));
this.parseMethod(method, isGenerator, isAsync);
classBody.body.push(this.finishNode(method, "ClassMethod"));
};
pp.parseClassId = function (node, isStatement) {
node.id = this.match(tt.name) ? this.parseIdent() : isStatement ? this.unexpected() : null;
pp.parseClassId = function (node, isStatement, optionalId) {
if (this.match(tt.name)) {
node.id = this.parseIdentifier();
} else {
if (optionalId || !isStatement) {
node.id = null;
} else {
this.unexpected();
}
}
};
pp.parseClassSuper = function (node) {
@ -623,8 +787,8 @@ pp.parseExport = function (node) {
if (this.match(tt.star)) {
let specifier = this.startNode();
this.next();
if (this.options.features["es7.exportExtensions"] && this.eatContextual("as")) {
specifier.exported = this.parseIdent();
if (this.hasPlugin("exportExtensions") && this.eatContextual("as")) {
specifier.exported = this.parseIdentifier();
node.specifiers = [this.finishNode(specifier, "ExportNamespaceSpecifier")];
this.parseExportSpecifiersMaybe(node);
this.parseExportFrom(node, true);
@ -632,30 +796,31 @@ pp.parseExport = function (node) {
this.parseExportFrom(node, true);
return this.finishNode(node, "ExportAllDeclaration");
}
} else if (this.options.features["es7.exportExtensions"] && this.isExportDefaultSpecifier()) {
} else if (this.hasPlugin("exportExtensions") && this.isExportDefaultSpecifier()) {
let specifier = this.startNode();
specifier.exported = this.parseIdent(true);
specifier.exported = this.parseIdentifier(true);
node.specifiers = [this.finishNode(specifier, "ExportDefaultSpecifier")];
if (this.match(tt.comma) && this.lookahead().type === tt.star) {
this.expect(tt.comma);
let specifier = this.startNode();
this.expect(tt.star);
this.expectContextual("as");
specifier.exported = this.parseIdent();
specifier.exported = this.parseIdentifier();
node.specifiers.push(this.finishNode(specifier, "ExportNamespaceSpecifier"));
} else {
this.parseExportSpecifiersMaybe(node);
}
this.parseExportFrom(node, true);
} else if (this.eat(tt._default)) { // export default ...
let possibleDeclaration = this.match(tt._function) || this.match(tt._class);
let expr = this.parseMaybeAssign();
let needsSemi = true;
if (possibleDeclaration) {
needsSemi = false;
if (expr.id) {
expr.type = expr.type === "FunctionExpression" ? "FunctionDeclaration" : "ClassDeclaration";
}
let expr = this.startNode();
let needsSemi = false;
if (this.eat(tt._function)) {
expr = this.parseFunction(expr, true, false, false, true);
} else if (this.match(tt._class)) {
expr = this.parseClass(expr, true, true);
} else {
needsSemi = true;
expr = this.parseMaybeAssign();
}
node.declaration = expr;
if (needsSemi) this.semicolon();
@ -687,7 +852,7 @@ pp.isExportDefaultSpecifier = function () {
return false;
}
var lookahead = this.lookahead();
let lookahead = this.lookahead();
return lookahead.type === tt.comma || (lookahead.type === tt.name && lookahead.value === "from");
};
@ -713,12 +878,12 @@ pp.parseExportFrom = function (node, expect?) {
};
pp.shouldParseExportDeclaration = function () {
return this.options.features["es7.asyncFunctions"] && this.isContextual("async");
return this.hasPlugin("asyncFunctions") && this.isContextual("async");
};
pp.checkExport = function (node) {
if (this.state.decorators.length) {
var isClass = node.declaration && (node.declaration.type === "ClassDeclaration" || node.declaration.type === "ClassExpression");
let isClass = node.declaration && (node.declaration.type === "ClassDeclaration" || node.declaration.type === "ClassExpression");
if (!node.declaration || !isClass) {
this.raise(node.start, "You can only use decorators on an export when exporting a class");
}
@ -729,7 +894,10 @@ pp.checkExport = function (node) {
// Parses a comma-separated list of module exports.
pp.parseExportSpecifiers = function () {
let nodes = [], first = true;
let nodes = [];
let first = true;
let needsFrom;
// export { x, y as z } [from '...']
this.expect(tt.braceL);
@ -741,12 +909,20 @@ pp.parseExportSpecifiers = function () {
if (this.eat(tt.braceR)) break;
}
let isDefault = this.match(tt._default);
if (isDefault && !needsFrom) needsFrom = true;
let node = this.startNode();
node.local = this.parseIdent(this.match(tt._default));
node.exported = this.eatContextual("as") ? this.parseIdent(true) : node.local.__clone();
node.local = this.parseIdentifier(isDefault);
node.exported = this.eatContextual("as") ? this.parseIdentifier(true) : node.local.__clone();
nodes.push(this.finishNode(node, "ExportSpecifier"));
}
// https://github.com/ember-cli/ember-cli/pull/3739
if (needsFrom && !this.isContextual("from")) {
this.unexpected();
}
return nodes;
};
@ -772,11 +948,11 @@ pp.parseImport = function (node) {
// Parses a comma-separated list of module imports.
pp.parseImportSpecifiers = function (node) {
var first = true;
let first = true;
if (this.match(tt.name)) {
// import defaultObj, { x, y as z } from '...'
var startPos = this.state.start, startLoc = this.state.startLoc;
node.specifiers.push(this.parseImportSpecifierDefault(this.parseIdent(), startPos, startLoc));
let startPos = this.state.start, startLoc = this.state.startLoc;
node.specifiers.push(this.parseImportSpecifierDefault(this.parseIdentifier(), startPos, startLoc));
if (!this.eat(tt.comma)) return;
}
@ -784,7 +960,7 @@ pp.parseImportSpecifiers = function (node) {
let specifier = this.startNode();
this.next();
this.expectContextual("as");
specifier.local = this.parseIdent();
specifier.local = this.parseIdentifier();
this.checkLVal(specifier.local, true);
node.specifiers.push(this.finishNode(specifier, "ImportNamespaceSpecifier"));
return;
@ -800,15 +976,15 @@ pp.parseImportSpecifiers = function (node) {
}
let specifier = this.startNode();
specifier.imported = this.parseIdent(true);
specifier.local = this.eatContextual("as") ? this.parseIdent() : specifier.imported.__clone();
specifier.imported = this.parseIdentifier(true);
specifier.local = this.eatContextual("as") ? this.parseIdentifier() : specifier.imported.__clone();
this.checkLVal(specifier.local, true);
node.specifiers.push(this.finishNode(specifier, "ImportSpecifier"));
}
};
pp.parseImportSpecifierDefault = function (id, startPos, startLoc) {
var node = this.startNodeAt(startPos, startLoc);
let node = this.startNodeAt(startPos, startLoc);
node.local = id;
this.checkLVal(node.local, true);
return this.finishNode(node, "ImportDefaultSpecifier");

View File

@ -1,3 +1,5 @@
/* @flow */
import { types as tt } from "../tokenizer/types";
import Parser from "./index";
import { lineBreak } from "../util/whitespace";
@ -6,10 +8,13 @@ const pp = Parser.prototype;
// ## Parser utilities
// Test whether a statement node is the string literal `"use strict"`.
// TODO
pp.isUseStrict = function (stmt) {
return stmt.type === "ExpressionStatement" && stmt.expression.type === "Literal" && stmt.expression.raw.slice(1, -1) === "use strict";
pp.addExtra = function (node, key, val) {
if (!node) return;
let extra = node.extra = node.extra || {};
extra[key] = val;
};
// TODO
@ -54,6 +59,12 @@ pp.canInsertSemicolon = function () {
lineBreak.test(this.input.slice(this.state.lastTokEnd, this.state.start));
};
// TODO
pp.isLineTerminator = function () {
return this.eat(tt.semi) || this.canInsertSemicolon();
};
// Consume a semicolon, or, failing that, see if we are allowed to
// pretend that there is a semicolon at this position.

View File

@ -1,13 +1,15 @@
/* @flow */
import { types as tt } from "../tokenizer/types";
import Parser from "../parser";
var pp = Parser.prototype;
let pp = Parser.prototype;
pp.flowParseTypeInitialiser = function (tok) {
var oldInType = this.state.inType;
let oldInType = this.state.inType;
this.state.inType = true;
this.expect(tok || tt.colon);
var type = this.flowParseType();
let type = this.flowParseType();
this.state.inType = oldInType;
return type;
};
@ -21,10 +23,10 @@ pp.flowParseDeclareClass = function (node) {
pp.flowParseDeclareFunction = function (node) {
this.next();
var id = node.id = this.parseIdent();
let id = node.id = this.parseIdentifier();
var typeNode = this.startNode();
var typeContainer = this.startNode();
let typeNode = this.startNode();
let typeContainer = this.startNode();
if (this.isRelational("<")) {
typeNode.typeParameters = this.flowParseTypeParameterDeclaration();
@ -33,7 +35,7 @@ pp.flowParseDeclareFunction = function (node) {
}
this.expect(tt.parenL);
var tmp = this.flowParseFunctionTypeParams();
let tmp = this.flowParseFunctionTypeParams();
typeNode.params = tmp.params;
typeNode.rest = tmp.rest;
this.expect(tt.parenR);
@ -76,14 +78,14 @@ pp.flowParseDeclareModule = function (node) {
if (this.match(tt.string)) {
node.id = this.parseExprAtom();
} else {
node.id = this.parseIdent();
node.id = this.parseIdentifier();
}
var bodyNode = node.body = this.startNode();
var body = bodyNode.body = [];
let bodyNode = node.body = this.startNode();
let body = bodyNode.body = [];
this.expect(tt.braceL);
while (!this.match(tt.braceR)) {
var node2 = this.startNode();
let node2 = this.startNode();
// todo: declare check
this.next();
@ -100,7 +102,7 @@ pp.flowParseDeclareModule = function (node) {
// Interfaces
pp.flowParseInterfaceish = function (node, allowStatic) {
node.id = this.parseIdent();
node.id = this.parseIdentifier();
if (this.isRelational("<")) {
node.typeParameters = this.flowParseTypeParameterDeclaration();
@ -120,9 +122,9 @@ pp.flowParseInterfaceish = function (node, allowStatic) {
};
pp.flowParseInterfaceExtends = function () {
var node = this.startNode();
let node = this.startNode();
node.id = this.parseIdent();
node.id = this.parseIdentifier();
if (this.isRelational("<")) {
node.typeParameters = this.flowParseTypeParameterInstantiation();
} else {
@ -140,7 +142,7 @@ pp.flowParseInterface = function (node) {
// Type aliases
pp.flowParseTypeAlias = function (node) {
node.id = this.parseIdent();
node.id = this.parseIdentifier();
if (this.isRelational("<")) {
node.typeParameters = this.flowParseTypeParameterDeclaration();
@ -157,7 +159,7 @@ pp.flowParseTypeAlias = function (node) {
// Type annotations
pp.flowParseTypeParameterDeclaration = function () {
var node = this.startNode();
let node = this.startNode();
node.params = [];
this.expectRelational("<");
@ -173,7 +175,7 @@ pp.flowParseTypeParameterDeclaration = function () {
};
pp.flowParseTypeParameterInstantiation = function () {
var node = this.startNode(), oldInType = this.state.inType;
let node = this.startNode(), oldInType = this.state.inType;
node.params = [];
this.state.inType = true;
@ -193,7 +195,7 @@ pp.flowParseTypeParameterInstantiation = function () {
};
pp.flowParseObjectPropertyKey = function () {
return (this.match(tt.num) || this.match(tt.string)) ? this.parseExprAtom() : this.parseIdent(true);
return (this.match(tt.num) || this.match(tt.string)) ? this.parseExprAtom() : this.parseIdentifier(true);
};
pp.flowParseObjectTypeIndexer = function (node, isStatic) {
@ -236,7 +238,7 @@ pp.flowParseObjectTypeMethodish = function (node) {
};
pp.flowParseObjectTypeMethod = function (startPos, startLoc, isStatic, key) {
var node = this.startNodeAt(startPos, startLoc);
let node = this.startNodeAt(startPos, startLoc);
node.value = this.flowParseObjectTypeMethodish(this.startNodeAt(startPos, startLoc));
node.static = isStatic;
node.key = key;
@ -246,7 +248,7 @@ pp.flowParseObjectTypeMethod = function (startPos, startLoc, isStatic, key) {
};
pp.flowParseObjectTypeCallProperty = function (node, isStatic) {
var valueNode = this.startNode();
let valueNode = this.startNode();
node.static = isStatic;
node.value = this.flowParseObjectTypeMethodish(valueNode);
this.flowObjectTypeSemicolon();
@ -254,10 +256,10 @@ pp.flowParseObjectTypeCallProperty = function (node, isStatic) {
};
pp.flowParseObjectType = function (allowStatic) {
var nodeStart = this.startNode();
var node;
var propertyKey;
var isStatic;
let nodeStart = this.startNode();
let node;
let propertyKey;
let isStatic;
nodeStart.callProperties = [];
nodeStart.properties = [];
@ -266,8 +268,8 @@ pp.flowParseObjectType = function (allowStatic) {
this.expect(tt.braceL);
while (!this.match(tt.braceR)) {
var optional = false;
var startPos = this.state.start, startLoc = this.state.startLoc;
let optional = false;
let startPos = this.state.start, startLoc = this.state.startLoc;
node = this.startNode();
if (allowStatic && this.isContextual("static")) {
this.next();
@ -280,7 +282,7 @@ pp.flowParseObjectType = function (allowStatic) {
nodeStart.callProperties.push(this.flowParseObjectTypeCallProperty(node, allowStatic));
} else {
if (isStatic && this.match(tt.colon)) {
propertyKey = this.parseIdent();
propertyKey = this.parseIdentifier();
} else {
propertyKey = this.flowParseObjectPropertyKey();
}
@ -313,15 +315,15 @@ pp.flowObjectTypeSemicolon = function () {
};
pp.flowParseGenericType = function (startPos, startLoc, id) {
var node = this.startNodeAt(startPos, startLoc);
let node = this.startNodeAt(startPos, startLoc);
node.typeParameters = null;
node.id = id;
while (this.eat(tt.dot)) {
var node2 = this.startNodeAt(startPos, startLoc);
let node2 = this.startNodeAt(startPos, startLoc);
node2.qualification = node.id;
node2.id = this.parseIdent();
node2.id = this.parseIdentifier();
node.id = this.finishNode(node2, "QualifiedTypeIdentifier");
}
@ -333,14 +335,14 @@ pp.flowParseGenericType = function (startPos, startLoc, id) {
};
pp.flowParseTypeofType = function () {
var node = this.startNode();
let node = this.startNode();
this.expect(tt._typeof);
node.argument = this.flowParsePrimaryType();
return this.finishNode(node, "TypeofTypeAnnotation");
};
pp.flowParseTupleType = function () {
var node = this.startNode();
let node = this.startNode();
node.types = [];
this.expect(tt.bracketL);
// We allow trailing commas
@ -354,9 +356,9 @@ pp.flowParseTupleType = function () {
};
pp.flowParseFunctionTypeParam = function () {
var optional = false;
var node = this.startNode();
node.name = this.parseIdent();
let optional = false;
let node = this.startNode();
node.name = this.parseIdentifier();
if (this.eat(tt.question)) {
optional = true;
}
@ -366,7 +368,7 @@ pp.flowParseFunctionTypeParam = function () {
};
pp.flowParseFunctionTypeParams = function () {
var ret = { params: [], rest: null };
let ret = { params: [], rest: null };
while (this.match(tt.name)) {
ret.params.push(this.flowParseFunctionTypeParam());
if (!this.match(tt.parenR)) {
@ -409,15 +411,15 @@ pp.flowIdentToTypeAnnotation = function (startPos, startLoc, node, id) {
// primary types are kind of like primary expressions...they're the
// primitives with which other types are constructed.
pp.flowParsePrimaryType = function () {
var startPos = this.state.start, startLoc = this.state.startLoc;
var node = this.startNode();
var tmp;
var type;
var isGroupedType = false;
let startPos = this.state.start, startLoc = this.state.startLoc;
let node = this.startNode();
let tmp;
let type;
let isGroupedType = false;
switch (this.state.type) {
case tt.name:
return this.flowIdentToTypeAnnotation(startPos, startLoc, node, this.parseIdent());
return this.flowIdentToTypeAnnotation(startPos, startLoc, node, this.parseIdentifier());
case tt.braceL:
return this.flowParseObjectType();
@ -447,7 +449,7 @@ pp.flowParsePrimaryType = function () {
// Check to see if this is actually a grouped type
if (!this.match(tt.parenR) && !this.match(tt.ellipsis)) {
if (this.match(tt.name)) {
var token = this.lookahead().type;
let token = this.lookahead().type;
isGroupedType = token !== tt.question && token !== tt.colon;
} else {
isGroupedType = true;
@ -488,8 +490,9 @@ pp.flowParsePrimaryType = function () {
return this.finishNode(node, "FunctionTypeAnnotation");
case tt.string:
node.rawValue = node.value = this.state.value;
node.raw = this.input.slice(this.state.start, this.state.end);
node.value = this.state.value;
this.addExtra(node, "rawValue", node.value);
this.addExtra(node, "raw", this.input.slice(this.state.start, this.state.end));
this.next();
return this.finishNode(node, "StringLiteralTypeAnnotation");
@ -499,8 +502,9 @@ pp.flowParsePrimaryType = function () {
return this.finishNode(node, "BooleanLiteralTypeAnnotation");
case tt.num:
node.rawValue = node.value = this.state.value;
node.raw = this.input.slice(this.state.start, this.state.end);
node.value = this.state.value;
this.addExtra(node, "rawValue", node.value);
this.addExtra(node, "raw", this.input.slice(this.state.start, this.state.end));
this.next();
return this.finishNode(node, "NumberLiteralTypeAnnotation");
@ -514,8 +518,8 @@ pp.flowParsePrimaryType = function () {
};
pp.flowParsePostfixType = function () {
var node = this.startNode();
var type = node.elementType = this.flowParsePrimaryType();
let node = this.startNode();
let type = node.elementType = this.flowParsePrimaryType();
if (this.match(tt.bracketL)) {
this.expect(tt.bracketL);
this.expect(tt.bracketR);
@ -526,7 +530,7 @@ pp.flowParsePostfixType = function () {
};
pp.flowParsePrefixType = function () {
var node = this.startNode();
let node = this.startNode();
if (this.eat(tt.question)) {
node.typeAnnotation = this.flowParsePrefixType();
return this.finishNode(node, "NullableTypeAnnotation");
@ -536,8 +540,8 @@ pp.flowParsePrefixType = function () {
};
pp.flowParseIntersectionType = function () {
var node = this.startNode();
var type = this.flowParsePrefixType();
let node = this.startNode();
let type = this.flowParsePrefixType();
node.types = [type];
while (this.eat(tt.bitwiseAND)) {
node.types.push(this.flowParsePrefixType());
@ -546,8 +550,8 @@ pp.flowParseIntersectionType = function () {
};
pp.flowParseUnionType = function () {
var node = this.startNode();
var type = this.flowParseIntersectionType();
let node = this.startNode();
let type = this.flowParseIntersectionType();
node.types = [type];
while (this.eat(tt.bitwiseOR)) {
node.types.push(this.flowParseIntersectionType());
@ -556,22 +560,22 @@ pp.flowParseUnionType = function () {
};
pp.flowParseType = function () {
var oldInType = this.state.inType;
let oldInType = this.state.inType;
this.state.inType = true;
var type = this.flowParseUnionType();
let type = this.flowParseUnionType();
this.state.inType = oldInType;
return type;
};
pp.flowParseTypeAnnotation = function () {
var node = this.startNode();
let node = this.startNode();
node.typeAnnotation = this.flowParseTypeInitialiser();
return this.finishNode(node, "TypeAnnotation");
};
pp.flowParseTypeAnnotatableIdentifier = function (requireTypeAnnotation, canBeOptionalParam) {
var ident = this.parseIdent();
var isOptionalParam = false;
let ident = this.parseIdentifier();
let isOptionalParam = false;
if (canBeOptionalParam && this.eat(tt.question)) {
this.expect(tt.question);
@ -592,7 +596,7 @@ pp.flowParseTypeAnnotatableIdentifier = function (requireTypeAnnotation, canBeOp
};
export default function (instance) {
// function name(): string {}
// plain function return types: function name(): string {}
instance.extend("parseFunctionBody", function (inner) {
return function (node, allowExpression) {
if (this.match(tt.colon) && !allowExpression) {
@ -605,11 +609,12 @@ export default function (instance) {
};
});
// interfaces
instance.extend("parseStatement", function (inner) {
return function (declaration, topLevel) {
// strict mode handling of `interface` since it's a reserved word
if (this.strict && this.match(tt.name) && this.state.value === "interface") {
var node = this.startNode();
if (this.state.strict && this.match(tt.name) && this.state.value === "interface") {
let node = this.startNode();
this.next();
return this.flowParseInterface(node);
} else {
@ -618,6 +623,7 @@ export default function (instance) {
};
});
// declares, interfaces and type aliases
instance.extend("parseExpressionStatement", function (inner) {
return function (node, expr) {
if (expr.type === "Identifier") {
@ -638,6 +644,7 @@ export default function (instance) {
};
});
// export type
instance.extend("shouldParseExportDeclaration", function (inner) {
return function () {
return this.isContextual("type") || inner.call(this);
@ -647,7 +654,7 @@ export default function (instance) {
instance.extend("parseParenItem", function () {
return function (node, startLoc, startPos, forceArrow?) {
if (this.match(tt.colon)) {
var typeCastNode = this.startNodeAt(startLoc, startPos);
let typeCastNode = this.startNodeAt(startLoc, startPos);
typeCastNode.expression = node;
typeCastNode.typeAnnotation = this.flowParseTypeAnnotation();
@ -657,7 +664,7 @@ export default function (instance) {
if (this.eat(tt.arrow)) {
// ((lol): number => {});
var func = this.parseArrowExpression(this.startNodeAt(startLoc, startPos), [node]);
let func = this.parseArrowExpression(this.startNodeAt(startLoc, startPos), [node]);
func.returnType = typeCastNode.typeAnnotation;
return func;
} else {
@ -684,7 +691,7 @@ export default function (instance) {
if (this.isContextual("type")) {
node.exportKind = "type";
var declarationNode = this.startNode();
let declarationNode = this.startNode();
this.next();
if (this.match(tt.braceL)) {
@ -703,8 +710,8 @@ export default function (instance) {
});
instance.extend("parseClassId", function (inner) {
return function (node, isStatement) {
inner.call(this, node, isStatement);
return function (node) {
inner.apply(this, arguments);
if (this.isRelational("<")) {
node.typeParameters = this.flowParseTypeParameterDeclaration();
}
@ -723,6 +730,7 @@ export default function (instance) {
};
});
// ensure that inside flow types, we bypass the jsx parser plugin
instance.extend("readToken", function (inner) {
return function (code) {
if (this.state.inType && (code === 62 || code === 60)) {
@ -733,6 +741,7 @@ export default function (instance) {
};
});
// don't lex any token as a jsx one inside a flow type
instance.extend("jsx_readToken", function (inner) {
return function () {
if (!this.state.inType) return inner.call(this);
@ -744,10 +753,11 @@ export default function (instance) {
return node.expression;
}
// turn type casts that we found in function parameter head into type annotated params
instance.extend("toAssignableList", function (inner) {
return function (exprList, isBinding) {
for (var i = 0; i < exprList.length; i++) {
var expr = exprList[i];
for (let i = 0; i < exprList.length; i++) {
let expr = exprList[i];
if (expr && expr.type === "TypeCastExpression") {
exprList[i] = typeCastToParameter(expr);
}
@ -756,10 +766,12 @@ export default function (instance) {
};
});
// this is a list of nodes, from something like a call expression, we need to filter the
// type casts that we've found that are illegal in this context
instance.extend("toReferencedList", function () {
return function (exprList) {
for (var i = 0; i < exprList.length; i++) {
var expr = exprList[i];
for (let i = 0; i < exprList.length; i++) {
let expr = exprList[i];
if (expr && expr._exprListItem && expr.type === "TypeCastExpression") {
this.raise(expr.start, "Unexpected type cast");
}
@ -769,10 +781,12 @@ export default function (instance) {
};
});
// parse an item inside a expression list eg. `(NODE, NODE)` where NODE represents
// the position where this function is cal;ed
instance.extend("parseExprListItem", function (inner) {
return function (allowEmpty, refShorthandDefaultPos) {
var container = this.startNode();
var node = inner.call(this, allowEmpty, refShorthandDefaultPos);
let container = this.startNode();
let node = inner.call(this, allowEmpty, refShorthandDefaultPos);
if (this.match(tt.colon)) {
container._exprListItem = true;
container.expression = node;
@ -784,6 +798,7 @@ export default function (instance) {
};
});
// parse class property type annotations
instance.extend("parseClassProperty", function (inner) {
return function (node) {
if (this.match(tt.colon)) {
@ -793,24 +808,25 @@ export default function (instance) {
};
});
// determine whether or not we're currently in the position where a class property would appear
instance.extend("isClassProperty", function (inner) {
return function () {
return this.match(tt.colon) || inner.call(this);
};
});
// parse type parameters for class methods
instance.extend("parseClassMethod", function () {
return function (classBody, method, isGenerator, isAsync) {
var typeParameters;
if (this.isRelational("<")) {
typeParameters = this.flowParseTypeParameterDeclaration();
method.typeParameters = this.flowParseTypeParameterDeclaration();
}
method.value = this.parseMethod(isGenerator, isAsync);
method.value.typeParameters = typeParameters;
classBody.body.push(this.finishNode(method, "MethodDefinition"));
this.parseMethod(method, isGenerator, isAsync);
classBody.body.push(this.finishNode(method, "ClassMethod"));
};
});
// parse a the super class type parameters and implements
instance.extend("parseClassSuper", function (inner) {
return function (node, isStatement) {
inner.call(this, node, isStatement);
@ -819,10 +835,10 @@ export default function (instance) {
}
if (this.isContextual("implements")) {
this.next();
var implemented = node.implements = [];
let implemented = node.implements = [];
do {
let node = this.startNode();
node.id = this.parseIdent();
node.id = this.parseIdentifier();
if (this.isRelational("<")) {
node.typeParameters = this.flowParseTypeParameterInstantiation();
} else {
@ -834,9 +850,10 @@ export default function (instance) {
};
});
// parse type parameters for object method shorthand
instance.extend("parseObjPropValue", function (inner) {
return function (prop) {
var typeParameters;
let typeParameters;
// method shorthand
if (this.isRelational("<")) {
@ -848,7 +865,7 @@ export default function (instance) {
// add typeParameters if we found them
if (typeParameters) {
prop.value.typeParameters = typeParameters;
(prop.value || prop).typeParameters = typeParameters;
}
};
});
@ -866,13 +883,20 @@ export default function (instance) {
};
});
// parse typeof and type imports
instance.extend("parseImportSpecifiers", function (inner) {
return function (node) {
node.importKind = "value";
var kind = (this.match(tt._typeof) ? "typeof" : (this.isContextual("type") ? "type" : null));
let kind = null;
if (this.match(tt._typeof)) {
kind = "typeof";
} else if (this.isContextual("type")) {
kind = "type";
}
if (kind) {
var lh = this.lookahead();
let lh = this.lookahead();
if ((lh.type === tt.name && lh.value !== "from") || lh.type === tt.braceL || lh.type === tt.star) {
this.next();
node.importKind = kind;
@ -883,7 +907,7 @@ export default function (instance) {
};
});
// function foo<T>() {}
// parse function type parameters - function foo<T>() {}
instance.extend("parseFunctionParams", function (inner) {
return function (node) {
if (this.isRelational("<")) {
@ -893,7 +917,7 @@ export default function (instance) {
};
});
// var foo: string = bar
// parse flow type annotations on variable declarator heads - let foo: string = bar
instance.extend("parseVarHead", function (inner) {
return function (decl) {
inner.call(this, decl);
@ -904,7 +928,7 @@ export default function (instance) {
};
});
// var foo = (async (): number => {});
// parse the return type of an async arrow function - let foo = (async (): number => {});
instance.extend("parseAsyncArrowFromCallExpression", function (inner) {
return function (node, call) {
if (this.match(tt.colon)) {
@ -915,13 +939,21 @@ export default function (instance) {
};
});
// todo description
instance.extend("shouldParseAsyncArrow", function (inner) {
return function () {
return this.match(tt.colon) || inner.call(this);
};
});
// handle return types for arrow functions
instance.extend("parseParenAndDistinguishExpression", function (inner) {
return function (startPos, startLoc, canBeArrow, isAsync) {
startPos = startPos || this.state.start;
startLoc = startLoc || this.state.startLoc;
if (this.lookahead().type === tt.parenR) {
// var foo = (): number => {};
// let foo = (): number => {};
this.expect(tt.parenL);
this.expect(tt.parenR);
@ -930,11 +962,11 @@ export default function (instance) {
this.expect(tt.arrow);
return this.parseArrowExpression(node, [], isAsync);
} else {
// var foo = (foo): number => {};
// let foo = (foo): number => {};
let node = inner.call(this, startPos, startLoc, canBeArrow, isAsync);
if (this.match(tt.colon)) {
var state = this.state.clone();
let state = this.state.clone();
try {
return this.parseParenItem(node, startPos, startLoc, true);
} catch (err) {

View File

@ -1,3 +1,5 @@
/* @flow */
import XHTMLEntities from "./xhtml";
import { TokenType, types as tt } from "../../tokenizer/types";
import { TokContext, types as tc } from "../../tokenizer/context";
@ -24,7 +26,7 @@ tt.jsxTagStart.updateContext = function() {
};
tt.jsxTagEnd.updateContext = function(prevType) {
var out = this.state.context.pop();
let out = this.state.context.pop();
if (out === tc.j_oTag && prevType === tt.slash || out === tc.j_cTag) {
this.state.context.pop();
this.state.exprAllowed = this.curContext() === tc.j_expr;
@ -33,18 +35,19 @@ tt.jsxTagEnd.updateContext = function(prevType) {
}
};
var pp = Parser.prototype;
let pp = Parser.prototype;
// Reads inline JSX contents token.
pp.jsxReadToken = function() {
var out = "", chunkStart = this.state.pos;
let out = "";
let chunkStart = this.state.pos;
for (;;) {
if (this.state.pos >= this.input.length) {
this.raise(this.state.start, "Unterminated JSX contents");
}
var ch = this.input.charCodeAt(this.state.pos);
let ch = this.input.charCodeAt(this.state.pos);
switch (ch) {
case 60: // "<"
@ -78,8 +81,8 @@ pp.jsxReadToken = function() {
};
pp.jsxReadNewLine = function(normalizeCRLF) {
var ch = this.input.charCodeAt(this.state.pos);
var out;
let ch = this.input.charCodeAt(this.state.pos);
let out;
++this.state.pos;
if (ch === 13 && this.input.charCodeAt(this.state.pos) === 10) {
++this.state.pos;
@ -94,13 +97,14 @@ pp.jsxReadNewLine = function(normalizeCRLF) {
};
pp.jsxReadString = function(quote) {
var out = "", chunkStart = ++this.state.pos;
let out = "";
let chunkStart = ++this.state.pos;
for (;;) {
if (this.state.pos >= this.input.length) {
this.raise(this.state.start, "Unterminated string constant");
}
var ch = this.input.charCodeAt(this.state.pos);
let ch = this.input.charCodeAt(this.state.pos);
if (ch === quote) break;
if (ch === 38) { // "&"
out += this.input.slice(chunkStart, this.state.pos);
@ -119,10 +123,12 @@ pp.jsxReadString = function(quote) {
};
pp.jsxReadEntity = function() {
var str = "", count = 0, entity;
var ch = this.input[this.state.pos];
let str = "";
let count = 0;
let entity;
let ch = this.input[this.state.pos];
var startPos = ++this.state.pos;
let startPos = ++this.state.pos;
while (this.state.pos < this.input.length && count++ < 10) {
ch = this.input[this.state.pos++];
if (ch === ";") {
@ -159,7 +165,8 @@ pp.jsxReadEntity = function() {
// by isIdentifierStart in readToken.
pp.jsxReadWord = function() {
var ch, start = this.state.pos;
let ch;
let start = this.state.pos;
do {
ch = this.input.charCodeAt(++this.state.pos);
} while (isIdentifierChar(ch) || ch === 45); // "-"
@ -185,7 +192,7 @@ function getQualifiedJSXName(object) {
// Parse next token as JSX identifier
pp.jsxParseIdentifier = function() {
var node = this.startNode();
let node = this.startNode();
if (this.match(tt.jsxName)) {
node.name = this.state.value;
} else if (this.state.type.keyword) {
@ -200,11 +207,11 @@ pp.jsxParseIdentifier = function() {
// Parse namespaced identifier.
pp.jsxParseNamespacedName = function() {
var startPos = this.state.start, startLoc = this.state.startLoc;
var name = this.jsxParseIdentifier();
let startPos = this.state.start, startLoc = this.state.startLoc;
let name = this.jsxParseIdentifier();
if (!this.eat(tt.colon)) return name;
var node = this.startNodeAt(startPos, startLoc);
let node = this.startNodeAt(startPos, startLoc);
node.namespace = name;
node.name = this.jsxParseIdentifier();
return this.finishNode(node, "JSXNamespacedName");
@ -214,10 +221,10 @@ pp.jsxParseNamespacedName = function() {
// or single identifier.
pp.jsxParseElementName = function() {
var startPos = this.state.start, startLoc = this.state.startLoc;
var node = this.jsxParseNamespacedName();
let startPos = this.state.start, startLoc = this.state.startLoc;
let node = this.jsxParseNamespacedName();
while (this.eat(tt.dot)) {
var newNode = this.startNodeAt(startPos, startLoc);
let newNode = this.startNodeAt(startPos, startLoc);
newNode.object = node;
newNode.property = this.jsxParseIdentifier();
node = this.finishNode(newNode, "JSXMemberExpression");
@ -228,7 +235,7 @@ pp.jsxParseElementName = function() {
// Parses any type of JSX attribute value.
pp.jsxParseAttributeValue = function() {
var node;
let node;
switch (this.state.type) {
case tt.braceL:
node = this.jsxParseExpressionContainer();
@ -241,7 +248,7 @@ pp.jsxParseAttributeValue = function() {
case tt.jsxTagStart:
case tt.string:
node = this.parseExprAtom();
node.rawValue = null;
node.extra = null;
return node;
default:
@ -249,27 +256,20 @@ pp.jsxParseAttributeValue = function() {
}
};
// JSXEmptyExpression is unique type since it doesn"t actually parse anything,
// JSXEmptyExpression is unique type since it doesn't actually parse anything,
// and so it should start at the end of last read token (left brace) and finish
// at the beginning of the next one (right brace).
pp.jsxParseEmptyExpression = function() {
var tmp = this.state.start;
this.state.start = this.state.lastTokEnd;
this.state.lastTokEnd = tmp;
tmp = this.state.startLoc;
this.state.startLoc = this.state.lastTokEndLoc;
this.state.lastTokEndLoc = tmp;
return this.finishNode(this.startNode(), "JSXEmptyExpression");
let node = this.startNodeAt(this.lastTokEnd, this.lastTokEndLoc);
return this.finishNodeAt(node, "JSXEmptyExpression", this.start, this.startLoc);
};
// Parses JSX expression enclosed into curly brackets.
pp.jsxParseExpressionContainer = function() {
var node = this.startNode();
let node = this.startNode();
this.next();
if (this.match(tt.braceR)) {
node.expression = this.jsxParseEmptyExpression();
@ -283,7 +283,7 @@ pp.jsxParseExpressionContainer = function() {
// Parses following JSX attribute name-value pair.
pp.jsxParseAttribute = function() {
var node = this.startNode();
let node = this.startNode();
if (this.eat(tt.braceL)) {
this.expect(tt.ellipsis);
node.argument = this.parseMaybeAssign();
@ -298,7 +298,7 @@ pp.jsxParseAttribute = function() {
// Parses JSX opening tag starting after "<".
pp.jsxParseOpeningElementAt = function(startPos, startLoc) {
var node = this.startNodeAt(startPos, startLoc);
let node = this.startNodeAt(startPos, startLoc);
node.attributes = [];
node.name = this.jsxParseElementName();
while (!this.match(tt.slash) && !this.match(tt.jsxTagEnd)) {
@ -312,7 +312,7 @@ pp.jsxParseOpeningElementAt = function(startPos, startLoc) {
// Parses JSX closing tag starting after "</".
pp.jsxParseClosingElementAt = function(startPos, startLoc) {
var node = this.startNodeAt(startPos, startLoc);
let node = this.startNodeAt(startPos, startLoc);
node.name = this.jsxParseElementName();
this.expect(tt.jsxTagEnd);
return this.finishNode(node, "JSXClosingElement");
@ -322,10 +322,10 @@ pp.jsxParseClosingElementAt = function(startPos, startLoc) {
// (starting after "<"), attributes, contents and closing tag.
pp.jsxParseElementAt = function(startPos, startLoc) {
var node = this.startNodeAt(startPos, startLoc);
var children = [];
var openingElement = this.jsxParseOpeningElementAt(startPos, startLoc);
var closingElement = null;
let node = this.startNodeAt(startPos, startLoc);
let children = [];
let openingElement = this.jsxParseOpeningElementAt(startPos, startLoc);
let closingElement = null;
if (!openingElement.selfClosing) {
contents: for (;;) {
@ -373,7 +373,7 @@ pp.jsxParseElementAt = function(startPos, startLoc) {
// Parses entire JSX element from current position.
pp.jsxParseElement = function() {
var startPos = this.state.start, startLoc = this.state.startLoc;
let startPos = this.state.start, startLoc = this.state.startLoc;
this.next();
return this.jsxParseElementAt(startPos, startLoc);
};
@ -382,9 +382,9 @@ export default function(instance) {
instance.extend("parseExprAtom", function(inner) {
return function(refShortHandDefaultPos) {
if (this.match(tt.jsxText)) {
var node = this.parseLiteral(this.state.value);
let node = this.parseLiteral(this.state.value, "JSXText");
// https://github.com/babel/babel/issues/2078
node.rawValue = null;
node.extra = null;
return node;
} else if (this.match(tt.jsxTagStart)) {
return this.jsxParseElement();
@ -396,7 +396,7 @@ export default function(instance) {
instance.extend("readToken", function(inner) {
return function(code) {
var context = this.curContext();
let context = this.curContext();
if (context === tc.j_expr) {
return this.jsxReadToken();
@ -429,7 +429,7 @@ export default function(instance) {
instance.extend("updateContext", function(inner) {
return function(prevType) {
if (this.match(tt.braceL)) {
var curContext = this.curContext();
let curContext = this.curContext();
if (curContext === tc.j_oTag) {
this.state.context.push(tc.b_expr);
} else if (curContext === tc.j_expr) {

View File

@ -1,3 +1,5 @@
/* @flow */
// The algorithm used to determine whether a regexp can appear at a
// given point in the program is loosely based on sweet.js' approach.
// See https://github.com/mozilla/sweet.js/wiki/design
@ -5,12 +7,22 @@
import { types as tt } from "./types";
export class TokContext {
constructor(token, isExpr, preserveSpace, override) {
constructor(
token: string,
isExpr?: boolean,
preserveSpace?: boolean,
override?: Function,
) {
this.token = token;
this.isExpr = !!isExpr;
this.preserveSpace = !!preserveSpace;
this.override = override;
}
token: string;
isExpr: boolean;
preserveSpace: boolean;
override: ?Function;
}
export const types = {

View File

@ -1,4 +1,7 @@
import { isIdentifierStart, isIdentifierChar } from "../util/identifier";
/* @flow */
import type { TokenType } from "./types";
import { isIdentifierStart, isIdentifierChar, isKeyword } from "../util/identifier";
import { types as tt, keywords as keywordTypes } from "./types";
import { types as ct } from "./context";
import { SourceLocation } from "../util/location";
@ -17,46 +20,37 @@ export class Token {
this.end = state.end;
this.loc = new SourceLocation(state.startLoc, state.endLoc);
}
type: TokenType;
value: any;
start: number;
end: number;
loc: SourceLocation;
}
// ## Tokenizer
// Are we running under Rhino?
/* global Packages */
const isRhino = typeof Packages === "object" && Object.prototype.toString.call(Packages) === "[object JavaPackage]";
// Parse a regular expression. Some context-awareness is necessary,
// since a '/' inside a '[]' set does not end the expression.
function tryCreateRegexp(src, flags, throwErrorStart) {
try {
return new RegExp(src, flags);
} catch (e) {
if (throwErrorStart !== undefined) {
if (e instanceof SyntaxError) this.raise(throwErrorStart, "Error parsing regular expression: " + e.message);
this.raise(e);
}
function codePointToString(code) {
// UTF-16 Decoding
if (code <= 0xFFFF) {
return String.fromCharCode(code);
} else {
return String.fromCharCode(((code - 0x10000) >> 10) + 0xD800, ((code - 0x10000) & 1023) + 0xDC00);
}
}
var regexpUnicodeSupport = !!tryCreateRegexp("\uffff", "u");
function codePointToString(code) {
// UTF-16 Decoding
if (code <= 0xFFFF) return String.fromCharCode(code);
return String.fromCharCode(((code - 0x10000) >> 10) + 0xD800, ((code - 0x10000) & 1023) + 0xDC00);
}
export default class Tokenizer {
constructor(input) {
constructor(options, input) {
this.state = new State;
this.state.init(input);
this.state.init(options, input);
}
// Move to the next token
next() {
this.state.tokens.push(new Token(this.state));
if (!this.isLookahead) {
this.state.tokens.push(new Token(this.state));
}
this.state.lastTokEnd = this.state.end;
this.state.lastTokStart = this.state.start;
@ -84,11 +78,21 @@ export default class Tokenizer {
// TODO
isKeyword(word) {
return isKeyword(word);
}
// TODO
lookahead() {
var old = this.state;
this.state = old.clone();
let old = this.state;
this.state = old.clone(true);
this.isLookahead = true;
this.next();
var curr = this.state.clone();
this.isLookahead = false;
let curr = this.state.clone(true);
this.state = old;
return curr;
}
@ -97,7 +101,7 @@ export default class Tokenizer {
// pedantic tests (`"use strict"; 010;` should fail).
setStrict(strict) {
this.strict = strict;
this.state.strict = strict;
if (!this.match(tt.num) && !this.match(tt.string)) return;
this.state.pos = this.state.start;
while (this.state.pos < this.state.lineStart) {
@ -118,6 +122,8 @@ export default class Tokenizer {
let curContext = this.curContext();
if (!curContext || !curContext.preserveSpace) this.skipSpace();
this.state.containsOctal = false;
this.state.octalPosition = null;
this.state.start = this.state.pos;
this.state.startLoc = this.state.curPosition();
if (this.state.pos >= this.input.length) return this.finishToken(tt.eof);
@ -132,10 +138,11 @@ export default class Tokenizer {
readToken(code) {
// Identifier or keyword. '\uXXXX' sequences are allowed in
// identifiers, so '\' also dispatches to that.
if (isIdentifierStart(code, true) || code === 92 /* '\' */)
if (isIdentifierStart(code, true) || code === 92 /* '\' */) {
return this.readWord();
return this.getTokenFromCode(code);
} else {
return this.getTokenFromCode(code);
}
}
fullCharCodeAtPos() {
@ -147,17 +154,19 @@ export default class Tokenizer {
}
pushComment(block, text, start, end, startLoc, endLoc) {
var comment = {
let comment = {
type: block ? "CommentBlock" : "CommentLine",
value: text,
start: start,
end: end,
loc: new SourceLocation(startLoc, endLoc),
range: [start, end]
loc: new SourceLocation(startLoc, endLoc)
};
this.state.tokens.push(comment);
this.state.comments.push(comment);
if (!this.isLookahead) {
this.state.tokens.push(comment);
this.state.comments.push(comment);
}
this.addComment(comment);
}
@ -291,11 +300,11 @@ export default class Tokenizer {
}
readToken_mult_modulo(code) { // '%*'
var type = code === 42 ? tt.star : tt.modulo;
var width = 1;
var next = this.input.charCodeAt(this.state.pos + 1);
let type = code === 42 ? tt.star : tt.modulo;
let width = 1;
let next = this.input.charCodeAt(this.state.pos + 1);
if (next === 42 && this.options.features["es7.exponentiationOperator"]) { // '*'
if (next === 42 && this.hasPlugin("exponentiationOperator")) { // '*'
width++;
next = this.input.charCodeAt(this.state.pos + 2);
type = tt.exponent;
@ -398,7 +407,7 @@ export default class Tokenizer {
case 125: ++this.state.pos; return this.finishToken(tt.braceR);
case 58:
if (this.options.features["es7.functionBind"] && this.input.charCodeAt(this.state.pos + 1) === 58) {
if (this.hasPlugin("functionBind") && this.input.charCodeAt(this.state.pos + 1) === 58) {
return this.finishOp(tt.doubleColon, 2);
} else {
++this.state.pos;
@ -492,41 +501,13 @@ export default class Tokenizer {
// Need to use `readWord1` because '\uXXXX' sequences are allowed
// here (don't ask).
let mods = this.readWord1();
let tmp = content;
if (mods) {
let validFlags = /^[gmsiyu]*$/;
if (!validFlags.test(mods)) this.raise(start, "Invalid regular expression flag");
if (mods.indexOf("u") >= 0 && !regexpUnicodeSupport) {
// Replace each astral symbol and every Unicode escape sequence that
// possibly represents an astral symbol or a paired surrogate with a
// single ASCII symbol to avoid throwing on regular expressions that
// are only valid in combination with the `/u` flag.
// Note: replacing with the ASCII symbol `x` might cause false
// negatives in unlikely scenarios. For example, `[\u{61}-b]` is a
// perfectly valid pattern that is equivalent to `[a-b]`, but it would
// be replaced by `[x-b]` which throws an error.
tmp = tmp.replace(/\\u\{([0-9a-fA-F]+)\}/g, (match, code, offset) => {
code = Number("0x" + code);
if (code > 0x10FFFF) this.raise(start + offset + 3, "Code point out of bounds");
return "x";
});
tmp = tmp.replace(/\\u([a-fA-F0-9]{4})|[\uD800-\uDBFF][\uDC00-\uDFFF]/g, "x");
}
}
// Detect invalid regular expressions.
let value = null;
// Rhino's regular expression parser is flaky and throws uncatchable exceptions,
// so don't do detection if we are running under Rhino
if (!isRhino) {
tryCreateRegexp.call(this, tmp, undefined, start);
// Get a regular expression object for this pattern-flag pair, or `null` in
// case the current environment doesn't support the flags it uses.
value = tryCreateRegexp.call(this, content, mods);
}
return this.finishToken(tt.regexp, {
pattern: content,
flags: mods,
value
flags: mods
});
}
@ -589,7 +570,7 @@ export default class Tokenizer {
val = parseFloat(str);
} else if (!octal || str.length === 1) {
val = parseInt(str, 10);
} else if (/[89]/.test(str) || this.strict) {
} else if (/[89]/.test(str) || this.state.strict) {
this.raise(start, "Invalid number");
} else {
val = parseInt(str, 8);
@ -705,8 +686,14 @@ export default class Tokenizer {
octalStr = octalStr.slice(0, -1);
octal = parseInt(octalStr, 8);
}
if (octal > 0 && (this.strict || inTemplate)) {
this.raise(this.state.pos - 2, "Octal literal in strict mode");
if (octal > 0) {
if (!this.state.containsOctal) {
this.state.containsOctal = true;
this.state.octalPosition = this.state.pos - 2;
}
if (this.state.strict || inTemplate) {
this.raise(this.state.pos - 2, "Octal literal in strict mode");
}
}
this.state.pos += octalStr.length - 1;
return String.fromCharCode(octal);
@ -769,8 +756,9 @@ export default class Tokenizer {
readWord() {
let word = this.readWord1();
let type = tt.name;
if (!this.state.containsEsc && this.isKeyword(word))
if (!this.state.containsEsc && this.isKeyword(word)) {
type = keywordTypes[word];
}
return this.finishToken(type, word);
}

View File

@ -1,77 +1,139 @@
/* @flow */
import type { TokContext } from "./context";
import type { Token } from "./index";
import { Position } from "../util/location";
import { types as ct } from "./context";
import { types as tt } from "./types";
export default class State {
init(input) {
init(options: Object, input: string) {
this.strict = options.strictMode === false ? false : options.sourceType === "module";
this.input = input;
// Used to signify the start of a potential arrow function
this.potentialArrowAt = -1;
// Flags to track whether we are in a function, a generator.
this.inFunction = this.inGenerator = false;
this.inMethod = this.inFunction = this.inGenerator = this.inAsync = false;
// Labels in scope.
this.labels = [];
// Leading decorators.
this.decorators = [];
// Token store.
this.tokens = [];
// Comment store.
this.comments = [];
// Comment attachment store
this.trailingComments = [];
this.leadingComments = [];
this.commentStack = [];
// The current position of the tokenizer in the input.
this.pos = this.lineStart = 0;
this.curLine = 1;
// Properties of the current token:
// Its type
this.type = tt.eof;
// For tokens that include more information than their type, the value
this.value = null;
// Its start and end offset
this.start = this.end = this.pos;
// And, if locations are used, the {line, column} object
// corresponding to those offsets
this.startLoc = this.endLoc = this.curPosition();
// Position information for the previous token
this.lastTokEndLoc = this.lastTokStartLoc = null;
this.lastTokStart = this.lastTokEnd = this.pos;
// The context stack is used to superficially track syntactic
// context to predict whether a regular expression is allowed in a
// given position.
this.context = [ct.b_stat];
this.exprAllowed = true;
// Used to signal to callers of `readWord1` whether the word
// contained any escape sequences. This is needed because words with
// escape sequences must not be interpreted as keywords.
this.containsEsc = false;
this.containsEsc = this.containsOctal = false;
this.octalPosition = null;
return this;
}
// TODO
strict: boolean;
// TODO
input: string;
// Used to signify the start of a potential arrow function
potentialArrowAt: number;
// Flags to track whether we are in a function, a generator.
inFunction: boolean;
inGenerator: boolean;
inMethod: boolean;
// Labels in scope.
labels: Array<Object>;
// Leading decorators.
decorators: Array<Object>;
// Token store.
tokens: Array<Object>;
// Comment store.
comments: Array<Object>;
// Comment attachment store
trailingComments: Array<Object>;
leadingComments: Array<Object>;
commentStack: Array<Object>;
// The current position of the tokenizer in the input.
pos: number;
lineStart: number;
curLine: number;
// Properties of the current token:
// Its type
type: Token;
// For tokens that include more information than their type, the value
value: any;
// Its start and end offset
start: number;
end: number;
// And, if locations are used, the {line, column} object
// corresponding to those offsets
startLoc: Position;
endLoc: Position;
// Position information for the previous token
lastTokEndLoc: ?Position;
lastTokStartLoc: ?Position;
lastTokStart: number;
lastTokEnd: number;
// The context stack is used to superficially track syntactic
// context to predict whether a regular expression is allowed in a
// given position.
context: Array<TokContext>;
exprAllowed: boolean;
// Used to signal to callers of `readWord1` whether the word
// contained any escape sequences. This is needed because words with
// escape sequences must not be interpreted as keywords.
containsEsc: boolean;
// TODO
containsOctal: boolean;
octalPosition: ?number;
curPosition() {
return new Position(this.curLine, this.pos - this.lineStart);
}
clone() {
var state = new State;
for (var key in this) {
var val = this[key];
if (Array.isArray(val)) val = val.slice();
clone(skipArrays?) {
let state = new State;
for (let key in this) {
let val = this[key];
if ((!skipArrays || key === "context") && Array.isArray(val)) {
val = val.slice();
}
state[key] = val;
}
return state;

View File

@ -1,3 +1,5 @@
/* @flow */
// ## Token types
// The assignment of fine-grained, information-carrying type objects
@ -113,7 +115,7 @@ kw("catch");
kw("continue");
kw("debugger");
kw("default", beforeExpr);
kw("do", {isLoop: true});
kw("do", {isLoop: true, beforeExpr: true});
kw("else", beforeExpr);
kw("finally");
kw("for", {isLoop: true});

View File

@ -1,3 +1,5 @@
/* @flow */
// This is a trick taken from Esprima. It turns out that, on
// non-Chrome browsers, to check whether a string is in a set, a
// predicate containing a big ugly `switch` statement is faster than
@ -47,7 +49,7 @@ nonASCIIidentifierStartChars = nonASCIIidentifierChars = null;
// offset starts at 0x10000, and each pair of numbers represents an
// offset to the next range, and then a size of the range. They were
// generated by tools/generate-identifier-regex.js
var astralIdentifierStartCodes = [
let astralIdentifierStartCodes = [
0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 17, 26, 6, 37, 11, 29, 3, 35, 5,
7, 2, 4, 43, 157, 99, 39, 9, 51, 157, 310, 10, 21, 11, 7, 153, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30,
98, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 26, 45, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14,
@ -60,7 +62,7 @@ var astralIdentifierStartCodes = [
0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2,
4, 2, 16, 4421, 42710, 42, 4148, 12, 221, 16355, 541
];
var astralIdentifierCodes = [
let astralIdentifierCodes = [
509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 1306, 2, 54, 14, 32, 9, 16, 3, 46, 10,
54, 9, 7, 2, 37, 13, 2, 9, 52, 0, 13, 2, 49, 13, 16, 9, 83, 11, 168, 11, 6, 9, 8, 2, 57, 0, 2, 6, 3, 1, 3, 2, 10,
0, 11, 1, 3, 6, 4, 4, 316, 19, 13, 9, 214, 6, 3, 8, 112, 16, 16, 9, 82, 12, 9, 9, 535, 9, 20855, 9, 135, 4, 60, 6,

View File

@ -1,3 +1,5 @@
/* @flow */
import { lineBreakG } from "./whitespace";
// These are used when `options.locations` is on, for the

View File

@ -1,3 +1,5 @@
/* @flow */
// Matches a whole line break (where CRLF is considered a single
// line break). Used to count lines.

View File

@ -104,17 +104,15 @@
"line": 3,
"column": 13
}
},
"range": [
15,
24
]
}
}
]
}
]
],
"directives": []
}
]
],
"directives": []
},
"comments": [
{
@ -131,11 +129,7 @@
"line": 3,
"column": 13
}
},
"range": [
15,
24
]
}
}
]
}

View File

@ -72,11 +72,7 @@
"line": 2,
"column": 13
}
},
"range": [
14,
23
]
}
}
]
},
@ -94,7 +90,8 @@
"column": 20
}
},
"body": []
"body": [],
"directives": []
},
"alternate": null,
"leadingComments": [
@ -112,15 +109,12 @@
"line": 1,
"column": 9
}
},
"range": [
0,
9
]
}
}
]
}
]
],
"directives": []
},
"comments": [
{
@ -137,11 +131,7 @@
"line": 1,
"column": 9
}
},
"range": [
0,
9
]
}
},
{
"type": "CommentBlock",
@ -157,11 +147,7 @@
"line": 2,
"column": 13
}
},
"range": [
14,
23
]
}
}
]
}

View File

@ -43,7 +43,7 @@
}
},
"declaration": {
"type": "ClassExpression",
"type": "ClassDeclaration",
"start": 51,
"end": 121,
"loc": {
@ -74,7 +74,7 @@
},
"body": [
{
"type": "MethodDefinition",
"type": "ClassMethod",
"start": 103,
"end": 119,
"loc": {
@ -107,40 +107,26 @@
},
"static": false,
"kind": "method",
"value": {
"type": "FunctionExpression",
"start": 110,
"id": null,
"generator": false,
"expression": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 112,
"end": 119,
"loc": {
"start": {
"line": 8,
"column": 11
"column": 13
},
"end": {
"line": 9,
"column": 5
}
},
"id": null,
"generator": false,
"expression": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 112,
"end": 119,
"loc": {
"start": {
"line": 8,
"column": 13
},
"end": {
"line": 9,
"column": 5
}
},
"body": []
}
"body": [],
"directives": []
},
"leadingComments": [
{
@ -157,11 +143,7 @@
"line": 7,
"column": 7
}
},
"range": [
63,
98
]
}
}
]
}
@ -185,15 +167,12 @@
"line": 3,
"column": 3
}
},
"range": [
0,
35
]
}
}
]
}
]
],
"directives": []
},
"comments": [
{
@ -210,11 +189,7 @@
"line": 3,
"column": 3
}
},
"range": [
0,
35
]
}
},
{
"type": "CommentBlock",
@ -230,11 +205,7 @@
"line": 7,
"column": 7
}
},
"range": [
63,
98
]
}
}
]
}

View File

@ -139,11 +139,7 @@
"line": 2,
"column": 16
}
},
"range": [
19,
31
]
}
}
],
"trailingComments": [
@ -161,18 +157,16 @@
"line": 4,
"column": 15
}
},
"range": [
47,
58
]
}
}
]
}
]
],
"directives": []
}
}
]
],
"directives": []
},
"comments": [
{
@ -189,11 +183,7 @@
"line": 2,
"column": 16
}
},
"range": [
19,
31
]
}
},
{
"type": "CommentBlock",
@ -209,11 +199,7 @@
"line": 4,
"column": 15
}
},
"range": [
47,
58
]
}
}
]
}

View File

@ -105,11 +105,7 @@
"line": 2,
"column": 16
}
},
"range": [
19,
31
]
}
}
],
"trailingComments": [
@ -127,18 +123,16 @@
"line": 4,
"column": 15
}
},
"range": [
50,
61
]
}
}
]
}
]
],
"directives": []
}
}
]
],
"directives": []
},
"comments": [
{
@ -155,11 +149,7 @@
"line": 2,
"column": 16
}
},
"range": [
19,
31
]
}
},
{
"type": "CommentBlock",
@ -175,11 +165,7 @@
"line": 4,
"column": 15
}
},
"range": [
50,
61
]
}
}
]
}

View File

@ -106,11 +106,7 @@
"line": 2,
"column": 16
}
},
"range": [
19,
31
]
}
}
],
"trailingComments": [
@ -128,18 +124,16 @@
"line": 4,
"column": 15
}
},
"range": [
48,
59
]
}
}
]
}
]
],
"directives": []
}
}
]
],
"directives": []
},
"comments": [
{
@ -156,11 +150,7 @@
"line": 2,
"column": 16
}
},
"range": [
19,
31
]
}
},
{
"type": "CommentBlock",
@ -176,11 +166,7 @@
"line": 4,
"column": 15
}
},
"range": [
48,
59
]
}
}
]
}

View File

@ -91,7 +91,7 @@
}
},
"argument": {
"type": "Literal",
"type": "NumberLiteral",
"start": 42,
"end": 44,
"loc": {
@ -104,9 +104,11 @@
"column": 12
}
},
"extra": {
"rawValue": 55,
"raw": "55"
},
"value": 55,
"rawValue": 55,
"raw": "55",
"leadingComments": null
},
"leadingComments": [
@ -124,11 +126,7 @@
"line": 2,
"column": 16
}
},
"range": [
19,
31
]
}
}
],
"trailingComments": [
@ -146,18 +144,16 @@
"line": 4,
"column": 15
}
},
"range": [
50,
61
]
}
}
]
}
]
],
"directives": []
}
}
]
],
"directives": []
},
"comments": [
{
@ -174,11 +170,7 @@
"line": 2,
"column": 16
}
},
"range": [
19,
31
]
}
},
{
"type": "CommentBlock",
@ -194,11 +186,7 @@
"line": 4,
"column": 15
}
},
"range": [
50,
61
]
}
}
]
}

View File

@ -91,7 +91,7 @@
}
},
"test": {
"type": "Literal",
"type": "BooleanLiteral",
"start": 37,
"end": 41,
"loc": {
@ -105,8 +105,6 @@
}
},
"value": true,
"rawValue": true,
"raw": "true",
"leadingComments": null
},
"body": {
@ -124,6 +122,7 @@
}
},
"body": [],
"directives": [],
"leadingComments": null,
"trailingComments": null
},
@ -142,11 +141,7 @@
"line": 1,
"column": 29
}
},
"range": [
15,
29
]
}
}
],
"trailingComments": [
@ -164,11 +159,7 @@
"line": 1,
"column": 56
}
},
"range": [
47,
56
]
}
}
]
},
@ -238,18 +229,16 @@
"line": 1,
"column": 56
}
},
"range": [
47,
56
]
}
}
]
}
]
],
"directives": []
}
}
]
],
"directives": []
},
"comments": [
{
@ -266,11 +255,7 @@
"line": 1,
"column": 29
}
},
"range": [
15,
29
]
}
},
{
"type": "CommentBlock",
@ -286,11 +271,7 @@
"line": 1,
"column": 56
}
},
"range": [
47,
56
]
}
}
]
}

View File

@ -140,7 +140,7 @@
},
"consequent": [],
"test": {
"type": "Literal",
"type": "NumberLiteral",
"start": 66,
"end": 67,
"loc": {
@ -153,9 +153,11 @@
"column": 14
}
},
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1,
"rawValue": 1,
"raw": "1",
"leadingComments": null
},
"leadingComments": [
@ -173,11 +175,7 @@
"line": 3,
"column": 14
}
},
"range": [
46,
52
]
}
}
],
"trailingComments": [
@ -195,11 +193,7 @@
"line": 5,
"column": 28
}
},
"range": [
81,
97
]
}
}
]
},
@ -267,7 +261,7 @@
}
],
"test": {
"type": "Literal",
"type": "NumberLiteral",
"start": 111,
"end": 112,
"loc": {
@ -280,9 +274,11 @@
"column": 14
}
},
"extra": {
"rawValue": 2,
"raw": "2"
},
"value": 2,
"rawValue": 2,
"raw": "2",
"leadingComments": null
},
"leadingComments": [
@ -300,20 +296,18 @@
"line": 5,
"column": 28
}
},
"range": [
81,
97
]
}
}
]
}
]
}
]
],
"directives": []
}
}
]
],
"directives": []
},
"comments": [
{
@ -330,11 +324,7 @@
"line": 3,
"column": 14
}
},
"range": [
46,
52
]
}
},
{
"type": "CommentLine",
@ -350,11 +340,7 @@
"line": 5,
"column": 28
}
},
"range": [
81,
97
]
}
}
]
}

View File

@ -75,7 +75,7 @@
},
"consequent": [],
"test": {
"type": "Literal",
"type": "NumberLiteral",
"start": 34,
"end": 35,
"loc": {
@ -88,9 +88,11 @@
"column": 10
}
},
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1,
"rawValue": 1,
"raw": "1",
"leadingComments": null
},
"leadingComments": [
@ -108,11 +110,7 @@
"line": 2,
"column": 10
}
},
"range": [
18,
24
]
}
}
],
"trailingComments": [
@ -130,11 +128,7 @@
"line": 4,
"column": 24
}
},
"range": [
45,
61
]
}
}
]
},
@ -202,7 +196,7 @@
}
],
"test": {
"type": "Literal",
"type": "NumberLiteral",
"start": 71,
"end": 72,
"loc": {
@ -215,9 +209,11 @@
"column": 10
}
},
"extra": {
"rawValue": 2,
"raw": "2"
},
"value": 2,
"rawValue": 2,
"raw": "2",
"leadingComments": null
},
"leadingComments": [
@ -235,17 +231,14 @@
"line": 4,
"column": 24
}
},
"range": [
45,
61
]
}
}
]
}
]
}
]
],
"directives": []
},
"comments": [
{
@ -262,11 +255,7 @@
"line": 2,
"column": 10
}
},
"range": [
18,
24
]
}
},
{
"type": "CommentLine",
@ -282,11 +271,7 @@
"line": 4,
"column": 24
}
},
"range": [
45,
61
]
}
}
]
}

View File

@ -157,7 +157,7 @@
}
],
"test": {
"type": "Literal",
"type": "NumberLiteral",
"start": 48,
"end": 49,
"loc": {
@ -170,9 +170,11 @@
"column": 14
}
},
"value": 2,
"rawValue": 2,
"raw": "2"
"extra": {
"rawValue": 2,
"raw": "2"
},
"value": 2
}
},
{
@ -210,7 +212,7 @@
}
],
"test": {
"type": "Literal",
"type": "NumberLiteral",
"start": 83,
"end": 84,
"loc": {
@ -223,9 +225,11 @@
"column": 14
}
},
"value": 1,
"rawValue": 1,
"raw": "1"
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
},
"trailingComments": [
{
@ -242,20 +246,18 @@
"line": 7,
"column": 20
}
},
"range": [
113,
125
]
}
}
]
}
]
}
]
],
"directives": []
}
}
]
],
"directives": []
},
"comments": [
{
@ -272,11 +274,7 @@
"line": 7,
"column": 20
}
},
"range": [
113,
125
]
}
}
]
}

View File

@ -501,7 +501,7 @@
},
"operator": "-",
"right": {
"type": "Literal",
"type": "NumberLiteral",
"start": 215,
"end": 216,
"loc": {
@ -514,9 +514,11 @@
"column": 78
}
},
"value": 1,
"rawValue": 1,
"raw": "1"
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
}
},
"computed": true
@ -527,7 +529,7 @@
}
],
"test": {
"type": "Literal",
"type": "StringLiteral",
"start": 116,
"end": 136,
"loc": {
@ -540,9 +542,11 @@
"column": 37
}
},
"value": "SequenceExpression",
"rawValue": "SequenceExpression",
"raw": "\"SequenceExpression\""
"extra": {
"rawValue": "SequenceExpression",
"raw": "\"SequenceExpression\""
},
"value": "SequenceExpression"
},
"trailingComments": [
{
@ -559,11 +563,7 @@
"line": 7,
"column": 25
}
},
"range": [
232,
245
]
}
}
]
}
@ -584,7 +584,7 @@
}
},
"argument": {
"type": "Literal",
"type": "BooleanLiteral",
"start": 271,
"end": 276,
"loc": {
@ -598,8 +598,6 @@
}
},
"value": false,
"rawValue": false,
"raw": "false",
"leadingComments": null
},
"leadingComments": [
@ -617,23 +615,22 @@
"line": 7,
"column": 25
}
},
"range": [
232,
245
]
}
}
]
}
]
],
"directives": []
}
}
]
],
"directives": []
}
}
}
}
]
],
"directives": []
},
"comments": [
{
@ -650,11 +647,7 @@
"line": 7,
"column": 25
}
},
"range": [
232,
245
]
}
}
]
}

View File

@ -94,7 +94,7 @@
}
],
"test": {
"type": "Literal",
"type": "NumberLiteral",
"start": 22,
"end": 23,
"loc": {
@ -107,9 +107,11 @@
"column": 10
}
},
"value": 1,
"rawValue": 1,
"raw": "1"
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
},
"trailingComments": [
{
@ -126,17 +128,14 @@
"line": 4,
"column": 16
}
},
"range": [
44,
56
]
}
}
]
}
]
}
]
],
"directives": []
},
"comments": [
{
@ -153,11 +152,7 @@
"line": 4,
"column": 16
}
},
"range": [
44,
56
]
}
}
]
}

View File

@ -43,7 +43,7 @@
}
},
"test": {
"type": "Literal",
"type": "BooleanLiteral",
"start": 4,
"end": 8,
"loc": {
@ -56,9 +56,7 @@
"column": 8
}
},
"value": true,
"rawValue": true,
"raw": "true"
"value": true
},
"consequent": {
"type": "BlockStatement",
@ -74,7 +72,8 @@
"column": 1
}
},
"body": []
"body": [],
"directives": []
},
"alternate": null
},
@ -93,7 +92,7 @@
}
},
"expression": {
"type": "Literal",
"type": "RegexLiteral",
"start": 15,
"end": 20,
"loc": {
@ -106,13 +105,14 @@
"column": 5
}
},
"raw": "/foo/",
"regex": {
"pattern": "foo",
"flags": ""
}
"extra": {
"raw": "/foo/"
},
"pattern": "foo",
"flags": ""
}
}
]
],
"directives": []
}
}

View File

@ -89,7 +89,7 @@
},
"elements": [
{
"type": "Literal",
"type": "NumberLiteral",
"start": 6,
"end": 8,
"loc": {
@ -102,14 +102,17 @@
"column": 8
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
]
}
}
}
]
],
"directives": []
}
}

View File

@ -27,9 +27,10 @@
}
},
"sourceType": "script",
"body": [
"body": [],
"directives": [
{
"type": "ExpressionStatement",
"type": "Directive",
"start": 0,
"end": 14,
"loc": {
@ -42,8 +43,8 @@
"column": 6
}
},
"expression": {
"type": "Literal",
"value": {
"type": "DirectiveLiteral",
"start": 0,
"end": 14,
"loc": {
@ -56,9 +57,11 @@
"column": 6
}
},
"value": "Helloworld",
"rawValue": "Helloworld",
"raw": "\"Hello\\\nworld\""
"value": "Hello\\\nworld",
"extra": {
"raw": "\"Hello\\\nworld\"",
"rawValue": "Hello\\\nworld"
}
}
}
]

View File

@ -27,9 +27,10 @@
}
},
"sourceType": "script",
"body": [
"body": [],
"directives": [
{
"type": "ExpressionStatement",
"type": "Directive",
"start": 0,
"end": 14,
"loc": {
@ -42,8 +43,8 @@
"column": 14
}
},
"expression": {
"type": "Literal",
"value": {
"type": "DirectiveLiteral",
"start": 0,
"end": 14,
"loc": {
@ -56,9 +57,11 @@
"column": 14
}
},
"value": "Hello\u0001World",
"rawValue": "Hello\u0001World",
"raw": "\"Hello\\1World\""
"value": "Hello\\1World",
"extra": {
"raw": "\"Hello\\1World\"",
"rawValue": "Hello\\1World"
}
}
}
]

View File

@ -74,7 +74,7 @@
"name": "x"
},
"init": {
"type": "Literal",
"type": "RegexLiteral",
"start": 8,
"end": 16,
"loc": {
@ -87,16 +87,17 @@
"column": 16
}
},
"raw": "/[a-z]/i",
"regex": {
"pattern": "[a-z]",
"flags": "i"
}
"extra": {
"raw": "/[a-z]/i"
},
"pattern": "[a-z]",
"flags": "i"
}
}
],
"kind": "var"
}
]
],
"directives": []
}
}
}

View File

@ -74,7 +74,7 @@
"name": "x"
},
"init": {
"type": "Literal",
"type": "RegexLiteral",
"start": 8,
"end": 16,
"loc": {
@ -87,16 +87,17 @@
"column": 16
}
},
"raw": "/[x-z]/i",
"regex": {
"pattern": "[x-z]",
"flags": "i"
}
"extra": {
"raw": "/[x-z]/i"
},
"pattern": "[x-z]",
"flags": "i"
}
}
],
"kind": "var"
}
]
],
"directives": []
}
}
}

View File

@ -74,7 +74,7 @@
"name": "x"
},
"init": {
"type": "Literal",
"type": "RegexLiteral",
"start": 8,
"end": 16,
"loc": {
@ -87,16 +87,17 @@
"column": 16
}
},
"raw": "/[a-c]/i",
"regex": {
"pattern": "[a-c]",
"flags": "i"
}
"extra": {
"raw": "/[a-c]/i"
},
"pattern": "[a-c]",
"flags": "i"
}
}
],
"kind": "var"
}
]
],
"directives": []
}
}
}

View File

@ -74,7 +74,7 @@
"name": "x"
},
"init": {
"type": "Literal",
"type": "RegexLiteral",
"start": 8,
"end": 17,
"loc": {
@ -87,16 +87,17 @@
"column": 17
}
},
"raw": "/[P QR]/i",
"regex": {
"pattern": "[P QR]",
"flags": "i"
}
"extra": {
"raw": "/[P QR]/i"
},
"pattern": "[P QR]",
"flags": "i"
}
}
],
"kind": "var"
}
]
],
"directives": []
}
}
}

View File

@ -74,7 +74,7 @@
"name": "x"
},
"init": {
"type": "Literal",
"type": "RegexLiteral",
"start": 8,
"end": 18,
"loc": {
@ -87,16 +87,17 @@
"column": 18
}
},
"raw": "/foo\\/bar/",
"regex": {
"pattern": "foo\\/bar",
"flags": ""
}
"extra": {
"raw": "/foo\\/bar/"
},
"pattern": "foo\\/bar",
"flags": ""
}
}
],
"kind": "var"
}
]
],
"directives": []
}
}
}

View File

@ -74,7 +74,7 @@
"name": "x"
},
"init": {
"type": "Literal",
"type": "RegexLiteral",
"start": 8,
"end": 21,
"loc": {
@ -87,16 +87,17 @@
"column": 21
}
},
"raw": "/=([^=\\s])+/g",
"regex": {
"pattern": "=([^=\\s])+",
"flags": "g"
}
"extra": {
"raw": "/=([^=\\s])+/g"
},
"pattern": "=([^=\\s])+",
"flags": "g"
}
}
],
"kind": "var"
}
]
],
"directives": []
}
}
}

View File

@ -74,7 +74,7 @@
"name": "x"
},
"init": {
"type": "Literal",
"type": "RegexLiteral",
"start": 8,
"end": 22,
"loc": {
@ -87,16 +87,17 @@
"column": 22
}
},
"raw": "/[P QR]/\\u0067",
"regex": {
"pattern": "[P QR]",
"flags": "g"
}
"extra": {
"raw": "/[P QR]/\\u0067"
},
"pattern": "[P QR]",
"flags": "g"
}
}
],
"kind": "var"
}
]
],
"directives": []
}
}
}

View File

@ -91,7 +91,7 @@
null,
null,
{
"type": "Literal",
"type": "NumberLiteral",
"start": 9,
"end": 11,
"loc": {
@ -104,14 +104,17 @@
"column": 11
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
]
}
}
}
]
],
"directives": []
}
}

View File

@ -101,7 +101,9 @@
"name": "foo"
},
"arguments": [],
"parenthesizedExpression": true
"extra": {
"parenthesized": true
}
},
"property": {
"type": "Identifier",
@ -124,6 +126,7 @@
"arguments": []
}
}
]
],
"directives": []
}
}

View File

@ -71,11 +71,14 @@
}
},
"name": "foo",
"parenthesizedExpression": true
"extra": {
"parenthesized": true
}
},
"arguments": []
}
}
]
],
"directives": []
}
}

View File

@ -89,7 +89,7 @@
},
"elements": [
{
"type": "Literal",
"type": "NumberLiteral",
"start": 6,
"end": 7,
"loc": {
@ -102,12 +102,14 @@
"column": 7
}
},
"value": 1,
"rawValue": 1,
"raw": "1"
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
},
{
"type": "Literal",
"type": "NumberLiteral",
"start": 9,
"end": 10,
"loc": {
@ -120,12 +122,14 @@
"column": 10
}
},
"value": 2,
"rawValue": 2,
"raw": "2"
"extra": {
"rawValue": 2,
"raw": "2"
},
"value": 2
},
{
"type": "Literal",
"type": "NumberLiteral",
"start": 12,
"end": 13,
"loc": {
@ -138,14 +142,17 @@
"column": 13
}
},
"value": 3,
"rawValue": 3,
"raw": "3"
"extra": {
"rawValue": 3,
"raw": "3"
},
"value": 3
}
]
}
}
}
]
],
"directives": []
}
}

View File

@ -87,7 +87,7 @@
"name": "universe"
},
"property": {
"type": "Literal",
"type": "NumberLiteral",
"start": 9,
"end": 11,
"loc": {
@ -100,9 +100,11 @@
"column": 11
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
},
"computed": true
},
@ -125,6 +127,7 @@
"computed": false
}
}
]
],
"directives": []
}
}

View File

@ -88,7 +88,7 @@
},
"arguments": [
{
"type": "Literal",
"type": "NumberLiteral",
"start": 9,
"end": 11,
"loc": {
@ -101,9 +101,11 @@
"column": 11
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
]
},
@ -126,6 +128,7 @@
"computed": false
}
}
]
],
"directives": []
}
}

View File

@ -116,7 +116,7 @@
},
"arguments": [
{
"type": "Literal",
"type": "NumberLiteral",
"start": 9,
"end": 11,
"loc": {
@ -129,9 +129,11 @@
"column": 11
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
]
},
@ -155,7 +157,7 @@
},
"arguments": [
{
"type": "Literal",
"type": "NumberLiteral",
"start": 22,
"end": 24,
"loc": {
@ -168,12 +170,14 @@
"column": 24
}
},
"value": 14,
"rawValue": 14,
"raw": "14"
"extra": {
"rawValue": 14,
"raw": "14"
},
"value": 14
},
{
"type": "Literal",
"type": "NumberLiteral",
"start": 26,
"end": 27,
"loc": {
@ -186,12 +190,14 @@
"column": 27
}
},
"value": 3,
"rawValue": 3,
"raw": "3"
"extra": {
"rawValue": 3,
"raw": "3"
},
"value": 3
},
{
"type": "Literal",
"type": "NumberLiteral",
"start": 29,
"end": 31,
"loc": {
@ -204,9 +210,11 @@
"column": 31
}
},
"value": 77,
"rawValue": 77,
"raw": "77"
"extra": {
"rawValue": 77,
"raw": "77"
},
"value": 77
}
]
},
@ -229,6 +237,7 @@
"computed": false
}
}
]
],
"directives": []
}
}

View File

@ -170,7 +170,7 @@
},
"arguments": [
{
"type": "Literal",
"type": "NumberLiteral",
"start": 40,
"end": 44,
"loc": {
@ -183,13 +183,16 @@
"column": 44
}
},
"value": 2014,
"rawValue": 2014,
"raw": "2014"
"extra": {
"rawValue": 2014,
"raw": "2014"
},
"value": 2014
}
]
}
}
]
],
"directives": []
}
}

View File

@ -89,7 +89,7 @@
},
"elements": [
{
"type": "Literal",
"type": "NumberLiteral",
"start": 6,
"end": 7,
"loc": {
@ -102,12 +102,14 @@
"column": 7
}
},
"value": 1,
"rawValue": 1,
"raw": "1"
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
},
{
"type": "Literal",
"type": "NumberLiteral",
"start": 9,
"end": 10,
"loc": {
@ -120,13 +122,15 @@
"column": 10
}
},
"value": 2,
"rawValue": 2,
"raw": "2"
"extra": {
"rawValue": 2,
"raw": "2"
},
"value": 2
},
null,
{
"type": "Literal",
"type": "NumberLiteral",
"start": 13,
"end": 14,
"loc": {
@ -139,14 +143,17 @@
"column": 14
}
},
"value": 3,
"rawValue": 3,
"raw": "3"
"extra": {
"rawValue": 3,
"raw": "3"
},
"value": 3
}
]
}
}
}
]
],
"directives": []
}
}

View File

@ -73,7 +73,7 @@
"name": "y"
},
"consequent": {
"type": "Literal",
"type": "NumberLiteral",
"start": 4,
"end": 5,
"loc": {
@ -86,12 +86,14 @@
"column": 5
}
},
"value": 1,
"rawValue": 1,
"raw": "1"
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
},
"alternate": {
"type": "Literal",
"type": "NumberLiteral",
"start": 8,
"end": 9,
"loc": {
@ -104,12 +106,15 @@
"column": 9
}
},
"value": 2,
"rawValue": 2,
"raw": "2"
"extra": {
"rawValue": 2,
"raw": "2"
},
"value": 2
}
}
}
]
],
"directives": []
}
}

View File

@ -105,7 +105,7 @@
}
},
"consequent": {
"type": "Literal",
"type": "NumberLiteral",
"start": 9,
"end": 10,
"loc": {
@ -118,12 +118,14 @@
"column": 10
}
},
"value": 1,
"rawValue": 1,
"raw": "1"
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
},
"alternate": {
"type": "Literal",
"type": "NumberLiteral",
"start": 13,
"end": 14,
"loc": {
@ -136,12 +138,15 @@
"column": 14
}
},
"value": 2,
"rawValue": 2,
"raw": "2"
"extra": {
"rawValue": 2,
"raw": "2"
},
"value": 2
}
}
}
]
],
"directives": []
}
}

View File

@ -74,7 +74,7 @@
"name": "x"
},
"right": {
"type": "Literal",
"type": "NumberLiteral",
"start": 4,
"end": 6,
"loc": {
@ -87,12 +87,15 @@
"column": 6
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
}
}
]
],
"directives": []
}
}

View File

@ -43,7 +43,7 @@
}
},
"expression": {
"type": "Literal",
"type": "NullLiteral",
"start": 0,
"end": 4,
"loc": {
@ -55,10 +55,7 @@
"line": 1,
"column": 4
}
},
"value": null,
"rawValue": null,
"raw": "null"
}
}
}
]

View File

@ -74,7 +74,7 @@
"name": "eval"
},
"right": {
"type": "Literal",
"type": "NumberLiteral",
"start": 7,
"end": 9,
"loc": {
@ -87,12 +87,15 @@
"column": 9
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
}
}
]
],
"directives": []
}
}

View File

@ -74,7 +74,7 @@
"name": "arguments"
},
"right": {
"type": "Literal",
"type": "NumberLiteral",
"start": 12,
"end": 14,
"loc": {
@ -87,12 +87,15 @@
"column": 14
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
}
}
]
],
"directives": []
}
}

View File

@ -74,7 +74,7 @@
"name": "x"
},
"right": {
"type": "Literal",
"type": "NumberLiteral",
"start": 5,
"end": 7,
"loc": {
@ -87,12 +87,15 @@
"column": 7
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
}
}
]
],
"directives": []
}
}

View File

@ -74,7 +74,7 @@
"name": "x"
},
"right": {
"type": "Literal",
"type": "NumberLiteral",
"start": 5,
"end": 7,
"loc": {
@ -87,12 +87,15 @@
"column": 7
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
}
}
]
],
"directives": []
}
}

View File

@ -74,7 +74,7 @@
"name": "x"
},
"right": {
"type": "Literal",
"type": "NumberLiteral",
"start": 5,
"end": 7,
"loc": {
@ -87,12 +87,15 @@
"column": 7
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
}
}
]
],
"directives": []
}
}

View File

@ -74,7 +74,7 @@
"name": "x"
},
"right": {
"type": "Literal",
"type": "NumberLiteral",
"start": 5,
"end": 7,
"loc": {
@ -87,12 +87,15 @@
"column": 7
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
}
}
]
],
"directives": []
}
}

View File

@ -74,7 +74,7 @@
"name": "x"
},
"right": {
"type": "Literal",
"type": "NumberLiteral",
"start": 5,
"end": 7,
"loc": {
@ -87,12 +87,15 @@
"column": 7
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
}
}
]
],
"directives": []
}
}

View File

@ -74,7 +74,7 @@
"name": "x"
},
"right": {
"type": "Literal",
"type": "NumberLiteral",
"start": 6,
"end": 8,
"loc": {
@ -87,12 +87,15 @@
"column": 8
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
}
}
]
],
"directives": []
}
}

View File

@ -74,7 +74,7 @@
"name": "x"
},
"right": {
"type": "Literal",
"type": "NumberLiteral",
"start": 6,
"end": 8,
"loc": {
@ -87,12 +87,15 @@
"column": 8
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
}
}
]
],
"directives": []
}
}

View File

@ -74,7 +74,7 @@
"name": "x"
},
"right": {
"type": "Literal",
"type": "NumberLiteral",
"start": 7,
"end": 9,
"loc": {
@ -87,12 +87,15 @@
"column": 9
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
}
}
]
],
"directives": []
}
}

View File

@ -74,7 +74,7 @@
"name": "x"
},
"right": {
"type": "Literal",
"type": "NumberLiteral",
"start": 5,
"end": 7,
"loc": {
@ -87,12 +87,15 @@
"column": 7
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
}
}
]
],
"directives": []
}
}

View File

@ -74,7 +74,7 @@
"name": "x"
},
"right": {
"type": "Literal",
"type": "NumberLiteral",
"start": 5,
"end": 7,
"loc": {
@ -87,12 +87,15 @@
"column": 7
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
}
}
]
],
"directives": []
}
}

View File

@ -74,7 +74,7 @@
"name": "x"
},
"right": {
"type": "Literal",
"type": "NumberLiteral",
"start": 5,
"end": 7,
"loc": {
@ -87,12 +87,15 @@
"column": 7
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
}
}
]
],
"directives": []
}
}

View File

@ -74,7 +74,7 @@
"name": "x"
},
"init": {
"type": "Literal",
"type": "NumberLiteral",
"start": 8,
"end": 10,
"loc": {
@ -87,14 +87,17 @@
"column": 10
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
}
],
"kind": "var"
}
]
],
"directives": []
}
}

View File

@ -74,7 +74,7 @@
"name": "eval"
},
"init": {
"type": "Literal",
"type": "NumberLiteral",
"start": 11,
"end": 13,
"loc": {
@ -87,9 +87,11 @@
"column": 13
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
},
{
@ -123,7 +125,7 @@
"name": "arguments"
},
"init": {
"type": "Literal",
"type": "NumberLiteral",
"start": 27,
"end": 29,
"loc": {
@ -136,14 +138,17 @@
"column": 29
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
}
],
"kind": "var"
}
]
],
"directives": []
}
}

View File

@ -89,7 +89,7 @@
},
"properties": [
{
"type": "Property",
"type": "ObjectProperty",
"start": 6,
"end": 16,
"loc": {
@ -122,7 +122,7 @@
"name": "answer"
},
"value": {
"type": "Literal",
"type": "NumberLiteral",
"start": 14,
"end": 16,
"loc": {
@ -135,16 +135,18 @@
"column": 16
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
},
"kind": "init"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
}
]
}
}
}
]
],
"directives": []
}
}

View File

@ -74,7 +74,7 @@
"name": "x"
},
"init": {
"type": "Literal",
"type": "NumberLiteral",
"start": 8,
"end": 10,
"loc": {
@ -87,9 +87,11 @@
"column": 10
}
},
"value": 14,
"rawValue": 14,
"raw": "14"
"extra": {
"rawValue": 14,
"raw": "14"
},
"value": 14
}
},
{
@ -123,7 +125,7 @@
"name": "y"
},
"init": {
"type": "Literal",
"type": "NumberLiteral",
"start": 16,
"end": 17,
"loc": {
@ -136,9 +138,11 @@
"column": 17
}
},
"value": 3,
"rawValue": 3,
"raw": "3"
"extra": {
"rawValue": 3,
"raw": "3"
},
"value": 3
}
},
{
@ -172,7 +176,7 @@
"name": "z"
},
"init": {
"type": "Literal",
"type": "NumberLiteral",
"start": 23,
"end": 27,
"loc": {
@ -185,14 +189,17 @@
"column": 27
}
},
"value": 1977,
"rawValue": 1977,
"raw": "1977"
"extra": {
"rawValue": 1977,
"raw": "1977"
},
"value": 1977
}
}
],
"kind": "var"
}
]
],
"directives": []
}
}

View File

@ -104,13 +104,17 @@
"column": 26
}
},
"body": []
"body": [],
"directives": []
},
"parenthesizedExpression": true
"extra": {
"parenthesized": true
}
}
},
"alternate": null
}
]
],
"directives": []
}
}

View File

@ -89,7 +89,7 @@
},
"properties": [
{
"type": "Property",
"type": "ObjectProperty",
"start": 6,
"end": 12,
"loc": {
@ -122,7 +122,7 @@
"name": "if"
},
"value": {
"type": "Literal",
"type": "NumberLiteral",
"start": 10,
"end": 12,
"loc": {
@ -135,16 +135,18 @@
"column": 12
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
},
"kind": "init"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
}
]
}
}
}
]
],
"directives": []
}
}

View File

@ -104,7 +104,7 @@
"name": "x"
},
"init": {
"type": "Literal",
"type": "NumberLiteral",
"start": 21,
"end": 22,
"loc": {
@ -117,9 +117,11 @@
"column": 22
}
},
"value": 0,
"rawValue": 0,
"raw": "0"
"extra": {
"rawValue": 0,
"raw": "0"
},
"value": 0
}
}
],
@ -127,6 +129,7 @@
},
"alternate": null
}
]
],
"directives": []
}
}

View File

@ -90,7 +90,7 @@
}
},
"test": {
"type": "Literal",
"type": "BooleanLiteral",
"start": 18,
"end": 22,
"loc": {
@ -103,11 +103,10 @@
"column": 22
}
},
"value": true,
"rawValue": true,
"raw": "true"
"value": true
}
}
]
],
"directives": []
}
}

View File

@ -90,7 +90,7 @@
}
},
"test": {
"type": "Literal",
"type": "BooleanLiteral",
"start": 18,
"end": 22,
"loc": {
@ -103,11 +103,10 @@
"column": 22
}
},
"value": true,
"rawValue": true,
"raw": "true"
"value": true
}
}
]
],
"directives": []
}
}

View File

@ -153,7 +153,8 @@
}
}
}
]
],
"directives": []
},
"test": {
"type": "BinaryExpression",
@ -187,7 +188,7 @@
},
"operator": "<",
"right": {
"type": "Literal",
"type": "NumberLiteral",
"start": 28,
"end": 30,
"loc": {
@ -200,12 +201,15 @@
"column": 30
}
},
"value": 10,
"rawValue": 10,
"raw": "10"
"extra": {
"rawValue": 10,
"raw": "10"
},
"value": 10
}
}
}
]
],
"directives": []
}
}

View File

@ -71,10 +71,11 @@
"column": 8
}
},
"body": []
"body": [],
"directives": []
},
"test": {
"type": "Literal",
"type": "BooleanLiteral",
"start": 16,
"end": 21,
"loc": {
@ -87,9 +88,7 @@
"column": 21
}
},
"value": false,
"rawValue": false,
"raw": "false"
"value": false
}
},
{
@ -107,7 +106,7 @@
}
},
"expression": {
"type": "Literal",
"type": "BooleanLiteral",
"start": 23,
"end": 28,
"loc": {
@ -120,13 +119,13 @@
"column": 28
}
},
"value": false,
"rawValue": false,
"raw": "false"
"value": false
}
}
]
],
"directives": []
}
]
],
"directives": []
}
}

View File

@ -43,7 +43,7 @@
}
},
"test": {
"type": "Literal",
"type": "BooleanLiteral",
"start": 7,
"end": 11,
"loc": {
@ -56,9 +56,7 @@
"column": 11
}
},
"value": true,
"rawValue": true,
"raw": "true"
"value": true
},
"body": {
"type": "ExpressionStatement",
@ -108,6 +106,7 @@
}
}
}
]
],
"directives": []
}
}

View File

@ -74,7 +74,7 @@
},
"operator": "<",
"right": {
"type": "Literal",
"type": "NumberLiteral",
"start": 11,
"end": 13,
"loc": {
@ -87,9 +87,11 @@
"column": 13
}
},
"value": 10,
"rawValue": 10,
"raw": "10"
"extra": {
"rawValue": 10,
"raw": "10"
},
"value": 10
}
},
"body": {
@ -203,9 +205,11 @@
}
}
}
]
],
"directives": []
}
}
]
],
"directives": []
}
}

View File

@ -89,7 +89,7 @@
},
"properties": [
{
"type": "Property",
"type": "ObjectProperty",
"start": 6,
"end": 14,
"loc": {
@ -122,7 +122,7 @@
"name": "true"
},
"value": {
"type": "Literal",
"type": "NumberLiteral",
"start": 12,
"end": 14,
"loc": {
@ -135,16 +135,18 @@
"column": 14
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
},
"kind": "init"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
}
]
}
}
}
]
],
"directives": []
}
}

View File

@ -74,7 +74,7 @@
"name": "x"
},
"right": {
"type": "Literal",
"type": "NumberLiteral",
"start": 8,
"end": 9,
"loc": {
@ -87,9 +87,11 @@
"column": 9
}
},
"value": 0,
"rawValue": 0,
"raw": "0"
"extra": {
"rawValue": 0,
"raw": "0"
},
"value": 0
}
},
"test": null,
@ -110,6 +112,7 @@
}
}
}
]
],
"directives": []
}
}

View File

@ -88,7 +88,7 @@
"name": "x"
},
"init": {
"type": "Literal",
"type": "NumberLiteral",
"start": 12,
"end": 13,
"loc": {
@ -101,9 +101,11 @@
"column": 13
}
},
"value": 0,
"rawValue": 0,
"raw": "0"
"extra": {
"rawValue": 0,
"raw": "0"
},
"value": 0
}
}
],
@ -127,6 +129,7 @@
}
}
}
]
],
"directives": []
}
}

View File

@ -88,7 +88,7 @@
"name": "x"
},
"init": {
"type": "Literal",
"type": "NumberLiteral",
"start": 12,
"end": 13,
"loc": {
@ -101,9 +101,11 @@
"column": 13
}
},
"value": 0,
"rawValue": 0,
"raw": "0"
"extra": {
"rawValue": 0,
"raw": "0"
},
"value": 0
}
},
{
@ -137,7 +139,7 @@
"name": "y"
},
"init": {
"type": "Literal",
"type": "NumberLiteral",
"start": 19,
"end": 20,
"loc": {
@ -150,9 +152,11 @@
"column": 20
}
},
"value": 1,
"rawValue": 1,
"raw": "1"
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
}
}
],
@ -176,6 +180,7 @@
}
}
}
]
],
"directives": []
}
}

View File

@ -74,7 +74,7 @@
"name": "x"
},
"right": {
"type": "Literal",
"type": "NumberLiteral",
"start": 8,
"end": 9,
"loc": {
@ -87,9 +87,11 @@
"column": 9
}
},
"value": 0,
"rawValue": 0,
"raw": "0"
"extra": {
"rawValue": 0,
"raw": "0"
},
"value": 0
}
},
"test": {
@ -124,7 +126,7 @@
},
"operator": "<",
"right": {
"type": "Literal",
"type": "NumberLiteral",
"start": 15,
"end": 17,
"loc": {
@ -137,9 +139,11 @@
"column": 17
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
},
"update": null,
@ -159,6 +163,7 @@
}
}
}
]
],
"directives": []
}
}

View File

@ -74,7 +74,7 @@
"name": "x"
},
"right": {
"type": "Literal",
"type": "NumberLiteral",
"start": 8,
"end": 9,
"loc": {
@ -87,9 +87,11 @@
"column": 9
}
},
"value": 0,
"rawValue": 0,
"raw": "0"
"extra": {
"rawValue": 0,
"raw": "0"
},
"value": 0
}
},
"test": {
@ -124,7 +126,7 @@
},
"operator": "<",
"right": {
"type": "Literal",
"type": "NumberLiteral",
"start": 15,
"end": 17,
"loc": {
@ -137,9 +139,11 @@
"column": 17
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
},
"update": {
@ -191,6 +195,7 @@
}
}
}
]
],
"directives": []
}
}

View File

@ -74,7 +74,7 @@
"name": "x"
},
"right": {
"type": "Literal",
"type": "NumberLiteral",
"start": 8,
"end": 9,
"loc": {
@ -87,9 +87,11 @@
"column": 9
}
},
"value": 0,
"rawValue": 0,
"raw": "0"
"extra": {
"rawValue": 0,
"raw": "0"
},
"value": 0
}
},
"test": {
@ -124,7 +126,7 @@
},
"operator": "<",
"right": {
"type": "Literal",
"type": "NumberLiteral",
"start": 15,
"end": 17,
"loc": {
@ -137,9 +139,11 @@
"column": 17
}
},
"value": 42,
"rawValue": 42,
"raw": "42"
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
},
"update": {
@ -240,6 +244,7 @@
}
}
}
]
],
"directives": []
}
}

View File

@ -1 +0,0 @@
for (var x = 42 in list) process(x);

View File

@ -1 +0,0 @@
for (var i = function() { return 10 in [] } in list) process(x);

Some files were not shown because too many files have changed in this diff Show More