diff options
author | Alex Lam S.L <alexlamsl@gmail.com> | 2017-03-05 12:51:11 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-03-05 12:51:11 +0800 |
commit | 1f0333e9f146311e0e412fbd0783c0e1e63c7802 (patch) | |
tree | 8ad032bf7c16c7c89086331499a1c066407a2374 | |
parent | eb98a7f2f38f5de16b50560199ee7ec719a1e945 (diff) | |
download | tracifyjs-1f0333e9f146311e0e412fbd0783c0e1e63c7802.tar.gz tracifyjs-1f0333e9f146311e0e412fbd0783c0e1e63c7802.zip |
stay safe with constants in IE8- (#1547)
- `undefined` etc. can be redefined at top-level for IE8-, so disable related optimisations
- fixed `--support-ie8` catch mangle bug
-rw-r--r-- | README.md | 2 | ||||
-rwxr-xr-x | bin/uglifyjs | 2 | ||||
-rw-r--r-- | lib/compress.js | 4 | ||||
-rw-r--r-- | lib/scope.js | 22 | ||||
-rw-r--r-- | test/compress/screw-ie8.js | 42 |
5 files changed, 52 insertions, 20 deletions
@@ -75,8 +75,6 @@ The available options are: --support-ie8 Use this flag to support Internet Explorer 6/7/8. Equivalent to setting `screw_ie8: false` in `minify()` for `compress`, `mangle` and `output` options. - Note: `--support-ie8` may generate incorrect code - for `try`/`catch` in ES5 compliant browsers. --expr Parse a single expression, rather than a program (for parsing JSON) -p, --prefix Skip prefix for original filenames that appear diff --git a/bin/uglifyjs b/bin/uglifyjs index 4dd234dc..e39a4b4b 100755 --- a/bin/uglifyjs +++ b/bin/uglifyjs @@ -26,7 +26,7 @@ mangling you need to use `-c` and `-m`.\ .describe("source-map-include-sources", "Pass this flag if you want to include the content of source files in the source map as sourcesContent property.") .describe("in-source-map", "Input source map, useful if you're compressing JS that was generated from some other original code.") .describe("screw-ie8", "Do not support Internet Explorer 6/7/8. This flag is enabled by default.") - .describe("support-ie8", "Support non-standard Internet Explorer 6/7/8 javascript. Note: may generate incorrect code for try/catch in ES5 compliant browsers.") + .describe("support-ie8", "Support non-standard Internet Explorer 6/7/8 javascript.") .describe("expr", "Parse a single expression, rather than a program (for parsing JSON)") .describe("p", "Skip prefix for original filenames that appear in source maps. \ For example -p 3 will drop 3 directories from file names and ensure they are relative paths. \ diff --git a/lib/compress.js b/lib/compress.js index 7eead2c1..4a5f6395 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -3348,7 +3348,9 @@ merge(Compressor.prototype, { return def; } // testing against !self.scope.uses_with first is an optimization - if (self.undeclared() && !isLHS(self, compressor.parent()) + if (compressor.option("screw_ie8") + && self.undeclared() + && !isLHS(self, compressor.parent()) && (!self.scope.uses_with || !compressor.find_parent(AST_With))) { switch (self.name) { case "undefined": diff --git a/lib/scope.js b/lib/scope.js index ae0c5777..b00fcb4a 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -97,7 +97,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){ var labels = new Dictionary(); var defun = null; var tw = new TreeWalker(function(node, descend){ - if (options.screw_ie8 && node instanceof AST_Catch) { + if (node instanceof AST_Catch) { var save_scope = scope; scope = new AST_Scope(node); scope.init_scope_vars(); @@ -158,8 +158,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){ def.init = tw.parent().value; } else if (node instanceof AST_SymbolCatch) { - (options.screw_ie8 ? scope : defun) - .def_variable(node); + scope.def_variable(node); } else if (node instanceof AST_LabelRef) { var sym = labels.get(node.name); @@ -209,6 +208,23 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){ }); self.walk(tw); + // pass 3: fix up any scoping issue with IE8 + if (!options.screw_ie8) { + self.walk(new TreeWalker(function(node, descend) { + if (node instanceof AST_SymbolCatch) { + var name = node.name; + var scope = node.thedef.scope.parent_scope; + var def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node); + node.thedef.references.forEach(function(ref) { + ref.thedef = def; + ref.reference(options); + }); + node.thedef = def; + return true; + } + })); + } + if (options.cache) { this.cname = options.cache.cname; } diff --git a/test/compress/screw-ie8.js b/test/compress/screw-ie8.js index 31c448fd..51379b15 100644 --- a/test/compress/screw-ie8.js +++ b/test/compress/screw-ie8.js @@ -17,6 +17,26 @@ dont_screw: { expect_exact: 'f("\\x0B");'; } +do_screw_constants: { + options = { + screw_ie8: true, + } + input: { + f(undefined, Infinity); + } + expect_exact: "f(void 0,1/0);" +} + +dont_screw_constants: { + options = { + screw_ie8: false, + } + input: { + f(undefined, Infinity); + } + expect_exact: "f(undefined,Infinity);" +} + do_screw_try_catch: { options = { screw_ie8: true }; mangle = { screw_ie8: true }; @@ -46,8 +66,6 @@ do_screw_try_catch: { } dont_screw_try_catch: { - // This test is known to generate incorrect code for screw_ie8=false. - // Update expected result in the event this bug is ever fixed. options = { screw_ie8: false }; mangle = { screw_ie8: false }; beautify = { screw_ie8: false }; @@ -64,11 +82,11 @@ dont_screw_try_catch: { } expect: { bad = function(n){ - return function(n){ + return function(t){ try{ - t() - } catch(t) { - n(t) + n() + } catch(n) { + t(n) } } }; @@ -104,8 +122,6 @@ do_screw_try_catch_undefined: { } dont_screw_try_catch_undefined: { - // This test is known to generate incorrect code for screw_ie8=false. - // Update expected result in the event this bug is ever fixed. options = { screw_ie8: false }; mangle = { screw_ie8: false }; beautify = { screw_ie8: false }; @@ -121,14 +137,14 @@ dont_screw_try_catch_undefined: { }; } expect: { - function a(o){ + function a(n){ try{ throw "Stuff" - } catch (n) { - console.log("caught: "+n) + } catch (undefined) { + console.log("caught: " + undefined) } - console.log("undefined is " + n); - return o === n + console.log("undefined is " + undefined); + return n === undefined } } } |