217 lines
6.4 KiB
JavaScript
217 lines
6.4 KiB
JavaScript
/* */
|
|
"format cjs";
|
|
"use strict";
|
|
|
|
var _babelToolsProtectJs2 = require("./../../babel/tools/protect.js");
|
|
|
|
var _babelToolsProtectJs3 = _interopRequireDefault(_babelToolsProtectJs2);
|
|
|
|
var _tokentype = require("./tokentype");
|
|
|
|
var _state = require("./state");
|
|
|
|
var _identifier = require("./identifier");
|
|
|
|
var _util = require("./util");
|
|
|
|
_babelToolsProtectJs3["default"](module);
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
|
|
|
var pp = _state.Parser.prototype;
|
|
|
|
// Convert existing expression atom to assignable pattern
|
|
// if possible.
|
|
|
|
pp.toAssignable = function (node, isBinding) {
|
|
if (this.options.ecmaVersion >= 6 && node) {
|
|
switch (node.type) {
|
|
case "Identifier":
|
|
case "ObjectPattern":
|
|
case "ArrayPattern":
|
|
case "AssignmentPattern":
|
|
break;
|
|
|
|
case "ObjectExpression":
|
|
node.type = "ObjectPattern";
|
|
for (var i = 0; i < node.properties.length; i++) {
|
|
var prop = node.properties[i];
|
|
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);
|
|
}
|
|
break;
|
|
|
|
case "ArrayExpression":
|
|
node.type = "ArrayPattern";
|
|
this.toAssignableList(node.elements, isBinding);
|
|
break;
|
|
|
|
case "AssignmentExpression":
|
|
if (node.operator === "=") {
|
|
node.type = "AssignmentPattern";
|
|
delete node.operator;
|
|
} else {
|
|
this.raise(node.left.end, "Only '=' operator can be used for specifying default value.");
|
|
}
|
|
break;
|
|
|
|
case "MemberExpression":
|
|
if (!isBinding) break;
|
|
|
|
default:
|
|
this.raise(node.start, "Assigning to rvalue");
|
|
}
|
|
}
|
|
return node;
|
|
};
|
|
|
|
// Convert list of expression atoms to binding list.
|
|
|
|
pp.toAssignableList = function (exprList, isBinding) {
|
|
var end = exprList.length;
|
|
if (end) {
|
|
var last = exprList[end - 1];
|
|
if (last && last.type == "RestElement") {
|
|
--end;
|
|
} else if (last && last.type == "SpreadElement") {
|
|
last.type = "RestElement";
|
|
var arg = last.argument;
|
|
this.toAssignable(arg, isBinding);
|
|
if (arg.type !== "Identifier" && arg.type !== "MemberExpression" && arg.type !== "ArrayPattern") this.unexpected(arg.start);
|
|
--end;
|
|
}
|
|
}
|
|
for (var i = 0; i < end; i++) {
|
|
var elt = exprList[i];
|
|
if (elt) this.toAssignable(elt, isBinding);
|
|
}
|
|
return exprList;
|
|
};
|
|
|
|
// Parses spread element.
|
|
|
|
pp.parseSpread = function (refShorthandDefaultPos) {
|
|
var node = this.startNode();
|
|
this.next();
|
|
node.argument = this.parseMaybeAssign(refShorthandDefaultPos);
|
|
return this.finishNode(node, "SpreadElement");
|
|
};
|
|
|
|
pp.parseRest = function () {
|
|
var node = this.startNode();
|
|
this.next();
|
|
node.argument = this.type === _tokentype.types.name || this.type === _tokentype.types.bracketL ? this.parseBindingAtom() : this.unexpected();
|
|
return this.finishNode(node, "RestElement");
|
|
};
|
|
|
|
// Parses lvalue (assignable) atom.
|
|
|
|
pp.parseBindingAtom = function () {
|
|
if (this.options.ecmaVersion < 6) return this.parseIdent();
|
|
switch (this.type) {
|
|
case _tokentype.types.name:
|
|
return this.parseIdent();
|
|
|
|
case _tokentype.types.bracketL:
|
|
var node = this.startNode();
|
|
this.next();
|
|
node.elements = this.parseBindingList(_tokentype.types.bracketR, true, true);
|
|
return this.finishNode(node, "ArrayPattern");
|
|
|
|
case _tokentype.types.braceL:
|
|
return this.parseObj(true);
|
|
|
|
default:
|
|
this.unexpected();
|
|
}
|
|
};
|
|
|
|
pp.parseBindingList = function (close, allowEmpty, allowTrailingComma) {
|
|
var elts = [],
|
|
first = true;
|
|
while (!this.eat(close)) {
|
|
if (first) first = false;else this.expect(_tokentype.types.comma);
|
|
if (allowEmpty && this.type === _tokentype.types.comma) {
|
|
elts.push(null);
|
|
} else if (allowTrailingComma && this.afterTrailingComma(close)) {
|
|
break;
|
|
} else if (this.type === _tokentype.types.ellipsis) {
|
|
elts.push(this.parseAssignableListItemTypes(this.parseRest()));
|
|
this.expect(close);
|
|
break;
|
|
} else {
|
|
var left = this.parseMaybeDefault();
|
|
this.parseAssignableListItemTypes(left);
|
|
elts.push(this.parseMaybeDefault(null, left));
|
|
}
|
|
}
|
|
return elts;
|
|
};
|
|
|
|
pp.parseAssignableListItemTypes = function (param) {
|
|
return param;
|
|
};
|
|
|
|
// Parses assignment pattern around given atom if possible.
|
|
|
|
pp.parseMaybeDefault = function (startPos, left) {
|
|
startPos = startPos || this.markPosition();
|
|
left = left || this.parseBindingAtom();
|
|
if (!this.eat(_tokentype.types.eq)) return left;
|
|
var node = this.startNodeAt(startPos);
|
|
node.operator = "=";
|
|
node.left = left;
|
|
node.right = this.parseMaybeAssign();
|
|
return this.finishNode(node, "AssignmentPattern");
|
|
};
|
|
|
|
// Verify that a node is an lval — something that can be assigned
|
|
// to.
|
|
|
|
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 (checkClashes) {
|
|
if (_util.has(checkClashes, expr.name)) this.raise(expr.start, "Argument name clash in strict mode");
|
|
checkClashes[expr.name] = true;
|
|
}
|
|
break;
|
|
|
|
case "MemberExpression":
|
|
if (isBinding) this.raise(expr.start, (isBinding ? "Binding" : "Assigning to") + " member expression");
|
|
break;
|
|
|
|
case "ObjectPattern":
|
|
for (var i = 0; i < expr.properties.length; i++) {
|
|
var prop = expr.properties[i];
|
|
if (prop.type === "Property") prop = prop.value;
|
|
this.checkLVal(prop, isBinding, checkClashes);
|
|
}
|
|
break;
|
|
|
|
case "ArrayPattern":
|
|
for (var i = 0; i < expr.elements.length; i++) {
|
|
var elem = expr.elements[i];
|
|
if (elem) this.checkLVal(elem, isBinding, checkClashes);
|
|
}
|
|
break;
|
|
|
|
case "AssignmentPattern":
|
|
this.checkLVal(expr.left, isBinding, checkClashes);
|
|
break;
|
|
|
|
case "SpreadProperty":
|
|
case "RestElement":
|
|
this.checkLVal(expr.argument, isBinding, checkClashes);
|
|
break;
|
|
|
|
case "ParenthesizedExpression":
|
|
this.checkLVal(expr.expression, isBinding, checkClashes);
|
|
break;
|
|
|
|
default:
|
|
this.raise(expr.start, (isBinding ? "Binding" : "Assigning to") + " rvalue");
|
|
}
|
|
}; |