add esprima tests and fix bugs picked up by it
This commit is contained in:
@@ -229,7 +229,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,10 +245,10 @@ 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.options.features["es7.trailingFunctionCommas"], possibleAsync);
|
||||
base = this.finishNode(node, "CallExpression");
|
||||
|
||||
if (possibleAsync && (this.match(tt.colon) || this.match(tt.arrow))) {
|
||||
if (possibleAsync && this.shouldParseAsyncArrow()) {
|
||||
base = this.parseAsyncArrowFromCallExpression(this.startNodeAt(startPos, startLoc), node);
|
||||
} else {
|
||||
this.toReferencedList(node.arguments);
|
||||
@@ -264,6 +264,38 @@ 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();
|
||||
this.expect(tt.arrow);
|
||||
@@ -286,16 +318,51 @@ 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.inFunction) {
|
||||
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();
|
||||
}
|
||||
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();
|
||||
// NOTE: falls through to _let
|
||||
if (!this.state.inGenerator && this.strict) this.unexpected();
|
||||
|
||||
case tt._let:
|
||||
case tt.name:
|
||||
node = this.startNode();
|
||||
let id = this.parseIdentifier(true);
|
||||
|
||||
if (this.options.features["es7.asyncFunctions"]) {
|
||||
if (id.name === "await") {
|
||||
if (this.inAsync) 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.parseIdentifier()];
|
||||
this.expect(tt.arrow);
|
||||
// var foo = bar => {};
|
||||
return this.parseArrowExpression(node, params, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (canBeArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) {
|
||||
return this.parseArrowExpression(node, [id]);
|
||||
}
|
||||
|
||||
return id;
|
||||
|
||||
|
||||
case tt._do:
|
||||
if (this.options.features["es7.doExpressions"]) {
|
||||
@@ -311,30 +378,6 @@ pp.parseExprAtom = function (refShorthandDefaultPos) {
|
||||
return this.finishNode(node, "DoExpression");
|
||||
}
|
||||
|
||||
case tt.name:
|
||||
node = this.startNode();
|
||||
let id = this.parseIdent(true);
|
||||
|
||||
if (this.options.features["es7.asyncFunctions"]) {
|
||||
if (id.name === "await") {
|
||||
if (this.inAsync) 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()];
|
||||
this.expect(tt.arrow);
|
||||
// var foo = bar => {};
|
||||
return this.parseArrowExpression(node, params, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (canBeArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) {
|
||||
return this.parseArrowExpression(node, [id]);
|
||||
}
|
||||
|
||||
return id;
|
||||
|
||||
case tt.regexp:
|
||||
let value = this.state.value;
|
||||
node = this.parseLiteral(value.value);
|
||||
@@ -430,7 +473,7 @@ pp.parseParenAndDistinguishExpression = function (startPos, startLoc, canBeArrow
|
||||
|
||||
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;
|
||||
@@ -454,6 +497,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);
|
||||
@@ -497,11 +541,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");
|
||||
@@ -592,7 +636,7 @@ pp.parseObj = function (isPattern, refShorthandDefaultPos) {
|
||||
}
|
||||
if (!isPattern && this.options.features["es7.asyncFunctions"] && this.isContextual("async")) {
|
||||
if (isGenerator) this.unexpected();
|
||||
var asyncId = this.parseIdent();
|
||||
var asyncId = this.parseIdentifier();
|
||||
if (this.match(tt.colon) || this.match(tt.parenL) || this.match(tt.braceR)) {
|
||||
prop.key = asyncId;
|
||||
} else {
|
||||
@@ -629,22 +673,27 @@ pp.parseObjPropValue = function (prop, startPos, startLoc, isGenerator, isAsync,
|
||||
let paramCount = prop.kind === "get" ? 0 : 1;
|
||||
if (prop.value.params.length !== paramCount) {
|
||||
let start = prop.value.start;
|
||||
if (prop.kind === "get")
|
||||
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";
|
||||
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);
|
||||
var illegalBinding = this.isKeyword(prop.key.name);
|
||||
if (!illegalBinding && this.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();
|
||||
@@ -663,7 +712,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);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -723,16 +772,19 @@ pp.parseFunctionBody = function (node, allowExpression) {
|
||||
// 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;
|
||||
var checkLVal = this.strict;
|
||||
// arrow function
|
||||
if (allowExpression) checkLVal = true;
|
||||
// normal function
|
||||
if (!isExpression && node.body.body.length && this.isUseStrict(node.body.body[0])) checkLVal = true;
|
||||
if (checkLVal) {
|
||||
let nameHash = Object.create(null);
|
||||
if (node.id) {
|
||||
this.checkLVal(node.id, true);
|
||||
}
|
||||
for (let param of (node.params: Array)) {
|
||||
this.checkLVal(param, true, nameHash);
|
||||
}
|
||||
this.strict = oldStrict;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -773,19 +825,21 @@ 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 (this.isName()) {
|
||||
if (!liberal && this.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();
|
||||
}
|
||||
|
||||
this.next();
|
||||
return this.finishNode(node, "Identifier");
|
||||
};
|
||||
|
||||
@@ -92,17 +92,22 @@ 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();
|
||||
if (this.isName() || this.match(tt.bracketL)) {
|
||||
node.argument = this.parseBindingAtom();
|
||||
} else {
|
||||
this.unexpected();
|
||||
}
|
||||
return this.finishNode(node, "RestElement");
|
||||
};
|
||||
|
||||
// Parses lvalue (assignable) atom.
|
||||
|
||||
pp.parseBindingAtom = function () {
|
||||
switch (this.state.type) {
|
||||
case tt.name:
|
||||
return this.parseIdent();
|
||||
if (this.isName()) {
|
||||
return this.parseIdentifier(true);
|
||||
}
|
||||
|
||||
switch (this.state.type) {
|
||||
case tt.bracketL:
|
||||
let node = this.startNode();
|
||||
this.next();
|
||||
@@ -163,8 +168,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.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,7 +186,7 @@ pp.checkLVal = function (expr, isBinding, checkClashes) {
|
||||
break;
|
||||
|
||||
case "ObjectPattern":
|
||||
for (let prop of (expr.properties: Array)) {
|
||||
for (let prop of (expr.properties: Array)) {
|
||||
if (prop.type === "Property") prop = prop.value;
|
||||
this.checkLVal(prop, isBinding, checkClashes);
|
||||
}
|
||||
|
||||
@@ -72,8 +72,27 @@ 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:
|
||||
// NOTE: falls through to _const
|
||||
if (!this.strict) {
|
||||
let state = this.state.clone();
|
||||
this.next();
|
||||
|
||||
var isBindingAtomStart = this.isName() || this.match(tt.braceL) || this.match(tt.bracketL);
|
||||
|
||||
// set back lookahead
|
||||
this.state = state;
|
||||
|
||||
if (!isBindingAtomStart) break;
|
||||
}
|
||||
|
||||
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();
|
||||
@@ -92,7 +111,7 @@ pp.parseStatement = function (declaration, topLevel) {
|
||||
case tt.name:
|
||||
if (this.options.features["es7.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 +120,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);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -158,7 +176,7 @@ pp.parseBreakContinueStatement = function (node, keyword) {
|
||||
} else if (!this.match(tt.name)) {
|
||||
this.unexpected();
|
||||
} else {
|
||||
node.label = this.parseIdent();
|
||||
node.label = this.parseIdentifier();
|
||||
this.semicolon();
|
||||
}
|
||||
|
||||
@@ -487,12 +505,12 @@ pp.parseFunction = function (node, isStatement, allowExpressionBody, isAsync, op
|
||||
this.initFunction(node, isAsync);
|
||||
node.generator = this.eat(tt.star);
|
||||
|
||||
if (isStatement && !optionalId && !this.match(tt.name)) {
|
||||
if (isStatement && !optionalId && !this.isName()) {
|
||||
this.unexpected();
|
||||
}
|
||||
|
||||
if (this.match(tt.name)) {
|
||||
node.id = this.parseIdent();
|
||||
if (this.isName()) {
|
||||
node.id = this.parseIdentifier();
|
||||
}
|
||||
|
||||
this.parseFunctionParams(node);
|
||||
@@ -613,7 +631,7 @@ pp.parseClassMethod = function (classBody, method, isGenerator, isAsync) {
|
||||
|
||||
pp.parseClassId = function (node, isStatement, optionalId) {
|
||||
if (this.match(tt.name)) {
|
||||
node.id = this.parseIdent();
|
||||
node.id = this.parseIdentifier();
|
||||
} else {
|
||||
if (optionalId || !isStatement) {
|
||||
node.id = null;
|
||||
@@ -636,7 +654,7 @@ pp.parseExport = function (node) {
|
||||
let specifier = this.startNode();
|
||||
this.next();
|
||||
if (this.options.features["es7.exportExtensions"] && this.eatContextual("as")) {
|
||||
specifier.exported = this.parseIdent();
|
||||
specifier.exported = this.parseIdentifier();
|
||||
node.specifiers = [this.finishNode(specifier, "ExportNamespaceSpecifier")];
|
||||
this.parseExportSpecifiersMaybe(node);
|
||||
this.parseExportFrom(node, true);
|
||||
@@ -646,14 +664,14 @@ pp.parseExport = function (node) {
|
||||
}
|
||||
} else if (this.options.features["es7.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);
|
||||
@@ -744,7 +762,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);
|
||||
|
||||
@@ -756,12 +777,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;
|
||||
};
|
||||
|
||||
@@ -791,7 +820,7 @@ pp.parseImportSpecifiers = function (node) {
|
||||
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));
|
||||
node.specifiers.push(this.parseImportSpecifierDefault(this.parseIdentifier(), startPos, startLoc));
|
||||
if (!this.eat(tt.comma)) return;
|
||||
}
|
||||
|
||||
@@ -799,7 +828,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;
|
||||
@@ -815,8 +844,8 @@ 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"));
|
||||
}
|
||||
|
||||
@@ -28,6 +28,23 @@ pp.expectRelational = function (op) {
|
||||
}
|
||||
};
|
||||
|
||||
// TODO
|
||||
|
||||
pp.isName = function () {
|
||||
if (this.match(tt.name)) {
|
||||
return true;
|
||||
} else if (!this.strict) {
|
||||
var keyword = this.state.type.keyword;
|
||||
if (keyword === "let") {
|
||||
return true;
|
||||
} else if (keyword === "yield") {
|
||||
return !this.state.inGenerator;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
// Tests whether parsed token is a contextual keyword.
|
||||
|
||||
pp.isContextual = function (name) {
|
||||
|
||||
Reference in New Issue
Block a user