Avoid shadowing name of function expression with function argument
authorMihai Bazon <mihai@bazon.net>
Tue, 29 Oct 2013 11:18:09 +0000 (13:18 +0200)
committerMihai Bazon <mihai@bazon.net>
Tue, 29 Oct 2013 11:18:09 +0000 (13:18 +0200)
Close #179, #326, #327

lib/scope.js

index 713a2c9..af6aebf 100644 (file)
@@ -64,9 +64,9 @@ SymbolDef.prototype = {
     mangle: function(options) {
         if (!this.mangled_name && !this.unmangleable(options)) {
             var s = this.scope;
-            if (this.orig[0] instanceof AST_SymbolLambda && !options.screw_ie8)
+            if (!options.screw_ie8 && this.orig[0] instanceof AST_SymbolLambda)
                 s = s.parent_scope;
-            this.mangled_name = s.next_mangled(options);
+            this.mangled_name = s.next_mangled(options, this);
         }
     }
 };
@@ -256,6 +256,19 @@ AST_Scope.DEFMETHOD("next_mangled", function(options){
     }
 });
 
+AST_Function.DEFMETHOD("next_mangled", function(options, def){
+    // #179, #326
+    // in Safary strict mode, something like (function x(x){...}) is a syntax error;
+    // a function expression's argument cannot shadow the function expression's name
+
+    var tricky_def = def.orig[0] instanceof AST_SymbolFunarg && this.name && this.name.definition();
+    while (true) {
+        var name = AST_Lambda.prototype.next_mangled.call(this, options, def);
+        if (!(tricky_def && tricky_def.mangled_name == name))
+            return name;
+    }
+});
+
 AST_Scope.DEFMETHOD("references", function(sym){
     if (sym instanceof AST_Symbol) sym = sym.definition();
     return this.enclosed.indexOf(sym) < 0 ? null : sym;