aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMihai Bazon <mihai@bazon.net>2013-11-28 16:43:30 +0200
committerMihai Bazon <mihai@bazon.net>2013-11-28 16:43:30 +0200
commitd2190c2bf340d807a0c8595dbc2f849aa3bcc443 (patch)
tree4ec009a6b861db9e70fcfe69c03162a65a856134
parentea1064257206cfa8d55ee6aad05536f940cc38a4 (diff)
downloadtracifyjs-d2190c2bf340d807a0c8595dbc2f849aa3bcc443.tar.gz
tracifyjs-d2190c2bf340d807a0c8595dbc2f849aa3bcc443.zip
Properly scope `catch` identifier when --screw-ie8
Fix #344
-rw-r--r--lib/ast.js8
-rw-r--r--lib/compress.js4
-rw-r--r--lib/scope.js36
3 files changed, 19 insertions, 29 deletions
diff --git a/lib/ast.js b/lib/ast.js
index 0fa48e28..1a291e31 100644
--- a/lib/ast.js
+++ b/lib/ast.js
@@ -498,12 +498,6 @@ var AST_Try = DEFNODE("Try", "bcatch bfinally", {
}
}, 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: {
@@ -515,7 +509,7 @@ var AST_Catch = DEFNODE("Catch", "argname", {
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"
diff --git a/lib/compress.js b/lib/compress.js
index 3cc59e2c..95dd64d6 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -1669,10 +1669,10 @@ merge(Compressor.prototype, {
return arg.value;
}).join(",") + "){" + self.args[self.args.length - 1].value + "})()";
var ast = parse(code);
- ast.figure_out_scope();
+ ast.figure_out_scope({ screw_ie8: compressor.option("screw_ie8") });
var comp = new Compressor(compressor.options);
ast = ast.transform(comp);
- ast.figure_out_scope();
+ ast.figure_out_scope({ screw_ie8: compressor.option("screw_ie8") });
ast.mangle_names();
var fun;
try {
diff --git a/lib/scope.js b/lib/scope.js
index 49b04811..ed189d49 100644
--- a/lib/scope.js
+++ b/lib/scope.js
@@ -71,27 +71,28 @@ SymbolDef.prototype = {
}
};
-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) {
@@ -108,7 +109,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
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
@@ -116,22 +117,17 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
// 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);