Avoid effect of element access expression (#39174)
* Avoid effect of element access expression * Avoid unnecessary copy * Add more tests
This commit is contained in:
parent
d610bbdaef
commit
6b4d0bff40
|
@ -25,7 +25,7 @@ namespace ts {
|
|||
if (isLogicalOrCoalescingAssignmentExpression(binaryExpression)) {
|
||||
return transformLogicalAssignment(binaryExpression);
|
||||
}
|
||||
// falls through
|
||||
// falls through
|
||||
default:
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
@ -37,32 +37,41 @@ namespace ts {
|
|||
let left = skipParentheses(visitNode(binaryExpression.left, visitor, isLeftHandSideExpression));
|
||||
let assignmentTarget = left;
|
||||
const right = skipParentheses(visitNode(binaryExpression.right, visitor, isExpression));
|
||||
|
||||
if (isAccessExpression(left)) {
|
||||
const tempVariable = factory.createTempVariable(hoistVariableDeclaration);
|
||||
const propertyAccessTargetSimpleCopiable = isSimpleCopiableExpression(left.expression);
|
||||
const propertyAccessTarget = propertyAccessTargetSimpleCopiable ? left.expression :
|
||||
factory.createTempVariable(hoistVariableDeclaration);
|
||||
const propertyAccessTargetAssignment = propertyAccessTargetSimpleCopiable ? left.expression : factory.createAssignment(
|
||||
propertyAccessTarget,
|
||||
left.expression
|
||||
);
|
||||
|
||||
if (isPropertyAccessExpression(left)) {
|
||||
assignmentTarget = factory.createPropertyAccessExpression(
|
||||
tempVariable,
|
||||
propertyAccessTarget,
|
||||
left.name
|
||||
);
|
||||
left = factory.createPropertyAccessExpression(
|
||||
factory.createAssignment(
|
||||
tempVariable,
|
||||
left.expression
|
||||
),
|
||||
propertyAccessTargetAssignment,
|
||||
left.name
|
||||
);
|
||||
}
|
||||
else {
|
||||
const elementAccessArgumentSimpleCopiable = isSimpleCopiableExpression(left.argumentExpression);
|
||||
const elementAccessArgument = elementAccessArgumentSimpleCopiable ? left.argumentExpression :
|
||||
factory.createTempVariable(hoistVariableDeclaration);
|
||||
|
||||
assignmentTarget = factory.createElementAccessExpression(
|
||||
tempVariable,
|
||||
left.argumentExpression
|
||||
propertyAccessTarget,
|
||||
elementAccessArgument
|
||||
);
|
||||
left = factory.createElementAccessExpression(
|
||||
factory.createAssignment(
|
||||
tempVariable,
|
||||
left.expression
|
||||
),
|
||||
left.argumentExpression
|
||||
propertyAccessTargetAssignment,
|
||||
elementAccessArgumentSimpleCopiable ? left.argumentExpression : factory.createAssignment(
|
||||
elementAccessArgument,
|
||||
left.argumentExpression
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
//// [logicalAssignment10.ts]
|
||||
var count = 0;
|
||||
var obj = {};
|
||||
function incr() {
|
||||
return ++count;
|
||||
}
|
||||
|
||||
const oobj = {
|
||||
obj
|
||||
}
|
||||
|
||||
obj[incr()] ??= incr();
|
||||
oobj["obj"][incr()] ??= incr();
|
||||
|
||||
|
||||
//// [logicalAssignment10.js]
|
||||
var _a, _b;
|
||||
var _c, _d, _e;
|
||||
var count = 0;
|
||||
var obj = {};
|
||||
function incr() {
|
||||
return ++count;
|
||||
}
|
||||
const oobj = {
|
||||
obj
|
||||
};
|
||||
(_a = obj[_c = incr()]) !== null && _a !== void 0 ? _a : (obj[_c] = incr());
|
||||
(_b = (_d = oobj["obj"])[_e = incr()]) !== null && _b !== void 0 ? _b : (_d[_e] = incr());
|
|
@ -0,0 +1,32 @@
|
|||
=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment10.ts ===
|
||||
var count = 0;
|
||||
>count : Symbol(count, Decl(logicalAssignment10.ts, 0, 3))
|
||||
|
||||
var obj = {};
|
||||
>obj : Symbol(obj, Decl(logicalAssignment10.ts, 1, 3))
|
||||
|
||||
function incr() {
|
||||
>incr : Symbol(incr, Decl(logicalAssignment10.ts, 1, 13))
|
||||
|
||||
return ++count;
|
||||
>count : Symbol(count, Decl(logicalAssignment10.ts, 0, 3))
|
||||
}
|
||||
|
||||
const oobj = {
|
||||
>oobj : Symbol(oobj, Decl(logicalAssignment10.ts, 6, 5))
|
||||
|
||||
obj
|
||||
>obj : Symbol(obj, Decl(logicalAssignment10.ts, 6, 14))
|
||||
}
|
||||
|
||||
obj[incr()] ??= incr();
|
||||
>obj : Symbol(obj, Decl(logicalAssignment10.ts, 1, 3))
|
||||
>incr : Symbol(incr, Decl(logicalAssignment10.ts, 1, 13))
|
||||
>incr : Symbol(incr, Decl(logicalAssignment10.ts, 1, 13))
|
||||
|
||||
oobj["obj"][incr()] ??= incr();
|
||||
>oobj : Symbol(oobj, Decl(logicalAssignment10.ts, 6, 5))
|
||||
>"obj" : Symbol(obj, Decl(logicalAssignment10.ts, 6, 14))
|
||||
>incr : Symbol(incr, Decl(logicalAssignment10.ts, 1, 13))
|
||||
>incr : Symbol(incr, Decl(logicalAssignment10.ts, 1, 13))
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment10.ts ===
|
||||
var count = 0;
|
||||
>count : number
|
||||
>0 : 0
|
||||
|
||||
var obj = {};
|
||||
>obj : {}
|
||||
>{} : {}
|
||||
|
||||
function incr() {
|
||||
>incr : () => number
|
||||
|
||||
return ++count;
|
||||
>++count : number
|
||||
>count : number
|
||||
}
|
||||
|
||||
const oobj = {
|
||||
>oobj : { obj: {}; }
|
||||
>{ obj} : { obj: {}; }
|
||||
|
||||
obj
|
||||
>obj : {}
|
||||
}
|
||||
|
||||
obj[incr()] ??= incr();
|
||||
>obj[incr()] ??= incr() : any
|
||||
>obj[incr()] : error
|
||||
>obj : {}
|
||||
>incr() : number
|
||||
>incr : () => number
|
||||
>incr() : number
|
||||
>incr : () => number
|
||||
|
||||
oobj["obj"][incr()] ??= incr();
|
||||
>oobj["obj"][incr()] ??= incr() : any
|
||||
>oobj["obj"][incr()] : error
|
||||
>oobj["obj"] : {}
|
||||
>oobj : { obj: {}; }
|
||||
>"obj" : "obj"
|
||||
>incr() : number
|
||||
>incr : () => number
|
||||
>incr() : number
|
||||
>incr : () => number
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
//// [logicalAssignment10.ts]
|
||||
var count = 0;
|
||||
var obj = {};
|
||||
function incr() {
|
||||
return ++count;
|
||||
}
|
||||
|
||||
const oobj = {
|
||||
obj
|
||||
}
|
||||
|
||||
obj[incr()] ??= incr();
|
||||
oobj["obj"][incr()] ??= incr();
|
||||
|
||||
|
||||
//// [logicalAssignment10.js]
|
||||
var _a, _b, _c;
|
||||
var count = 0;
|
||||
var obj = {};
|
||||
function incr() {
|
||||
return ++count;
|
||||
}
|
||||
const oobj = {
|
||||
obj
|
||||
};
|
||||
obj[_a = incr()] ?? (obj[_a] = incr());
|
||||
(_b = oobj["obj"])[_c = incr()] ?? (_b[_c] = incr());
|
|
@ -0,0 +1,32 @@
|
|||
=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment10.ts ===
|
||||
var count = 0;
|
||||
>count : Symbol(count, Decl(logicalAssignment10.ts, 0, 3))
|
||||
|
||||
var obj = {};
|
||||
>obj : Symbol(obj, Decl(logicalAssignment10.ts, 1, 3))
|
||||
|
||||
function incr() {
|
||||
>incr : Symbol(incr, Decl(logicalAssignment10.ts, 1, 13))
|
||||
|
||||
return ++count;
|
||||
>count : Symbol(count, Decl(logicalAssignment10.ts, 0, 3))
|
||||
}
|
||||
|
||||
const oobj = {
|
||||
>oobj : Symbol(oobj, Decl(logicalAssignment10.ts, 6, 5))
|
||||
|
||||
obj
|
||||
>obj : Symbol(obj, Decl(logicalAssignment10.ts, 6, 14))
|
||||
}
|
||||
|
||||
obj[incr()] ??= incr();
|
||||
>obj : Symbol(obj, Decl(logicalAssignment10.ts, 1, 3))
|
||||
>incr : Symbol(incr, Decl(logicalAssignment10.ts, 1, 13))
|
||||
>incr : Symbol(incr, Decl(logicalAssignment10.ts, 1, 13))
|
||||
|
||||
oobj["obj"][incr()] ??= incr();
|
||||
>oobj : Symbol(oobj, Decl(logicalAssignment10.ts, 6, 5))
|
||||
>"obj" : Symbol(obj, Decl(logicalAssignment10.ts, 6, 14))
|
||||
>incr : Symbol(incr, Decl(logicalAssignment10.ts, 1, 13))
|
||||
>incr : Symbol(incr, Decl(logicalAssignment10.ts, 1, 13))
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment10.ts ===
|
||||
var count = 0;
|
||||
>count : number
|
||||
>0 : 0
|
||||
|
||||
var obj = {};
|
||||
>obj : {}
|
||||
>{} : {}
|
||||
|
||||
function incr() {
|
||||
>incr : () => number
|
||||
|
||||
return ++count;
|
||||
>++count : number
|
||||
>count : number
|
||||
}
|
||||
|
||||
const oobj = {
|
||||
>oobj : { obj: {}; }
|
||||
>{ obj} : { obj: {}; }
|
||||
|
||||
obj
|
||||
>obj : {}
|
||||
}
|
||||
|
||||
obj[incr()] ??= incr();
|
||||
>obj[incr()] ??= incr() : any
|
||||
>obj[incr()] : error
|
||||
>obj : {}
|
||||
>incr() : number
|
||||
>incr : () => number
|
||||
>incr() : number
|
||||
>incr : () => number
|
||||
|
||||
oobj["obj"][incr()] ??= incr();
|
||||
>oobj["obj"][incr()] ??= incr() : any
|
||||
>oobj["obj"][incr()] : error
|
||||
>oobj["obj"] : {}
|
||||
>oobj : { obj: {}; }
|
||||
>"obj" : "obj"
|
||||
>incr() : number
|
||||
>incr : () => number
|
||||
>incr() : number
|
||||
>incr : () => number
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
//// [logicalAssignment10.ts]
|
||||
var count = 0;
|
||||
var obj = {};
|
||||
function incr() {
|
||||
return ++count;
|
||||
}
|
||||
|
||||
const oobj = {
|
||||
obj
|
||||
}
|
||||
|
||||
obj[incr()] ??= incr();
|
||||
oobj["obj"][incr()] ??= incr();
|
||||
|
||||
|
||||
//// [logicalAssignment10.js]
|
||||
var count = 0;
|
||||
var obj = {};
|
||||
function incr() {
|
||||
return ++count;
|
||||
}
|
||||
const oobj = {
|
||||
obj
|
||||
};
|
||||
obj[incr()] ??= incr();
|
||||
oobj["obj"][incr()] ??= incr();
|
|
@ -0,0 +1,32 @@
|
|||
=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment10.ts ===
|
||||
var count = 0;
|
||||
>count : Symbol(count, Decl(logicalAssignment10.ts, 0, 3))
|
||||
|
||||
var obj = {};
|
||||
>obj : Symbol(obj, Decl(logicalAssignment10.ts, 1, 3))
|
||||
|
||||
function incr() {
|
||||
>incr : Symbol(incr, Decl(logicalAssignment10.ts, 1, 13))
|
||||
|
||||
return ++count;
|
||||
>count : Symbol(count, Decl(logicalAssignment10.ts, 0, 3))
|
||||
}
|
||||
|
||||
const oobj = {
|
||||
>oobj : Symbol(oobj, Decl(logicalAssignment10.ts, 6, 5))
|
||||
|
||||
obj
|
||||
>obj : Symbol(obj, Decl(logicalAssignment10.ts, 6, 14))
|
||||
}
|
||||
|
||||
obj[incr()] ??= incr();
|
||||
>obj : Symbol(obj, Decl(logicalAssignment10.ts, 1, 3))
|
||||
>incr : Symbol(incr, Decl(logicalAssignment10.ts, 1, 13))
|
||||
>incr : Symbol(incr, Decl(logicalAssignment10.ts, 1, 13))
|
||||
|
||||
oobj["obj"][incr()] ??= incr();
|
||||
>oobj : Symbol(oobj, Decl(logicalAssignment10.ts, 6, 5))
|
||||
>"obj" : Symbol(obj, Decl(logicalAssignment10.ts, 6, 14))
|
||||
>incr : Symbol(incr, Decl(logicalAssignment10.ts, 1, 13))
|
||||
>incr : Symbol(incr, Decl(logicalAssignment10.ts, 1, 13))
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment10.ts ===
|
||||
var count = 0;
|
||||
>count : number
|
||||
>0 : 0
|
||||
|
||||
var obj = {};
|
||||
>obj : {}
|
||||
>{} : {}
|
||||
|
||||
function incr() {
|
||||
>incr : () => number
|
||||
|
||||
return ++count;
|
||||
>++count : number
|
||||
>count : number
|
||||
}
|
||||
|
||||
const oobj = {
|
||||
>oobj : { obj: {}; }
|
||||
>{ obj} : { obj: {}; }
|
||||
|
||||
obj
|
||||
>obj : {}
|
||||
}
|
||||
|
||||
obj[incr()] ??= incr();
|
||||
>obj[incr()] ??= incr() : any
|
||||
>obj[incr()] : error
|
||||
>obj : {}
|
||||
>incr() : number
|
||||
>incr : () => number
|
||||
>incr() : number
|
||||
>incr : () => number
|
||||
|
||||
oobj["obj"][incr()] ??= incr();
|
||||
>oobj["obj"][incr()] ??= incr() : any
|
||||
>oobj["obj"][incr()] : error
|
||||
>oobj["obj"] : {}
|
||||
>oobj : { obj: {}; }
|
||||
>"obj" : "obj"
|
||||
>incr() : number
|
||||
>incr : () => number
|
||||
>incr() : number
|
||||
>incr : () => number
|
||||
|
|
@ -31,13 +31,13 @@ c.foo.bar().baz ??= result.foo.bar().baz
|
|||
//// [logicalAssignment2.js]
|
||||
"use strict";
|
||||
var _a, _b, _c;
|
||||
var _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
||||
(_d = a).baz && (_d.baz = result.baz);
|
||||
(_e = b).baz || (_e.baz = result.baz);
|
||||
(_a = (_f = c).baz) !== null && _a !== void 0 ? _a : (_f.baz = result.baz);
|
||||
(_g = a.foo)["baz"] && (_g["baz"] = result.foo.baz);
|
||||
(_h = b.foo)["baz"] || (_h["baz"] = result.foo.baz);
|
||||
(_b = (_j = c.foo)["baz"]) !== null && _b !== void 0 ? _b : (_j["baz"] = result.foo.baz);
|
||||
(_k = a.foo.bar()).baz && (_k.baz = result.foo.bar().baz);
|
||||
(_l = b.foo.bar()).baz || (_l.baz = result.foo.bar().baz);
|
||||
(_c = (_m = c.foo.bar()).baz) !== null && _c !== void 0 ? _c : (_m.baz = result.foo.bar().baz);
|
||||
var _d, _e, _f, _g, _h, _j;
|
||||
a.baz && (a.baz = result.baz);
|
||||
b.baz || (b.baz = result.baz);
|
||||
(_a = c.baz) !== null && _a !== void 0 ? _a : (c.baz = result.baz);
|
||||
(_d = a.foo)["baz"] && (_d["baz"] = result.foo.baz);
|
||||
(_e = b.foo)["baz"] || (_e["baz"] = result.foo.baz);
|
||||
(_b = (_f = c.foo)["baz"]) !== null && _b !== void 0 ? _b : (_f["baz"] = result.foo.baz);
|
||||
(_g = a.foo.bar()).baz && (_g.baz = result.foo.bar().baz);
|
||||
(_h = b.foo.bar()).baz || (_h.baz = result.foo.bar().baz);
|
||||
(_c = (_j = c.foo.bar()).baz) !== null && _c !== void 0 ? _c : (_j.baz = result.foo.bar().baz);
|
||||
|
|
|
@ -30,13 +30,13 @@ c.foo.bar().baz ??= result.foo.bar().baz
|
|||
|
||||
//// [logicalAssignment2.js]
|
||||
"use strict";
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
||||
(_a = a).baz && (_a.baz = result.baz);
|
||||
(_b = b).baz || (_b.baz = result.baz);
|
||||
(_c = c).baz ?? (_c.baz = result.baz);
|
||||
(_d = a.foo)["baz"] && (_d["baz"] = result.foo.baz);
|
||||
(_e = b.foo)["baz"] || (_e["baz"] = result.foo.baz);
|
||||
(_f = c.foo)["baz"] ?? (_f["baz"] = result.foo.baz);
|
||||
(_g = a.foo.bar()).baz && (_g.baz = result.foo.bar().baz);
|
||||
(_h = b.foo.bar()).baz || (_h.baz = result.foo.bar().baz);
|
||||
(_j = c.foo.bar()).baz ?? (_j.baz = result.foo.bar().baz);
|
||||
var _a, _b, _c, _d, _e, _f;
|
||||
a.baz && (a.baz = result.baz);
|
||||
b.baz || (b.baz = result.baz);
|
||||
c.baz ?? (c.baz = result.baz);
|
||||
(_a = a.foo)["baz"] && (_a["baz"] = result.foo.baz);
|
||||
(_b = b.foo)["baz"] || (_b["baz"] = result.foo.baz);
|
||||
(_c = c.foo)["baz"] ?? (_c["baz"] = result.foo.baz);
|
||||
(_d = a.foo.bar()).baz && (_d.baz = result.foo.bar().baz);
|
||||
(_e = b.foo.bar()).baz || (_e.baz = result.foo.bar().baz);
|
||||
(_f = c.foo.bar()).baz ?? (_f.baz = result.foo.bar().baz);
|
||||
|
|
|
@ -17,7 +17,6 @@ declare const c: A;
|
|||
//// [logicalAssignment3.js]
|
||||
"use strict";
|
||||
var _a;
|
||||
var _b, _c, _d;
|
||||
(_b = a).baz && (_b.baz = result.baz);
|
||||
(_c = b).baz || (_c.baz = result.baz);
|
||||
(_a = (_d = c).baz) !== null && _a !== void 0 ? _a : (_d.baz = result.baz);
|
||||
a.baz && (a.baz = result.baz);
|
||||
b.baz || (b.baz = result.baz);
|
||||
(_a = c.baz) !== null && _a !== void 0 ? _a : (c.baz = result.baz);
|
||||
|
|
|
@ -16,7 +16,6 @@ declare const c: A;
|
|||
|
||||
//// [logicalAssignment3.js]
|
||||
"use strict";
|
||||
var _a, _b, _c;
|
||||
(_a = a).baz && (_a.baz = result.baz);
|
||||
(_b = b).baz || (_b.baz = result.baz);
|
||||
(_c = c).baz ?? (_c.baz = result.baz);
|
||||
a.baz && (a.baz = result.baz);
|
||||
b.baz || (b.baz = result.baz);
|
||||
c.baz ?? (c.baz = result.baz);
|
||||
|
|
|
@ -8,6 +8,5 @@ x.a &&= false;
|
|||
//// [logicalAssignment9.js]
|
||||
"use strict";
|
||||
var _a;
|
||||
var _b, _c;
|
||||
(_a = (_b = x).a) !== null && _a !== void 0 ? _a : (_b.a = true);
|
||||
(_c = x).a && (_c.a = false);
|
||||
(_a = x.a) !== null && _a !== void 0 ? _a : (x.a = true);
|
||||
x.a && (x.a = false);
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
// @target: esnext, es2020, es2015
|
||||
|
||||
var count = 0;
|
||||
var obj = {};
|
||||
function incr() {
|
||||
return ++count;
|
||||
}
|
||||
|
||||
const oobj = {
|
||||
obj
|
||||
}
|
||||
|
||||
obj[incr()] ??= incr();
|
||||
oobj["obj"][incr()] ??= incr();
|
Loading…
Reference in a new issue