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
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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. \
|
||||
|
||||
@@ -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":
|
||||
|
||||
22
lib/scope.js
22
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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user