Factor parseSubscript out of parseSubscripts (#576)
This commit is contained in:
parent
dc87d99713
commit
50ae16de38
@ -294,99 +294,109 @@ export default class ExpressionParser extends LValParser {
|
|||||||
return this.parseSubscripts(expr, startPos, startLoc);
|
return this.parseSubscripts(expr, startPos, startLoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
parseSubscripts(base: N.Expression, startPos: number, startLoc: Position, noCalls?: boolean): N.Expression {
|
parseSubscripts(base: N.Expression, startPos: number, startLoc: Position, noCalls?: ?boolean) {
|
||||||
for (;;) {
|
const state = { stop: false };
|
||||||
if (!noCalls && this.eat(tt.doubleColon)) {
|
do {
|
||||||
const node = this.startNodeAt(startPos, startLoc);
|
base = this.parseSubscript(base, startPos, startLoc, noCalls, state);
|
||||||
node.object = base;
|
} while (!state.stop);
|
||||||
node.callee = this.parseNoCallExpr();
|
return base;
|
||||||
return this.parseSubscripts(this.finishNode(node, "BindExpression"), startPos, startLoc, noCalls);
|
}
|
||||||
|
|
||||||
} else if (this.match(tt.questionDot)) {
|
/** @param state Set 'state.stop = true' to indicate that we should stop parsing subscripts. */
|
||||||
if (!this.hasPlugin("optionalChaining")) {
|
parseSubscript(base: N.Expression, startPos: number, startLoc: Position, noCalls: ?boolean, state: { stop: boolean }): N.Expression {
|
||||||
this.raise(startPos, "You can only use optional-chaining when the 'optionalChaining' plugin is enabled.");
|
if (!noCalls && this.eat(tt.doubleColon)) {
|
||||||
}
|
const node = this.startNodeAt(startPos, startLoc);
|
||||||
|
node.object = base;
|
||||||
|
node.callee = this.parseNoCallExpr();
|
||||||
|
state.stop = true;
|
||||||
|
return this.parseSubscripts(this.finishNode(node, "BindExpression"), startPos, startLoc, noCalls);
|
||||||
|
|
||||||
if (noCalls && this.lookahead().type == tt.parenL) {
|
} else if (this.match(tt.questionDot)) {
|
||||||
return base;
|
if (!this.hasPlugin("optionalChaining")) {
|
||||||
}
|
this.raise(startPos, "You can only use optional-chaining when the 'optionalChaining' plugin is enabled.");
|
||||||
this.next();
|
}
|
||||||
|
|
||||||
const node = this.startNodeAt(startPos, startLoc);
|
if (noCalls && this.lookahead().type == tt.parenL) {
|
||||||
|
state.stop = true;
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
this.next();
|
||||||
|
|
||||||
if (this.eat(tt.bracketL)) {
|
const node = this.startNodeAt(startPos, startLoc);
|
||||||
node.object = base;
|
|
||||||
node.property = this.parseExpression();
|
|
||||||
node.computed = true;
|
|
||||||
node.optional = true;
|
|
||||||
this.expect(tt.bracketR);
|
|
||||||
base = this.finishNode(node, "MemberExpression");
|
|
||||||
} else if (this.eat(tt.parenL)) {
|
|
||||||
const possibleAsync = this.state.potentialArrowAt === base.start &&
|
|
||||||
base.type === "Identifier" &&
|
|
||||||
base.name === "async" &&
|
|
||||||
!this.canInsertSemicolon();
|
|
||||||
|
|
||||||
node.callee = base;
|
if (this.eat(tt.bracketL)) {
|
||||||
node.arguments = this.parseCallExpressionArguments(tt.parenR, possibleAsync);
|
|
||||||
node.optional = true;
|
|
||||||
|
|
||||||
base = this.finishNode(node, "CallExpression");
|
|
||||||
} else {
|
|
||||||
node.object = base;
|
|
||||||
node.property = this.parseIdentifier(true);
|
|
||||||
node.computed = false;
|
|
||||||
node.optional = true;
|
|
||||||
base = this.finishNode(node, "MemberExpression");
|
|
||||||
}
|
|
||||||
} else if (this.eat(tt.dot)) {
|
|
||||||
const node = this.startNodeAt(startPos, startLoc);
|
|
||||||
node.object = base;
|
|
||||||
node.property = this.hasPlugin("classPrivateProperties") ? this.parseMaybePrivateName() : this.parseIdentifier(true);
|
|
||||||
node.computed = false;
|
|
||||||
base = this.finishNode(node, "MemberExpression");
|
|
||||||
} else if (this.eat(tt.bracketL)) {
|
|
||||||
const node = this.startNodeAt(startPos, startLoc);
|
|
||||||
node.object = base;
|
node.object = base;
|
||||||
node.property = this.parseExpression();
|
node.property = this.parseExpression();
|
||||||
node.computed = true;
|
node.computed = true;
|
||||||
|
node.optional = true;
|
||||||
this.expect(tt.bracketR);
|
this.expect(tt.bracketR);
|
||||||
base = this.finishNode(node, "MemberExpression");
|
return this.finishNode(node, "MemberExpression");
|
||||||
} else if (!noCalls && this.match(tt.parenL)) {
|
} else if (this.eat(tt.parenL)) {
|
||||||
const possibleAsync = this.state.potentialArrowAt === base.start && base.type === "Identifier" && base.name === "async" && !this.canInsertSemicolon();
|
const possibleAsync = this.state.potentialArrowAt === base.start &&
|
||||||
this.next();
|
base.type === "Identifier" &&
|
||||||
|
base.name === "async" &&
|
||||||
|
!this.canInsertSemicolon();
|
||||||
|
|
||||||
const node = this.startNodeAt(startPos, startLoc);
|
|
||||||
node.callee = base;
|
node.callee = base;
|
||||||
node.arguments = this.parseCallExpressionArguments(tt.parenR, possibleAsync);
|
node.arguments = this.parseCallExpressionArguments(tt.parenR, possibleAsync);
|
||||||
if (node.callee.type === "Import") {
|
node.optional = true;
|
||||||
if (node.arguments.length !== 1) {
|
|
||||||
this.raise(node.start, "import() requires exactly one argument");
|
|
||||||
}
|
|
||||||
|
|
||||||
const importArg = node.arguments[0];
|
return this.finishNode(node, "CallExpression");
|
||||||
if (importArg && importArg.type === "SpreadElement") {
|
|
||||||
this.raise(importArg.start, "... is not allowed in import()");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
base = this.finishNode(node, "CallExpression");
|
|
||||||
|
|
||||||
if (possibleAsync && this.shouldParseAsyncArrow()) {
|
|
||||||
return this.parseAsyncArrowFromCallExpression(this.startNodeAt(startPos, startLoc), node);
|
|
||||||
} else {
|
|
||||||
this.toReferencedList(node.arguments);
|
|
||||||
}
|
|
||||||
} else if (this.match(tt.backQuote)) {
|
|
||||||
const node = this.startNodeAt(startPos, startLoc);
|
|
||||||
node.tag = base;
|
|
||||||
node.quasi = this.parseTemplate(true);
|
|
||||||
base = this.finishNode(node, "TaggedTemplateExpression");
|
|
||||||
} else {
|
} else {
|
||||||
return base;
|
node.object = base;
|
||||||
|
node.property = this.parseIdentifier(true);
|
||||||
|
node.computed = false;
|
||||||
|
node.optional = true;
|
||||||
|
return this.finishNode(node, "MemberExpression");
|
||||||
}
|
}
|
||||||
|
} else if (this.eat(tt.dot)) {
|
||||||
|
const node = this.startNodeAt(startPos, startLoc);
|
||||||
|
node.object = base;
|
||||||
|
node.property = this.hasPlugin("classPrivateProperties") ? this.parseMaybePrivateName() : this.parseIdentifier(true);
|
||||||
|
node.computed = false;
|
||||||
|
return this.finishNode(node, "MemberExpression");
|
||||||
|
} else if (this.eat(tt.bracketL)) {
|
||||||
|
const node = this.startNodeAt(startPos, startLoc);
|
||||||
|
node.object = base;
|
||||||
|
node.property = this.parseExpression();
|
||||||
|
node.computed = true;
|
||||||
|
this.expect(tt.bracketR);
|
||||||
|
return this.finishNode(node, "MemberExpression");
|
||||||
|
} else if (!noCalls && this.match(tt.parenL)) {
|
||||||
|
const possibleAsync = this.state.potentialArrowAt === base.start && base.type === "Identifier" && base.name === "async" && !this.canInsertSemicolon();
|
||||||
|
this.next();
|
||||||
|
|
||||||
|
const node = this.startNodeAt(startPos, startLoc);
|
||||||
|
node.callee = base;
|
||||||
|
node.arguments = this.parseCallExpressionArguments(tt.parenR, possibleAsync);
|
||||||
|
if (node.callee.type === "Import") {
|
||||||
|
if (node.arguments.length !== 1) {
|
||||||
|
this.raise(node.start, "import() requires exactly one argument");
|
||||||
|
}
|
||||||
|
|
||||||
|
const importArg = node.arguments[0];
|
||||||
|
if (importArg && importArg.type === "SpreadElement") {
|
||||||
|
this.raise(importArg.start, "... is not allowed in import()");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.finishNode(node, "CallExpression");
|
||||||
|
|
||||||
|
if (possibleAsync && this.shouldParseAsyncArrow()) {
|
||||||
|
state.stop = true;
|
||||||
|
return this.parseAsyncArrowFromCallExpression(this.startNodeAt(startPos, startLoc), node);
|
||||||
|
} else {
|
||||||
|
this.toReferencedList(node.arguments);
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
} else if (this.match(tt.backQuote)) {
|
||||||
|
const node = this.startNodeAt(startPos, startLoc);
|
||||||
|
node.tag = base;
|
||||||
|
node.quasi = this.parseTemplate(true);
|
||||||
|
return this.finishNode(node, "TaggedTemplateExpression");
|
||||||
|
} else {
|
||||||
|
state.stop = true;
|
||||||
|
return base;
|
||||||
}
|
}
|
||||||
// istanbul ignore next
|
|
||||||
throw new Error("Unreachable");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
parseCallExpressionArguments(close: TokenType, possibleAsyncArrow: boolean): $ReadOnlyArray<?N.Expression> {
|
parseCallExpressionArguments(close: TokenType, possibleAsyncArrow: boolean): $ReadOnlyArray<?N.Expression> {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user