From 4fe630431c37ffb81466959e9ea9797d6d2de21a Mon Sep 17 00:00:00 2001 From: Richard van Velzen Date: Sat, 23 Apr 2016 23:48:33 +0200 Subject: [PATCH 1/3] Hoist functions when reversing if (x) return; ... vs. if (!x) ... Fixes #1052 --- lib/compress.js | 18 ++++++++++++++++-- test/compress/issue-1052.js | 27 +++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 test/compress/issue-1052.js diff --git a/lib/compress.js b/lib/compress.js index 53618ae1..2bcfcf30 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -578,11 +578,13 @@ merge(Compressor.prototype, { CHANGED = true; stat = stat.clone(); stat.condition = stat.condition.negate(compressor); + var body = as_statement_array(stat.alternative).concat(ret); + var funs = extract_functions_from_statement_array(body); stat.body = make_node(AST_BlockStatement, stat, { - body: as_statement_array(stat.alternative).concat(ret) + body: body }); stat.alternative = null; - ret = [ stat.transform(compressor) ]; + ret = funs.concat([ stat.transform(compressor) ]); continue loop; } //--- @@ -840,6 +842,18 @@ merge(Compressor.prototype, { }; + function extract_functions_from_statement_array(statements) { + var funs = []; + for (var i = statements.length - 1; i >= 0; --i) { + var stat = statements[i]; + if (stat instanceof AST_Defun) { + statements.splice(i, 1); + funs.unshift(stat); + } + } + return funs; + } + function extract_declarations_from_unreachable_code(compressor, stat, target) { if (!(stat instanceof AST_Defun)) { compressor.warn("Dropping unreachable code [{file}:{line},{col}]", stat.start); diff --git a/test/compress/issue-1052.js b/test/compress/issue-1052.js new file mode 100644 index 00000000..067eea4a --- /dev/null +++ b/test/compress/issue-1052.js @@ -0,0 +1,27 @@ +hoist_funs_when_handling_if_return_rerversal: { + options = { if_return: true, hoist_funs: false }; + input: { + "use strict"; + + ( function() { + if ( !window ) { + return; + } + + function f() {} + function g() {} + } )(); + } + expect: { + "use strict"; + + ( function() { + function f() {} + function g() {} + + // NOTE: other compression steps will reduce this + // down to just `window`. + if ( window ); + } )(); + } +} From 4d9a0856870fc8feb07771fe2e27d93c8613e857 Mon Sep 17 00:00:00 2001 From: Richard van Velzen Date: Tue, 26 Apr 2016 11:43:03 +0200 Subject: [PATCH 2/3] Add test case for hoisting a single function --- test/compress/issue-1052.js | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/test/compress/issue-1052.js b/test/compress/issue-1052.js index 067eea4a..bad28a8f 100644 --- a/test/compress/issue-1052.js +++ b/test/compress/issue-1052.js @@ -1,8 +1,6 @@ -hoist_funs_when_handling_if_return_rerversal: { +multiple_functions: { options = { if_return: true, hoist_funs: false }; input: { - "use strict"; - ( function() { if ( !window ) { return; @@ -13,8 +11,6 @@ hoist_funs_when_handling_if_return_rerversal: { } )(); } expect: { - "use strict"; - ( function() { function f() {} function g() {} @@ -25,3 +21,23 @@ hoist_funs_when_handling_if_return_rerversal: { } )(); } } + +single_function: { + options = { if_return: true, hoist_funs: false }; + input: { + ( function() { + if ( !window ) { + return; + } + + function f() {} + } )(); + } + expect: { + ( function() { + function f() {} + + if ( window ); + } )(); + } +} From e9224ab4441ddb352566a52b84f1384bf5b8a8d8 Mon Sep 17 00:00:00 2001 From: Richard van Velzen Date: Tue, 26 Apr 2016 11:49:55 +0200 Subject: [PATCH 3/3] Add test cases for slightly more esoteric cases --- test/compress/issue-1052.js | 53 +++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/test/compress/issue-1052.js b/test/compress/issue-1052.js index bad28a8f..0a77f006 100644 --- a/test/compress/issue-1052.js +++ b/test/compress/issue-1052.js @@ -41,3 +41,56 @@ single_function: { } )(); } } + +deeply_nested: { + options = { if_return: true, hoist_funs: false }; + input: { + ( function() { + if ( !window ) { + return; + } + + function f() {} + function g() {} + + if ( !document ) { + return; + } + + function h() {} + } )(); + } + expect: { + ( function() { + function f() {} + function g() {} + + function h() {} + + // NOTE: other compression steps will reduce this + // down to just `window`. + if ( window ) + if (document); + } )(); + } +} + +not_hoisted_when_already_nested: { + options = { if_return: true, hoist_funs: false }; + input: { + ( function() { + if ( !window ) { + return; + } + + if ( foo ) function f() {} + + } )(); + } + expect: { + ( function() { + if ( window ) + if ( foo ) function f() {} + } )(); + } +}