Skip to content

Commit

Permalink
enhance unused (#5511)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexlamsl committed Jun 12, 2022
1 parent 5d69545 commit b6f250f
Show file tree
Hide file tree
Showing 4 changed files with 239 additions and 11 deletions.
58 changes: 47 additions & 11 deletions lib/compress.js
Expand Up @@ -6634,6 +6634,7 @@ Compressor.prototype.compress = function(node) {
var for_ins = Object.create(null);
var in_use = [];
var in_use_ids = Object.create(null); // avoid expensive linear scans of in_use
var lambda_ids = Object.create(null);
var value_read = Object.create(null);
var value_modified = Object.create(null);
var var_defs = Object.create(null);
Expand Down Expand Up @@ -6669,9 +6670,13 @@ Compressor.prototype.compress = function(node) {
in_use_ids[def.id] = true;
in_use.push(def);
}
if (node.extends) node.extends.walk(tw);
var used = tw.parent() instanceof AST_ExportDefault;
if (used) export_defaults[def.id] = true;
if (used) {
export_defaults[def.id] = true;
} else if (drop && !(def.id in lambda_ids)) {
lambda_ids[def.id] = 1;
}
if (node.extends) node.extends.walk(tw);
var values = [];
node.properties.forEach(function(prop) {
if (prop.key instanceof AST_Node) prop.key.walk(tw);
Expand All @@ -6691,16 +6696,18 @@ Compressor.prototype.compress = function(node) {
}
if (node instanceof AST_LambdaDefinition) {
var def = node.name.definition();
if ((!drop_funcs || def.exported) && !(def.id in in_use_ids)) {
var drop = drop_funcs && !def.exported;
if (!drop && !(def.id in in_use_ids)) {
in_use_ids[def.id] = true;
in_use.push(def);
}
initializations.add(def.id, node);
if (tw.parent() instanceof AST_ExportDefault) {
export_defaults[def.id] = true;
} else {
return true;
return;
}
if (drop && !(def.id in lambda_ids)) lambda_ids[def.id] = 1;
return true;
}
if (node instanceof AST_Definitions) {
node.definitions.forEach(function(defn) {
Expand Down Expand Up @@ -6730,6 +6737,7 @@ Compressor.prototype.compress = function(node) {
}
assignments.add(def.id, defn);
}
unmark_lambda(def);
return true;
}, tw);
if (side_effects) value.walk(tw);
Expand Down Expand Up @@ -6921,6 +6929,14 @@ Compressor.prototype.compress = function(node) {
});
}
}
if (node instanceof AST_Binary && node.operator == "instanceof") {
var sym = node.right;
if (!(sym instanceof AST_SymbolRef)) return;
if (sym.definition().id in in_use_ids) return;
var lhs = node.left.drop_side_effect_free(compressor);
var value = make_node(AST_False, node).optimize(compressor);
return lhs ? make_sequence(node, [ lhs, value ]) : value;
}
if (node instanceof AST_Call) {
calls_to_drop_args.push(node);
node.args = node.args.map(function(arg) {
Expand Down Expand Up @@ -7463,6 +7479,14 @@ Compressor.prototype.compress = function(node) {
return nodes && nodes.indexOf(node);
}

function unmark_lambda(def) {
if (lambda_ids[def.id] > 1 && !(def.id in in_use_ids)) {
in_use_ids[def.id] = true;
in_use.push(def);
}
lambda_ids[def.id] = 0;
}

function verify_safe_usage(def, read, modified) {
if (def.id in in_use_ids) return;
if (read && modified) {
Expand Down Expand Up @@ -7514,17 +7538,18 @@ Compressor.prototype.compress = function(node) {
var def = node.expression.definition();
if (def.scope.resolve() === self) assignments.add(def.id, node);
}
var node_def, props = [], sym = assign_as_unused(node, props);
if (sym && ((node_def = sym.definition()).scope.resolve() === self
|| self.variables.get(sym.name) === node_def)
&& !(is_arguments(node_def) && !all(self.argnames, function(argname) {
var props = [], sym = assign_as_unused(node, props);
if (sym) {
var node_def = sym.definition();
if (node_def.scope.resolve() !== self && self.variables.get(sym.name) !== node_def) return;
if (is_arguments(node_def) && !all(self.argnames, function(argname) {
return !argname.match_symbol(function(node) {
if (node instanceof AST_SymbolFunarg) {
var def = node.definition();
return def.references.length > def.replaced;
}
}, true);
}))) {
})) return;
if (node.write_only === "p" && node.right.may_throw_on_access(compressor, true)) return;
var assign = props.assign;
if (assign) {
Expand Down Expand Up @@ -7554,6 +7579,17 @@ Compressor.prototype.compress = function(node) {
}
}
if (track_assigns(node_def, sym) && is_lhs(sym, node) !== sym) add_assigns(node_def, sym);
unmark_lambda(node_def);
return true;
}
if (node instanceof AST_Binary) {
if (node.operator != "instanceof") return;
var sym = node.right;
if (!(sym instanceof AST_SymbolRef)) return;
var id = sym.definition().id;
if (!lambda_ids[id]) return;
node.left.walk(tw);
lambda_ids[id]++;
return true;
}
if (node instanceof AST_ForIn) {
Expand All @@ -7575,7 +7611,7 @@ Compressor.prototype.compress = function(node) {
return true;
}
if (node instanceof AST_SymbolRef) {
node_def = node.definition();
var node_def = node.definition();
if (!(node_def.id in in_use_ids)) {
in_use_ids[node_def.id] = true;
in_use.push(node_def);
Expand Down
82 changes: 82 additions & 0 deletions test/compress/classes.js
Expand Up @@ -1283,6 +1283,88 @@ instanceof_lambda: {
node_version: ">=4"
}

drop_instanceof: {
options = {
booleans: true,
toplevel: true,
unused: true,
}
input: {
"use strict";
class A {}
console.log({} instanceof A, Math instanceof A);
}
expect: {
"use strict";
console.log(!1, (Math, !1));
}
expect_stdout: "false false"
node_version: ">=4"
}

keep_instanceof_1: {
options = {
toplevel: true,
unused: true,
}
input: {
"use strict";
class A {}
var A;
console.log({} instanceof A, Math instanceof A);
}
expect: {
"use strict";
class A {}
var A;
console.log({} instanceof A, Math instanceof A);
}
expect_stdout: SyntaxError("Identifier has already been declared")
node_version: ">=4"
}

keep_instanceof_2: {
options = {
toplevel: true,
unused: true,
}
input: {
"use strict";
var A = Object;
class A {}
console.log({} instanceof A, Math instanceof A);
}
expect: {
"use strict";
var A = Object;
class A {}
console.log({} instanceof A, Math instanceof A);
}
expect_stdout: SyntaxError("Identifier has already been declared")
node_version: ">=4"
}

keep_instanceof_3: {
options = {
toplevel: true,
unused: true,
}
input: {
"use strict";
class A {}
A = Object;
console.log({} instanceof A, Math instanceof A);
}
expect: {
"use strict";
class A {}
A = Object;
console.log({} instanceof A, Math instanceof A);
}
expect_stdout: "true true"
node_version: ">=4"
}

issue_805_1: {
options = {
inline: true,
Expand Down
70 changes: 70 additions & 0 deletions test/compress/drop-unused.js
Expand Up @@ -671,6 +671,76 @@ iife: {
}
}

drop_instanceof: {
options = {
booleans: true,
toplevel: true,
unused: true,
}
input: {
function f() {}
console.log({} instanceof f, Math instanceof f);
}
expect: {
console.log(!1, (Math, !1));
}
expect_stdout: "false false"
}

keep_instanceof_1: {
options = {
toplevel: true,
unused: true,
}
input: {
function f() {}
var f;
console.log({} instanceof f, Math instanceof f);
}
expect: {
function f() {}
var f;
console.log({} instanceof f, Math instanceof f);
}
expect_stdout: "false false"
}

keep_instanceof_2: {
options = {
toplevel: true,
unused: true,
}
input: {
function f() {}
var f = Object;
console.log({} instanceof f, Math instanceof f);
}
expect: {
function f() {}
var f = Object;
console.log({} instanceof f, Math instanceof f);
}
expect_stdout: "true true"
}

keep_instanceof_3: {
options = {
toplevel: true,
unused: true,
}
input: {
f = Object;
function f() {}
console.log({} instanceof f, Math instanceof f);
}
expect: {
f = Object;
function f() {}
console.log({} instanceof f, Math instanceof f);
}
expect_stdout: "true true"
}

issue_1539: {
options = {
collapse_vars: true,
Expand Down
40 changes: 40 additions & 0 deletions test/compress/exports.js
Expand Up @@ -417,6 +417,46 @@ hoist_funs: {
expect_exact: "export function f(){}export default async function*g(){}"
}

instanceof_default_class: {
options = {
toplevel: true,
unused: true,
}
input: {
export default class A {
f(a) {
return a instanceof A;
}
}
}
expect: {
export default class A {
f(a) {
return a instanceof A;
}
}
}
}

instanceof_default_function: {
options = {
toplevel: true,
unused: true,
}
input: {
export default function f() {
if (!(this instanceof f))
throw new Error("must instantiate");
}
}
expect: {
export default function f() {
if (!(this instanceof f))
throw new Error("must instantiate");
}
}
}

issue_4742_join_vars_1: {
options = {
join_vars: true,
Expand Down

0 comments on commit b6f250f

Please sign in to comment.