From 58459d0e60b6eca8fc305ff857bd4532ce0244fa Mon Sep 17 00:00:00 2001 From: "Ashley (Scirra)" Date: Mon, 10 Oct 2016 12:55:53 +0100 Subject: [PATCH 1/2] Add treat_as_global option to mangle_properties This enables mangling of global references using a given list of global alias names, which can be e.g. "window", "self", etc. depending on context. --- lib/propmangle.js | 61 +++++++++++++++++++++++++++++++++++-- test/compress/properties.js | 46 ++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 3 deletions(-) diff --git a/lib/propmangle.js b/lib/propmangle.js index 4187db121c5..a98cd8bbc13 100644 --- a/lib/propmangle.js +++ b/lib/propmangle.js @@ -83,7 +83,8 @@ function mangle_properties(ast, options) { cache : null, only_cache : false, regex : null, - ignore_quoted : false + ignore_quoted : false, + treat_as_global : [] }); var reserved = options.reserved; @@ -104,7 +105,21 @@ function mangle_properties(ast, options) { var names_to_mangle = []; var unmangleable = []; var ignored = {}; - + + if (!cache.global_defs) cache.global_defs = {}; + + var treat_as_global = options.treat_as_global; + var mangle_globals = !!treat_as_global.length; + + function is_global_alias(name) + { + return treat_as_global.indexOf(name) >= 0; + } + + // TODO: don't know if this is necessary to get scope information? + //if (mangle_globals) + // ast.figure_out_scope(); + // step 1: find candidates to mangle ast.walk(new TreeWalker(function(node){ if (node instanceof AST_ObjectKeyVal) { @@ -116,6 +131,17 @@ function mangle_properties(ast, options) { } else if (node instanceof AST_Dot) { add(node.property); + + // if the left side of the dot is a global alias (e.g. window.foo), and the left side + // does not refer to a local variable, add it to a list of global definitions. + if (mangle_globals && + node.expression instanceof AST_SymbolRef && + node.expression.global() && + is_global_alias(node.expression.name) && + !is_global_alias(node.property)) + { + cache.global_defs[node.property] = true; + } } else if (node instanceof AST_Sub) { addStrings(node.property, ignore_quoted); @@ -123,6 +149,16 @@ function mangle_properties(ast, options) { else if (node instanceof AST_ConciseMethod) { add(node.name.name); } + else if (node instanceof AST_SymbolRef) { + // if this term stands alone (e.g. just 'foo' where 'foo' cannot be shown to + // be a local variable in scope), also treat it as a global definition. + if (mangle_globals && + node.global() && + !is_global_alias(node.name)) + { + cache.global_defs[node.name] = true; + } + } })); // step 2: transform the tree, renaming properties @@ -147,6 +183,18 @@ function mangle_properties(ast, options) { node.name.name = mangle(node.name.name); } } + else if (node instanceof AST_SymbolRef) { + // if this is a standalone global reference which does not refer to a local variable in scope, + // and it's on our list of global definitions, then mangle it. + if (mangle_globals && + node.global() && + node.name in cache.global_defs) + { + var mangled_name = mangle(node.name); + node.name = mangled_name; + node.definition().mangled_name = mangled_name; + } + } // else if (node instanceof AST_String) { // if (should_mangle(node.value)) { // AST_Node.warn( @@ -178,7 +226,8 @@ function mangle_properties(ast, options) { if (regex && !regex.test(name)) return false; if (reserved.indexOf(name) >= 0) return false; return cache.props.has(name) - || names_to_mangle.indexOf(name) >= 0; + || names_to_mangle.indexOf(name) >= 0 + || (mangle_globals && name in cache.global_defs); } function add(name, ignore) { @@ -205,6 +254,12 @@ function mangle_properties(ast, options) { do { mangled = base54(++cache.cname); } while (!can_mangle(mangled)); + + // HACK: to avoid mangled global references colliding with local variable names, use + // a prefix on all mangled global names to effectively move them to a different namespace. + if (mangle_globals && name in cache.global_defs) + mangled = "g_" + mangled; + cache.props.set(name, mangled); } return mangled; diff --git a/test/compress/properties.js b/test/compress/properties.js index 7ef6a014d86..94b6434fc64 100644 --- a/test/compress/properties.js +++ b/test/compress/properties.js @@ -143,6 +143,52 @@ mangle_unquoted_properties: { } } +mangle_global_properties: { + mangle_props = { + treat_as_global: ["window"], + reserved: ["console", "log"] + } + input: { + window.foo = {}; + foo.bar = 1; + external.baz = 2; + console.log(external); + } + expect: { + window.g_a = {}; + g_a.b = 1; + g_d.c = 2; + console.log(g_d); + } +} + +mangle_global_properties_not_local: { + options = { + } + mangle_props = { + treat_as_global: ["self"], + reserved: ["console", "log"] + } + input: { + self.foo = {}; + function test() + { + var self = this; + console.log(self.bar); + }; + console.log(typeof bar); + } + expect: { + self.g_a = {}; + function test() + { + var self = this; + console.log(self.b); + }; + console.log(typeof g_b); + } +} + first_256_chars_as_properties: { beautify = { ascii_only: true, From c8a71e279e5fa1a34798ca680341543d4e50b7ad Mon Sep 17 00:00:00 2001 From: "Ashley (Scirra)" Date: Tue, 11 Oct 2016 13:17:40 +0100 Subject: [PATCH 2/2] Style updates Update style and remove some commented code --- lib/propmangle.js | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/lib/propmangle.js b/lib/propmangle.js index a98cd8bbc13..52705393fc1 100644 --- a/lib/propmangle.js +++ b/lib/propmangle.js @@ -84,7 +84,7 @@ function mangle_properties(ast, options) { only_cache : false, regex : null, ignore_quoted : false, - treat_as_global : [] + treat_as_global : [], }); var reserved = options.reserved; @@ -116,10 +116,6 @@ function mangle_properties(ast, options) { return treat_as_global.indexOf(name) >= 0; } - // TODO: don't know if this is necessary to get scope information? - //if (mangle_globals) - // ast.figure_out_scope(); - // step 1: find candidates to mangle ast.walk(new TreeWalker(function(node){ if (node instanceof AST_ObjectKeyVal) { @@ -138,8 +134,7 @@ function mangle_properties(ast, options) { node.expression instanceof AST_SymbolRef && node.expression.global() && is_global_alias(node.expression.name) && - !is_global_alias(node.property)) - { + !is_global_alias(node.property)) { cache.global_defs[node.property] = true; } } @@ -154,8 +149,7 @@ function mangle_properties(ast, options) { // be a local variable in scope), also treat it as a global definition. if (mangle_globals && node.global() && - !is_global_alias(node.name)) - { + !is_global_alias(node.name)) { cache.global_defs[node.name] = true; } } @@ -188,8 +182,7 @@ function mangle_properties(ast, options) { // and it's on our list of global definitions, then mangle it. if (mangle_globals && node.global() && - node.name in cache.global_defs) - { + node.name in cache.global_defs) { var mangled_name = mangle(node.name); node.name = mangled_name; node.definition().mangled_name = mangled_name;