diff --git a/src/ast/nodes/ConditionalExpression.ts b/src/ast/nodes/ConditionalExpression.ts index 052a76702c5..d90eb639713 100644 --- a/src/ast/nodes/ConditionalExpression.ts +++ b/src/ast/nodes/ConditionalExpression.ts @@ -45,10 +45,12 @@ export default class ConditionalExpression extends NodeBase implements Deoptimiz if (this.usedBranch !== null) { const unusedBranch = this.usedBranch === this.consequent ? this.alternate : this.consequent; this.usedBranch = null; + const expressionsToBeDeoptimized = this.expressionsToBeDeoptimized; + this.expressionsToBeDeoptimized = []; if (this.wasPathDeoptimizedWhileOptimized) { unusedBranch.deoptimizePath(UNKNOWN_PATH); } - for (const expression of this.expressionsToBeDeoptimized) { + for (const expression of expressionsToBeDeoptimized) { expression.deoptimizeCache(); } } diff --git a/src/ast/nodes/LogicalExpression.ts b/src/ast/nodes/LogicalExpression.ts index 8dd2a628a4e..6d6ea9fd785 100644 --- a/src/ast/nodes/LogicalExpression.ts +++ b/src/ast/nodes/LogicalExpression.ts @@ -48,10 +48,12 @@ export default class LogicalExpression extends NodeBase implements Deoptimizable deoptimizeCache() { if (this.usedBranch !== null) { this.usedBranch = null; + const expressionsToBeDeoptimized = this.expressionsToBeDeoptimized; + this.expressionsToBeDeoptimized = []; if (this.wasPathDeoptimizedWhileOptimized) { this.unusedBranch!.deoptimizePath(UNKNOWN_PATH); } - for (const expression of this.expressionsToBeDeoptimized) { + for (const expression of expressionsToBeDeoptimized) { expression.deoptimizeCache(); } } diff --git a/src/ast/nodes/MemberExpression.ts b/src/ast/nodes/MemberExpression.ts index 8de9672fe15..099a1c3a274 100644 --- a/src/ast/nodes/MemberExpression.ts +++ b/src/ast/nodes/MemberExpression.ts @@ -115,11 +115,13 @@ export default class MemberExpression extends NodeBase implements DeoptimizableE } deoptimizeCache() { + const expressionsToBeDeoptimized = this.expressionsToBeDeoptimized; + this.expressionsToBeDeoptimized = []; this.propertyKey = UnknownKey; if (this.wasPathDeoptimizedWhileOptimized) { this.object.deoptimizePath(UNKNOWN_PATH); } - for (const expression of this.expressionsToBeDeoptimized) { + for (const expression of expressionsToBeDeoptimized) { expression.deoptimizeCache(); } } diff --git a/src/ast/variables/LocalVariable.ts b/src/ast/variables/LocalVariable.ts index cd4cbd681e6..56e21339be2 100644 --- a/src/ast/variables/LocalVariable.ts +++ b/src/ast/variables/LocalVariable.ts @@ -70,7 +70,9 @@ export default class LocalVariable extends Variable { if (path.length === 0) { if (!this.isReassigned) { this.isReassigned = true; - for (const expression of this.expressionsToBeDeoptimized) { + const expressionsToBeDeoptimized = this.expressionsToBeDeoptimized; + this.expressionsToBeDeoptimized = []; + for (const expression of expressionsToBeDeoptimized) { expression.deoptimizeCache(); } if (this.init) { diff --git a/test/form/samples/recursive-assignments/_expected/es.js b/test/form/samples/recursive-assignments/_expected.js similarity index 100% rename from test/form/samples/recursive-assignments/_expected/es.js rename to test/form/samples/recursive-assignments/_expected.js diff --git a/test/form/samples/recursive-assignments/_expected/amd.js b/test/form/samples/recursive-assignments/_expected/amd.js deleted file mode 100644 index 9dd7aaebe68..00000000000 --- a/test/form/samples/recursive-assignments/_expected/amd.js +++ /dev/null @@ -1,15 +0,0 @@ -define(function () { 'use strict'; - - let foo = () => function () {}; - foo.value = foo; - - while ( foo.value ) { - foo = foo.value; - } - - foo(); - foo()(); - new (foo())(); - foo.bar = 1; - -}); diff --git a/test/form/samples/recursive-assignments/_expected/cjs.js b/test/form/samples/recursive-assignments/_expected/cjs.js deleted file mode 100644 index 5cbf3b4ab1d..00000000000 --- a/test/form/samples/recursive-assignments/_expected/cjs.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict'; - -let foo = () => function () {}; -foo.value = foo; - -while ( foo.value ) { - foo = foo.value; -} - -foo(); -foo()(); -new (foo())(); -foo.bar = 1; diff --git a/test/form/samples/recursive-assignments/_expected/iife.js b/test/form/samples/recursive-assignments/_expected/iife.js deleted file mode 100644 index b8be3815254..00000000000 --- a/test/form/samples/recursive-assignments/_expected/iife.js +++ /dev/null @@ -1,16 +0,0 @@ -(function () { - 'use strict'; - - let foo = () => function () {}; - foo.value = foo; - - while ( foo.value ) { - foo = foo.value; - } - - foo(); - foo()(); - new (foo())(); - foo.bar = 1; - -}()); diff --git a/test/form/samples/recursive-assignments/_expected/system.js b/test/form/samples/recursive-assignments/_expected/system.js deleted file mode 100644 index 17e2926482e..00000000000 --- a/test/form/samples/recursive-assignments/_expected/system.js +++ /dev/null @@ -1,20 +0,0 @@ -System.register([], function () { - 'use strict'; - return { - execute: function () { - - let foo = () => function () {}; - foo.value = foo; - - while ( foo.value ) { - foo = foo.value; - } - - foo(); - foo()(); - new (foo())(); - foo.bar = 1; - - } - }; -}); diff --git a/test/form/samples/recursive-assignments/_expected/umd.js b/test/form/samples/recursive-assignments/_expected/umd.js deleted file mode 100644 index c917270abda..00000000000 --- a/test/form/samples/recursive-assignments/_expected/umd.js +++ /dev/null @@ -1,18 +0,0 @@ -(function (factory) { - typeof define === 'function' && define.amd ? define(factory) : - factory(); -}((function () { 'use strict'; - - let foo = () => function () {}; - foo.value = foo; - - while ( foo.value ) { - foo = foo.value; - } - - foo(); - foo()(); - new (foo())(); - foo.bar = 1; - -}))); diff --git a/test/form/samples/self-deoptimization/_config.js b/test/form/samples/self-deoptimization/_config.js new file mode 100644 index 00000000000..d86ca391dc4 --- /dev/null +++ b/test/form/samples/self-deoptimization/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'handles situations where a member expression is deoptimized while being deoptimized' +}; diff --git a/test/form/samples/self-deoptimization/_expected.js b/test/form/samples/self-deoptimization/_expected.js new file mode 100644 index 00000000000..9af4a91d8ba --- /dev/null +++ b/test/form/samples/self-deoptimization/_expected.js @@ -0,0 +1,10 @@ +function foo(a) { + var b = bar({}, a); + b && b.delete(); +} + +function bar(a, b) { + return (b = 1) ? a.a[b] || null : null; +} + +foo({}); diff --git a/test/form/samples/self-deoptimization/main.js b/test/form/samples/self-deoptimization/main.js new file mode 100644 index 00000000000..9af4a91d8ba --- /dev/null +++ b/test/form/samples/self-deoptimization/main.js @@ -0,0 +1,10 @@ +function foo(a) { + var b = bar({}, a); + b && b.delete(); +} + +function bar(a, b) { + return (b = 1) ? a.a[b] || null : null; +} + +foo({});