From 5fb7ae9a427ed2c48f72b5e4609006c9b94d0753 Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Mon, 20 Sep 2021 01:15:15 -0400 Subject: [PATCH] Keep iife assignment in return statement for async/generators Fixes #1029 --- lib/compress/index.js | 10 ++- test/compress/dead-code.js | 154 +++++++++++++++++++++++++++++++++++++ 2 files changed, 163 insertions(+), 1 deletion(-) diff --git a/lib/compress/index.js b/lib/compress/index.js index b03525510..c7ce05e35 100644 --- a/lib/compress/index.js +++ b/lib/compress/index.js @@ -3587,7 +3587,15 @@ function is_reachable(self, defs) { if (node instanceof AST_Scope && node !== self) { var parent = info.parent(); - if (parent instanceof AST_Call && parent.expression === node) return; + if ( + parent instanceof AST_Call + && parent.expression === node + // Async/Generators aren't guaranteed to sync evaluate all of + // their body steps, so it's possible they close over the variable. + && !(node.async || node.is_generator) + ) { + return; + } if (walk(node, find_ref)) return walk_abort; diff --git a/test/compress/dead-code.js b/test/compress/dead-code.js index f4bbba435..7b5492780 100644 --- a/test/compress/dead-code.js +++ b/test/compress/dead-code.js @@ -1253,3 +1253,157 @@ issue_718: { export {y} } } + +issue_1029_1: { + options = { + dead_code: true, + } + input: { + function asyncFn() { + let promise; + return promise = (async () => { + await true; + console.log(promise); + })() + } + asyncFn({}); + } + expect: { + function asyncFn() { + let promise; + return promise = (async () => { + await true; + console.log(promise); + })(); + } + asyncFn({}); + } +} + +issue_1029_2: { + options = { + dead_code: true, + } + input: { + function asyncFn() { + let promise; + return promise = (async () => { + console.log(promise); + })() + } + asyncFn({}); + } + expect: { + function asyncFn() { + let promise; + return promise = (async () => { + console.log(promise); + })(); + } + asyncFn({}); + } +} + +issue_1029_3: { + options = { + dead_code: true, + } + input: { + function genFn() { + let gen; + return gen = function*() { + console.log(gen); + }(); + } + genFn({}).next(); + } + expect: { + function genFn() { + let gen; + return gen = function* () { + console.log(gen); + }(); + } + genFn({}).next(); + } +} + +issue_1029_4: { + options = { + dead_code: true, + } + input: { + function fn() { + let val + return val = function() { + console.log(val); + return {}; + }(); + } + fn(); + } + expect: { + function fn() { + let val + return function() { + console.log(val); + return {}; + }(); + } + fn(); + } +} + +issue_1029_5: { + options = { + dead_code: true, + } + input: { + function fn() { + let val + return val = function() { + setTimeout(() => console.log(val)); + return {}; + }(); + } + fn(); + } + expect: { + function fn() { + let val + return val = function() { + setTimeout(() => console.log(val)); + return {}; + }(); + } + fn(); + } +} + +issue_1029_6: { + options = { + dead_code: true, + } + input: { + function fn() { + let val + return val = function() { + setTimeout(() => { + (() => console.log(val))(); + }) + return {}; + }(); + } + fn(); + } + expect: { + function fn() { + let val + return val = function() { + setTimeout(() => console.log(val)); + return {}; + }(); + } + fn(); + } +}