@agoric/babel-parser
Version:
A JavaScript parser
362 lines (281 loc) • 10.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _types = require("../tokenizer/types");
var _identifier = require("../util/identifier");
var _node = require("./node");
var _scopeflags = require("../util/scopeflags");
var _util = require("./util");
var _location = require("./location");
const unwrapParenthesizedExpression = node => {
return node.type === "ParenthesizedExpression" ? unwrapParenthesizedExpression(node.expression) : node;
};
class LValParser extends _node.NodeUtils {
toAssignable(node) {
var _node$extra, _node$extra3;
let parenthesized = undefined;
if (node.type === "ParenthesizedExpression" || ((_node$extra = node.extra) == null ? void 0 : _node$extra.parenthesized)) {
parenthesized = unwrapParenthesizedExpression(node);
if (parenthesized.type !== "Identifier" && parenthesized.type !== "MemberExpression") {
this.raise(node.start, _location.Errors.InvalidParenthesizedAssignment);
}
}
switch (node.type) {
case "Identifier":
case "ObjectPattern":
case "ArrayPattern":
case "AssignmentPattern":
break;
case "ObjectExpression":
node.type = "ObjectPattern";
for (let i = 0, length = node.properties.length, last = length - 1; i < length; i++) {
var _node$extra2;
const prop = node.properties[i];
const isLast = i === last;
this.toAssignableObjectExpressionProp(prop, isLast);
if (isLast && prop.type === "RestElement" && ((_node$extra2 = node.extra) == null ? void 0 : _node$extra2.trailingComma)) {
this.raiseRestNotLast(node.extra.trailingComma);
}
}
break;
case "ObjectProperty":
this.toAssignable(node.value);
break;
case "SpreadElement":
{
this.checkToRestConversion(node);
node.type = "RestElement";
const arg = node.argument;
this.toAssignable(arg);
break;
}
case "ArrayExpression":
node.type = "ArrayPattern";
this.toAssignableList(node.elements, (_node$extra3 = node.extra) == null ? void 0 : _node$extra3.trailingComma);
break;
case "AssignmentExpression":
if (node.operator !== "=") {
this.raise(node.left.end, _location.Errors.MissingEqInAssignment);
}
node.type = "AssignmentPattern";
delete node.operator;
this.toAssignable(node.left);
break;
case "ParenthesizedExpression":
this.toAssignable(parenthesized);
break;
default:
}
return node;
}
toAssignableObjectExpressionProp(prop, isLast) {
if (prop.type === "ObjectMethod") {
const error = prop.kind === "get" || prop.kind === "set" ? _location.Errors.PatternHasAccessor : _location.Errors.PatternHasMethod;
this.raise(prop.key.start, error);
} else if (prop.type === "SpreadElement" && !isLast) {
this.raiseRestNotLast(prop.start);
} else {
this.toAssignable(prop);
}
}
toAssignableList(exprList, trailingCommaPos) {
let end = exprList.length;
if (end) {
const last = exprList[end - 1];
if (last && last.type === "RestElement") {
--end;
} else if (last && last.type === "SpreadElement") {
last.type = "RestElement";
const arg = last.argument;
this.toAssignable(arg);
if (arg.type !== "Identifier" && arg.type !== "MemberExpression" && arg.type !== "ArrayPattern" && arg.type !== "ObjectPattern") {
this.unexpected(arg.start);
}
if (trailingCommaPos) {
this.raiseTrailingCommaAfterRest(trailingCommaPos);
}
--end;
}
}
for (let i = 0; i < end; i++) {
const elt = exprList[i];
if (elt) {
this.toAssignable(elt);
if (elt.type === "RestElement") {
this.raiseRestNotLast(elt.start);
}
}
}
return exprList;
}
toReferencedList(exprList, isParenthesizedExpr) {
return exprList;
}
toReferencedListDeep(exprList, isParenthesizedExpr) {
this.toReferencedList(exprList, isParenthesizedExpr);
for (let _i = 0; _i < exprList.length; _i++) {
const expr = exprList[_i];
if (expr && expr.type === "ArrayExpression") {
this.toReferencedListDeep(expr.elements);
}
}
}
parseSpread(refExpressionErrors, refNeedsArrowPos) {
const node = this.startNode();
this.next();
node.argument = this.parseMaybeAssign(false, refExpressionErrors, undefined, refNeedsArrowPos);
return this.finishNode(node, "SpreadElement");
}
parseRestBinding() {
const node = this.startNode();
this.next();
node.argument = this.parseBindingAtom();
return this.finishNode(node, "RestElement");
}
parseBindingAtom() {
switch (this.state.type) {
case _types.types.bracketL:
{
const node = this.startNode();
this.next();
node.elements = this.parseBindingList(_types.types.bracketR, 93, true);
return this.finishNode(node, "ArrayPattern");
}
case _types.types.braceL:
return this.parseObj(_types.types.braceR, true);
}
return this.parseIdentifier();
}
parseBindingList(close, closeCharCode, allowEmpty, allowModifiers) {
const elts = [];
let 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.parseRestBinding()));
this.checkCommaAfterRest(closeCharCode);
this.expect(close);
break;
} else {
const decorators = [];
if (this.match(_types.types.at) && this.hasPlugin("decorators")) {
this.raise(this.state.start, _location.Errors.UnsupportedParameterDecorator);
}
while (this.match(_types.types.at)) {
decorators.push(this.parseDecorator());
}
elts.push(this.parseAssignableListItem(allowModifiers, decorators));
}
}
return elts;
}
parseAssignableListItem(allowModifiers, decorators) {
const left = this.parseMaybeDefault();
this.parseAssignableListItemTypes(left);
const elt = this.parseMaybeDefault(left.start, left.loc.start, left);
if (decorators.length) {
left.decorators = decorators;
}
return elt;
}
parseAssignableListItemTypes(param) {
return param;
}
parseMaybeDefault(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;
const node = this.startNodeAt(startPos, startLoc);
node.left = left;
node.right = this.parseMaybeAssign();
return this.finishNode(node, "AssignmentPattern");
}
checkLVal(expr, bindingType = _scopeflags.BIND_NONE, checkClashes, contextDescription, disallowLetBinding, strictModeChanged = false) {
switch (expr.type) {
case "Identifier":
if (this.state.strict && (strictModeChanged ? (0, _identifier.isStrictBindReservedWord)(expr.name, this.inModule) : (0, _identifier.isStrictBindOnlyReservedWord)(expr.name))) {
this.raise(expr.start, bindingType === _scopeflags.BIND_NONE ? _location.Errors.StrictEvalArguments : _location.Errors.StrictEvalArgumentsBinding, expr.name);
}
if (checkClashes) {
const key = `_${expr.name}`;
if (checkClashes[key]) {
this.raise(expr.start, _location.Errors.ParamDupe);
} else {
checkClashes[key] = true;
}
}
if (disallowLetBinding && expr.name === "let") {
this.raise(expr.start, _location.Errors.LetInLexicalBinding);
}
if (!(bindingType & _scopeflags.BIND_NONE)) {
this.scope.declareName(expr.name, bindingType, expr.start);
}
break;
case "MemberExpression":
if (bindingType !== _scopeflags.BIND_NONE) {
this.raise(expr.start, _location.Errors.InvalidPropertyBindingPattern);
}
break;
case "ObjectPattern":
for (let _i2 = 0, _expr$properties = expr.properties; _i2 < _expr$properties.length; _i2++) {
let prop = _expr$properties[_i2];
if (prop.type === "ObjectProperty") prop = prop.value;else if (prop.type === "ObjectMethod") continue;
this.checkLVal(prop, bindingType, checkClashes, "object destructuring pattern", disallowLetBinding);
}
break;
case "ArrayPattern":
for (let _i3 = 0, _expr$elements = expr.elements; _i3 < _expr$elements.length; _i3++) {
const elem = _expr$elements[_i3];
if (elem) {
this.checkLVal(elem, bindingType, checkClashes, "array destructuring pattern", disallowLetBinding);
}
}
break;
case "AssignmentPattern":
this.checkLVal(expr.left, bindingType, checkClashes, "assignment pattern");
break;
case "RestElement":
this.checkLVal(expr.argument, bindingType, checkClashes, "rest element");
break;
case "ParenthesizedExpression":
this.checkLVal(expr.expression, bindingType, checkClashes, "parenthesized expression");
break;
default:
{
this.raise(expr.start, bindingType === _scopeflags.BIND_NONE ? _location.Errors.InvalidLhs : _location.Errors.InvalidLhsBinding, contextDescription);
}
}
}
checkToRestConversion(node) {
if (node.argument.type !== "Identifier" && node.argument.type !== "MemberExpression") {
this.raise(node.argument.start, _location.Errors.InvalidRestAssignmentPattern);
}
}
checkCommaAfterRest(close) {
if (this.match(_types.types.comma)) {
if (this.lookaheadCharCode() === close) {
this.raiseTrailingCommaAfterRest(this.state.start);
} else {
this.raiseRestNotLast(this.state.start);
}
}
}
raiseRestNotLast(pos) {
throw this.raise(pos, _location.Errors.ElementAfterRest);
}
raiseTrailingCommaAfterRest(pos) {
this.raise(pos, _location.Errors.RestTrailingComma);
}
}
exports.default = LValParser;