}
}, 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", {
$documentation: "A `catch` node; only makes sense as part of a `try` statement",
$propdoc: {
walk_body(this, visitor);
});
}
-}, AST_Block);
+}, AST_Scope);
var AST_Finally = DEFNODE("Finally", null, {
$documentation: "A `finally` node; only makes sense as part of a `try` statement"
}
};
-AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
- // This does what ast_add_scope did in UglifyJS v1.
- //
- // 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.
+AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
+ options = defaults(options, {
+ screw_ie8: false
+ });
// pass 1: setup scope chaining and handle definitions
var self = this;
var scope = self.parent_scope = null;
+ var defun = null;
var nesting = 0;
var tw = new TreeWalker(function(node, descend){
if (node instanceof AST_Scope) {
node.init_scope_vars(nesting);
var save_scope = node.parent_scope = scope;
- ++nesting;
+ var save_defun = defun;
+ if (!(node instanceof AST_Catch)) {
+ defun = node;
+ }
scope = node;
- descend();
+ ++nesting; descend(); --nesting;
scope = save_scope;
- --nesting;
+ defun = save_defun;
return true; // don't descend again in TreeWalker
}
if (node instanceof AST_Directive) {
node.scope = scope;
}
if (node instanceof AST_SymbolLambda) {
- scope.def_function(node);
+ defun.def_function(node);
}
else if (node instanceof AST_SymbolDefun) {
// Careful here, the scope where this should be defined is
// scope when we encounter the AST_Defun node (which is
// instanceof AST_Scope) but we get to the symbol a bit
// later.
- (node.scope = scope.parent_scope).def_function(node);
+ (node.scope = defun.parent_scope).def_function(node);
}
else if (node instanceof AST_SymbolVar
|| node instanceof AST_SymbolConst) {
- var def = scope.def_variable(node);
+ var def = defun.def_variable(node);
def.constant = node instanceof AST_SymbolConst;
def.init = tw.parent().value;
}
else if (node instanceof AST_SymbolCatch) {
- // XXX: this is wrong according to ECMA-262 (12.4). the
- // `catch` argument name should be visible only inside the
- // 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);
+ (options.screw_ie8 ? scope : defun)
+ .def_variable(node);
}
});
self.walk(tw);