react-scripts
Version:
Configuration and scripts for Create React App.
337 lines (281 loc) • 9.63 kB
JavaScript
"use strict";
var _getIterator2 = require("babel-runtime/core-js/get-iterator");
var _getIterator3 = _interopRequireDefault(_getIterator2);
var _types = require("../tokenizer/types");
var _index = require("./index");
var _index2 = _interopRequireDefault(_index);
var _identifier = require("../util/identifier");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var pp = _index2.default.prototype;
// Convert existing expression atom to assignable pattern
// if possible.
/* eslint indent: 0 */
pp.toAssignable = function (node, isBinding) {
if (node) {
switch (node.type) {
case "Identifier":
case "ObjectPattern":
case "ArrayPattern":
case "AssignmentPattern":
break;
case "ObjectExpression":
node.type = "ObjectPattern";
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = (0, _getIterator3.default)(node.properties), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var prop = _step.value;
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");
}
} else {
this.toAssignable(prop, isBinding);
}
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
break;
case "ObjectProperty":
this.toAssignable(node.value, isBinding);
break;
case "SpreadProperty":
node.type = "RestProperty";
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;
};
// Convert list of expression atoms to a list of
pp.toReferencedList = function (exprList) {
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.parseBindingIdentifier();
return this.finishNode(node, "RestElement");
};
pp.shouldAllowYieldIdentifier = function () {
return this.match(_types.types._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 _types.types._yield:
if (this.state.strict || this.state.inGenerator) this.unexpected();
// fall-through
case _types.types.name:
return this.parseIdentifier(true);
case _types.types.bracketL:
var node = this.startNode();
this.next();
node.elements = this.parseBindingList(_types.types.bracketR, true);
return this.finishNode(node, "ArrayPattern");
case _types.types.braceL:
return this.parseObj(true);
default:
this.unexpected();
}
};
pp.parseBindingList = function (close, allowEmpty) {
var elts = [];
var first = true;
while (!this.eat(close)) {
if (first) {
first = false;
} else {
this.expect(_types.types.comma);
}
if (allowEmpty && this.match(_types.types.comma)) {
elts.push(null);
} else if (this.eat(close)) {
break;
} else if (this.match(_types.types.ellipsis)) {
elts.push(this.parseAssignableListItemTypes(this.parseRest()));
this.expect(close);
break;
} else {
var decorators = [];
while (this.match(_types.types.at)) {
decorators.push(this.parseDecorator());
}
var left = this.parseMaybeDefault();
if (decorators.length) {
left.decorators = decorators;
}
this.parseAssignableListItemTypes(left);
elts.push(this.parseMaybeDefault(left.start, left.loc.start, left));
}
}
return elts;
};
pp.parseAssignableListItemTypes = function (param) {
return param;
};
// Parses assignment pattern around given atom if possible.
pp.parseMaybeDefault = function (startPos, startLoc, left) {
startLoc = startLoc || this.state.startLoc;
startPos = startPos || this.state.start;
left = left || this.parseBindingAtom();
if (!this.eat(_types.types.eq)) return left;
var node = this.startNodeAt(startPos, startLoc);
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.state.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) {
// we need to prefix this with an underscore for the cases where we have a key of
// `__proto__`. there's a bug in old V8 where the following wouldn't work:
//
// > var obj = Object.create(null);
// undefined
// > obj.__proto__
// null
// > obj.__proto__ = true;
// true
// > obj.__proto__
// null
var key = "_" + expr.name;
if (checkClashes[key]) {
this.raise(expr.start, "Argument name clash in strict mode");
} else {
checkClashes[key] = true;
}
}
break;
case "MemberExpression":
if (isBinding) this.raise(expr.start, (isBinding ? "Binding" : "Assigning to") + " member expression");
break;
case "ObjectPattern":
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = (0, _getIterator3.default)(expr.properties), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var prop = _step2.value;
if (prop.type === "ObjectProperty") prop = prop.value;
this.checkLVal(prop, isBinding, checkClashes);
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
break;
case "ArrayPattern":
var _iteratorNormalCompletion3 = true;
var _didIteratorError3 = false;
var _iteratorError3 = undefined;
try {
for (var _iterator3 = (0, _getIterator3.default)(expr.elements), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
var elem = _step3.value;
if (elem) this.checkLVal(elem, isBinding, checkClashes);
}
} catch (err) {
_didIteratorError3 = true;
_iteratorError3 = err;
} finally {
try {
if (!_iteratorNormalCompletion3 && _iterator3.return) {
_iterator3.return();
}
} finally {
if (_didIteratorError3) {
throw _iteratorError3;
}
}
}
break;
case "AssignmentPattern":
this.checkLVal(expr.left, isBinding, checkClashes);
break;
case "RestProperty":
case "RestElement":
this.checkLVal(expr.argument, isBinding, checkClashes);
break;
default:
this.raise(expr.start, (isBinding ? "Binding" : "Assigning to") + " rvalue");
}
};