Add ??= to Logical Assignment Operators (#7623)
`??=` is being merged into the Logical Assignment Operator proposal, and the overall proposal will wait until nullish coalescing is finalized.
This commit is contained in:
parent
023f8bd1cb
commit
a7bddc02ba
@ -17,6 +17,8 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "7.0.0-beta.42",
|
"@babel/core": "7.0.0-beta.42",
|
||||||
"@babel/helper-plugin-test-runner": "7.0.0-beta.42"
|
"@babel/helper-plugin-test-runner": "7.0.0-beta.42",
|
||||||
|
"@babel/plugin-proposal-nullish-coalescing-operator": "7.0.0-beta.42",
|
||||||
|
"@babel/plugin-syntax-nullish-coalescing-operator": "7.0.0-beta.42"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,7 @@ export default declare(api => {
|
|||||||
AssignmentExpression(path) {
|
AssignmentExpression(path) {
|
||||||
const { node, scope } = path;
|
const { node, scope } = path;
|
||||||
const { operator, left, right } = node;
|
const { operator, left, right } = node;
|
||||||
if (operator !== "||=" && operator !== "&&=") {
|
if (operator !== "||=" && operator !== "&&=" && operator !== "??=") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,4 @@
|
|||||||
|
let o;
|
||||||
|
o ??= {};
|
||||||
|
o.a ??= 1;
|
||||||
|
o["b"] ??= 2;
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["proposal-logical-assignment-operators", "syntax-nullish-coalescing-operator"]
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
var _o, _o2, _b;
|
||||||
|
|
||||||
|
let o;
|
||||||
|
o ?? (o = {});
|
||||||
|
(_o = o).a ?? (_o.a = 1);
|
||||||
|
(_o2 = o)[_b = "b"] ?? (_o2[_b] = 2);
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
var x = undefined;
|
||||||
|
var sets = 0;
|
||||||
|
var obj = {
|
||||||
|
get x() {
|
||||||
|
return x;
|
||||||
|
},
|
||||||
|
|
||||||
|
set x(value) {
|
||||||
|
sets++;
|
||||||
|
x = value;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
assert.equal(obj.x ??= 1, 1);
|
||||||
|
assert.equal(sets, 1);
|
||||||
|
assert.equal(obj.x ??= 2, 1);
|
||||||
|
assert.equal(sets, 1);
|
||||||
|
|
||||||
|
var gets = 0;
|
||||||
|
var deep = {
|
||||||
|
get obj() {
|
||||||
|
gets++;
|
||||||
|
return obj;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
obj.x = undefined;
|
||||||
|
assert.equal(deep.obj.x ??= 1, 1);
|
||||||
|
assert.equal(gets, 1);
|
||||||
|
assert.equal(deep.obj.x ??= 2, 1);
|
||||||
|
assert.equal(gets, 2);
|
||||||
|
|
||||||
|
var key = 0;
|
||||||
|
obj.x = undefined;
|
||||||
|
assert.equal(obj[++key] ??= 1, 1);
|
||||||
|
assert.equal(key, 1);
|
||||||
|
key = 0;
|
||||||
|
assert.equal(obj[++key] ??= 2, 1);
|
||||||
|
assert.equal(key, 1);
|
||||||
|
|
||||||
|
obj.x = undefined;
|
||||||
|
key = 0;
|
||||||
|
assert.equal(deep.obj[++key] ??= 1, 1);
|
||||||
|
assert.equal(gets, 3);
|
||||||
|
assert.equal(key, 1);
|
||||||
|
key = 0;
|
||||||
|
assert.equal(deep.obj[++key] ??= 2, 1);
|
||||||
|
assert.equal(gets, 4);
|
||||||
|
assert.equal(key, 1);
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
var x = undefined;
|
||||||
|
var sets = 0;
|
||||||
|
var obj = {
|
||||||
|
get x() {
|
||||||
|
return x;
|
||||||
|
},
|
||||||
|
|
||||||
|
set x(value) {
|
||||||
|
sets++;
|
||||||
|
x = value;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
assert.equal(obj.x ??= 1, 1);
|
||||||
|
assert.equal(sets, 1);
|
||||||
|
assert.equal(obj.x ??= 2, 1);
|
||||||
|
assert.equal(sets, 1);
|
||||||
|
|
||||||
|
var gets = 0;
|
||||||
|
var deep = {
|
||||||
|
get obj() {
|
||||||
|
gets++;
|
||||||
|
return obj;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
obj.x = undefined;
|
||||||
|
assert.equal(deep.obj.x ??= 1, 1);
|
||||||
|
assert.equal(gets, 1);
|
||||||
|
assert.equal(deep.obj.x ??= 2, 1);
|
||||||
|
assert.equal(gets, 2);
|
||||||
|
|
||||||
|
var key = 0;
|
||||||
|
obj.x = undefined;
|
||||||
|
assert.equal(obj[++key] ??= 1, 1);
|
||||||
|
assert.equal(key, 1);
|
||||||
|
key = 0;
|
||||||
|
assert.equal(obj[++key] ??= 2, 1);
|
||||||
|
assert.equal(key, 1);
|
||||||
|
|
||||||
|
obj.x = undefined;
|
||||||
|
key = 0;
|
||||||
|
assert.equal(deep.obj[++key] ??= 1, 1);
|
||||||
|
assert.equal(gets, 3);
|
||||||
|
assert.equal(key, 1);
|
||||||
|
key = 0;
|
||||||
|
assert.equal(deep.obj[++key] ??= 2, 1);
|
||||||
|
assert.equal(gets, 4);
|
||||||
|
assert.equal(key, 1);
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["proposal-logical-assignment-operators", "proposal-nullish-coalescing-operator"]
|
||||||
|
}
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
var _obj$x, _obj$x2, _deep$obj, _x, _deep$obj2, _x2, _ref, _obj, _ref2, _obj2, _deep$obj3, _ref3, _ref4, _deep$obj4, _ref5, _ref6;
|
||||||
|
|
||||||
|
var x = undefined;
|
||||||
|
var sets = 0;
|
||||||
|
var obj = {
|
||||||
|
get x() {
|
||||||
|
return x;
|
||||||
|
},
|
||||||
|
|
||||||
|
set x(value) {
|
||||||
|
sets++;
|
||||||
|
x = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
assert.equal((_obj$x = obj.x) !== null && _obj$x !== void 0 ? _obj$x : obj.x = 1, 1);
|
||||||
|
assert.equal(sets, 1);
|
||||||
|
assert.equal((_obj$x2 = obj.x) !== null && _obj$x2 !== void 0 ? _obj$x2 : obj.x = 2, 1);
|
||||||
|
assert.equal(sets, 1);
|
||||||
|
var gets = 0;
|
||||||
|
var deep = {
|
||||||
|
get obj() {
|
||||||
|
gets++;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
obj.x = undefined;
|
||||||
|
assert.equal((_x = (_deep$obj = deep.obj).x) !== null && _x !== void 0 ? _x : _deep$obj.x = 1, 1);
|
||||||
|
assert.equal(gets, 1);
|
||||||
|
assert.equal((_x2 = (_deep$obj2 = deep.obj).x) !== null && _x2 !== void 0 ? _x2 : _deep$obj2.x = 2, 1);
|
||||||
|
assert.equal(gets, 2);
|
||||||
|
var key = 0;
|
||||||
|
obj.x = undefined;
|
||||||
|
assert.equal((_obj = obj[_ref = ++key]) !== null && _obj !== void 0 ? _obj : obj[_ref] = 1, 1);
|
||||||
|
assert.equal(key, 1);
|
||||||
|
key = 0;
|
||||||
|
assert.equal((_obj2 = obj[_ref2 = ++key]) !== null && _obj2 !== void 0 ? _obj2 : obj[_ref2] = 2, 1);
|
||||||
|
assert.equal(key, 1);
|
||||||
|
obj.x = undefined;
|
||||||
|
key = 0;
|
||||||
|
assert.equal((_ref4 = (_deep$obj3 = deep.obj)[_ref3 = ++key]) !== null && _ref4 !== void 0 ? _ref4 : _deep$obj3[_ref3] = 1, 1);
|
||||||
|
assert.equal(gets, 3);
|
||||||
|
assert.equal(key, 1);
|
||||||
|
key = 0;
|
||||||
|
assert.equal((_ref6 = (_deep$obj4 = deep.obj)[_ref5 = ++key]) !== null && _ref6 !== void 0 ? _ref6 : _deep$obj4[_ref5] = 2, 1);
|
||||||
|
assert.equal(gets, 4);
|
||||||
|
assert.equal(key, 1);
|
||||||
@ -299,10 +299,6 @@ export default class ExpressionParser extends LValParser {
|
|||||||
this.state.potentialArrowAt = startPos;
|
this.state.potentialArrowAt = startPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.operator === "??") {
|
|
||||||
this.expectPlugin("nullishCoalescingOperator");
|
|
||||||
}
|
|
||||||
|
|
||||||
node.right = this.parseExprOp(
|
node.right = this.parseExprOp(
|
||||||
this.parseMaybeUnary(),
|
this.parseMaybeUnary(),
|
||||||
startPos,
|
startPos,
|
||||||
|
|||||||
@ -607,8 +607,16 @@ export default class Tokenizer extends LocationParser {
|
|||||||
const next = this.input.charCodeAt(this.state.pos + 1);
|
const next = this.input.charCodeAt(this.state.pos + 1);
|
||||||
const next2 = this.input.charCodeAt(this.state.pos + 2);
|
const next2 = this.input.charCodeAt(this.state.pos + 2);
|
||||||
if (next === charCodes.questionMark) {
|
if (next === charCodes.questionMark) {
|
||||||
// '??'
|
this.expectPlugin("nullishCoalescingOperator");
|
||||||
this.finishOp(tt.nullishCoalescing, 2);
|
|
||||||
|
if (next2 === charCodes.equalsTo) {
|
||||||
|
// '??='
|
||||||
|
this.expectPlugin("logicalAssignment");
|
||||||
|
this.finishOp(tt.assign, 3);
|
||||||
|
} else {
|
||||||
|
// '??'
|
||||||
|
this.finishOp(tt.nullishCoalescing, 2);
|
||||||
|
}
|
||||||
} else if (
|
} else if (
|
||||||
next === charCodes.dot &&
|
next === charCodes.dot &&
|
||||||
!(next2 >= charCodes.digit0 && next2 <= charCodes.digit9)
|
!(next2 >= charCodes.digit0 && next2 <= charCodes.digit9)
|
||||||
|
|||||||
@ -0,0 +1,2 @@
|
|||||||
|
a ??= b;
|
||||||
|
obj.a ??= b;
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["logicalAssignment"],
|
||||||
|
"throws": "This experimental syntax requires enabling the parser plugin: 'nullishCoalescingOperator' (1:2)"
|
||||||
|
}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
a ??= b;
|
||||||
|
obj.a ??= b;
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["nullishCoalescingOperator"],
|
||||||
|
"throws": "This experimental syntax requires enabling the parser plugin: 'logicalAssignment' (1:2)"
|
||||||
|
}
|
||||||
2
packages/babylon/test/fixtures/experimental/logical-assignment-operator/qq-equals/input.js
vendored
Normal file
2
packages/babylon/test/fixtures/experimental/logical-assignment-operator/qq-equals/input.js
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
a ??= b;
|
||||||
|
obj.a ??= b;
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["logicalAssignment", "nullishCoalescingOperator"]
|
||||||
|
}
|
||||||
197
packages/babylon/test/fixtures/experimental/logical-assignment-operator/qq-equals/output.json
vendored
Normal file
197
packages/babylon/test/fixtures/experimental/logical-assignment-operator/qq-equals/output.json
vendored
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
{
|
||||||
|
"type": "File",
|
||||||
|
"start": 0,
|
||||||
|
"end": 21,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 12
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"program": {
|
||||||
|
"type": "Program",
|
||||||
|
"start": 0,
|
||||||
|
"end": 21,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 12
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceType": "script",
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"start": 0,
|
||||||
|
"end": 8,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"expression": {
|
||||||
|
"type": "AssignmentExpression",
|
||||||
|
"start": 0,
|
||||||
|
"end": 7,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 7
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"operator": "??=",
|
||||||
|
"left": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 0,
|
||||||
|
"end": 1,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 1
|
||||||
|
},
|
||||||
|
"identifierName": "a"
|
||||||
|
},
|
||||||
|
"name": "a"
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 6,
|
||||||
|
"end": 7,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 6
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 7
|
||||||
|
},
|
||||||
|
"identifierName": "b"
|
||||||
|
},
|
||||||
|
"name": "b"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"start": 9,
|
||||||
|
"end": 21,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 12
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"expression": {
|
||||||
|
"type": "AssignmentExpression",
|
||||||
|
"start": 9,
|
||||||
|
"end": 20,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 11
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"operator": "??=",
|
||||||
|
"left": {
|
||||||
|
"type": "MemberExpression",
|
||||||
|
"start": 9,
|
||||||
|
"end": 14,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"object": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 9,
|
||||||
|
"end": 12,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 3
|
||||||
|
},
|
||||||
|
"identifierName": "obj"
|
||||||
|
},
|
||||||
|
"name": "obj"
|
||||||
|
},
|
||||||
|
"property": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 13,
|
||||||
|
"end": 14,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 4
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 5
|
||||||
|
},
|
||||||
|
"identifierName": "a"
|
||||||
|
},
|
||||||
|
"name": "a"
|
||||||
|
},
|
||||||
|
"computed": false
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 19,
|
||||||
|
"end": 20,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 10
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 11
|
||||||
|
},
|
||||||
|
"identifierName": "b"
|
||||||
|
},
|
||||||
|
"name": "b"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"directives": []
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"throws": "This experimental syntax requires enabling the parser plugin: 'nullishCoalescingOperator' (1:7)"
|
"throws": "This experimental syntax requires enabling the parser plugin: 'nullishCoalescingOperator' (1:4)"
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user