Skip to content

Commit cbfd7ec

Browse files
committed
Fix bug in objectrestspread
1 parent 1191e87 commit cbfd7ec

21 files changed

Lines changed: 67 additions & 134 deletions

internal/transformers/estransforms/objectrestspread.go

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ type objectRestSpreadTransformer struct {
4545
compilerOptions *core.CompilerOptions
4646

4747
inExportedVariableStatement bool
48+
expressionResultIsUnused bool
4849

4950
ctx flattenContext
5051
parametersWithPrecedingObjectRestOrSpread map[*ast.Node]struct{}
@@ -78,13 +79,24 @@ func (ch *objectRestSpreadTransformer) visit(node *ast.Node) *ast.Node {
7879
if node.SubtreeFacts()&ast.SubtreeContainsESObjectRestOrSpread == 0 && ch.parametersWithPrecedingObjectRestOrSpread == nil {
7980
return node
8081
}
82+
// Save the expressionResultIsUnused flag set by the parent for this node,
83+
// then reset to false for children (the default). Specific cases below override as needed.
84+
expressionResultIsUnused := ch.expressionResultIsUnused
85+
ch.expressionResultIsUnused = false
86+
defer func() { ch.expressionResultIsUnused = expressionResultIsUnused }()
8187
switch node.Kind {
8288
case ast.KindSourceFile:
8389
return ch.visitSourceFile(node.AsSourceFile())
8490
case ast.KindObjectLiteralExpression:
8591
return ch.visitObjectLiteralExpression(node.AsObjectLiteralExpression())
8692
case ast.KindBinaryExpression:
87-
return ch.visitBinaryExpression(node.AsBinaryExpression())
93+
return ch.visitBinaryExpression(node.AsBinaryExpression(), expressionResultIsUnused)
94+
case ast.KindExpressionStatement:
95+
ch.expressionResultIsUnused = true
96+
return ch.Visitor().VisitEachChild(node)
97+
case ast.KindParenthesizedExpression:
98+
ch.expressionResultIsUnused = expressionResultIsUnused
99+
return ch.Visitor().VisitEachChild(node)
88100
case ast.KindForOfStatement:
89101
return ch.visitForOftatement(node.AsForInOrOfStatement())
90102
case ast.KindVariableStatement:
@@ -608,16 +620,21 @@ func (ch *objectRestSpreadTransformer) createForOfBindingStatement(node *ast.Nod
608620
}
609621
}
610622

611-
func (ch *objectRestSpreadTransformer) visitBinaryExpression(node *ast.BinaryExpression) *ast.Node {
612-
if !(ast.IsDestructuringAssignment(node.AsNode()) && ast.ContainsObjectRestOrSpread(node.Left)) {
613-
return ch.Visitor().VisitEachChild(node.AsNode())
623+
func (ch *objectRestSpreadTransformer) visitBinaryExpression(node *ast.BinaryExpression, expressionResultIsUnused bool) *ast.Node {
624+
if ast.IsDestructuringAssignment(node.AsNode()) && ast.ContainsObjectRestOrSpread(node.Left) {
625+
return ch.flattenDestructuringAssignment(node, !expressionResultIsUnused)
614626
}
615-
return ch.flattenDestructuringAssignment(
616-
node,
617-
)
627+
if node.OperatorToken.Kind == ast.KindCommaToken {
628+
ch.expressionResultIsUnused = true
629+
left := ch.Visitor().VisitNode(node.Left)
630+
ch.expressionResultIsUnused = expressionResultIsUnused
631+
right := ch.Visitor().VisitNode(node.Right)
632+
return ch.Factory().UpdateBinaryExpression(node, nil, left, nil, node.OperatorToken, right)
633+
}
634+
return ch.Visitor().VisitEachChild(node.AsNode())
618635
}
619636

620-
func (ch *objectRestSpreadTransformer) flattenDestructuringAssignment(node *ast.BinaryExpression) *ast.Node {
637+
func (ch *objectRestSpreadTransformer) flattenDestructuringAssignment(node *ast.BinaryExpression, needsValue bool) *ast.Node {
621638
location := node.Loc
622639
var value *ast.Node
623640
if ast.IsDestructuringAssignment(node.AsNode()) {
@@ -642,11 +659,12 @@ func (ch *objectRestSpreadTransformer) flattenDestructuringAssignment(node *ast.
642659
// If the right-hand value of the assignment is also an assignment target then
643660
// we need to cache the right-hand value.
644661
value = ch.ensureIdentifier(value, false, location)
645-
} else {
662+
} else if needsValue {
663+
// If the right-hand value of the destructuring assignment needs to be preserved (as
664+
// is the case when the destructuring assignment is part of a larger expression),
665+
// then we need to cache the right-hand value.
646666
value = ch.ensureIdentifier(value, true, location)
647-
}
648-
649-
if ast.NodeIsSynthesized(node.AsNode()) {
667+
} else if ast.NodeIsSynthesized(node.AsNode()) {
650668
// Generally, the source map location for a destructuring assignment is the root
651669
// expression.
652670
//
@@ -659,6 +677,13 @@ func (ch *objectRestSpreadTransformer) flattenDestructuringAssignment(node *ast.
659677

660678
ch.flattenBindingOrAssignmentElement(node.AsNode(), value, location, ast.IsDestructuringAssignment(node.AsNode()))
661679

680+
if value != nil && needsValue {
681+
if len(ch.ctx.currentExpressions) == 0 {
682+
return value
683+
}
684+
ch.ctx.currentExpressions = append(ch.ctx.currentExpressions, value)
685+
}
686+
662687
res := ch.Factory().InlineExpressions(ch.ctx.currentExpressions)
663688
if res != nil {
664689
return res

testdata/baselines/reference/submodule/compiler/destructuringAssignmentWithStrictNullChecks.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,5 @@ var __rest = (this && this.__rest) || function (s, e) {
1818
}
1919
return t;
2020
};
21-
var _a;
2221
let bar;
23-
(_a = {}, bar = __rest(_a, []));
22+
(bar = __rest({}, []));

testdata/baselines/reference/submodule/compiler/destructuringAssignmentWithStrictNullChecks.js.diff

Lines changed: 0 additions & 10 deletions
This file was deleted.

testdata/baselines/reference/submodule/compiler/nestedObjectRest.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ var __rest = (this && this.__rest) || function (s, e) {
2020
}
2121
return t;
2222
};
23-
var _a, _b, _c;
23+
var _a, _b;
2424
// https://github.com/microsoft/TypeScript/issues/43400
2525
var x, y;
26-
_a = [{ abc: 1 }], [_b] = _a, x = __rest(_b, []);
27-
for (let _d of [[{ abc: 1 }]]) {
28-
[_c] = _d, y = __rest(_c, []);
26+
[_a] = [{ abc: 1 }], x = __rest(_a, []);
27+
for (let _c of [[{ abc: 1 }]]) {
28+
[_b] = _c, y = __rest(_b, []);
2929
;
3030
}

testdata/baselines/reference/submodule/compiler/nestedObjectRest.js.diff

Lines changed: 0 additions & 18 deletions
This file was deleted.

testdata/baselines/reference/submodule/compiler/objectRestSpread.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,6 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar
5353
var _a, _b, _c, _d;
5454
let obj = {};
5555
(Object.assign({}, obj));
56-
let _e = {}, { prop = Object.assign({}, obj) } = _e, _f = _e.more, more = _f === void 0 ? (_a = Object.assign({}, obj), obj = __rest(_a, [])) : _f, _g = '' + 'other', _h = _e[_g], other = _h === void 0 ? Object.assign({}, obj) : _h, _j = _e.yetAnother, _k = _j === void 0 ? Object.assign({}, obj) : _j, _l = _k.nested, _m = _l === void 0 ? Object.assign({}, obj) : _l, _o = 'nested' + 'prop', _p = _m[_o], nestedProp = _p === void 0 ? Object.assign({}, obj) : _p, nestedRest = __rest(_m, [typeof _o === "symbol" ? _o : _o + ""]), { fn = function () { return __asyncGenerator(this, arguments, function* () { }); } } = _e, props = __rest(_e, ["prop", "more", typeof _g === "symbol" ? _g : _g + "", "yetAnother", "fn"]);
56+
let _e = {}, { prop = Object.assign({}, obj) } = _e, _f = _e.more, more = _f === void 0 ? (_a = Object.assign({}, obj), obj = __rest(_a, []), _a) : _f, _g = '' + 'other', _h = _e[_g], other = _h === void 0 ? Object.assign({}, obj) : _h, _j = _e.yetAnother, _k = _j === void 0 ? Object.assign({}, obj) : _j, _l = _k.nested, _m = _l === void 0 ? Object.assign({}, obj) : _l, _o = 'nested' + 'prop', _p = _m[_o], nestedProp = _p === void 0 ? Object.assign({}, obj) : _p, nestedRest = __rest(_m, [typeof _o === "symbol" ? _o : _o + ""]), { fn = function () { return __asyncGenerator(this, arguments, function* () { }); } } = _e, props = __rest(_e, ["prop", "more", typeof _g === "symbol" ? _g : _g + "", "yetAnother", "fn"]);
5757
(_b = {}, { prop = Object.assign({}, obj) } = _b, _c = '' + 'other', _d = _b[_c], other = _d === void 0 ? Object.assign({}, obj) : _d, props = __rest(_b, ["prop", typeof _c === "symbol" ? _c : _c + ""]));
5858
function test(_a) { var { prop = Object.assign({}, obj) } = _a, props = __rest(_a, ["prop"]); }

testdata/baselines/reference/submodule/compiler/objectRestSpread.js.diff

Lines changed: 0 additions & 10 deletions
This file was deleted.

testdata/baselines/reference/submodule/conformance/elementAccessChain.3.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ var __rest = (this && this.__rest) || function (s, e) {
4444
}
4545
return t;
4646
};
47-
var _a, _b;
4847
(obj === null || obj === void 0 ? void 0 : obj["a"])++;
4948
(obj === null || obj === void 0 ? void 0 : obj.a["b"])++;
5049
(obj === null || obj === void 0 ? void 0 : obj["a"])--;
@@ -67,7 +66,7 @@ for (obj === null || obj === void 0 ? void 0 : obj.a["b"] of [])
6766
;
6867
({ a: obj === null || obj === void 0 ? void 0 : obj["a"] } = { a: 1 });
6968
({ a: obj === null || obj === void 0 ? void 0 : obj.a["b"] } = { a: 1 });
70-
(_a = { a: 1 }, (obj === null || obj === void 0 ? void 0 : obj["a"]) = __rest(_a, []));
71-
(_b = { a: 1 }, (obj === null || obj === void 0 ? void 0 : obj.a["b"]) = __rest(_b, []));
69+
((obj === null || obj === void 0 ? void 0 : obj["a"]) = __rest({ a: 1 }, []));
70+
((obj === null || obj === void 0 ? void 0 : obj.a["b"]) = __rest({ a: 1 }, []));
7271
[...obj === null || obj === void 0 ? void 0 : obj["a"]] = [];
7372
[...obj === null || obj === void 0 ? void 0 : obj.a["b"]] = [];

testdata/baselines/reference/submodule/conformance/elementAccessChain.3.js.diff

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,6 @@
11
--- old.elementAccessChain.3.js
22
+++ new.elementAccessChain.3.js
3-
@@= skipped -43, +43 lines =@@
4-
}
5-
return t;
6-
};
7-
+var _a, _b;
8-
(obj === null || obj === void 0 ? void 0 : obj["a"])++;
9-
(obj === null || obj === void 0 ? void 0 : obj.a["b"])++;
10-
(obj === null || obj === void 0 ? void 0 : obj["a"])--;
11-
@@= skipped -8, +9 lines =@@
3+
@@= skipped -51, +51 lines =@@
124
++(obj === null || obj === void 0 ? void 0 : obj.a["b"]);
135
--(obj === null || obj === void 0 ? void 0 : obj["a"]);
146
--(obj === null || obj === void 0 ? void 0 : obj.a["b"]);
@@ -29,7 +21,7 @@
2921
({ a: obj === null || obj === void 0 ? void 0 : obj.a["b"] } = { a: 1 });
3022
-(obj === null || obj === void 0 ? void 0 : obj["a"] = __rest({ a: 1 }, []));
3123
-(obj === null || obj === void 0 ? void 0 : obj.a["b"] = __rest({ a: 1 }, []));
32-
+(_a = { a: 1 }, (obj === null || obj === void 0 ? void 0 : obj["a"]) = __rest(_a, []));
33-
+(_b = { a: 1 }, (obj === null || obj === void 0 ? void 0 : obj.a["b"]) = __rest(_b, []));
24+
+((obj === null || obj === void 0 ? void 0 : obj["a"]) = __rest({ a: 1 }, []));
25+
+((obj === null || obj === void 0 ? void 0 : obj.a["b"]) = __rest({ a: 1 }, []));
3426
[...obj === null || obj === void 0 ? void 0 : obj["a"]] = [];
3527
[...obj === null || obj === void 0 ? void 0 : obj.a["b"]] = [];

testdata/baselines/reference/submodule/conformance/privateWriteOnlyAccessorRead.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,15 @@ class Test {
5555
set #valueOne(v) { }
5656
set #valueCompound(v) { }
5757
m() {
58-
var _a, _b;
5958
const foo = { bar: 1 };
6059
console.log(this.#value); // error
6160
this.#value = { foo }; // ok
6261
this.#value = { foo }; // ok
6362
this.#value.foo = foo; // error
6463
({ o: this.#value } = { o: { foo } }); //ok
65-
(_a = { foo }, this.#value = __rest(_a, [])); //ok
64+
(this.#value = __rest({ foo }, [])); //ok
6665
({ foo: this.#value.foo } = { foo }); //error
67-
(_b = { foo }, this.#value.foo = __rest(_b.foo, [])); //error
66+
(this.#value.foo = __rest({ foo }.foo, [])); //error
6867
let r = { o: this.#value }; //error
6968
[this.#valueOne, ...this.#valueRest] = [1, 2, 3];
7069
let arr = [

0 commit comments

Comments
 (0)