From 65ee5af78ca3ec85dee8870a452845f1a4c871f7 Mon Sep 17 00:00:00 2001 From: Andrew Levine Date: Tue, 2 Jun 2015 15:32:10 -0500 Subject: [PATCH 1/5] Add keep_fnames compressor option to README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index f3eb5f71..42579151 100644 --- a/README.md +++ b/README.md @@ -345,6 +345,11 @@ to set `true`; it's effectively a shortcut for `foo=true`). compressor from discarding unused function arguments. You need this for code which relies on `Function.length`. +- `keep_fnames` -- default `false`. Pass `true` to prevent the + compressor from mangling/discarding function names. Useful for code relying on + `Function.prototype.name`. + + ### The `unsafe` option It enables some transformations that *might* break code logic in certain From 4fba3e0b80c3d1a5df04fa524f550868443aa784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Gonz=C3=A1lez=20Palomo?= Date: Mon, 15 Jun 2015 18:03:06 +0200 Subject: [PATCH 2/5] fromString option, use index from argument array for filename instead of "?" The index allows the caller to map things like parse errors back to the code chunk where they appeared. --- tools/node.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/node.js b/tools/node.js index cbe49e39..2eb90363 100644 --- a/tools/node.js +++ b/tools/node.js @@ -73,13 +73,13 @@ exports.minify = function(files, options) { } else { if (typeof files == "string") files = [ files ]; - files.forEach(function(file){ + files.forEach(function(file, i){ var code = options.fromString ? file : fs.readFileSync(file, "utf8"); sourcesContent[file] = code; toplevel = UglifyJS.parse(code, { - filename: options.fromString ? "?" : file, + filename: options.fromString ? i : file, toplevel: toplevel }); }); From 8108c7ffafac2eff8b9d9d263f6f6b89ed13c003 Mon Sep 17 00:00:00 2001 From: Kosei Kitahara Date: Tue, 28 Jul 2015 21:36:22 +0900 Subject: [PATCH 3/5] Support wrap and exportAll options. --- tools/node.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/node.js b/tools/node.js index cbe49e39..7bba3231 100644 --- a/tools/node.js +++ b/tools/node.js @@ -84,6 +84,9 @@ exports.minify = function(files, options) { }); }); } + if (options.wrap) { + toplevel = toplevel.wrap_commonjs(options.wrap, options.exportAll); + } // 2. compress if (options.compress) { From 759b3f7d6df1cecaefd987218373ce3db3646845 Mon Sep 17 00:00:00 2001 From: Richard van Velzen Date: Fri, 31 Jul 2015 15:56:33 +0200 Subject: [PATCH 4/5] Fix mangling of property names which overwrite unmangleable properties Fixes #747. --- lib/propmangle.js | 26 ++++++++++++++------------ test/compress/issue-747.js | 37 +++++++++++++++++++++++++++++++++++++ test/run-tests.js | 3 +++ 3 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 test/compress/issue-747.js diff --git a/lib/propmangle.js b/lib/propmangle.js index 086709e6..840bda91 100644 --- a/lib/propmangle.js +++ b/lib/propmangle.js @@ -83,6 +83,7 @@ function mangle_properties(ast, options) { var regex = options.regex; var names_to_mangle = []; + var unmangleable = []; // step 1: find candidates to mangle ast.walk(new TreeWalker(function(node){ @@ -108,20 +109,14 @@ function mangle_properties(ast, options) { // step 2: transform the tree, renaming properties return ast.transform(new TreeTransformer(function(node){ if (node instanceof AST_ObjectKeyVal) { - if (should_mangle(node.key)) { - node.key = mangle(node.key); - } + node.key = mangle(node.key); } else if (node instanceof AST_ObjectProperty) { // setter or getter - if (should_mangle(node.key.name)) { - node.key.name = mangle(node.key.name); - } + node.key.name = mangle(node.key.name); } else if (node instanceof AST_Dot) { - if (should_mangle(node.property)) { - node.property = mangle(node.property); - } + node.property = mangle(node.property); } else if (node instanceof AST_Sub) { node.property = mangleStrings(node.property); @@ -143,6 +138,7 @@ function mangle_properties(ast, options) { // only function declarations after this line function can_mangle(name) { + if (unmangleable.indexOf(name) >= 0) return false; if (reserved.indexOf(name) >= 0) return false; if (options.only_cache) { return cache.props.has(name); @@ -161,9 +157,17 @@ function mangle_properties(ast, options) { function add(name) { if (can_mangle(name)) push_uniq(names_to_mangle, name); + + if (!should_mangle(name)) { + push_uniq(unmangleable, name); + } } function mangle(name) { + if (!should_mangle(name)) { + return name; + } + var mangled = cache.props.get(name); if (!mangled) { do { @@ -206,9 +210,7 @@ function mangle_properties(ast, options) { node.cdr = mangleStrings(node.cdr); } else if (node instanceof AST_String) { - if (should_mangle(node.value)) { - node.value = mangle(node.value); - } + node.value = mangle(node.value); } else if (node instanceof AST_Conditional) { node.consequent = mangleStrings(node.consequent); diff --git a/test/compress/issue-747.js b/test/compress/issue-747.js new file mode 100644 index 00000000..0a4e4502 --- /dev/null +++ b/test/compress/issue-747.js @@ -0,0 +1,37 @@ +dont_reuse_prop: { + mangle_props = { + regex: /asd/ + }; + + input: { + var obj = {}; + obj.a = 123; + obj.asd = 256; + console.log(obj.a); + } + expect: { + var obj = {}; + obj.a = 123; + obj.b = 256; + console.log(obj.a); + } +} + +unmangleable_props_should_always_be_reserved: { + mangle_props = { + regex: /asd/ + }; + + input: { + var obj = {}; + obj.asd = 256; + obj.a = 123; + console.log(obj.a); + } + expect: { + var obj = {}; + obj.b = 256; + obj.a = 123; + console.log(obj.a); + } +} \ No newline at end of file diff --git a/test/run-tests.js b/test/run-tests.js index d97e5cf1..fc7476f9 100755 --- a/test/run-tests.js +++ b/test/run-tests.js @@ -92,6 +92,9 @@ function run_compress_tests() { } var input = as_toplevel(test.input); var input_code = make_code(test.input); + if (test.mangle_props) { + input = U.mangle_properties(input, test.mangle_props); + } var output = input.transform(cmp); output.figure_out_scope(); output = make_code(output, false); From 3ff0b9e0c97f9eae70756763354e59fc0d675795 Mon Sep 17 00:00:00 2001 From: Christopher Chedeau Date: Mon, 10 Aug 2015 11:22:36 -0700 Subject: [PATCH 5/5] [Fix] --define replaces SymbolRefs in LHS of assignments See #208 for context --- lib/compress.js | 10 +++++++++- test/compress/issue-208.js | 11 +++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 test/compress/issue-208.js diff --git a/lib/compress.js b/lib/compress.js index 401a1c75..ac306fc3 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -2277,7 +2277,15 @@ merge(Compressor.prototype, { }); OPT(AST_SymbolRef, function(self, compressor){ - if (self.undeclared()) { + function isLHS(symbol, parent) { + return ( + parent instanceof AST_Binary && + parent.operator === '=' && + parent.left === symbol + ); + } + + if (self.undeclared() && !isLHS(self, compressor.parent())) { var defines = compressor.option("global_defs"); if (defines && defines.hasOwnProperty(self.name)) { return make_node_from_constant(compressor, defines[self.name], self); diff --git a/test/compress/issue-208.js b/test/compress/issue-208.js new file mode 100644 index 00000000..14752b8a --- /dev/null +++ b/test/compress/issue-208.js @@ -0,0 +1,11 @@ +do_not_update_lhs: { + options = { global_defs: { DEBUG: false } }; + input: { DEBUG = false; } + expect: { DEBUG = false; } +} + +do_update_rhs: { + options = { global_defs: { DEBUG: false } }; + input: { MY_DEBUG = DEBUG; } + expect: { MY_DEBUG = false; } +}