Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
15a148ff6d | ||
|
|
428e19fed2 | ||
|
|
f65e55dff4 | ||
|
|
b634018618 | ||
|
|
fa3300f314 | ||
|
|
bd0886a2c0 | ||
|
|
248f304f02 | ||
|
|
dc5f70eab5 | ||
|
|
df8c5623af | ||
|
|
a790c09c91 | ||
|
|
8f35a363d9 | ||
|
|
d2190c2bf3 | ||
|
|
ea10642572 | ||
|
|
dfa395f6ff |
@@ -249,6 +249,9 @@ to set `true`; it's effectively a shortcut for `foo=true`).
|
|||||||
statement would get discarded. The current implementation adds some
|
statement would get discarded. The current implementation adds some
|
||||||
overhead (compression will be slower).
|
overhead (compression will be slower).
|
||||||
|
|
||||||
|
- `drop_console` -- default `false`. Pass `true` to discard calls to
|
||||||
|
`console.*` functions.
|
||||||
|
|
||||||
### The `unsafe` option
|
### The `unsafe` option
|
||||||
|
|
||||||
It enables some transformations that *might* break code logic in certain
|
It enables some transformations that *might* break code logic in certain
|
||||||
|
|||||||
@@ -498,12 +498,6 @@ var AST_Try = DEFNODE("Try", "bcatch bfinally", {
|
|||||||
}
|
}
|
||||||
}, AST_Block);
|
}, AST_Block);
|
||||||
|
|
||||||
// XXX: this is wrong according to ECMA-262 (12.4). the catch block
|
|
||||||
// should introduce another scope, as the argname should be visible
|
|
||||||
// only inside the catch block. However, doing it this way because of
|
|
||||||
// IE which simply introduces the name in the surrounding scope. If
|
|
||||||
// we ever want to fix this then AST_Catch should inherit from
|
|
||||||
// AST_Scope.
|
|
||||||
var AST_Catch = DEFNODE("Catch", "argname", {
|
var AST_Catch = DEFNODE("Catch", "argname", {
|
||||||
$documentation: "A `catch` node; only makes sense as part of a `try` statement",
|
$documentation: "A `catch` node; only makes sense as part of a `try` statement",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ function Compressor(options, false_by_default) {
|
|||||||
pure_funcs : null,
|
pure_funcs : null,
|
||||||
negate_iife : !false_by_default,
|
negate_iife : !false_by_default,
|
||||||
screw_ie8 : false,
|
screw_ie8 : false,
|
||||||
|
drop_console : false,
|
||||||
|
|
||||||
warnings : true,
|
warnings : true,
|
||||||
global_defs : {}
|
global_defs : {}
|
||||||
@@ -1669,10 +1670,10 @@ merge(Compressor.prototype, {
|
|||||||
return arg.value;
|
return arg.value;
|
||||||
}).join(",") + "){" + self.args[self.args.length - 1].value + "})()";
|
}).join(",") + "){" + self.args[self.args.length - 1].value + "})()";
|
||||||
var ast = parse(code);
|
var ast = parse(code);
|
||||||
ast.figure_out_scope();
|
ast.figure_out_scope({ screw_ie8: compressor.option("screw_ie8") });
|
||||||
var comp = new Compressor(compressor.options);
|
var comp = new Compressor(compressor.options);
|
||||||
ast = ast.transform(comp);
|
ast = ast.transform(comp);
|
||||||
ast.figure_out_scope();
|
ast.figure_out_scope({ screw_ie8: compressor.option("screw_ie8") });
|
||||||
ast.mangle_names();
|
ast.mangle_names();
|
||||||
var fun;
|
var fun;
|
||||||
try {
|
try {
|
||||||
@@ -1773,6 +1774,14 @@ merge(Compressor.prototype, {
|
|||||||
return make_node(AST_Undefined, self).transform(compressor);
|
return make_node(AST_Undefined, self).transform(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (compressor.option("drop_console")) {
|
||||||
|
if (self.expression instanceof AST_PropAccess &&
|
||||||
|
self.expression.expression instanceof AST_SymbolRef &&
|
||||||
|
self.expression.expression.name == "console" &&
|
||||||
|
self.expression.expression.undeclared()) {
|
||||||
|
return make_node(AST_Undefined, self).transform(compressor);
|
||||||
|
}
|
||||||
|
}
|
||||||
return self.evaluate(compressor)[0];
|
return self.evaluate(compressor)[0];
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1811,10 +1820,16 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
if (compressor.option("cascade")) {
|
if (compressor.option("cascade")) {
|
||||||
if (self.car instanceof AST_Assign
|
if (self.car instanceof AST_Assign
|
||||||
&& !self.car.left.has_side_effects(compressor)
|
&& !self.car.left.has_side_effects(compressor)) {
|
||||||
&& self.car.left.equivalent_to(self.cdr)) {
|
if (self.car.left.equivalent_to(self.cdr)) {
|
||||||
return self.car;
|
return self.car;
|
||||||
}
|
}
|
||||||
|
if (self.cdr instanceof AST_Call
|
||||||
|
&& self.cdr.expression.equivalent_to(self.car.left)) {
|
||||||
|
self.cdr.expression = self.car;
|
||||||
|
return self.cdr;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!self.car.has_side_effects(compressor)
|
if (!self.car.has_side_effects(compressor)
|
||||||
&& !self.cdr.has_side_effects(compressor)
|
&& !self.cdr.has_side_effects(compressor)
|
||||||
&& self.car.equivalent_to(self.cdr)) {
|
&& self.car.equivalent_to(self.cdr)) {
|
||||||
|
|||||||
49
lib/scope.js
49
lib/scope.js
@@ -71,27 +71,34 @@ SymbolDef.prototype = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
|
AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||||
// This does what ast_add_scope did in UglifyJS v1.
|
options = defaults(options, {
|
||||||
//
|
screw_ie8: false
|
||||||
// Part of it could be done at parse time, but it would complicate
|
});
|
||||||
// the parser (and it's already kinda complex). It's also worth
|
|
||||||
// having it separated because we might need to call it multiple
|
|
||||||
// times on the same tree.
|
|
||||||
|
|
||||||
// pass 1: setup scope chaining and handle definitions
|
// pass 1: setup scope chaining and handle definitions
|
||||||
var self = this;
|
var self = this;
|
||||||
var scope = self.parent_scope = null;
|
var scope = self.parent_scope = null;
|
||||||
|
var defun = null;
|
||||||
var nesting = 0;
|
var nesting = 0;
|
||||||
var tw = new TreeWalker(function(node, descend){
|
var tw = new TreeWalker(function(node, descend){
|
||||||
|
if (options.screw_ie8 && node instanceof AST_Catch) {
|
||||||
|
var save_scope = scope;
|
||||||
|
scope = new AST_Scope(node);
|
||||||
|
scope.init_scope_vars(nesting);
|
||||||
|
scope.parent_scope = save_scope;
|
||||||
|
descend();
|
||||||
|
scope = save_scope;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (node instanceof AST_Scope) {
|
if (node instanceof AST_Scope) {
|
||||||
node.init_scope_vars(nesting);
|
node.init_scope_vars(nesting);
|
||||||
var save_scope = node.parent_scope = scope;
|
var save_scope = node.parent_scope = scope;
|
||||||
++nesting;
|
var save_defun = defun;
|
||||||
scope = node;
|
defun = scope = node;
|
||||||
descend();
|
++nesting; descend(); --nesting;
|
||||||
scope = save_scope;
|
scope = save_scope;
|
||||||
--nesting;
|
defun = save_defun;
|
||||||
return true; // don't descend again in TreeWalker
|
return true; // don't descend again in TreeWalker
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Directive) {
|
if (node instanceof AST_Directive) {
|
||||||
@@ -108,7 +115,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
|
|||||||
node.scope = scope;
|
node.scope = scope;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_SymbolLambda) {
|
if (node instanceof AST_SymbolLambda) {
|
||||||
scope.def_function(node);
|
defun.def_function(node);
|
||||||
}
|
}
|
||||||
else if (node instanceof AST_SymbolDefun) {
|
else if (node instanceof AST_SymbolDefun) {
|
||||||
// Careful here, the scope where this should be defined is
|
// Careful here, the scope where this should be defined is
|
||||||
@@ -116,22 +123,17 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
|
|||||||
// scope when we encounter the AST_Defun node (which is
|
// scope when we encounter the AST_Defun node (which is
|
||||||
// instanceof AST_Scope) but we get to the symbol a bit
|
// instanceof AST_Scope) but we get to the symbol a bit
|
||||||
// later.
|
// later.
|
||||||
(node.scope = scope.parent_scope).def_function(node);
|
(node.scope = defun.parent_scope).def_function(node);
|
||||||
}
|
}
|
||||||
else if (node instanceof AST_SymbolVar
|
else if (node instanceof AST_SymbolVar
|
||||||
|| node instanceof AST_SymbolConst) {
|
|| node instanceof AST_SymbolConst) {
|
||||||
var def = scope.def_variable(node);
|
var def = defun.def_variable(node);
|
||||||
def.constant = node instanceof AST_SymbolConst;
|
def.constant = node instanceof AST_SymbolConst;
|
||||||
def.init = tw.parent().value;
|
def.init = tw.parent().value;
|
||||||
}
|
}
|
||||||
else if (node instanceof AST_SymbolCatch) {
|
else if (node instanceof AST_SymbolCatch) {
|
||||||
// XXX: this is wrong according to ECMA-262 (12.4). the
|
(options.screw_ie8 ? scope : defun)
|
||||||
// `catch` argument name should be visible only inside the
|
.def_variable(node);
|
||||||
// catch block. For a quick fix AST_Catch should inherit
|
|
||||||
// from AST_Scope. Keeping it this way because of IE,
|
|
||||||
// which doesn't obey the standard. (it introduces the
|
|
||||||
// identifier in the enclosing scope)
|
|
||||||
scope.def_variable(node);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
self.walk(tw);
|
self.walk(tw);
|
||||||
@@ -244,6 +246,11 @@ AST_Scope.DEFMETHOD("next_mangled", function(options){
|
|||||||
out: while (true) {
|
out: while (true) {
|
||||||
var m = base54(++this.cname);
|
var m = base54(++this.cname);
|
||||||
if (!is_identifier(m)) continue; // skip over "do"
|
if (!is_identifier(m)) continue; // skip over "do"
|
||||||
|
|
||||||
|
// https://github.com/mishoo/UglifyJS2/issues/242 -- do not
|
||||||
|
// shadow a name excepted from mangling.
|
||||||
|
if (options.except.indexOf(m) >= 0) continue;
|
||||||
|
|
||||||
// we must ensure that the mangled name does not shadow a name
|
// we must ensure that the mangled name does not shadow a name
|
||||||
// from some parent scope that is referenced in this or in
|
// from some parent scope that is referenced in this or in
|
||||||
// inner scopes.
|
// inner scopes.
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ function SourceMap(options) {
|
|||||||
file : null,
|
file : null,
|
||||||
root : null,
|
root : null,
|
||||||
orig : null,
|
orig : null,
|
||||||
|
|
||||||
|
orig_line_diff : 0,
|
||||||
|
dest_line_diff : 0,
|
||||||
});
|
});
|
||||||
var generator = new MOZ_SourceMap.SourceMapGenerator({
|
var generator = new MOZ_SourceMap.SourceMapGenerator({
|
||||||
file : options.file,
|
file : options.file,
|
||||||
@@ -67,8 +70,8 @@ function SourceMap(options) {
|
|||||||
name = info.name;
|
name = info.name;
|
||||||
}
|
}
|
||||||
generator.addMapping({
|
generator.addMapping({
|
||||||
generated : { line: gen_line, column: gen_col },
|
generated : { line: gen_line + options.dest_line_diff, column: gen_col },
|
||||||
original : { line: orig_line, column: orig_col },
|
original : { line: orig_line + options.orig_line_diff, column: orig_col },
|
||||||
source : source,
|
source : source,
|
||||||
name : name
|
name : name
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -82,9 +82,12 @@ function repeat_string(str, i) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function DefaultsError(msg, defs) {
|
function DefaultsError(msg, defs) {
|
||||||
|
Error.call(this, msg);
|
||||||
this.msg = msg;
|
this.msg = msg;
|
||||||
this.defs = defs;
|
this.defs = defs;
|
||||||
};
|
};
|
||||||
|
DefaultsError.prototype = Object.create(Error.prototype);
|
||||||
|
DefaultsError.prototype.constructor = DefaultsError;
|
||||||
|
|
||||||
DefaultsError.croak = function(msg, defs) {
|
DefaultsError.croak = function(msg, defs) {
|
||||||
throw new DefaultsError(msg, defs);
|
throw new DefaultsError(msg, defs);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
||||||
"homepage": "http://lisperator.net/uglifyjs",
|
"homepage": "http://lisperator.net/uglifyjs",
|
||||||
"main": "tools/node.js",
|
"main": "tools/node.js",
|
||||||
"version": "2.4.5",
|
"version": "2.4.8",
|
||||||
"engines": { "node" : ">=0.4.0" },
|
"engines": { "node" : ">=0.4.0" },
|
||||||
"maintainers": [{
|
"maintainers": [{
|
||||||
"name": "Mihai Bazon",
|
"name": "Mihai Bazon",
|
||||||
|
|||||||
@@ -119,3 +119,47 @@ unused_keep_setter_arg: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unused_var_in_catch: {
|
||||||
|
options = { unused: true };
|
||||||
|
input: {
|
||||||
|
function foo() {
|
||||||
|
try {
|
||||||
|
foo();
|
||||||
|
} catch(ex) {
|
||||||
|
var x = 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function foo() {
|
||||||
|
try {
|
||||||
|
foo();
|
||||||
|
} catch(ex) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
used_var_in_catch: {
|
||||||
|
options = { unused: true };
|
||||||
|
input: {
|
||||||
|
function foo() {
|
||||||
|
try {
|
||||||
|
foo();
|
||||||
|
} catch(ex) {
|
||||||
|
var x = 10;
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function foo() {
|
||||||
|
try {
|
||||||
|
foo();
|
||||||
|
} catch(ex) {
|
||||||
|
var x = 10;
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user