|
|
|
@ -25,10 +25,6 @@ var _tokentype = _dereq_("./tokentype");
|
|
|
|
|
|
|
|
|
|
var _state = _dereq_("./state");
|
|
|
|
|
|
|
|
|
|
var _identifier = _dereq_("./identifier");
|
|
|
|
|
|
|
|
|
|
var _util = _dereq_("./util");
|
|
|
|
|
|
|
|
|
|
var pp = _state.Parser.prototype;
|
|
|
|
|
|
|
|
|
|
// Check if property name clashes with already added.
|
|
|
|
@ -38,8 +34,7 @@ var pp = _state.Parser.prototype;
|
|
|
|
|
|
|
|
|
|
pp.checkPropClash = function (prop, propHash) {
|
|
|
|
|
if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand)) return;
|
|
|
|
|
var key = prop.key,
|
|
|
|
|
name = undefined;
|
|
|
|
|
var key = prop.key;var name = undefined;
|
|
|
|
|
switch (key.type) {
|
|
|
|
|
case "Identifier":
|
|
|
|
|
name = key.name;break;
|
|
|
|
@ -49,6 +44,7 @@ pp.checkPropClash = function (prop, propHash) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
var kind = prop.kind;
|
|
|
|
|
|
|
|
|
|
if (this.options.ecmaVersion >= 6) {
|
|
|
|
|
if (name === "__proto__" && kind === "init") {
|
|
|
|
|
if (propHash.proto) this.raise(key.start, "Redefinition of __proto__ property");
|
|
|
|
@ -56,9 +52,9 @@ pp.checkPropClash = function (prop, propHash) {
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
var other = undefined;
|
|
|
|
|
if (_util.has(propHash, name)) {
|
|
|
|
|
other = propHash[name];
|
|
|
|
|
name = "$" + name;
|
|
|
|
|
var other = propHash[name];
|
|
|
|
|
if (other) {
|
|
|
|
|
var isGetSet = kind !== "init";
|
|
|
|
|
if ((this.strict || isGetSet) && other[kind] || !(isGetSet ^ other.init)) this.raise(key.start, "Redefinition of property");
|
|
|
|
|
} else {
|
|
|
|
@ -86,14 +82,14 @@ pp.checkPropClash = function (prop, propHash) {
|
|
|
|
|
// and object pattern might appear (so it's possible to raise
|
|
|
|
|
// delayed syntax error at correct position).
|
|
|
|
|
|
|
|
|
|
pp.parseExpression = function (noIn, refShorthandDefaultPos) {
|
|
|
|
|
pp.parseExpression = function (noIn, refDestructuringErrors) {
|
|
|
|
|
var startPos = this.start,
|
|
|
|
|
startLoc = this.startLoc;
|
|
|
|
|
var expr = this.parseMaybeAssign(noIn, refShorthandDefaultPos);
|
|
|
|
|
var expr = this.parseMaybeAssign(noIn, refDestructuringErrors);
|
|
|
|
|
if (this.type === _tokentype.types.comma) {
|
|
|
|
|
var node = this.startNodeAt(startPos, startLoc);
|
|
|
|
|
node.expressions = [expr];
|
|
|
|
|
while (this.eat(_tokentype.types.comma)) node.expressions.push(this.parseMaybeAssign(noIn, refShorthandDefaultPos));
|
|
|
|
|
while (this.eat(_tokentype.types.comma)) node.expressions.push(this.parseMaybeAssign(noIn, refDestructuringErrors));
|
|
|
|
|
return this.finishNode(node, "SequenceExpression");
|
|
|
|
|
}
|
|
|
|
|
return expr;
|
|
|
|
@ -102,43 +98,42 @@ pp.parseExpression = function (noIn, refShorthandDefaultPos) {
|
|
|
|
|
// Parse an assignment expression. This includes applications of
|
|
|
|
|
// operators like `+=`.
|
|
|
|
|
|
|
|
|
|
pp.parseMaybeAssign = function (noIn, refShorthandDefaultPos, afterLeftParse) {
|
|
|
|
|
pp.parseMaybeAssign = function (noIn, refDestructuringErrors, afterLeftParse) {
|
|
|
|
|
if (this.type == _tokentype.types._yield && this.inGenerator) return this.parseYield();
|
|
|
|
|
|
|
|
|
|
var failOnShorthandAssign = undefined;
|
|
|
|
|
if (!refShorthandDefaultPos) {
|
|
|
|
|
refShorthandDefaultPos = { start: 0 };
|
|
|
|
|
failOnShorthandAssign = true;
|
|
|
|
|
} else {
|
|
|
|
|
failOnShorthandAssign = false;
|
|
|
|
|
var validateDestructuring = false;
|
|
|
|
|
if (!refDestructuringErrors) {
|
|
|
|
|
refDestructuringErrors = { shorthandAssign: 0, trailingComma: 0 };
|
|
|
|
|
validateDestructuring = true;
|
|
|
|
|
}
|
|
|
|
|
var startPos = this.start,
|
|
|
|
|
startLoc = this.startLoc;
|
|
|
|
|
if (this.type == _tokentype.types.parenL || this.type == _tokentype.types.name) this.potentialArrowAt = this.start;
|
|
|
|
|
var left = this.parseMaybeConditional(noIn, refShorthandDefaultPos);
|
|
|
|
|
var left = this.parseMaybeConditional(noIn, refDestructuringErrors);
|
|
|
|
|
if (afterLeftParse) left = afterLeftParse.call(this, left, startPos, startLoc);
|
|
|
|
|
if (this.type.isAssign) {
|
|
|
|
|
if (validateDestructuring) this.checkPatternErrors(refDestructuringErrors, true);
|
|
|
|
|
var node = this.startNodeAt(startPos, startLoc);
|
|
|
|
|
node.operator = this.value;
|
|
|
|
|
node.left = this.type === _tokentype.types.eq ? this.toAssignable(left) : left;
|
|
|
|
|
refShorthandDefaultPos.start = 0; // reset because shorthand default was used correctly
|
|
|
|
|
refDestructuringErrors.shorthandAssign = 0; // reset because shorthand default was used correctly
|
|
|
|
|
this.checkLVal(left);
|
|
|
|
|
this.next();
|
|
|
|
|
node.right = this.parseMaybeAssign(noIn);
|
|
|
|
|
return this.finishNode(node, "AssignmentExpression");
|
|
|
|
|
} else if (failOnShorthandAssign && refShorthandDefaultPos.start) {
|
|
|
|
|
this.unexpected(refShorthandDefaultPos.start);
|
|
|
|
|
} else {
|
|
|
|
|
if (validateDestructuring) this.checkExpressionErrors(refDestructuringErrors, true);
|
|
|
|
|
}
|
|
|
|
|
return left;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Parse a ternary conditional (`?:`) operator.
|
|
|
|
|
|
|
|
|
|
pp.parseMaybeConditional = function (noIn, refShorthandDefaultPos) {
|
|
|
|
|
pp.parseMaybeConditional = function (noIn, refDestructuringErrors) {
|
|
|
|
|
var startPos = this.start,
|
|
|
|
|
startLoc = this.startLoc;
|
|
|
|
|
var expr = this.parseExprOps(noIn, refShorthandDefaultPos);
|
|
|
|
|
if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr;
|
|
|
|
|
var expr = this.parseExprOps(noIn, refDestructuringErrors);
|
|
|
|
|
if (this.checkExpressionErrors(refDestructuringErrors)) return expr;
|
|
|
|
|
if (this.eat(_tokentype.types.question)) {
|
|
|
|
|
var node = this.startNodeAt(startPos, startLoc);
|
|
|
|
|
node.test = expr;
|
|
|
|
@ -152,11 +147,11 @@ pp.parseMaybeConditional = function (noIn, refShorthandDefaultPos) {
|
|
|
|
|
|
|
|
|
|
// Start the precedence parser.
|
|
|
|
|
|
|
|
|
|
pp.parseExprOps = function (noIn, refShorthandDefaultPos) {
|
|
|
|
|
pp.parseExprOps = function (noIn, refDestructuringErrors) {
|
|
|
|
|
var startPos = this.start,
|
|
|
|
|
startLoc = this.startLoc;
|
|
|
|
|
var expr = this.parseMaybeUnary(refShorthandDefaultPos);
|
|
|
|
|
if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr;
|
|
|
|
|
var expr = this.parseMaybeUnary(refDestructuringErrors);
|
|
|
|
|
if (this.checkExpressionErrors(refDestructuringErrors)) return expr;
|
|
|
|
|
return this.parseExprOp(expr, startPos, startLoc, -1, noIn);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -187,7 +182,7 @@ pp.parseExprOp = function (left, leftStartPos, leftStartLoc, minPrec, noIn) {
|
|
|
|
|
|
|
|
|
|
// Parse unary operators, both prefix and postfix.
|
|
|
|
|
|
|
|
|
|
pp.parseMaybeUnary = function (refShorthandDefaultPos) {
|
|
|
|
|
pp.parseMaybeUnary = function (refDestructuringErrors) {
|
|
|
|
|
if (this.type.prefix) {
|
|
|
|
|
var node = this.startNode(),
|
|
|
|
|
update = this.type === _tokentype.types.incDec;
|
|
|
|
@ -195,14 +190,14 @@ pp.parseMaybeUnary = function (refShorthandDefaultPos) {
|
|
|
|
|
node.prefix = true;
|
|
|
|
|
this.next();
|
|
|
|
|
node.argument = this.parseMaybeUnary();
|
|
|
|
|
if (refShorthandDefaultPos && refShorthandDefaultPos.start) this.unexpected(refShorthandDefaultPos.start);
|
|
|
|
|
this.checkExpressionErrors(refDestructuringErrors, true);
|
|
|
|
|
if (update) this.checkLVal(node.argument);else if (this.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");
|
|
|
|
|
}
|
|
|
|
|
var startPos = this.start,
|
|
|
|
|
startLoc = this.startLoc;
|
|
|
|
|
var expr = this.parseExprSubscripts(refShorthandDefaultPos);
|
|
|
|
|
if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr;
|
|
|
|
|
var expr = this.parseExprSubscripts(refDestructuringErrors);
|
|
|
|
|
if (this.checkExpressionErrors(refDestructuringErrors)) return expr;
|
|
|
|
|
while (this.type.postfix && !this.canInsertSemicolon()) {
|
|
|
|
|
var node = this.startNodeAt(startPos, startLoc);
|
|
|
|
|
node.operator = this.value;
|
|
|
|
@ -217,11 +212,12 @@ pp.parseMaybeUnary = function (refShorthandDefaultPos) {
|
|
|
|
|
|
|
|
|
|
// Parse call, dot, and `[]`-subscript expressions.
|
|
|
|
|
|
|
|
|
|
pp.parseExprSubscripts = function (refShorthandDefaultPos) {
|
|
|
|
|
pp.parseExprSubscripts = function (refDestructuringErrors) {
|
|
|
|
|
var startPos = this.start,
|
|
|
|
|
startLoc = this.startLoc;
|
|
|
|
|
var expr = this.parseExprAtom(refShorthandDefaultPos);
|
|
|
|
|
if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr;
|
|
|
|
|
var expr = this.parseExprAtom(refDestructuringErrors);
|
|
|
|
|
var skipArrowSubscripts = expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")";
|
|
|
|
|
if (this.checkExpressionErrors(refDestructuringErrors) || skipArrowSubscripts) return expr;
|
|
|
|
|
return this.parseSubscripts(expr, startPos, startLoc);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -261,7 +257,7 @@ pp.parseSubscripts = function (base, startPos, startLoc, noCalls) {
|
|
|
|
|
// `new`, or an expression wrapped in punctuation like `()`, `[]`,
|
|
|
|
|
// or `{}`.
|
|
|
|
|
|
|
|
|
|
pp.parseExprAtom = function (refShorthandDefaultPos) {
|
|
|
|
|
pp.parseExprAtom = function (refDestructuringErrors) {
|
|
|
|
|
var node = undefined,
|
|
|
|
|
canBeArrow = this.potentialArrowAt == this.start;
|
|
|
|
|
switch (this.type) {
|
|
|
|
@ -277,6 +273,18 @@ pp.parseExprAtom = function (refShorthandDefaultPos) {
|
|
|
|
|
if (this.inGenerator) this.unexpected();
|
|
|
|
|
|
|
|
|
|
case _tokentype.types.name:
|
|
|
|
|
// quick hack to allow async and await
|
|
|
|
|
if (this.value == "async" && /^[ \t]+function\b/.test(this.input.slice(this.end))) {
|
|
|
|
|
node = this.startNode();
|
|
|
|
|
this.next();
|
|
|
|
|
return this.parseExprAtom(refDestructuringErrors);
|
|
|
|
|
}
|
|
|
|
|
if (this.value == "await" && /^[ \t]+[\w\x1f-\uffff]/.test(this.input.slice(this.end))) {
|
|
|
|
|
node = this.startNode();
|
|
|
|
|
this.next();
|
|
|
|
|
return this.parseExprAtom(refDestructuringErrors);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var startPos = this.start,
|
|
|
|
|
startLoc = this.startLoc;
|
|
|
|
|
var id = this.parseIdent(this.type !== _tokentype.types.name);
|
|
|
|
@ -309,11 +317,11 @@ pp.parseExprAtom = function (refShorthandDefaultPos) {
|
|
|
|
|
if (this.options.ecmaVersion >= 7 && this.type === _tokentype.types._for) {
|
|
|
|
|
return this.parseComprehension(node, false);
|
|
|
|
|
}
|
|
|
|
|
node.elements = this.parseExprList(_tokentype.types.bracketR, true, true, refShorthandDefaultPos);
|
|
|
|
|
node.elements = this.parseExprList(_tokentype.types.bracketR, true, true, refDestructuringErrors);
|
|
|
|
|
return this.finishNode(node, "ArrayExpression");
|
|
|
|
|
|
|
|
|
|
case _tokentype.types.braceL:
|
|
|
|
|
return this.parseObj(false, refShorthandDefaultPos);
|
|
|
|
|
return this.parseObj(false, refDestructuringErrors);
|
|
|
|
|
|
|
|
|
|
case _tokentype.types._function:
|
|
|
|
|
node = this.startNode();
|
|
|
|
@ -364,7 +372,7 @@ pp.parseParenAndDistinguishExpression = function (canBeArrow) {
|
|
|
|
|
innerStartLoc = this.startLoc;
|
|
|
|
|
var exprList = [],
|
|
|
|
|
first = true;
|
|
|
|
|
var refShorthandDefaultPos = { start: 0 },
|
|
|
|
|
var refDestructuringErrors = { shorthandAssign: 0, trailingComma: 0 },
|
|
|
|
|
spreadStart = undefined,
|
|
|
|
|
innerParenStart = undefined;
|
|
|
|
|
while (this.type !== _tokentype.types.parenR) {
|
|
|
|
@ -377,7 +385,7 @@ pp.parseParenAndDistinguishExpression = function (canBeArrow) {
|
|
|
|
|
if (this.type === _tokentype.types.parenL && !innerParenStart) {
|
|
|
|
|
innerParenStart = this.start;
|
|
|
|
|
}
|
|
|
|
|
exprList.push(this.parseMaybeAssign(false, refShorthandDefaultPos, this.parseParenItem));
|
|
|
|
|
exprList.push(this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
var innerEndPos = this.start,
|
|
|
|
@ -385,13 +393,14 @@ pp.parseParenAndDistinguishExpression = function (canBeArrow) {
|
|
|
|
|
this.expect(_tokentype.types.parenR);
|
|
|
|
|
|
|
|
|
|
if (canBeArrow && !this.canInsertSemicolon() && this.eat(_tokentype.types.arrow)) {
|
|
|
|
|
this.checkPatternErrors(refDestructuringErrors, true);
|
|
|
|
|
if (innerParenStart) this.unexpected(innerParenStart);
|
|
|
|
|
return this.parseParenArrowList(startPos, startLoc, exprList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!exprList.length) this.unexpected(this.lastTokStart);
|
|
|
|
|
if (spreadStart) this.unexpected(spreadStart);
|
|
|
|
|
if (refShorthandDefaultPos.start) this.unexpected(refShorthandDefaultPos.start);
|
|
|
|
|
this.checkExpressionErrors(refDestructuringErrors, true);
|
|
|
|
|
|
|
|
|
|
if (exprList.length > 1) {
|
|
|
|
|
val = this.startNodeAt(innerStartPos, innerStartLoc);
|
|
|
|
@ -421,9 +430,11 @@ pp.parseParenArrowList = function (startPos, startLoc, exprList) {
|
|
|
|
|
return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// New's precedence is slightly tricky. It must allow its argument
|
|
|
|
|
// to be a `[]` or dot subscript expression, but not a call — at
|
|
|
|
|
// least, not without wrapping it in parentheses. Thus, it uses the
|
|
|
|
|
// New's precedence is slightly tricky. It must allow its argument to
|
|
|
|
|
// be a `[]` or dot subscript expression, but not a call — at least,
|
|
|
|
|
// not without wrapping it in parentheses. Thus, it uses the noCalls
|
|
|
|
|
// argument to parseSubscripts to prevent it from consuming the
|
|
|
|
|
// argument list.
|
|
|
|
|
|
|
|
|
|
var empty = [];
|
|
|
|
|
|
|
|
|
@ -434,6 +445,7 @@ pp.parseNew = function () {
|
|
|
|
|
node.meta = meta;
|
|
|
|
|
node.property = this.parseIdent(true);
|
|
|
|
|
if (node.property.name !== "target") this.raise(node.property.start, "The only valid meta property for new is new.target");
|
|
|
|
|
if (!this.inFunction) this.raise(node.start, "new.target can only be used in functions");
|
|
|
|
|
return this.finishNode(node, "MetaProperty");
|
|
|
|
|
}
|
|
|
|
|
var startPos = this.start,
|
|
|
|
@ -474,7 +486,7 @@ pp.parseTemplate = function () {
|
|
|
|
|
|
|
|
|
|
// Parse an object literal or binding pattern.
|
|
|
|
|
|
|
|
|
|
pp.parseObj = function (isPattern, refShorthandDefaultPos) {
|
|
|
|
|
pp.parseObj = function (isPattern, refDestructuringErrors) {
|
|
|
|
|
var node = this.startNode(),
|
|
|
|
|
first = true,
|
|
|
|
|
propHash = {};
|
|
|
|
@ -493,23 +505,23 @@ pp.parseObj = function (isPattern, refShorthandDefaultPos) {
|
|
|
|
|
if (this.options.ecmaVersion >= 6) {
|
|
|
|
|
prop.method = false;
|
|
|
|
|
prop.shorthand = false;
|
|
|
|
|
if (isPattern || refShorthandDefaultPos) {
|
|
|
|
|
if (isPattern || refDestructuringErrors) {
|
|
|
|
|
startPos = this.start;
|
|
|
|
|
startLoc = this.startLoc;
|
|
|
|
|
}
|
|
|
|
|
if (!isPattern) isGenerator = this.eat(_tokentype.types.star);
|
|
|
|
|
}
|
|
|
|
|
this.parsePropertyName(prop);
|
|
|
|
|
this.parsePropertyValue(prop, isPattern, isGenerator, startPos, startLoc, refShorthandDefaultPos);
|
|
|
|
|
this.parsePropertyValue(prop, isPattern, isGenerator, startPos, startLoc, refDestructuringErrors);
|
|
|
|
|
this.checkPropClash(prop, propHash);
|
|
|
|
|
node.properties.push(this.finishNode(prop, "Property"));
|
|
|
|
|
}
|
|
|
|
|
return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression");
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
pp.parsePropertyValue = function (prop, isPattern, isGenerator, startPos, startLoc, refShorthandDefaultPos) {
|
|
|
|
|
pp.parsePropertyValue = function (prop, isPattern, isGenerator, startPos, startLoc, refDestructuringErrors) {
|
|
|
|
|
if (this.eat(_tokentype.types.colon)) {
|
|
|
|
|
prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refShorthandDefaultPos);
|
|
|
|
|
prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors);
|
|
|
|
|
prop.kind = "init";
|
|
|
|
|
} else if (this.options.ecmaVersion >= 6 && this.type === _tokentype.types.parenL) {
|
|
|
|
|
if (isPattern) this.unexpected();
|
|
|
|
@ -526,13 +538,14 @@ pp.parsePropertyValue = function (prop, isPattern, isGenerator, startPos, startL
|
|
|
|
|
var start = prop.value.start;
|
|
|
|
|
if (prop.kind === "get") this.raise(start, "getter should have no params");else this.raise(start, "setter should have exactly one param");
|
|
|
|
|
}
|
|
|
|
|
if (prop.kind === "set" && prop.value.params[0].type === "RestElement") this.raise(prop.value.params[0].start, "Setter cannot use rest params");
|
|
|
|
|
} else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") {
|
|
|
|
|
prop.kind = "init";
|
|
|
|
|
if (isPattern) {
|
|
|
|
|
if (this.isKeyword(prop.key.name) || this.strict && (_identifier.reservedWords.strictBind(prop.key.name) || _identifier.reservedWords.strict(prop.key.name)) || !this.options.allowReserved && this.isReservedWord(prop.key.name)) this.raise(prop.key.start, "Binding " + prop.key.name);
|
|
|
|
|
if (this.keywords.test(prop.key.name) || (this.strict ? this.reservedWordsStrictBind : this.reservedWords).test(prop.key.name)) this.raise(prop.key.start, "Binding " + prop.key.name);
|
|
|
|
|
prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key);
|
|
|
|
|
} else if (this.type === _tokentype.types.eq && refShorthandDefaultPos) {
|
|
|
|
|
if (!refShorthandDefaultPos.start) refShorthandDefaultPos.start = this.start;
|
|
|
|
|
} else if (this.type === _tokentype.types.eq && refDestructuringErrors) {
|
|
|
|
|
if (!refDestructuringErrors.shorthandAssign) refDestructuringErrors.shorthandAssign = this.start;
|
|
|
|
|
prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key);
|
|
|
|
|
} else {
|
|
|
|
|
prop.value = prop.key;
|
|
|
|
@ -572,10 +585,7 @@ pp.parseMethod = function (isGenerator) {
|
|
|
|
|
this.initFunction(node);
|
|
|
|
|
this.expect(_tokentype.types.parenL);
|
|
|
|
|
node.params = this.parseBindingList(_tokentype.types.parenR, false, false);
|
|
|
|
|
var allowExpressionBody = undefined;
|
|
|
|
|
if (this.options.ecmaVersion >= 6) {
|
|
|
|
|
node.generator = isGenerator;
|
|
|
|
|
}
|
|
|
|
|
if (this.options.ecmaVersion >= 6) node.generator = isGenerator;
|
|
|
|
|
this.parseFunctionBody(node, false);
|
|
|
|
|
return this.finishNode(node, "FunctionExpression");
|
|
|
|
|
};
|
|
|
|
@ -591,8 +601,8 @@ pp.parseArrowExpression = function (node, params) {
|
|
|
|
|
|
|
|
|
|
// Parse function body and check parameters.
|
|
|
|
|
|
|
|
|
|
pp.parseFunctionBody = function (node, allowExpression) {
|
|
|
|
|
var isExpression = allowExpression && this.type !== _tokentype.types.braceL;
|
|
|
|
|
pp.parseFunctionBody = function (node, isArrowFunction) {
|
|
|
|
|
var isExpression = isArrowFunction && this.type !== _tokentype.types.braceL;
|
|
|
|
|
|
|
|
|
|
if (isExpression) {
|
|
|
|
|
node.body = this.parseMaybeAssign();
|
|
|
|
@ -613,13 +623,23 @@ pp.parseFunctionBody = function (node, allowExpression) {
|
|
|
|
|
// 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])) {
|
|
|
|
|
var nameHash = {},
|
|
|
|
|
oldStrict = this.strict;
|
|
|
|
|
var oldStrict = this.strict;
|
|
|
|
|
this.strict = true;
|
|
|
|
|
if (node.id) this.checkLVal(node.id, true);
|
|
|
|
|
for (var i = 0; i < node.params.length; i++) {
|
|
|
|
|
this.checkLVal(node.params[i], true, nameHash);
|
|
|
|
|
}this.strict = oldStrict;
|
|
|
|
|
this.checkParams(node);
|
|
|
|
|
this.strict = oldStrict;
|
|
|
|
|
} else if (isArrowFunction) {
|
|
|
|
|
this.checkParams(node);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Checks function params for various disallowed patterns such as using "eval"
|
|
|
|
|
// or "arguments" and duplicate parameters.
|
|
|
|
|
|
|
|
|
|
pp.checkParams = function (node) {
|
|
|
|
|
var nameHash = {};
|
|
|
|
|
for (var i = 0; i < node.params.length; i++) {
|
|
|
|
|
this.checkLVal(node.params[i], true, nameHash);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -629,17 +649,20 @@ pp.parseFunctionBody = function (node, allowExpression) {
|
|
|
|
|
// nothing in between them to be parsed as `null` (which is needed
|
|
|
|
|
// for array literals).
|
|
|
|
|
|
|
|
|
|
pp.parseExprList = function (close, allowTrailingComma, allowEmpty, refShorthandDefaultPos) {
|
|
|
|
|
pp.parseExprList = function (close, allowTrailingComma, allowEmpty, refDestructuringErrors) {
|
|
|
|
|
var elts = [],
|
|
|
|
|
first = true;
|
|
|
|
|
while (!this.eat(close)) {
|
|
|
|
|
if (!first) {
|
|
|
|
|
this.expect(_tokentype.types.comma);
|
|
|
|
|
if (this.type === close && refDestructuringErrors && !refDestructuringErrors.trailingComma) {
|
|
|
|
|
refDestructuringErrors.trailingComma = this.lastTokStart;
|
|
|
|
|
}
|
|
|
|
|
if (allowTrailingComma && this.afterTrailingComma(close)) break;
|
|
|
|
|
} else first = false;
|
|
|
|
|
|
|
|
|
|
var elt = undefined;
|
|
|
|
|
if (allowEmpty && this.type === _tokentype.types.comma) elt = null;else if (this.type === _tokentype.types.ellipsis) elt = this.parseSpread(refShorthandDefaultPos);else elt = this.parseMaybeAssign(false, refShorthandDefaultPos);
|
|
|
|
|
if (allowEmpty && this.type === _tokentype.types.comma) elt = null;else if (this.type === _tokentype.types.ellipsis) elt = this.parseSpread(refDestructuringErrors);else elt = this.parseMaybeAssign(false, refDestructuringErrors);
|
|
|
|
|
elts.push(elt);
|
|
|
|
|
}
|
|
|
|
|
return elts;
|
|
|
|
@ -653,7 +676,7 @@ pp.parseIdent = function (liberal) {
|
|
|
|
|
var node = this.startNode();
|
|
|
|
|
if (liberal && this.options.allowReserved == "never") liberal = false;
|
|
|
|
|
if (this.type === _tokentype.types.name) {
|
|
|
|
|
if (!liberal && (!this.options.allowReserved && this.isReservedWord(this.value) || this.strict && _identifier.reservedWords.strict(this.value) && (this.options.ecmaVersion >= 6 || this.input.slice(this.start, this.end).indexOf("\\") == -1))) this.raise(this.start, "The keyword '" + this.value + "' is reserved");
|
|
|
|
|
if (!liberal && (this.strict ? this.reservedWordsStrict : this.reservedWords).test(this.value) && (this.options.ecmaVersion >= 6 || this.input.slice(this.start, this.end).indexOf("\\") == -1)) this.raise(this.start, "The keyword '" + this.value + "' is reserved");
|
|
|
|
|
node.name = this.value;
|
|
|
|
|
} else if (liberal && this.type.keyword) {
|
|
|
|
|
node.name = this.type.keyword;
|
|
|
|
@ -701,7 +724,7 @@ pp.parseComprehension = function (node, isGenerator) {
|
|
|
|
|
return this.finishNode(node, "ComprehensionExpression");
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
},{"./identifier":"/src\\identifier.js","./state":"/src\\state.js","./tokentype":"/src\\tokentype.js","./util":"/src\\util.js"}],"/src\\identifier.js":[function(_dereq_,module,exports){
|
|
|
|
|
},{"./state":"/src\\state.js","./tokentype":"/src\\tokentype.js"}],"/src\\identifier.js":[function(_dereq_,module,exports){
|
|
|
|
|
// 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
|
|
|
|
@ -711,36 +734,19 @@ pp.parseComprehension = function (node, isGenerator) {
|
|
|
|
|
//
|
|
|
|
|
// It starts by sorting the words by length.
|
|
|
|
|
|
|
|
|
|
// Reserved word lists for various dialects of the language
|
|
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
|
|
exports.__esModule = true;
|
|
|
|
|
exports.isIdentifierStart = isIdentifierStart;
|
|
|
|
|
exports.isIdentifierChar = isIdentifierChar;
|
|
|
|
|
// Removed to create an eval-free library
|
|
|
|
|
|
|
|
|
|
// Reserved word lists for various dialects of the language
|
|
|
|
|
|
|
|
|
|
var reservedWords = {
|
|
|
|
|
3: function anonymous(str
|
|
|
|
|
/**/) {
|
|
|
|
|
switch(str.length){case 6:switch(str){case "double":case "export":case "import":case "native":case "public":case "static":case "throws":return true}return false;case 4:switch(str){case "byte":case "char":case "enum":case "goto":case "long":return true}return false;case 5:switch(str){case "class":case "final":case "float":case "short":case "super":return true}return false;case 7:switch(str){case "boolean":case "extends":case "package":case "private":return true}return false;case 9:switch(str){case "interface":case "protected":case "transient":return true}return false;case 8:switch(str){case "abstract":case "volatile":return true}return false;case 10:return str === "implements";case 3:return str === "int";case 12:return str === "synchronized";}
|
|
|
|
|
},
|
|
|
|
|
5: function anonymous(str
|
|
|
|
|
/**/) {
|
|
|
|
|
switch(str.length){case 5:switch(str){case "class":case "super":case "const":return true}return false;case 6:switch(str){case "export":case "import":return true}return false;case 4:return str === "enum";case 7:return str === "extends";}
|
|
|
|
|
},
|
|
|
|
|
6: function anonymous(str
|
|
|
|
|
/**/) {
|
|
|
|
|
switch(str){case "enum":case "await":return true}return false;
|
|
|
|
|
},
|
|
|
|
|
strict: function anonymous(str
|
|
|
|
|
/**/) {
|
|
|
|
|
switch(str.length){case 9:switch(str){case "interface":case "protected":return true}return false;case 7:switch(str){case "package":case "private":return true}return false;case 6:switch(str){case "public":case "static":return true}return false;case 10:return str === "implements";case 3:return str === "let";case 5:return str === "yield";}
|
|
|
|
|
},
|
|
|
|
|
strictBind: function anonymous(str
|
|
|
|
|
/**/) {
|
|
|
|
|
switch(str){case "eval":case "arguments":return true}return false;
|
|
|
|
|
}
|
|
|
|
|
3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile",
|
|
|
|
|
5: "class enum extends super const export import",
|
|
|
|
|
6: "enum",
|
|
|
|
|
strict: "implements interface let package private protected public static yield",
|
|
|
|
|
strictBind: "eval arguments"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
exports.reservedWords = reservedWords;
|
|
|
|
@ -749,14 +755,8 @@ exports.reservedWords = reservedWords;
|
|
|
|
|
var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this";
|
|
|
|
|
|
|
|
|
|
var keywords = {
|
|
|
|
|
5: function anonymous(str
|
|
|
|
|
/**/) {
|
|
|
|
|
switch(str.length){case 4:switch(str){case "case":case "else":case "with":case "null":case "true":case "void":case "this":return true}return false;case 5:switch(str){case "break":case "catch":case "throw":case "while":case "false":return true}return false;case 3:switch(str){case "for":case "try":case "var":case "new":return true}return false;case 6:switch(str){case "return":case "switch":case "typeof":case "delete":return true}return false;case 8:switch(str){case "continue":case "debugger":case "function":return true}return false;case 2:switch(str){case "do":case "if":case "in":return true}return false;case 7:switch(str){case "default":case "finally":return true}return false;case 10:return str === "instanceof";}
|
|
|
|
|
},
|
|
|
|
|
6: function anonymous(str
|
|
|
|
|
/**/) {
|
|
|
|
|
switch(str.length){case 5:switch(str){case "break":case "catch":case "throw":case "while":case "false":case "const":case "class":case "yield":case "super":return true}return false;case 4:switch(str){case "case":case "else":case "with":case "null":case "true":case "void":case "this":return true}return false;case 6:switch(str){case "return":case "switch":case "typeof":case "delete":case "export":case "import":return true}return false;case 3:switch(str){case "for":case "try":case "var":case "new":case "let":return true}return false;case 8:switch(str){case "continue":case "debugger":case "function":return true}return false;case 7:switch(str){case "default":case "finally":case "extends":return true}return false;case 2:switch(str){case "do":case "if":case "in":return true}return false;case 10:return str === "instanceof";}
|
|
|
|
|
}
|
|
|
|
|
5: ecma5AndLessKeywords,
|
|
|
|
|
6: ecma5AndLessKeywords + " let const class extends export import yield super"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
exports.keywords = keywords;
|
|
|
|
@ -793,11 +793,11 @@ function isIdentifierChar(code, astral) {
|
|
|
|
|
// Git repositories for Acorn are available at
|
|
|
|
|
//
|
|
|
|
|
// http://marijnhaverbeke.nl/git/acorn
|
|
|
|
|
// https://github.com/marijnh/acorn.git
|
|
|
|
|
// https://github.com/ternjs/acorn.git
|
|
|
|
|
//
|
|
|
|
|
// Please use the [github bug tracker][ghbt] to report issues.
|
|
|
|
|
//
|
|
|
|
|
// [ghbt]: https://github.com/marijnh/acorn/issues
|
|
|
|
|
// [ghbt]: https://github.com/ternjs/acorn/issues
|
|
|
|
|
//
|
|
|
|
|
// This file defines the main parser interface. The library also comes
|
|
|
|
|
// with a [error-tolerant parser][dammit] and an
|
|
|
|
@ -815,8 +815,6 @@ exports.tokenizer = tokenizer;
|
|
|
|
|
|
|
|
|
|
var _state = _dereq_("./state");
|
|
|
|
|
|
|
|
|
|
var _options = _dereq_("./options");
|
|
|
|
|
|
|
|
|
|
_dereq_("./parseutil");
|
|
|
|
|
|
|
|
|
|
_dereq_("./statement");
|
|
|
|
@ -829,6 +827,9 @@ _dereq_("./location");
|
|
|
|
|
|
|
|
|
|
exports.Parser = _state.Parser;
|
|
|
|
|
exports.plugins = _state.plugins;
|
|
|
|
|
|
|
|
|
|
var _options = _dereq_("./options");
|
|
|
|
|
|
|
|
|
|
exports.defaultOptions = _options.defaultOptions;
|
|
|
|
|
|
|
|
|
|
var _locutil = _dereq_("./locutil");
|
|
|
|
@ -865,7 +866,7 @@ var _whitespace = _dereq_("./whitespace");
|
|
|
|
|
exports.isNewLine = _whitespace.isNewLine;
|
|
|
|
|
exports.lineBreak = _whitespace.lineBreak;
|
|
|
|
|
exports.lineBreakG = _whitespace.lineBreakG;
|
|
|
|
|
var version = "2.1.1";
|
|
|
|
|
var version = "2.7.0";
|
|
|
|
|
|
|
|
|
|
exports.version = version;
|
|
|
|
|
// The main exported interface (under `self.acorn` when in the
|
|
|
|
@ -890,7 +891,7 @@ function parseExpressionAt(input, pos, options) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Acorn is organized as a tokenizer and a recursive-descent parser.
|
|
|
|
|
// The `tokenize` export provides an interface to the tokenizer.
|
|
|
|
|
// The `tokenizer` export provides an interface to the tokenizer.
|
|
|
|
|
|
|
|
|
|
function tokenizer(input, options) {
|
|
|
|
|
return new _state.Parser(options, input);
|
|
|
|
@ -940,7 +941,7 @@ var _whitespace = _dereq_("./whitespace");
|
|
|
|
|
|
|
|
|
|
var Position = (function () {
|
|
|
|
|
function Position(line, col) {
|
|
|
|
|
_classCallCheck(this, Position);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.line = line;
|
|
|
|
|
this.column = col;
|
|
|
|
@ -956,7 +957,7 @@ var Position = (function () {
|
|
|
|
|
exports.Position = Position;
|
|
|
|
|
|
|
|
|
|
var SourceLocation = function SourceLocation(p, start, end) {
|
|
|
|
|
_classCallCheck(this, SourceLocation);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.start = start;
|
|
|
|
|
this.end = end;
|
|
|
|
@ -991,8 +992,6 @@ var _tokentype = _dereq_("./tokentype");
|
|
|
|
|
|
|
|
|
|
var _state = _dereq_("./state");
|
|
|
|
|
|
|
|
|
|
var _identifier = _dereq_("./identifier");
|
|
|
|
|
|
|
|
|
|
var _util = _dereq_("./util");
|
|
|
|
|
|
|
|
|
|
var pp = _state.Parser.prototype;
|
|
|
|
@ -1006,7 +1005,6 @@ pp.toAssignable = function (node, isBinding) {
|
|
|
|
|
case "Identifier":
|
|
|
|
|
case "ObjectPattern":
|
|
|
|
|
case "ArrayPattern":
|
|
|
|
|
case "AssignmentPattern":
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case "ObjectExpression":
|
|
|
|
@ -1026,10 +1024,16 @@ pp.toAssignable = function (node, isBinding) {
|
|
|
|
|
case "AssignmentExpression":
|
|
|
|
|
if (node.operator === "=") {
|
|
|
|
|
node.type = "AssignmentPattern";
|
|
|
|
|
delete node.operator;
|
|
|
|
|
delete node.operator
|
|
|
|
|
// falls through to AssignmentPattern
|
|
|
|
|
;
|
|
|
|
|
} else {
|
|
|
|
|
this.raise(node.left.end, "Only '=' operator can be used for specifying default value.");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case "AssignmentPattern":
|
|
|
|
|
if (node.right.type === "YieldExpression") this.raise(node.right.start, "Yield expression cannot be a default value");
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case "ParenthesizedExpression":
|
|
|
|
@ -1061,6 +1065,8 @@ pp.toAssignableList = function (exprList, isBinding) {
|
|
|
|
|
if (arg.type !== "Identifier" && arg.type !== "MemberExpression" && arg.type !== "ArrayPattern") this.unexpected(arg.start);
|
|
|
|
|
--end;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isBinding && last.type === "RestElement" && last.argument.type !== "Identifier") this.unexpected(last.argument.start);
|
|
|
|
|
}
|
|
|
|
|
for (var i = 0; i < end; i++) {
|
|
|
|
|
var elt = exprList[i];
|
|
|
|
@ -1071,17 +1077,20 @@ pp.toAssignableList = function (exprList, isBinding) {
|
|
|
|
|
|
|
|
|
|
// Parses spread element.
|
|
|
|
|
|
|
|
|
|
pp.parseSpread = function (refShorthandDefaultPos) {
|
|
|
|
|
pp.parseSpread = function (refDestructuringErrors) {
|
|
|
|
|
var node = this.startNode();
|
|
|
|
|
this.next();
|
|
|
|
|
node.argument = this.parseMaybeAssign(refShorthandDefaultPos);
|
|
|
|
|
node.argument = this.parseMaybeAssign(refDestructuringErrors);
|
|
|
|
|
return this.finishNode(node, "SpreadElement");
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
pp.parseRest = function () {
|
|
|
|
|
pp.parseRest = function (allowNonIdent) {
|
|
|
|
|
var node = this.startNode();
|
|
|
|
|
this.next();
|
|
|
|
|
node.argument = this.type === _tokentype.types.name || this.type === _tokentype.types.bracketL ? this.parseBindingAtom() : this.unexpected();
|
|
|
|
|
|
|
|
|
|
// RestElement inside of a function parameter must be an identifier
|
|
|
|
|
if (allowNonIdent) node.argument = this.type === _tokentype.types.name ? this.parseIdent() : this.unexpected();else node.argument = this.type === _tokentype.types.name || this.type === _tokentype.types.bracketL ? this.parseBindingAtom() : this.unexpected();
|
|
|
|
|
|
|
|
|
|
return this.finishNode(node, "RestElement");
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -1107,7 +1116,7 @@ pp.parseBindingAtom = function () {
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
pp.parseBindingList = function (close, allowEmpty, allowTrailingComma) {
|
|
|
|
|
pp.parseBindingList = function (close, allowEmpty, allowTrailingComma, allowNonIdent) {
|
|
|
|
|
var elts = [],
|
|
|
|
|
first = true;
|
|
|
|
|
while (!this.eat(close)) {
|
|
|
|
@ -1117,7 +1126,7 @@ pp.parseBindingList = function (close, allowEmpty, allowTrailingComma) {
|
|
|
|
|
} else if (allowTrailingComma && this.afterTrailingComma(close)) {
|
|
|
|
|
break;
|
|
|
|
|
} else if (this.type === _tokentype.types.ellipsis) {
|
|
|
|
|
var rest = this.parseRest();
|
|
|
|
|
var rest = this.parseRest(allowNonIdent);
|
|
|
|
|
this.parseBindingListItem(rest);
|
|
|
|
|
elts.push(rest);
|
|
|
|
|
this.expect(close);
|
|
|
|
@ -1139,9 +1148,8 @@ pp.parseBindingListItem = function (param) {
|
|
|
|
|
|
|
|
|
|
pp.parseMaybeDefault = function (startPos, startLoc, left) {
|
|
|
|
|
left = left || this.parseBindingAtom();
|
|
|
|
|
if (!this.eat(_tokentype.types.eq)) return left;
|
|
|
|
|
if (this.options.ecmaVersion < 6 || !this.eat(_tokentype.types.eq)) return left;
|
|
|
|
|
var node = this.startNodeAt(startPos, startLoc);
|
|
|
|
|
node.operator = "=";
|
|
|
|
|
node.left = left;
|
|
|
|
|
node.right = this.parseMaybeAssign();
|
|
|
|
|
return this.finishNode(node, "AssignmentPattern");
|
|
|
|
@ -1153,9 +1161,9 @@ pp.parseMaybeDefault = function (startPos, startLoc, left) {
|
|
|
|
|
pp.checkLVal = function (expr, isBinding, checkClashes) {
|
|
|
|
|
switch (expr.type) {
|
|
|
|
|
case "Identifier":
|
|
|
|
|
if (this.strict && (_identifier.reservedWords.strictBind(expr.name) || _identifier.reservedWords.strict(expr.name))) this.raise(expr.start, (isBinding ? "Binding " : "Assigning to ") + expr.name + " in strict mode");
|
|
|
|
|
if (this.strict && this.reservedWordsStrictBind.test(expr.name)) this.raise(expr.start, (isBinding ? "Binding " : "Assigning to ") + expr.name + " in strict mode");
|
|
|
|
|
if (checkClashes) {
|
|
|
|
|
if (_util.has(checkClashes, expr.name)) this.raise(expr.start, "Argument name clash in strict mode");
|
|
|
|
|
if (_util.has(checkClashes, expr.name)) this.raise(expr.start, "Argument name clash");
|
|
|
|
|
checkClashes[expr.name] = true;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
@ -1193,7 +1201,7 @@ pp.checkLVal = function (expr, isBinding, checkClashes) {
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
},{"./identifier":"/src\\identifier.js","./state":"/src\\state.js","./tokentype":"/src\\tokentype.js","./util":"/src\\util.js"}],"/src\\node.js":[function(_dereq_,module,exports){
|
|
|
|
|
},{"./state":"/src\\state.js","./tokentype":"/src\\tokentype.js","./util":"/src\\util.js"}],"/src\\node.js":[function(_dereq_,module,exports){
|
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
|
|
exports.__esModule = true;
|
|
|
|
@ -1205,7 +1213,7 @@ var _state = _dereq_("./state");
|
|
|
|
|
var _locutil = _dereq_("./locutil");
|
|
|
|
|
|
|
|
|
|
var Node = function Node(parser, pos, loc) {
|
|
|
|
|
_classCallCheck(this, Node);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.type = "";
|
|
|
|
|
this.start = pos;
|
|
|
|
@ -1279,11 +1287,11 @@ var defaultOptions = {
|
|
|
|
|
// `onTrailingComma` is similar to `onInsertedSemicolon`, but for
|
|
|
|
|
// trailing commas.
|
|
|
|
|
onTrailingComma: null,
|
|
|
|
|
// 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,
|
|
|
|
|
// By default, reserved words are only enforced if ecmaVersion >= 5.
|
|
|
|
|
// Set `allowReserved` to a boolean value to explicitly turn this on
|
|
|
|
|
// an off. When this option has the value "never", reserved words
|
|
|
|
|
// and keywords can also not be used as property names.
|
|
|
|
|
allowReserved: null,
|
|
|
|
|
// When enabled, a return at the top level is not considered an
|
|
|
|
|
// error.
|
|
|
|
|
allowReturnOutsideFunction: false,
|
|
|
|
@ -1300,9 +1308,9 @@ var defaultOptions = {
|
|
|
|
|
locations: true,
|
|
|
|
|
// A function can be passed as `onToken` option, which will
|
|
|
|
|
// cause Acorn to call that function with object in the same
|
|
|
|
|
// format as tokenize() returns. Note that you are not
|
|
|
|
|
// allowed to call the parser from the callback—that will
|
|
|
|
|
// corrupt its internal state.
|
|
|
|
|
// format as tokens returned from `tokenizer().getToken()`. Note
|
|
|
|
|
// that you are not allowed to call the parser from the
|
|
|
|
|
// callback—that will corrupt its internal state.
|
|
|
|
|
onToken: null,
|
|
|
|
|
// A function can be passed as `onComment` option, which will
|
|
|
|
|
// cause Acorn to call that function with `(block, text, start,
|
|
|
|
@ -1349,7 +1357,9 @@ function getOptions(opts) {
|
|
|
|
|
var options = {};
|
|
|
|
|
for (var opt in defaultOptions) {
|
|
|
|
|
options[opt] = opts && _util.has(opts, opt) ? opts[opt] : defaultOptions[opt];
|
|
|
|
|
}if (_util.isArray(options.onToken)) {
|
|
|
|
|
}if (options.allowReserved == null) options.allowReserved = options.ecmaVersion < 5;
|
|
|
|
|
|
|
|
|
|
if (_util.isArray(options.onToken)) {
|
|
|
|
|
(function () {
|
|
|
|
|
var tokens = options.onToken;
|
|
|
|
|
options.onToken = function (token) {
|
|
|
|
@ -1466,6 +1476,18 @@ pp.unexpected = function (pos) {
|
|
|
|
|
this.raise(pos != null ? pos : this.start, "Unexpected token");
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
pp.checkPatternErrors = function (refDestructuringErrors, andThrow) {
|
|
|
|
|
var pos = refDestructuringErrors && refDestructuringErrors.trailingComma;
|
|
|
|
|
if (!andThrow) return !!pos;
|
|
|
|
|
if (pos) this.raise(pos, "Trailing comma is not permitted in destructuring patterns");
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
pp.checkExpressionErrors = function (refDestructuringErrors, andThrow) {
|
|
|
|
|
var pos = refDestructuringErrors && refDestructuringErrors.shorthandAssign;
|
|
|
|
|
if (!andThrow) return !!pos;
|
|
|
|
|
if (pos) this.raise(pos, "Shorthand property assignments are valid only in destructuring patterns");
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
},{"./state":"/src\\state.js","./tokentype":"/src\\tokentype.js","./whitespace":"/src\\whitespace.js"}],"/src\\state.js":[function(_dereq_,module,exports){
|
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
|
@ -1485,19 +1507,31 @@ var _options = _dereq_("./options");
|
|
|
|
|
var plugins = {};
|
|
|
|
|
|
|
|
|
|
exports.plugins = plugins;
|
|
|
|
|
function keywordRegexp(words) {
|
|
|
|
|
return new RegExp("^(" + words.replace(/ /g, "|") + ")$");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var Parser = (function () {
|
|
|
|
|
function Parser(options, input, startPos) {
|
|
|
|
|
_classCallCheck(this, Parser);
|
|
|
|
|
|
|
|
|
|
this.options = _options.getOptions(options);
|
|
|
|
|
this.sourceFile = this.options.sourceFile;
|
|
|
|
|
this.isKeyword = _identifier.keywords[this.options.ecmaVersion >= 6 ? 6 : 5];
|
|
|
|
|
this.isReservedWord = _identifier.reservedWords[this.options.ecmaVersion];
|
|
|
|
|
|
|
|
|
|
this.options = options = _options.getOptions(options);
|
|
|
|
|
this.sourceFile = options.sourceFile;
|
|
|
|
|
this.keywords = keywordRegexp(_identifier.keywords[options.ecmaVersion >= 6 ? 6 : 5]);
|
|
|
|
|
var reserved = options.allowReserved ? "" : _identifier.reservedWords[options.ecmaVersion] + (options.sourceType == "module" ? " await" : "");
|
|
|
|
|
this.reservedWords = keywordRegexp(reserved);
|
|
|
|
|
var reservedStrict = (reserved ? reserved + " " : "") + _identifier.reservedWords.strict;
|
|
|
|
|
this.reservedWordsStrict = keywordRegexp(reservedStrict);
|
|
|
|
|
this.reservedWordsStrictBind = keywordRegexp(reservedStrict + " " + _identifier.reservedWords.strictBind);
|
|
|
|
|
this.input = String(input);
|
|
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
|
|
|
|
|
// Load plugins
|
|
|
|
|
this.loadPlugins(this.options.plugins);
|
|
|
|
|
this.loadPlugins(options.plugins);
|
|
|
|
|
|
|
|
|
|
// Set up token state
|
|
|
|
|
|
|
|
|
@ -1533,7 +1567,7 @@ var Parser = (function () {
|
|
|
|
|
this.exprAllowed = true;
|
|
|
|
|
|
|
|
|
|
// Figure out if it's a module code.
|
|
|
|
|
this.strict = this.inModule = this.options.sourceType === "module";
|
|
|
|
|
this.strict = this.inModule = options.sourceType === "module";
|
|
|
|
|
|
|
|
|
|
// Used to signify the start of a potential arrow function
|
|
|
|
|
this.potentialArrowAt = -1;
|
|
|
|
@ -1544,9 +1578,19 @@ var Parser = (function () {
|
|
|
|
|
this.labels = [];
|
|
|
|
|
|
|
|
|
|
// If enabled, skip leading hashbang line.
|
|
|
|
|
if (this.pos === 0 && this.options.allowHashBang && this.input.slice(0, 2) === "#!") this.skipLineComment(2);
|
|
|
|
|
if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!") this.skipLineComment(2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// DEPRECATED Kept for backwards compatibility until 3.0 in case a plugin uses them
|
|
|
|
|
|
|
|
|
|
Parser.prototype.isKeyword = function isKeyword(word) {
|
|
|
|
|
return this.keywords.test(word);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Parser.prototype.isReservedWord = function isReservedWord(word) {
|
|
|
|
|
return this.reservedWords.test(word);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Parser.prototype.extend = function extend(name, f) {
|
|
|
|
|
this[name] = f(this[name]);
|
|
|
|
|
};
|
|
|
|
@ -1665,7 +1709,7 @@ pp.parseStatement = function (declaration, topLevel) {
|
|
|
|
|
case _tokentype.types._import:
|
|
|
|
|
if (!this.options.allowImportExportEverywhere) {
|
|
|
|
|
if (!topLevel) this.raise(this.start, "'import' and 'export' may only appear at the top level");
|
|
|
|
|
if (!this.inModule) this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'");
|
|
|
|
|
// if (!this.inModule) this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'");
|
|
|
|
|
}
|
|
|
|
|
return starttype === _tokentype.types._import ? this.parseImport(node) : this.parseExport(node);
|
|
|
|
|
|
|
|
|
@ -1741,14 +1785,15 @@ pp.parseForStatement = function (node) {
|
|
|
|
|
if ((this.type === _tokentype.types._in || this.options.ecmaVersion >= 6 && this.isContextual("of")) && _init.declarations.length === 1 && !(varKind !== _tokentype.types._var && _init.declarations[0].init)) return this.parseForIn(node, _init);
|
|
|
|
|
return this.parseFor(node, _init);
|
|
|
|
|
}
|
|
|
|
|
var refShorthandDefaultPos = { start: 0 };
|
|
|
|
|
var init = this.parseExpression(true, refShorthandDefaultPos);
|
|
|
|
|
var refDestructuringErrors = { shorthandAssign: 0, trailingComma: 0 };
|
|
|
|
|
var init = this.parseExpression(true, refDestructuringErrors);
|
|
|
|
|
if (this.type === _tokentype.types._in || this.options.ecmaVersion >= 6 && this.isContextual("of")) {
|
|
|
|
|
this.checkPatternErrors(refDestructuringErrors, true);
|
|
|
|
|
this.toAssignable(init);
|
|
|
|
|
this.checkLVal(init);
|
|
|
|
|
return this.parseForIn(node, init);
|
|
|
|
|
} else if (refShorthandDefaultPos.start) {
|
|
|
|
|
this.unexpected(refShorthandDefaultPos.start);
|
|
|
|
|
} else {
|
|
|
|
|
this.checkExpressionErrors(refDestructuringErrors, true);
|
|
|
|
|
}
|
|
|
|
|
return this.parseFor(node, init);
|
|
|
|
|
};
|
|
|
|
@ -1840,11 +1885,9 @@ pp.parseTryStatement = function (node) {
|
|
|
|
|
clause.param = this.parseBindingAtom();
|
|
|
|
|
this.checkLVal(clause.param, true);
|
|
|
|
|
this.expect(_tokentype.types.parenR);
|
|
|
|
|
clause.guard = null;
|
|
|
|
|
clause.body = this.parseBlock();
|
|
|
|
|
node.handler = this.finishNode(clause, "CatchClause");
|
|
|
|
|
}
|
|
|
|
|
node.guardedHandlers = empty;
|
|
|
|
|
node.finalizer = this.eat(_tokentype.types._finally) ? this.parseBlock() : null;
|
|
|
|
|
if (!node.handler && !node.finalizer) this.raise(node.start, "Missing catch or finally clause");
|
|
|
|
|
return this.finishNode(node, "TryStatement");
|
|
|
|
@ -1998,7 +2041,7 @@ pp.parseFunction = function (node, isStatement, allowExpressionBody) {
|
|
|
|
|
|
|
|
|
|
pp.parseFunctionParams = function (node) {
|
|
|
|
|
this.expect(_tokentype.types.parenL);
|
|
|
|
|
node.params = this.parseBindingList(_tokentype.types.parenR, false, false);
|
|
|
|
|
node.params = this.parseBindingList(_tokentype.types.parenR, false, false, true);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Parse a class declaration or literal (depending on the
|
|
|
|
@ -2049,6 +2092,7 @@ pp.parseClass = function (node, isStatement) {
|
|
|
|
|
var start = method.value.start;
|
|
|
|
|
if (method.kind === "get") this.raise(start, "getter should have no params");else this.raise(start, "setter should have exactly one param");
|
|
|
|
|
}
|
|
|
|
|
if (method.kind === "set" && method.value.params[0].type === "RestElement") this.raise(method.value.params[0].start, "Setter cannot use rest params");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
node.body = this.finishNode(classBody, "ClassBody");
|
|
|
|
@ -2105,6 +2149,13 @@ pp.parseExport = function (node) {
|
|
|
|
|
if (this.eatContextual("from")) {
|
|
|
|
|
node.source = this.type === _tokentype.types.string ? this.parseExprAtom() : this.unexpected();
|
|
|
|
|
} else {
|
|
|
|
|
// check for keywords used as local names
|
|
|
|
|
for (var i = 0; i < node.specifiers.length; i++) {
|
|
|
|
|
if (this.keywords.test(node.specifiers[i].local.name) || this.reservedWords.test(node.specifiers[i].local.name)) {
|
|
|
|
|
this.unexpected(node.specifiers[i].local.start);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
node.source = null;
|
|
|
|
|
}
|
|
|
|
|
this.semicolon();
|
|
|
|
@ -2145,7 +2196,6 @@ pp.parseImport = function (node) {
|
|
|
|
|
if (this.type === _tokentype.types.string) {
|
|
|
|
|
node.specifiers = empty;
|
|
|
|
|
node.source = this.parseExprAtom();
|
|
|
|
|
node.kind = "";
|
|
|
|
|
} else {
|
|
|
|
|
node.specifiers = this.parseImportSpecifiers();
|
|
|
|
|
this.expectContextual("from");
|
|
|
|
@ -2186,7 +2236,13 @@ pp.parseImportSpecifiers = function () {
|
|
|
|
|
|
|
|
|
|
var node = this.startNode();
|
|
|
|
|
node.imported = this.parseIdent(true);
|
|
|
|
|
node.local = this.eatContextual("as") ? this.parseIdent() : node.imported;
|
|
|
|
|
if (this.eatContextual("as")) {
|
|
|
|
|
node.local = this.parseIdent();
|
|
|
|
|
} else {
|
|
|
|
|
node.local = node.imported;
|
|
|
|
|
if (this.isKeyword(node.local.name)) this.unexpected(node.local.start);
|
|
|
|
|
if (this.reservedWordsStrict.test(node.local.name)) this.raise(node.local.start, "The keyword '" + node.local.name + "' is reserved");
|
|
|
|
|
}
|
|
|
|
|
this.checkLVal(node.local, true);
|
|
|
|
|
nodes.push(this.finishNode(node, "ImportSpecifier"));
|
|
|
|
|
}
|
|
|
|
@ -2211,7 +2267,7 @@ var _tokentype = _dereq_("./tokentype");
|
|
|
|
|
var _whitespace = _dereq_("./whitespace");
|
|
|
|
|
|
|
|
|
|
var TokContext = function TokContext(token, isExpr, preserveSpace, override) {
|
|
|
|
|
_classCallCheck(this, TokContext);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.token = token;
|
|
|
|
|
this.isExpr = !!isExpr;
|
|
|
|
@ -2326,7 +2382,7 @@ var _whitespace = _dereq_("./whitespace");
|
|
|
|
|
// used for the onToken callback and the external tokenizer.
|
|
|
|
|
|
|
|
|
|
var Token = function Token(p) {
|
|
|
|
|
_classCallCheck(this, Token);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.type = p.type;
|
|
|
|
|
this.value = p.value;
|
|
|
|
@ -2720,13 +2776,13 @@ pp.finishOp = function (type, size) {
|
|
|
|
|
// Parse a regular expression. Some context-awareness is necessary,
|
|
|
|
|
// since a '/' inside a '[]' set does not end the expression.
|
|
|
|
|
|
|
|
|
|
function tryCreateRegexp(src, flags, throwErrorAt) {
|
|
|
|
|
function tryCreateRegexp(src, flags, throwErrorAt, parser) {
|
|
|
|
|
try {
|
|
|
|
|
return new RegExp(src, flags);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
if (throwErrorAt !== undefined) {
|
|
|
|
|
if (e instanceof SyntaxError) this.raise(throwErrorAt, "Error parsing regular expression: " + e.message);
|
|
|
|
|
this.raise(e);
|
|
|
|
|
if (e instanceof SyntaxError) parser.raise(throwErrorAt, "Error parsing regular expression: " + e.message);
|
|
|
|
|
throw e;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -2756,8 +2812,8 @@ pp.readRegexp = function () {
|
|
|
|
|
var mods = this.readWord1();
|
|
|
|
|
var tmp = content;
|
|
|
|
|
if (mods) {
|
|
|
|
|
var validFlags = /^[gmsiy]*$/;
|
|
|
|
|
if (this.options.ecmaVersion >= 6) validFlags = /^[gmsiyu]*$/;
|
|
|
|
|
var validFlags = /^[gim]*$/;
|
|
|
|
|
if (this.options.ecmaVersion >= 6) validFlags = /^[gimuy]*$/;
|
|
|
|
|
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
|
|
|
|
@ -2768,7 +2824,7 @@ pp.readRegexp = function () {
|
|
|
|
|
// 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, function (match, code, offset) {
|
|
|
|
|
tmp = tmp.replace(/\\u\{([0-9a-fA-F]+)\}/g, function (_match, code, offset) {
|
|
|
|
|
code = Number("0x" + code);
|
|
|
|
|
if (code > 0x10FFFF) _this.raise(start + offset + 3, "Code point out of bounds");
|
|
|
|
|
return "x";
|
|
|
|
@ -2781,7 +2837,7 @@ pp.readRegexp = function () {
|
|
|
|
|
// 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(tmp, undefined, start);
|
|
|
|
|
tryCreateRegexp(tmp, undefined, start, this);
|
|
|
|
|
// 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(content, mods);
|
|
|
|
@ -2985,7 +3041,7 @@ pp.readEscapedChar = function (inTemplate) {
|
|
|
|
|
octalStr = octalStr.slice(0, -1);
|
|
|
|
|
octal = parseInt(octalStr, 8);
|
|
|
|
|
}
|
|
|
|
|
if (octal > 0 && (this.strict || inTemplate)) {
|
|
|
|
|
if (octalStr !== "0" && (this.strict || inTemplate)) {
|
|
|
|
|
this.raise(this.pos - 2, "Octal literal in strict mode");
|
|
|
|
|
}
|
|
|
|
|
this.pos += octalStr.length - 1;
|
|
|
|
@ -3004,20 +3060,14 @@ pp.readHexChar = function (len) {
|
|
|
|
|
return n;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 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.
|
|
|
|
|
|
|
|
|
|
var containsEsc;
|
|
|
|
|
|
|
|
|
|
// Read an identifier, and return it as a string. Sets `containsEsc`
|
|
|
|
|
// Read an identifier, and return it as a string. Sets `this.containsEsc`
|
|
|
|
|
// to whether the word contained a '\u' escape.
|
|
|
|
|
//
|
|
|
|
|
// Incrementally adds only escaped chars, adding other chunks as-is
|
|
|
|
|
// as a micro-optimization.
|
|
|
|
|
|
|
|
|
|
pp.readWord1 = function () {
|
|
|
|
|
containsEsc = false;
|
|
|
|
|
this.containsEsc = false;
|
|
|
|
|
var word = "",
|
|
|
|
|
first = true,
|
|
|
|
|
chunkStart = this.pos;
|
|
|
|
@ -3028,7 +3078,7 @@ pp.readWord1 = function () {
|
|
|
|
|
this.pos += ch <= 0xffff ? 1 : 2;
|
|
|
|
|
} else if (ch === 92) {
|
|
|
|
|
// "\"
|
|
|
|
|
containsEsc = true;
|
|
|
|
|
this.containsEsc = true;
|
|
|
|
|
word += this.input.slice(chunkStart, this.pos);
|
|
|
|
|
var escStart = this.pos;
|
|
|
|
|
if (this.input.charCodeAt(++this.pos) != 117) // "u"
|
|
|
|
@ -3052,7 +3102,7 @@ pp.readWord1 = function () {
|
|
|
|
|
pp.readWord = function () {
|
|
|
|
|
var word = this.readWord1();
|
|
|
|
|
var type = _tokentype.types.name;
|
|
|
|
|
if ((this.options.ecmaVersion >= 6 || !containsEsc) && this.isKeyword(word)) type = _tokentype.keywords[word];
|
|
|
|
|
if ((this.options.ecmaVersion >= 6 || !this.containsEsc) && this.keywords.test(word)) type = _tokentype.keywords[word];
|
|
|
|
|
return this.finishToken(type, word);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -3071,6 +3121,11 @@ pp.readWord = function () {
|
|
|
|
|
// be followed by an expression (thus, a slash after them would be a
|
|
|
|
|
// regular expression).
|
|
|
|
|
//
|
|
|
|
|
// The `startsExpr` property is used to check if the token ends a
|
|
|
|
|
// `yield` expression. It is set on all token types that either can
|
|
|
|
|
// directly start an expression (like a quotation mark) or can
|
|
|
|
|
// continue an expression (like the body of a string).
|
|
|
|
|
//
|
|
|
|
|
// `isLoop` marks a keyword as starting a loop, which is important
|
|
|
|
|
// to know when parsing a label, in order to allow or disallow
|
|
|
|
|
// continue jumps to that label.
|
|
|
|
@ -3084,7 +3139,6 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
|
|
|
|
|
var TokenType = function TokenType(label) {
|
|
|
|
|
var conf = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
|
|
|
|
|
|
|
|
|
|
_classCallCheck(this, TokenType);
|
|
|
|
|
|
|
|
|
|
this.label = label;
|
|
|
|
|
this.keyword = conf.keyword;
|
|
|
|
@ -3183,7 +3237,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 });
|
|
|
|
@ -3255,5 +3309,4 @@ exports.nonASCIIwhitespace = nonASCIIwhitespace;
|
|
|
|
|
|
|
|
|
|
},{}]},{},["/src\\index.js"])("/src\\index.js")
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
})
|
|
|
|
|
});
|