diff --git a/lib/compress.js b/lib/compress.js index 846c391b28..8ec9ab887c 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -5817,19 +5817,29 @@ merge(Compressor.prototype, { } else if (node instanceof AST_Unary) { if (node.write_only) sym = node.expression; } - if (/strict/.test(compressor.option("pure_getters"))) { - while (sym instanceof AST_PropAccess && !sym.expression.may_throw_on_access(compressor)) { - if (sym instanceof AST_Sub) props.unshift(sym.property); - sym = sym.expression; - nested = true; - } - } + if (/strict/.test(compressor.option("pure_getters"))) sym = extract_reference(sym, props); if (!(sym instanceof AST_SymbolRef)) return; var def = sym.definition(); if (export_defaults[def.id]) return; if (compressor.exposed(def)) return; if (!can_drop_symbol(sym, compressor, nested)) return; return sym; + + function extract_reference(node, props) { + if (node instanceof AST_PropAccess) { + var expr = node.expression; + if (!expr.may_throw_on_access(compressor)) { + nested = true; + if (props && node instanceof AST_Sub) props.unshift(node.property); + return extract_reference(expr, props); + } + } else if (node instanceof AST_Assign && node.operator == "=") { + var ref = extract_reference(node.right); + if (props) props.assign = node; + return ref; + } + return node; + } }; var assign_in_use = Object.create(null); var export_defaults = Object.create(null); @@ -6648,6 +6658,11 @@ merge(Compressor.prototype, { } }, true); }))) { + if (props.assign) { + props.assign.write_only = true; + props.assign.walk(tw); + delete props.assign.write_only; + } props.forEach(function(prop) { prop.walk(tw); }); diff --git a/test/compress/classes.js b/test/compress/classes.js index ca9ddfdddd..e8bff7528c 100644 --- a/test/compress/classes.js +++ b/test/compress/classes.js @@ -1541,3 +1541,23 @@ issue_4848: { expect_stdout: "PASS" node_version: ">=4" } + +drop_unused_self_reference: { + options = { + pure_getters: "strict", + reduce_vars: true, + toplevel: true, + unused: true, + } + input: { + "use strict"; + class A {} + (A.p = A).q = console.log("PASS"); + } + expect: { + "use strict"; + console.log("PASS"); + } + expect_stdout: "PASS" + node_version: ">=4" +} diff --git a/test/compress/functions.js b/test/compress/functions.js index 4d4cb66de3..3d19f497e0 100644 --- a/test/compress/functions.js +++ b/test/compress/functions.js @@ -6021,3 +6021,20 @@ issue_4823: { } expect_stdout: "function" } + +drop_unused_self_reference: { + options = { + pure_getters: "strict", + reduce_vars: true, + toplevel: true, + unused: true, + } + input: { + function f() {} + (f.p = f).q = console.log("PASS"); + } + expect: { + console.log("PASS"); + } + expect_stdout: "PASS" +} diff --git a/test/ufuzz/index.js b/test/ufuzz/index.js index 69760b220c..7210c6b21a 100644 --- a/test/ufuzz/index.js +++ b/test/ufuzz/index.js @@ -1796,7 +1796,7 @@ function createClassLiteral(recurmax, stmtDepth, canThrow, name) { if (SUPPORT.class_field && rng(2)) { s += internal || createObjectKey(recurmax, stmtDepth, canThrow); if (rng(5)) { - async = bug_async_class_await && fixed; + async = bug_async_class_await && fixed && 0; generator = false; s += " = " + createExpression(recurmax, NO_COMMA, stmtDepth, fixed ? canThrow : CANNOT_THROW); generator = save_generator; @@ -2000,7 +2000,7 @@ function isBannedKeyword(name) { case "arguments": return in_class; case "await": - return async; + return async !== false; case "yield": return generator || in_class; }