Skip to content

Commit

Permalink
babel#328 babel#205 ?. as nullPropagation. For now it only works for …
Browse files Browse the repository at this point in the history
…member access. (.? or ?.[) If the object is undefined this will return undefined. If the object on which you want to access the property is defined, the value of the propery will be given back.
  • Loading branch information
Kristof Degrave authored and Kristof Degrave committed Feb 11, 2017
1 parent b902fe6 commit 1eaf016
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 75 deletions.
2 changes: 1 addition & 1 deletion ast/spec.md
Expand Up @@ -857,7 +857,7 @@ interface MemberExpression <: Expression, Pattern {
object: Expression | Super;
property: Expression;
computed: boolean;
nullPropagation: boolean;
nullPropagation: boolean | null;
}
```

Expand Down
32 changes: 17 additions & 15 deletions src/parser/expression.js
Expand Up @@ -284,27 +284,29 @@ 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.questionDot)) {
let node = this.startNodeAt(startPos, startLoc);
node.object = base;
node.property = this.parseIdentifier(true);
node.computed = false;
node.nullPropagation = true;
base = this.finishNode(node, "MemberExpression");
} else if (this.eat(tt.questionDot)) {
base.nullPropagation = 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;
node.property = this.parseIdentifier(true);
node.computed = false;
node.nullPropagation = false;
base = this.finishNode(node, "MemberExpression");
} else if (this.eat(tt.questionBracketL)) {
let node = this.startNodeAt(startPos, startLoc);
node.object = base;
node.property = this.parseExpression();
node.computed = true;
node.nullPropagation = true;
this.expect(tt.bracketR);
} else if (this.eat(tt.bracketL)) {
const node = this.startNodeAt(startPos, startLoc);
node.object = base;
Expand Down
26 changes: 11 additions & 15 deletions src/tokenizer/index.js
Expand Up @@ -392,20 +392,16 @@ export default class Tokenizer {
}

readToken_question() { // '?'
let next = this.input.charCodeAt(this.state.pos + 1);
if(next === 46){ // 46 = question '.'
this.state.pos += 2;
return this.finishToken(tt.questionDot);
}
else if(next === 91){ // 91 = question '['
this.state.pos += 2;
return this.finishToken(tt.questionBracketL);
}
else {
++this.state.pos;
return this.finishToken(tt.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) {
Expand Down Expand Up @@ -825,7 +821,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);
Expand Down
3 changes: 1 addition & 2 deletions src/tokenizer/types.js
Expand Up @@ -75,8 +75,7 @@ export const types = {
doubleColon: new TokenType("::", { beforeExpr }),
dot: new TokenType("."),
question: new TokenType("?", { beforeExpr }),
questionBracketL: new TokenType("?[", { beforeExpr, startsExpr }),
questionBracketL: new TokenType("?."),
questionDot: new TokenType("?."),
arrow: new TokenType("=>", { beforeExpr }),
template: new TokenType("template"),
ellipsis: new TokenType("...", { beforeExpr }),
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/experimental/uncategorised/63/actual.js
Expand Up @@ -2,4 +2,4 @@ o?.x?.y

o?.x ? o.x.z?.w : o.y?.z?.w

o?[0]?[1]?.x
o?.[0]?.["1"]?.x
78 changes: 37 additions & 41 deletions test/fixtures/experimental/uncategorised/63/expected.json
@@ -1,29 +1,29 @@
{
"type": "File",
"start": 0,
"end": 50,
"end": 54,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 5,
"column": 12
"column": 16
}
},
"program": {
"type": "Program",
"start": 0,
"end": 50,
"end": 54,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 5,
"column": 12
"column": 16
}
},
"sourceType": "script",
Expand Down Expand Up @@ -85,7 +85,7 @@
}
},
"name": "o",
"existentialOperator": true
"nullPropagation": true
},
"property": {
"type": "Identifier",
Expand All @@ -104,7 +104,7 @@
"name": "x"
},
"computed": false,
"existentialOperator": true
"nullPropagation": true
},
"property": {
"type": "Identifier",
Expand Down Expand Up @@ -182,7 +182,7 @@
}
},
"name": "o",
"existentialOperator": true
"nullPropagation": true
},
"property": {
"type": "Identifier",
Expand Down Expand Up @@ -295,7 +295,7 @@
"name": "z"
},
"computed": false,
"existentialOperator": true
"nullPropagation": true
},
"property": {
"type": "Identifier",
Expand Down Expand Up @@ -390,7 +390,7 @@
"name": "y"
},
"computed": false,
"existentialOperator": true
"nullPropagation": true
},
"property": {
"type": "Identifier",
Expand All @@ -409,7 +409,7 @@
"name": "z"
},
"computed": false,
"existentialOperator": true
"nullPropagation": true
},
"property": {
"type": "Identifier",
Expand All @@ -434,57 +434,57 @@
{
"type": "ExpressionStatement",
"start": 38,
"end": 50,
"end": 54,
"loc": {
"start": {
"line": 5,
"column": 0
},
"end": {
"line": 5,
"column": 12
"column": 16
}
},
"expression": {
"type": "MemberExpression",
"start": 38,
"end": 50,
"end": 54,
"loc": {
"start": {
"line": 5,
"column": 0
},
"end": {
"line": 5,
"column": 12
"column": 16
}
},
"object": {
"type": "MemberExpression",
"start": 38,
"end": 47,
"end": 51,
"loc": {
"start": {
"line": 5,
"column": 0
},
"end": {
"line": 5,
"column": 9
"column": 13
}
},
"object": {
"type": "MemberExpression",
"start": 38,
"end": 43,
"end": 44,
"loc": {
"start": {
"line": 5,
"column": 0
},
"end": {
"line": 5,
"column": 5
"column": 6
}
},
"object": {
Expand All @@ -502,62 +502,58 @@
}
},
"name": "o",
"existentialOperator": true
"nullPropagation": true
},
"property": {
"type": "Literal",
"start": 41,
"end": 42,
"type": "NumericLiteral",
"start": 42,
"end": 43,
"loc": {
"start": {
"line": 5,
"column": 3
"column": 4
},
"end": {
"line": 5,
"column": 4
"column": 5
}
},
"value": 0,
"rawValue": 0,
"raw": "0"
"value": 0
},
"computed": true,
"existentialOperator": true
"nullPropagation": true
},
"property": {
"type": "Literal",
"start": 45,
"end": 46,
"type": "StringLiteral",
"start": 47,
"end": 50,
"loc": {
"start": {
"line": 5,
"column": 7
"column": 9
},
"end": {
"line": 5,
"column": 8
"column": 12
}
},
"value": 1,
"rawValue": 1,
"raw": "1"
"value": "1"
},
"computed": true,
"existentialOperator": true
"nullPropagation": true
},
"property": {
"type": "Identifier",
"start": 49,
"end": 50,
"start": 53,
"end": 54,
"loc": {
"start": {
"line": 5,
"column": 11
"column": 15
},
"end": {
"line": 5,
"column": 12
"column": 16
}
},
"name": "x"
Expand Down

0 comments on commit 1eaf016

Please sign in to comment.