Move support for negate_iife in the compressor, rather than code generator
(the code generator doesn't maintain enough context to know whether the return value is important or discarded) Fixes #272
This commit is contained in:
@@ -209,6 +209,9 @@ to set `true`; it's effectively a shortcut for `foo=true`).
|
||||
and `x = something(), x` into `x = something()`
|
||||
- `warnings` -- display warnings when dropping unreachable code or unused
|
||||
declarations etc.
|
||||
- `negate_iife` -- negate "Immediately-Called Function Expressions"
|
||||
where the return value is discarded, to avoid the parens that the
|
||||
code generator would insert.
|
||||
|
||||
### The `unsafe` option
|
||||
|
||||
@@ -296,10 +299,6 @@ can pass additional arguments that control the code output:
|
||||
you pass `false` then whenever possible we will use a newline instead of a
|
||||
semicolon, leading to more readable output of uglified code (size before
|
||||
gzip could be smaller; size after gzip insignificantly larger).
|
||||
- `negate-iife` (default `!beautify`) -- prefer negation, rather than
|
||||
parens, for "Immediately-Called Function Expressions". This defaults to
|
||||
`true` when beautification is off, and `false` if beautification is on;
|
||||
pass it manually to force a value.
|
||||
|
||||
### Keeping copyright notices or other comments
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@ function Compressor(options, false_by_default) {
|
||||
join_vars : !false_by_default,
|
||||
cascade : !false_by_default,
|
||||
side_effects : !false_by_default,
|
||||
negate_iife : !false_by_default,
|
||||
screw_ie8 : false,
|
||||
|
||||
warnings : true,
|
||||
@@ -214,6 +215,11 @@ merge(Compressor.prototype, {
|
||||
statements = join_consecutive_vars(statements, compressor);
|
||||
}
|
||||
} while (CHANGED);
|
||||
|
||||
if (compressor.option("negate_iife")) {
|
||||
negate_iifes(statements, compressor);
|
||||
}
|
||||
|
||||
return statements;
|
||||
|
||||
function eliminate_spurious_blocks(statements) {
|
||||
@@ -497,6 +503,40 @@ merge(Compressor.prototype, {
|
||||
}, []);
|
||||
};
|
||||
|
||||
function negate_iifes(statements, compressor) {
|
||||
statements.forEach(function(stat){
|
||||
if (stat instanceof AST_SimpleStatement) {
|
||||
stat.body = (function transform(thing) {
|
||||
return thing.transform(new TreeTransformer(function(node){
|
||||
if (node instanceof AST_Call && node.expression instanceof AST_Function) {
|
||||
return make_node(AST_UnaryPrefix, node, {
|
||||
operator: "!",
|
||||
expression: node
|
||||
});
|
||||
}
|
||||
else if (node instanceof AST_Call) {
|
||||
node.expression = transform(node.expression);
|
||||
}
|
||||
else if (node instanceof AST_Seq) {
|
||||
node.car = transform(node.car);
|
||||
}
|
||||
else if (node instanceof AST_Conditional) {
|
||||
var expr = transform(node.condition);
|
||||
if (expr !== node.condition) {
|
||||
// it has been negated, reverse
|
||||
node.condition = expr;
|
||||
var tmp = node.consequent;
|
||||
node.consequent = node.alternative;
|
||||
node.alternative = tmp;
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}));
|
||||
})(stat.body);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
function extract_declarations_from_unreachable_code(compressor, stat, target) {
|
||||
|
||||
@@ -61,7 +61,6 @@ function OutputStream(options) {
|
||||
comments : false,
|
||||
preserve_line : false,
|
||||
screw_ie8 : false,
|
||||
negate_iife : !(options && options.beautify),
|
||||
}, true);
|
||||
|
||||
var indentation = 0;
|
||||
@@ -351,21 +350,17 @@ function OutputStream(options) {
|
||||
|
||||
AST_Node.DEFMETHOD("print", function(stream, force_parens){
|
||||
var self = this, generator = self._codegen;
|
||||
stream.push_node(self);
|
||||
var needs_parens = self.needs_parens(stream);
|
||||
var fc = self instanceof AST_Function && stream.option("negate_iife");
|
||||
if (force_parens || (needs_parens && !fc)) {
|
||||
stream.with_parens(function(){
|
||||
self.add_comments(stream);
|
||||
self.add_source_map(stream);
|
||||
generator(self, stream);
|
||||
});
|
||||
} else {
|
||||
function doit() {
|
||||
self.add_comments(stream);
|
||||
if (needs_parens && fc) stream.print("!");
|
||||
self.add_source_map(stream);
|
||||
generator(self, stream);
|
||||
}
|
||||
stream.push_node(self);
|
||||
if (force_parens || self.needs_parens(stream)) {
|
||||
stream.with_parens(doit);
|
||||
} else {
|
||||
doit();
|
||||
}
|
||||
stream.pop_node();
|
||||
});
|
||||
|
||||
|
||||
76
test/compress/negate-iife.js
Normal file
76
test/compress/negate-iife.js
Normal file
@@ -0,0 +1,76 @@
|
||||
negate_iife_1: {
|
||||
options = {
|
||||
negate_iife: true
|
||||
};
|
||||
input: {
|
||||
(function(){ stuff() })();
|
||||
}
|
||||
expect: {
|
||||
!function(){ stuff() }();
|
||||
}
|
||||
}
|
||||
|
||||
negate_iife_2: {
|
||||
options = {
|
||||
negate_iife: true
|
||||
};
|
||||
input: {
|
||||
(function(){ return {} })().x = 10; // should not transform this one
|
||||
}
|
||||
expect: {
|
||||
(function(){ return {} })().x = 10;
|
||||
}
|
||||
}
|
||||
|
||||
negate_iife_3: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
};
|
||||
input: {
|
||||
(function(){ return true })() ? console.log(true) : console.log(false);
|
||||
}
|
||||
expect: {
|
||||
!function(){ return true }() ? console.log(false) : console.log(true);
|
||||
}
|
||||
}
|
||||
|
||||
negate_iife_3: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
sequences: true
|
||||
};
|
||||
input: {
|
||||
(function(){ return true })() ? console.log(true) : console.log(false);
|
||||
(function(){
|
||||
console.log("something");
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
!function(){ return true }() ? console.log(false) : console.log(true), function(){
|
||||
console.log("something");
|
||||
}();
|
||||
}
|
||||
}
|
||||
|
||||
negate_iife_4: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
sequences: true,
|
||||
conditionals: true,
|
||||
};
|
||||
input: {
|
||||
if ((function(){ return true })()) {
|
||||
console.log(true);
|
||||
} else {
|
||||
console.log(false);
|
||||
}
|
||||
(function(){
|
||||
console.log("something");
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
!function(){ return true }() ? console.log(false) : console.log(true), function(){
|
||||
console.log("something");
|
||||
}();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user