diff options
Diffstat (limited to 'lib/scope.js')
-rw-r--r-- | lib/scope.js | 95 |
1 files changed, 51 insertions, 44 deletions
diff --git a/lib/scope.js b/lib/scope.js index 8ce3e4da..ab207d60 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -118,11 +118,10 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) { descend(); scope = save_scope; defun = save_defun; - return true; // don't descend again in TreeWalker + return true; } if (node instanceof AST_With) { - for (var s = scope; s; s = s.parent_scope) - s.uses_with = true; + for (var s = scope; s; s = s.parent_scope) s.uses_with = true; return; } if (node instanceof AST_Symbol) { @@ -132,18 +131,13 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) { node.thedef = node; node.references = []; } - if (node instanceof AST_SymbolDefun || options.ie8 && node instanceof AST_SymbolLambda) { - // Careful here, the scope where this should be defined is - // the parent scope. The reason is that we enter a new - // scope when we encounter the AST_Defun node (which is - // instanceof AST_Scope) but we get to the symbol a bit - // later. - (node.scope = defun.parent_scope).def_function(node, defun); - } - else if (node instanceof AST_SymbolLambda) { + if (node instanceof AST_SymbolDefun) { + // This should be defined in the parent scope, as we encounter the + // AST_Defun node before getting to its AST_Symbol. + (node.scope = defun.parent_scope.resolve()).def_function(node, defun); + } else if (node instanceof AST_SymbolLambda) { defun.def_function(node, node.name == "arguments" ? undefined : defun); - } - else if (node instanceof AST_SymbolVar) { + } else if (node instanceof AST_SymbolVar) { defun.def_variable(node, node.TYPE == "SymbolVar" ? null : undefined); if (defun !== scope) { node.mark_enclosed(options); @@ -153,8 +147,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) { } node.reference(options); } - } - else if (node instanceof AST_SymbolCatch) { + } else if (node instanceof AST_SymbolCatch) { scope.def_variable(node).defun = defun; } }); @@ -162,9 +155,9 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) { // pass 2: find back references and eval self.globals = new Dictionary(); - var tw = new TreeWalker(function(node, descend) { - if (node instanceof AST_LoopControl && node.label) { - node.label.thedef.references.push(node); + var tw = new TreeWalker(function(node) { + if (node instanceof AST_LoopControl) { + if (node.label) node.label.thedef.references.push(node); return true; } if (node instanceof AST_SymbolRef) { @@ -185,35 +178,43 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) { return true; } // ensure mangling works if catch reuses a scope variable - var def; - if (node instanceof AST_SymbolCatch && (def = node.definition().redefined())) { - var s = node.scope; - while (s) { + if (node instanceof AST_SymbolCatch) { + var def = node.definition().redefined(); + if (def) for (var s = node.scope; s; s = s.parent_scope) { push_uniq(s.enclosed, def); if (s === def.scope) break; - s = s.parent_scope; } + return true; } }); self.walk(tw); // pass 3: fix up any scoping issue with IE8 - if (options.ie8) { - self.walk(new TreeWalker(function(node, descend) { - if (node instanceof AST_SymbolCatch) { - var name = node.name; - var refs = node.thedef.references; - var scope = node.thedef.defun; - var def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node); - refs.forEach(function(ref) { - ref.thedef = def; - ref.reference(options); - }); - node.thedef = def; - node.reference(options); - return true; + if (options.ie8) self.walk(new TreeWalker(function(node) { + if (node instanceof AST_SymbolCatch) { + redefine(node, node.thedef.defun); + return true; + } + if (node instanceof AST_SymbolLambda) { + var def = node.thedef; + if (def.orig.length == 1) { + redefine(node, node.scope.parent_scope); + node.thedef.init = def.init; } - })); + return true; + } + })); + + function redefine(node, scope) { + var name = node.name; + var refs = node.thedef.references; + var def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node); + refs.forEach(function(ref) { + ref.thedef = def; + ref.reference(options); + }); + node.thedef = def; + node.reference(options); } }); @@ -252,8 +253,7 @@ AST_Lambda.DEFMETHOD("init_scope_vars", function() { AST_Symbol.DEFMETHOD("mark_enclosed", function(options) { var def = this.definition(); - var s = this.scope; - while (s) { + for (var s = this.scope; s; s = s.parent_scope) { push_uniq(s.enclosed, def); if (options.keep_fnames) { s.functions.each(function(d) { @@ -261,7 +261,6 @@ AST_Symbol.DEFMETHOD("mark_enclosed", function(options) { }); } if (s === def.scope) break; - s = s.parent_scope; } }); @@ -298,6 +297,12 @@ AST_Scope.DEFMETHOD("def_variable", function(symbol, init) { return symbol.thedef = def; }); +AST_Lambda.DEFMETHOD("resolve", return_this); +AST_Scope.DEFMETHOD("resolve", function() { + return this.parent_scope; +}); +AST_Toplevel.DEFMETHOD("resolve", return_this); + function names_in_use(scope, options) { var names = scope.names_in_use; if (!names) { @@ -410,7 +415,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) { var save_nesting = lname; descend(); lname = save_nesting; - return true; // don't descend again in TreeWalker + return true; } if (node instanceof AST_Scope) { descend(); @@ -422,7 +427,9 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) { } if (node instanceof AST_Label) { var name; - do name = base54(++lname); while (!is_identifier(name)); + do { + name = base54(++lname); + } while (!is_identifier(name)); node.mangled_name = name; return true; } |