diff options
Diffstat (limited to 'node_modules/babylon/lib/parser/lval.js')
-rw-r--r-- | node_modules/babylon/lib/parser/lval.js | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/node_modules/babylon/lib/parser/lval.js b/node_modules/babylon/lib/parser/lval.js new file mode 100644 index 000000000..1bdbfa1f0 --- /dev/null +++ b/node_modules/babylon/lib/parser/lval.js @@ -0,0 +1,315 @@ +"use strict"; + +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, contextDescription) { + if (node) { + switch (node.type) { + case "Identifier": + case "ObjectPattern": + case "ArrayPattern": + case "AssignmentPattern": + break; + + case "ObjectExpression": + node.type = "ObjectPattern"; + for (var _iterator = node.properties, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var prop = _ref; + + 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, "object destructuring pattern"); + } + } + break; + + case "ObjectProperty": + this.toAssignable(node.value, isBinding, contextDescription); + break; + + case "SpreadProperty": + node.type = "RestProperty"; + break; + + case "ArrayExpression": + node.type = "ArrayPattern"; + this.toAssignableList(node.elements, isBinding, contextDescription); + 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: + { + var message = "Invalid left-hand side" + (contextDescription ? " in " + contextDescription : /* istanbul ignore next */"expression"); + this.raise(node.start, message); + } + } + } + return node; +}; + +// Convert list of expression atoms to binding list. + +pp.toAssignableList = function (exprList, isBinding, contextDescription) { + 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, contextDescription); + 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, contextDescription); + } + 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(false, 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, contextDescription) { + 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": + for (var _iterator2 = expr.properties, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var prop = _ref2; + + if (prop.type === "ObjectProperty") prop = prop.value; + this.checkLVal(prop, isBinding, checkClashes, "object destructuring pattern"); + } + break; + + case "ArrayPattern": + for (var _iterator3 = expr.elements, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) { + var _ref3; + + if (_isArray3) { + if (_i3 >= _iterator3.length) break; + _ref3 = _iterator3[_i3++]; + } else { + _i3 = _iterator3.next(); + if (_i3.done) break; + _ref3 = _i3.value; + } + + var elem = _ref3; + + if (elem) this.checkLVal(elem, isBinding, checkClashes, "array destructuring pattern"); + } + break; + + case "AssignmentPattern": + this.checkLVal(expr.left, isBinding, checkClashes, "assignment pattern"); + break; + + case "RestProperty": + this.checkLVal(expr.argument, isBinding, checkClashes, "rest property"); + break; + + case "RestElement": + this.checkLVal(expr.argument, isBinding, checkClashes, "rest element"); + break; + + default: + { + var message = (isBinding ? /* istanbul ignore next */"Binding invalid" : "Invalid") + " left-hand side" + (contextDescription ? " in " + contextDescription : /* istanbul ignore next */"expression"); + this.raise(expr.start, message); + } + } +};
\ No newline at end of file |