Permalink
Browse files

better fix for issue #128:

    (function(){
        var a = function fact(n){
            if (n == 1) return 1;
            else return n * fact(n - 1);
        };
        // console.log(fact(10)); // this errors out, `fact' not defined
        fact = 5;
        console.log(a(10)); // this works
    })();
    console.log(fact);

The above shows that when a function expression has a name, that name is not
introduced into the existing scope; instead it's only available in that
function's body (`fact' can call itself, but we can't call it from outside
by that name).  It also doesn't introduce a name, which is why setting fact
= 5 actually creates a global.

So UglifyJS is now able to mangle `fact' in the case above (or drop the name
in cases where the inner body is not referencing it).  The above mangles to:

    (function() {
        var a = function a(b) {
            return b == 1 ? 1 : b * a(b - 1);
        };
        fact = 5, console.log(a(10));
    })(), console.log(fact);
  • Loading branch information...
mishoo committed Apr 22, 2011
1 parent 56972f9 commit 84b85fa968fb50a47374d8e4a5735d438b7b0bbb
Showing with 15 additions and 12 deletions.
  1. +15 −12 lib/process.js
View
@@ -377,7 +377,9 @@ function ast_add_scope(ast) {
};
function _lambda(name, args, body) {
- return [ this[0], this[0] == "defun" ? define(name) : name, args, with_new_scope(function(){
+ var is_defun = this[0] == "defun";
+ return [ this[0], is_defun ? define(name) : name, args, with_new_scope(function(){
+ if (!is_defun) define(name);
MAP(args, define);
return MAP(body, walk);
})];
@@ -464,8 +466,10 @@ function ast_mangle(ast, options) {
};
function _lambda(name, args, body) {
- if (name) name = get_mangled(name);
+ var is_defun = this[0] == "defun";
+ if (is_defun && name) name = get_mangled(name);
body = with_scope(body.scope, function(){
+ if (!is_defun && name) name = get_mangled(name);
args = MAP(args, function(name){ return get_mangled(name) });
return MAP(body, walk);
});
@@ -751,9 +755,14 @@ function ast_squeeze(ast, options) {
};
function _lambda(name, args, body) {
- return [ this[0], name, args, with_scope(body.scope, function(){
- return tighten(MAP(body, walk), "lambda");
- }) ];
+ var is_defun = this[0] == "defun";
+ body = with_scope(body.scope, function(){
+ var ret = tighten(MAP(body, walk), "lambda");
+ if (!is_defun && name && !HOP(scope.refs, name))
+ name = null;
+ return ret;
+ });
+ return [ this[0], name, args, body ];
};
// we get here for blocks that have been already transformed.
@@ -959,13 +968,7 @@ function ast_squeeze(ast, options) {
return [ branch[0] ? walk(branch[0]) : null, block ];
}) ];
},
- "function": function() {
- var ret = _lambda.apply(this, arguments);
- if (ret[1] && !HOP(scope.refs, ret[1])) {
- ret[1] = null;
- }
- return ret;
- },
+ "function": _lambda,
"defun": _lambda,
"block": function(body) {
if (body) return rmblock([ "block", tighten(MAP(body, walk)) ]);

0 comments on commit 84b85fa

Please sign in to comment.