diff --git a/lib/ast.js b/lib/ast.js index 01fd54b2..172e1964 100644 --- a/lib/ast.js +++ b/lib/ast.js @@ -908,7 +908,7 @@ var AST_ConciseMethod = DEFNODE("ConciseMethod", "quote static is_generator asyn $documentation: "An ES6 concise method inside an object or class" }, AST_ObjectProperty); -var AST_Class = DEFNODE("Class", "name extends properties", { +var AST_Class = DEFNODE("Class", "name extends properties inlined", { $propdoc: { name: "[AST_SymbolClass|AST_SymbolDefClass?] optional class name.", extends: "[AST_Node]? optional parent class", diff --git a/lib/compress.js b/lib/compress.js index b1f063f5..550cbbef 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -329,6 +329,7 @@ merge(Compressor.prototype, { value = node.fixed_value(); if (value && ref_once(d) && !compressor.exposed(d)) { d.single_use = value instanceof AST_Lambda + || value instanceof AST_Class || d.scope === node.scope && value.is_constant_expression(); } else { d.single_use = false; @@ -386,7 +387,7 @@ merge(Compressor.prototype, { } } } - if (node instanceof AST_Defun) { + if (node instanceof AST_DefClass || node instanceof AST_Defun) { node.inlined = false; var d = node.name.definition(); if (compressor.exposed(d) || safe_to_read(d)) { @@ -403,6 +404,13 @@ merge(Compressor.prototype, { safe_ids = save_ids; return true; } + if (node instanceof AST_ClassExpression) { + node.inlined = false; + push(); + descend(); + pop(); + return true; + } if (is_func_expr(node)) { node.inlined = false; push(); @@ -2385,9 +2393,8 @@ merge(Compressor.prototype, { return false; return true; } - def(AST_Node, return_false); - def(AST_Constant, return_true); - def(AST_Lambda, function(scope){ + + function all_refs_local(scope) { var self = this; var result = true; self.walk(new TreeWalker(function(node) { @@ -2413,7 +2420,12 @@ merge(Compressor.prototype, { } })); return result; - }); + } + + def(AST_Node, return_false); + def(AST_Constant, return_true); + def(AST_Class, all_refs_local); + def(AST_Lambda, all_refs_local); def(AST_Unary, function(){ return this.expression.is_constant_expression(); }); @@ -4599,12 +4611,15 @@ merge(Compressor.prototype, { && is_lhs(self, compressor.parent()) !== self) { var d = self.definition(); var fixed = self.fixed_value(); + if (fixed instanceof AST_DefClass) { + d.fixed = fixed = make_node(AST_ClassExpression, fixed, fixed); + } if (fixed instanceof AST_Defun) { d.fixed = fixed = make_node(AST_Function, fixed, fixed); } - if (d.single_use && is_func_expr(fixed)) { + if (d.single_use && (is_func_expr(fixed) || fixed instanceof AST_ClassExpression)) { if (d.scope !== self.scope - && (!compressor.option("reduce_funcs") + && (!compressor.option("reduce_funcs") && is_func_expr(fixed) || d.escaped || fixed.inlined)) { d.single_use = false; diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js index 692fd837..a246709b 100644 --- a/test/compress/reduce_vars.js +++ b/test/compress/reduce_vars.js @@ -4849,7 +4849,7 @@ issue_2496: { new Foo("FAIL").run(); } expect: { - class Foo { + new class { constructor(message) { this.message = message; } @@ -4864,9 +4864,26 @@ issue_2496: { this.go(); }); } - } - new Foo("FAIL").run(); + }("FAIL").run(); } expect_stdout: "PASS" node_version: ">=6" } + +issue_2416: { + options = { + keep_classnames: true, + reduce_vars: true, + toplevel: true, + unused: true, + } + input: { + class Foo {} + console.log(Foo.name); + } + expect: { + console.log((class Foo {}).name); + } + expect_stdout: "Foo" + node_version: ">=6" +} diff --git a/test/mocha/spidermonkey.js b/test/mocha/spidermonkey.js index ccd11c43..709b89e5 100644 --- a/test/mocha/spidermonkey.js +++ b/test/mocha/spidermonkey.js @@ -10,7 +10,7 @@ describe("spidermonkey export/import sanity test", function() { var command = uglifyjs + " --self -cm --wrap SpiderUglify -o spidermonkey | " + uglifyjs + " -p spidermonkey -cm"; - exec(command, function(err, stdout) { + exec(command, { maxBuffer: 1048576 }, function(err, stdout) { if (err) throw err; eval(stdout);