"use strict";
|
|
Object.defineProperty(exports, "__esModule", {
|
value: true
|
});
|
exports.default = exports.ParseBindingListFlags = void 0;
|
var _types = require("../tokenizer/types");
|
var _identifier = require("../util/identifier");
|
var _node = require("./node");
|
var _scopeflags = require("../util/scopeflags");
|
var _parseError = require("../parse-error");
|
const getOwn = (object, key) => Object.hasOwnProperty.call(object, key) && object[key];
|
const unwrapParenthesizedExpression = node => {
|
return node.type === "ParenthesizedExpression" ? unwrapParenthesizedExpression(node.expression) : node;
|
};
|
var ParseBindingListFlags = {
|
ALLOW_EMPTY: 1,
|
IS_FUNCTION_PARAMS: 2,
|
IS_CONSTRUCTOR_PARAMS: 4
|
};
|
exports.ParseBindingListFlags = ParseBindingListFlags;
|
class LValParser extends _node.NodeUtils {
|
toAssignable(node, isLHS = false) {
|
var _node$extra, _node$extra3;
|
let parenthesized = undefined;
|
if (node.type === "ParenthesizedExpression" || (_node$extra = node.extra) != null && _node$extra.parenthesized) {
|
parenthesized = unwrapParenthesizedExpression(node);
|
if (isLHS) {
|
if (parenthesized.type === "Identifier") {
|
this.expressionScope.recordArrowParameterBindingError(_parseError.Errors.InvalidParenthesizedAssignment, {
|
at: node
|
});
|
} else if (parenthesized.type !== "MemberExpression") {
|
this.raise(_parseError.Errors.InvalidParenthesizedAssignment, {
|
at: node
|
});
|
}
|
} else {
|
this.raise(_parseError.Errors.InvalidParenthesizedAssignment, {
|
at: node
|
});
|
}
|
}
|
switch (node.type) {
|
case "Identifier":
|
case "ObjectPattern":
|
case "ArrayPattern":
|
case "AssignmentPattern":
|
case "RestElement":
|
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, isLHS);
|
if (isLast && prop.type === "RestElement" && (_node$extra2 = node.extra) != null && _node$extra2.trailingCommaLoc) {
|
this.raise(_parseError.Errors.RestTrailingComma, {
|
at: node.extra.trailingCommaLoc
|
});
|
}
|
}
|
break;
|
case "ObjectProperty":
|
{
|
const {
|
key,
|
value
|
} = node;
|
if (this.isPrivateName(key)) {
|
this.classScope.usePrivateName(this.getPrivateNameSV(key), key.loc.start);
|
}
|
this.toAssignable(value, isLHS);
|
break;
|
}
|
case "SpreadElement":
|
{
|
throw new Error("Internal @babel/parser error (this is a bug, please report it)." + " SpreadElement should be converted by .toAssignable's caller.");
|
}
|
case "ArrayExpression":
|
node.type = "ArrayPattern";
|
this.toAssignableList(node.elements, (_node$extra3 = node.extra) == null ? void 0 : _node$extra3.trailingCommaLoc, isLHS);
|
break;
|
case "AssignmentExpression":
|
if (node.operator !== "=") {
|
this.raise(_parseError.Errors.MissingEqInAssignment, {
|
at: node.left.loc.end
|
});
|
}
|
node.type = "AssignmentPattern";
|
delete node.operator;
|
this.toAssignable(node.left, isLHS);
|
break;
|
case "ParenthesizedExpression":
|
this.toAssignable(parenthesized, isLHS);
|
break;
|
default:
|
}
|
}
|
toAssignableObjectExpressionProp(prop, isLast, isLHS) {
|
if (prop.type === "ObjectMethod") {
|
this.raise(prop.kind === "get" || prop.kind === "set" ? _parseError.Errors.PatternHasAccessor : _parseError.Errors.PatternHasMethod, {
|
at: prop.key
|
});
|
} else if (prop.type === "SpreadElement") {
|
prop.type = "RestElement";
|
const arg = prop.argument;
|
this.checkToRestConversion(arg, false);
|
this.toAssignable(arg, isLHS);
|
if (!isLast) {
|
this.raise(_parseError.Errors.RestTrailingComma, {
|
at: prop
|
});
|
}
|
} else {
|
this.toAssignable(prop, isLHS);
|
}
|
}
|
toAssignableList(exprList, trailingCommaLoc, isLHS) {
|
const end = exprList.length - 1;
|
for (let i = 0; i <= end; i++) {
|
const elt = exprList[i];
|
if (!elt) continue;
|
if (elt.type === "SpreadElement") {
|
elt.type = "RestElement";
|
const arg = elt.argument;
|
this.checkToRestConversion(arg, true);
|
this.toAssignable(arg, isLHS);
|
} else {
|
this.toAssignable(elt, isLHS);
|
}
|
if (elt.type === "RestElement") {
|
if (i < end) {
|
this.raise(_parseError.Errors.RestTrailingComma, {
|
at: elt
|
});
|
} else if (trailingCommaLoc) {
|
this.raise(_parseError.Errors.RestTrailingComma, {
|
at: trailingCommaLoc
|
});
|
}
|
}
|
}
|
}
|
isAssignable(node, isBinding) {
|
switch (node.type) {
|
case "Identifier":
|
case "ObjectPattern":
|
case "ArrayPattern":
|
case "AssignmentPattern":
|
case "RestElement":
|
return true;
|
case "ObjectExpression":
|
{
|
const last = node.properties.length - 1;
|
return node.properties.every((prop, i) => {
|
return prop.type !== "ObjectMethod" && (i === last || prop.type !== "SpreadElement") && this.isAssignable(prop);
|
});
|
}
|
case "ObjectProperty":
|
return this.isAssignable(node.value);
|
case "SpreadElement":
|
return this.isAssignable(node.argument);
|
case "ArrayExpression":
|
return node.elements.every(element => element === null || this.isAssignable(element));
|
case "AssignmentExpression":
|
return node.operator === "=";
|
case "ParenthesizedExpression":
|
return this.isAssignable(node.expression);
|
case "MemberExpression":
|
case "OptionalMemberExpression":
|
return !isBinding;
|
default:
|
return false;
|
}
|
}
|
toReferencedList(exprList, isParenthesizedExpr) {
|
return exprList;
|
}
|
toReferencedListDeep(exprList, isParenthesizedExpr) {
|
this.toReferencedList(exprList, isParenthesizedExpr);
|
for (const expr of exprList) {
|
if ((expr == null ? void 0 : expr.type) === "ArrayExpression") {
|
this.toReferencedListDeep(expr.elements);
|
}
|
}
|
}
|
parseSpread(refExpressionErrors) {
|
const node = this.startNode();
|
this.next();
|
node.argument = this.parseMaybeAssignAllowIn(refExpressionErrors, undefined);
|
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 0:
|
{
|
const node = this.startNode();
|
this.next();
|
node.elements = this.parseBindingList(3, 93, ParseBindingListFlags.ALLOW_EMPTY);
|
return this.finishNode(node, "ArrayPattern");
|
}
|
case 5:
|
return this.parseObjectLike(8, true);
|
}
|
return this.parseIdentifier();
|
}
|
parseBindingList(close, closeCharCode, flags) {
|
const allowEmpty = flags & ParseBindingListFlags.ALLOW_EMPTY;
|
const elts = [];
|
let first = true;
|
while (!this.eat(close)) {
|
if (first) {
|
first = false;
|
} else {
|
this.expect(12);
|
}
|
if (allowEmpty && this.match(12)) {
|
elts.push(null);
|
} else if (this.eat(close)) {
|
break;
|
} else if (this.match(21)) {
|
elts.push(this.parseAssignableListItemTypes(this.parseRestBinding(), flags));
|
if (!this.checkCommaAfterRest(closeCharCode)) {
|
this.expect(close);
|
break;
|
}
|
} else {
|
const decorators = [];
|
if (this.match(26) && this.hasPlugin("decorators")) {
|
this.raise(_parseError.Errors.UnsupportedParameterDecorator, {
|
at: this.state.startLoc
|
});
|
}
|
while (this.match(26)) {
|
decorators.push(this.parseDecorator());
|
}
|
elts.push(this.parseAssignableListItem(flags, decorators));
|
}
|
}
|
return elts;
|
}
|
parseBindingRestProperty(prop) {
|
this.next();
|
prop.argument = this.parseIdentifier();
|
this.checkCommaAfterRest(125);
|
return this.finishNode(prop, "RestElement");
|
}
|
parseBindingProperty() {
|
const prop = this.startNode();
|
const {
|
type,
|
startLoc
|
} = this.state;
|
if (type === 21) {
|
return this.parseBindingRestProperty(prop);
|
} else if (type === 136) {
|
this.expectPlugin("destructuringPrivate", startLoc);
|
this.classScope.usePrivateName(this.state.value, startLoc);
|
prop.key = this.parsePrivateName();
|
} else {
|
this.parsePropertyName(prop);
|
}
|
prop.method = false;
|
return this.parseObjPropValue(prop, startLoc, false, false, true, false);
|
}
|
parseAssignableListItem(flags, decorators) {
|
const left = this.parseMaybeDefault();
|
this.parseAssignableListItemTypes(left, flags);
|
const elt = this.parseMaybeDefault(left.loc.start, left);
|
if (decorators.length) {
|
left.decorators = decorators;
|
}
|
return elt;
|
}
|
parseAssignableListItemTypes(param, flags) {
|
return param;
|
}
|
parseMaybeDefault(startLoc, left) {
|
var _startLoc, _left;
|
(_startLoc = startLoc) != null ? _startLoc : startLoc = this.state.startLoc;
|
left = (_left = left) != null ? _left : this.parseBindingAtom();
|
if (!this.eat(29)) return left;
|
const node = this.startNodeAt(startLoc);
|
node.left = left;
|
node.right = this.parseMaybeAssignAllowIn();
|
return this.finishNode(node, "AssignmentPattern");
|
}
|
isValidLVal(type, isUnparenthesizedInAssign, binding) {
|
return getOwn({
|
AssignmentPattern: "left",
|
RestElement: "argument",
|
ObjectProperty: "value",
|
ParenthesizedExpression: "expression",
|
ArrayPattern: "elements",
|
ObjectPattern: "properties"
|
}, type);
|
}
|
checkLVal(expression, {
|
in: ancestor,
|
binding = _scopeflags.BIND_NONE,
|
checkClashes = false,
|
strictModeChanged = false,
|
hasParenthesizedAncestor = false
|
}) {
|
var _expression$extra;
|
const type = expression.type;
|
if (this.isObjectMethod(expression)) return;
|
if (type === "MemberExpression") {
|
if (binding !== _scopeflags.BIND_NONE) {
|
this.raise(_parseError.Errors.InvalidPropertyBindingPattern, {
|
at: expression
|
});
|
}
|
return;
|
}
|
if (type === "Identifier") {
|
this.checkIdentifier(expression, binding, strictModeChanged);
|
const {
|
name
|
} = expression;
|
if (checkClashes) {
|
if (checkClashes.has(name)) {
|
this.raise(_parseError.Errors.ParamDupe, {
|
at: expression
|
});
|
} else {
|
checkClashes.add(name);
|
}
|
}
|
return;
|
}
|
const validity = this.isValidLVal(type, !(hasParenthesizedAncestor || (_expression$extra = expression.extra) != null && _expression$extra.parenthesized) && ancestor.type === "AssignmentExpression", binding);
|
if (validity === true) return;
|
if (validity === false) {
|
const ParseErrorClass = binding === _scopeflags.BIND_NONE ? _parseError.Errors.InvalidLhs : _parseError.Errors.InvalidLhsBinding;
|
this.raise(ParseErrorClass, {
|
at: expression,
|
ancestor
|
});
|
return;
|
}
|
const [key, isParenthesizedExpression] = Array.isArray(validity) ? validity : [validity, type === "ParenthesizedExpression"];
|
const nextAncestor = type === "ArrayPattern" || type === "ObjectPattern" || type === "ParenthesizedExpression" ? {
|
type
|
} : ancestor;
|
for (const child of [].concat(expression[key])) {
|
if (child) {
|
this.checkLVal(child, {
|
in: nextAncestor,
|
binding,
|
checkClashes,
|
strictModeChanged,
|
hasParenthesizedAncestor: isParenthesizedExpression
|
});
|
}
|
}
|
}
|
checkIdentifier(at, bindingType, strictModeChanged = false) {
|
if (this.state.strict && (strictModeChanged ? (0, _identifier.isStrictBindReservedWord)(at.name, this.inModule) : (0, _identifier.isStrictBindOnlyReservedWord)(at.name))) {
|
if (bindingType === _scopeflags.BIND_NONE) {
|
this.raise(_parseError.Errors.StrictEvalArguments, {
|
at,
|
referenceName: at.name
|
});
|
} else {
|
this.raise(_parseError.Errors.StrictEvalArgumentsBinding, {
|
at,
|
bindingName: at.name
|
});
|
}
|
}
|
if (bindingType & _scopeflags.BIND_FLAGS_NO_LET_IN_LEXICAL && at.name === "let") {
|
this.raise(_parseError.Errors.LetInLexicalBinding, {
|
at
|
});
|
}
|
if (!(bindingType & _scopeflags.BIND_NONE)) {
|
this.declareNameFromIdentifier(at, bindingType);
|
}
|
}
|
declareNameFromIdentifier(identifier, binding) {
|
this.scope.declareName(identifier.name, binding, identifier.loc.start);
|
}
|
checkToRestConversion(node, allowPattern) {
|
switch (node.type) {
|
case "ParenthesizedExpression":
|
this.checkToRestConversion(node.expression, allowPattern);
|
break;
|
case "Identifier":
|
case "MemberExpression":
|
break;
|
case "ArrayExpression":
|
case "ObjectExpression":
|
if (allowPattern) break;
|
default:
|
this.raise(_parseError.Errors.InvalidRestAssignmentPattern, {
|
at: node
|
});
|
}
|
}
|
checkCommaAfterRest(close) {
|
if (!this.match(12)) {
|
return false;
|
}
|
this.raise(this.lookaheadCharCode() === close ? _parseError.Errors.RestTrailingComma : _parseError.Errors.ElementAfterRest, {
|
at: this.state.startLoc
|
});
|
return true;
|
}
|
}
|
exports.default = LValParser;
|
|
//# sourceMappingURL=lval.js.map
|