Merge remote-tracking branch 'kristofdegrave/nullPropagation' into feat-optional-chaining
This commit is contained in:
@@ -284,14 +284,23 @@ pp.parseSubscripts = function (base, startPos, startLoc, noCalls) {
|
||||
node.object = base;
|
||||
node.callee = this.parseNoCallExpr();
|
||||
return this.parseSubscripts(this.finishNode(node, "BindExpression"), startPos, startLoc, noCalls);
|
||||
} else if (this.eat(tt.question)) {
|
||||
const node = this.startNodeAt(startPos, startLoc);
|
||||
node.object = base;
|
||||
node.optional = true;
|
||||
this.next();
|
||||
node.property = this.parseIdentifier(true);
|
||||
node.computed = false;
|
||||
base = this.finishNode(node, "MemberExpression");
|
||||
} else if (this.eat(tt.questionDot)) {
|
||||
base.optional = true;
|
||||
|
||||
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);
|
||||
base = this.finishNode(node, "MemberExpression");
|
||||
} else {
|
||||
const node = this.startNodeAt(startPos, startLoc);
|
||||
node.object = base;
|
||||
node.property = this.parseIdentifier(true);
|
||||
node.computed = false;
|
||||
base = this.finishNode(node, "MemberExpression");
|
||||
}
|
||||
} else if (this.eat(tt.dot)) {
|
||||
const node = this.startNodeAt(startPos, startLoc);
|
||||
node.object = base;
|
||||
@@ -303,6 +312,7 @@ pp.parseSubscripts = function (base, startPos, startLoc, noCalls) {
|
||||
node.object = base;
|
||||
node.property = this.parseExpression();
|
||||
node.computed = true;
|
||||
delete node.nullPropagation;
|
||||
this.expect(tt.bracketR);
|
||||
base = this.finishNode(node, "MemberExpression");
|
||||
} else if (!noCalls && this.match(tt.parenL)) {
|
||||
|
||||
@@ -391,6 +391,18 @@ export default class Tokenizer {
|
||||
return this.finishOp(code === 61 ? tt.eq : tt.prefix, 1);
|
||||
}
|
||||
|
||||
readToken_question() { // '?'
|
||||
const next = this.input.charCodeAt(this.state.pos + 1);
|
||||
if (next === 46) { // 46 = question '.'
|
||||
this.state.pos += 2;
|
||||
return this.finishToken(tt.questionDot);
|
||||
}
|
||||
else {
|
||||
++this.state.pos;
|
||||
return this.finishToken(tt.question);
|
||||
}
|
||||
}
|
||||
|
||||
getTokenFromCode(code) {
|
||||
switch (code) {
|
||||
// The interpretation of a dot depends on whether it is followed
|
||||
@@ -425,7 +437,7 @@ export default class Tokenizer {
|
||||
return this.finishToken(tt.colon);
|
||||
}
|
||||
|
||||
case 63: ++this.state.pos; return this.finishToken(tt.question);
|
||||
case 63: return this.readToken_question();
|
||||
case 64: ++this.state.pos; return this.finishToken(tt.at);
|
||||
|
||||
case 96: // '`'
|
||||
@@ -844,7 +856,7 @@ export default class Tokenizer {
|
||||
const type = this.state.type;
|
||||
let update;
|
||||
|
||||
if (type.keyword && prevType === tt.dot) {
|
||||
if (type.keyword && (prevType === tt.dot || prevType === tt.questionDot)) {
|
||||
this.state.exprAllowed = false;
|
||||
} else if (update = type.updateContext) {
|
||||
update.call(this, prevType);
|
||||
|
||||
@@ -75,6 +75,7 @@ export const types = {
|
||||
doubleColon: new TokenType("::", { beforeExpr }),
|
||||
dot: new TokenType("."),
|
||||
question: new TokenType("?", { beforeExpr }),
|
||||
questionDot: new TokenType("?."),
|
||||
arrow: new TokenType("=>", { beforeExpr }),
|
||||
template: new TokenType("template"),
|
||||
ellipsis: new TokenType("...", { beforeExpr }),
|
||||
|
||||
Reference in New Issue
Block a user