tidy up various interfaces (#4066)
authorAlex Lam S.L <alexlamsl@gmail.com>
Sun, 23 Aug 2020 20:39:38 +0000 (21:39 +0100)
committerGitHub <noreply@github.com>
Sun, 23 Aug 2020 20:39:38 +0000 (04:39 +0800)
lib/ast.js
lib/compress.js
lib/output.js
lib/propmangle.js
lib/scope.js

index 2c27cbb..b6d4ebb 100644 (file)
@@ -409,16 +409,16 @@ var AST_With = DEFNODE("With", "expression", {
 
 /* -----[ scope and functions ]----- */
 
-var AST_Scope = DEFNODE("Scope", "variables functions uses_with uses_eval parent_scope enclosed cname", {
+var AST_Scope = DEFNODE("Scope", "cname enclosed uses_eval uses_with parent_scope functions variables make_def", {
     $documentation: "Base class for all statements introducing a lexical scope",
     $propdoc: {
-        variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope",
-        functions: "[Object/S] like `variables`, but only lists function declarations",
-        uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
+        cname: "[integer/S] current index for mangling variables (used internally by the mangler)",
+        enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",
         uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`",
+        uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
         parent_scope: "[AST_Scope?/S] link to the parent scope",
-        enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",
-        cname: "[integer/S] current index for mangling variables (used internally by the mangler)",
+        functions: "[Object/S] like `variables`, but only lists function declarations",
+        variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope",
     },
     clone: function(deep) {
         var node = this._clone(deep);
index bcaecb8..3291f16 100644 (file)
@@ -3152,11 +3152,11 @@ merge(Compressor.prototype, {
             return this.expression._find_defs(compressor, "." + this.property + suffix);
         });
         def(AST_SymbolDeclaration, function(compressor) {
-            if (!this.global()) return;
+            if (!this.definition().global) return;
             if (HOP(compressor.option("global_defs"), this.name)) warn(this);
         });
         def(AST_SymbolRef, function(compressor, suffix) {
-            if (!this.global()) return;
+            if (!this.definition().global) return;
             var defines = compressor.option("global_defs");
             var name = this.name + suffix;
             if (HOP(defines, name)) return to_node(defines[name], this);
@@ -4700,7 +4700,7 @@ merge(Compressor.prototype, {
         });
 
         function log(sym, text, props) {
-            AST_Node[sym.unreferenced() ? "warn" : "info"](text, props);
+            AST_Node[sym.definition().references.length > 0 ? "info" : "warn"](text, props);
         }
 
         function template(sym) {
@@ -6395,7 +6395,7 @@ merge(Compressor.prototype, {
                         }
                     }));
                     var code = OutputStream();
-                    AST_BlockStatement.prototype._codegen.call(fun, fun, code);
+                    AST_BlockStatement.prototype._codegen.call(fun, code);
                     self.args = [
                         make_node(AST_String, self, {
                             value: fun.argnames.map(function(arg) {
index 19c37b2..82610fb 100644 (file)
@@ -630,13 +630,7 @@ function OutputStream(options) {
     var use_asm = false;
 
     AST_Node.DEFMETHOD("print", function(stream, force_parens) {
-        var self = this, generator = self._codegen;
-        function doit() {
-            stream.prepend_comments(self);
-            self.add_source_map(stream);
-            generator(self, stream);
-            stream.append_comments(self);
-        }
+        var self = this;
         stream.push_node(self);
         if (force_parens || self.needs_parens(stream)) {
             stream.with_parens(doit);
@@ -644,9 +638,14 @@ function OutputStream(options) {
             doit();
         }
         stream.pop_node();
-    });
-    AST_Node.DEFMETHOD("_print", AST_Node.prototype.print);
 
+        function doit() {
+            stream.prepend_comments(self);
+            self.add_source_map(stream);
+            self._codegen(stream);
+            stream.append_comments(self);
+        }
+    });
     AST_Node.DEFMETHOD("print_to_string", function(options) {
         var s = OutputStream(options);
         this.print(s);
@@ -813,9 +812,9 @@ function OutputStream(options) {
 
     /* -----[ PRINTERS ]----- */
 
-    DEFPRINT(AST_Directive, function(self, output) {
-        var quote = self.quote;
-        var value = self.value;
+    DEFPRINT(AST_Directive, function(output) {
+        var quote = this.quote;
+        var value = this.value;
         switch (output.option("quote_style")) {
           case 0:
           case 2:
@@ -828,7 +827,7 @@ function OutputStream(options) {
         output.print(quote + value + quote);
         output.semicolon();
     });
-    DEFPRINT(AST_Debugger, function(self, output) {
+    DEFPRINT(AST_Debugger, function(output) {
         output.print("debugger");
         output.semicolon();
     });
@@ -864,21 +863,21 @@ function OutputStream(options) {
         force_statement(this.body, output);
     });
 
-    DEFPRINT(AST_Statement, function(self, output) {
-        self.body.print(output);
+    DEFPRINT(AST_Statement, function(output) {
+        this.body.print(output);
         output.semicolon();
     });
-    DEFPRINT(AST_Toplevel, function(self, output) {
-        display_body(self.body, true, output, true);
+    DEFPRINT(AST_Toplevel, function(output) {
+        display_body(this.body, true, output, true);
         output.print("");
     });
-    DEFPRINT(AST_LabeledStatement, function(self, output) {
-        self.label.print(output);
+    DEFPRINT(AST_LabeledStatement, function(output) {
+        this.label.print(output);
         output.colon();
-        self.body.print(output);
+        this.body.print(output);
     });
-    DEFPRINT(AST_SimpleStatement, function(self, output) {
-        self.body.print(output);
+    DEFPRINT(AST_SimpleStatement, function(output) {
+        this.body.print(output);
         output.semicolon();
     });
     function print_braced_empty(self, output) {
@@ -895,13 +894,14 @@ function OutputStream(options) {
             });
         } else print_braced_empty(self, output);
     }
-    DEFPRINT(AST_BlockStatement, function(self, output) {
-        print_braced(self, output);
+    DEFPRINT(AST_BlockStatement, function(output) {
+        print_braced(this, output);
     });
-    DEFPRINT(AST_EmptyStatement, function(self, output) {
+    DEFPRINT(AST_EmptyStatement, function(output) {
         output.semicolon();
     });
-    DEFPRINT(AST_Do, function(self, output) {
+    DEFPRINT(AST_Do, function(output) {
+        var self = this;
         output.print("do");
         output.space();
         make_block(self.body, output);
@@ -913,7 +913,8 @@ function OutputStream(options) {
         });
         output.semicolon();
     });
-    DEFPRINT(AST_While, function(self, output) {
+    DEFPRINT(AST_While, function(output) {
+        var self = this;
         output.print("while");
         output.space();
         output.with_parens(function() {
@@ -922,7 +923,8 @@ function OutputStream(options) {
         output.space();
         self._do_print_body(output);
     });
-    DEFPRINT(AST_For, function(self, output) {
+    DEFPRINT(AST_For, function(output) {
+        var self = this;
         output.print("for");
         output.space();
         output.with_parens(function() {
@@ -951,7 +953,8 @@ function OutputStream(options) {
         output.space();
         self._do_print_body(output);
     });
-    DEFPRINT(AST_ForIn, function(self, output) {
+    DEFPRINT(AST_ForIn, function(output) {
+        var self = this;
         output.print("for");
         output.space();
         output.with_parens(function() {
@@ -964,7 +967,8 @@ function OutputStream(options) {
         output.space();
         self._do_print_body(output);
     });
-    DEFPRINT(AST_With, function(self, output) {
+    DEFPRINT(AST_With, function(output) {
+        var self = this;
         output.print("with");
         output.space();
         output.with_parens(function() {
@@ -975,7 +979,7 @@ function OutputStream(options) {
     });
 
     /* -----[ functions ]----- */
-    AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword) {
+    DEFPRINT(AST_Lambda, function(output, nokeyword) {
         var self = this;
         if (!nokeyword) {
             output.print("function");
@@ -993,32 +997,23 @@ function OutputStream(options) {
         output.space();
         print_braced(self, output, true);
     });
-    DEFPRINT(AST_Lambda, function(self, output) {
-        self._do_print(output);
-    });
 
     /* -----[ jumps ]----- */
-    function print_jump(output, kind, target) {
-        output.print(kind);
-        if (target) {
-            output.space();
-            target.print(output);
-        }
-        output.semicolon();
+    function print_jump(kind, prop) {
+        return function(output) {
+            output.print(kind);
+            var target = this[prop];
+            if (target) {
+                output.space();
+                target.print(output);
+            }
+            output.semicolon();
+        };
     }
-
-    DEFPRINT(AST_Return, function(self, output) {
-        print_jump(output, "return", self.value);
-    });
-    DEFPRINT(AST_Throw, function(self, output) {
-        print_jump(output, "throw", self.value);
-    });
-    DEFPRINT(AST_Break, function(self, output) {
-        print_jump(output, "break", self.label);
-    });
-    DEFPRINT(AST_Continue, function(self, output) {
-        print_jump(output, "continue", self.label);
-    });
+    DEFPRINT(AST_Return, print_jump("return", "value"));
+    DEFPRINT(AST_Throw, print_jump("throw", "value"));
+    DEFPRINT(AST_Break, print_jump("break", "label"));
+    DEFPRINT(AST_Continue, print_jump("continue", "label"));
 
     /* -----[ if ]----- */
     function make_then(self, output) {
@@ -1047,7 +1042,8 @@ function OutputStream(options) {
         }
         force_statement(self.body, output);
     }
-    DEFPRINT(AST_If, function(self, output) {
+    DEFPRINT(AST_If, function(output) {
+        var self = this;
         output.print("if");
         output.space();
         output.with_parens(function() {
@@ -1069,7 +1065,8 @@ function OutputStream(options) {
     });
 
     /* -----[ switch ]----- */
-    DEFPRINT(AST_Switch, function(self, output) {
+    DEFPRINT(AST_Switch, function(output) {
+        var self = this;
         output.print("switch");
         output.space();
         output.with_parens(function() {
@@ -1087,28 +1084,30 @@ function OutputStream(options) {
             });
         });
     });
-    AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output) {
+    function print_branch_body(self, output) {
         output.newline();
-        this.body.forEach(function(stmt) {
+        self.body.forEach(function(stmt) {
             output.indent();
             stmt.print(output);
             output.newline();
         });
-    });
-    DEFPRINT(AST_Default, function(self, output) {
+    }
+    DEFPRINT(AST_Default, function(output) {
         output.print("default:");
-        self._do_print_body(output);
+        print_branch_body(this, output);
     });
-    DEFPRINT(AST_Case, function(self, output) {
+    DEFPRINT(AST_Case, function(output) {
+        var self = this;
         output.print("case");
         output.space();
         self.expression.print(output);
         output.print(":");
-        self._do_print_body(output);
+        print_branch_body(self, output);
     });
 
     /* -----[ exceptions ]----- */
-    DEFPRINT(AST_Try, function(self, output) {
+    DEFPRINT(AST_Try, function(output) {
+        var self = this;
         output.print("try");
         output.space();
         print_braced(self, output);
@@ -1121,7 +1120,8 @@ function OutputStream(options) {
             self.bfinally.print(output);
         }
     });
-    DEFPRINT(AST_Catch, function(self, output) {
+    DEFPRINT(AST_Catch, function(output) {
+        var self = this;
         output.print("catch");
         output.space();
         output.with_parens(function() {
@@ -1130,13 +1130,14 @@ function OutputStream(options) {
         output.space();
         print_braced(self, output);
     });
-    DEFPRINT(AST_Finally, function(self, output) {
+    DEFPRINT(AST_Finally, function(output) {
         output.print("finally");
         output.space();
-        print_braced(self, output);
+        print_braced(this, output);
     });
 
-    DEFPRINT(AST_Var, function(self, output) {
+    DEFPRINT(AST_Var, function(output) {
+        var self = this;
         output.print("var");
         output.space();
         self.definitions.forEach(function(def, i) {
@@ -1161,7 +1162,8 @@ function OutputStream(options) {
         node.print(output, parens);
     }
 
-    DEFPRINT(AST_VarDef, function(self, output) {
+    DEFPRINT(AST_VarDef, function(output) {
+        var self = this;
         self.name.print(output);
         if (self.value) {
             output.space();
@@ -1185,18 +1187,19 @@ function OutputStream(options) {
             });
         });
     }
-    DEFPRINT(AST_Call, function(self, output) {
-        self.expression.print(output);
-        print_call_args(self, output);
+    DEFPRINT(AST_Call, function(output) {
+        this.expression.print(output);
+        print_call_args(this, output);
     });
-    DEFPRINT(AST_New, function(self, output) {
+    DEFPRINT(AST_New, function(output) {
+        var self = this;
         output.print("new");
         output.space();
         self.expression.print(output);
         if (need_constructor_parens(self, output)) print_call_args(self, output);
     });
-    DEFPRINT(AST_Sequence, function(self, output) {
-        self.expressions.forEach(function(node, index) {
+    DEFPRINT(AST_Sequence, function(output) {
+        this.expressions.forEach(function(node, index) {
             if (index > 0) {
                 output.comma();
                 if (output.should_break()) {
@@ -1207,7 +1210,8 @@ function OutputStream(options) {
             node.print(output);
         });
     });
-    DEFPRINT(AST_Dot, function(self, output) {
+    DEFPRINT(AST_Dot, function(output) {
+        var self = this;
         var expr = self.expression;
         expr.print(output);
         var prop = self.property;
@@ -1228,35 +1232,38 @@ function OutputStream(options) {
             output.print_name(prop);
         }
     });
-    DEFPRINT(AST_Sub, function(self, output) {
-        self.expression.print(output);
+    DEFPRINT(AST_Sub, function(output) {
+        this.expression.print(output);
         output.print("[");
-        self.property.print(output);
+        this.property.print(output);
         output.print("]");
     });
-    DEFPRINT(AST_UnaryPrefix, function(self, output) {
-        var op = self.operator;
+    DEFPRINT(AST_UnaryPrefix, function(output) {
+        var op = this.operator;
+        var exp = this.expression;
         output.print(op);
         if (/^[a-z]/i.test(op)
             || (/[+-]$/.test(op)
-                && self.expression instanceof AST_UnaryPrefix
-                && /^[+-]/.test(self.expression.operator))) {
+                && exp instanceof AST_UnaryPrefix
+                && /^[+-]/.test(exp.operator))) {
             output.space();
         }
-        self.expression.print(output);
+        exp.print(output);
     });
-    DEFPRINT(AST_UnaryPostfix, function(self, output) {
-        self.expression.print(output);
-        output.print(self.operator);
+    DEFPRINT(AST_UnaryPostfix, function(output) {
+        this.expression.print(output);
+        output.print(this.operator);
     });
-    DEFPRINT(AST_Binary, function(self, output) {
+    DEFPRINT(AST_Binary, function(output) {
+        var self = this;
         self.left.print(output);
         output.space();
         output.print(self.operator);
         output.space();
         self.right.print(output);
     });
-    DEFPRINT(AST_Conditional, function(self, output) {
+    DEFPRINT(AST_Conditional, function(output) {
+        var self = this;
         self.condition.print(output);
         output.space();
         output.print("?");
@@ -1268,10 +1275,10 @@ function OutputStream(options) {
     });
 
     /* -----[ literals ]----- */
-    DEFPRINT(AST_Array, function(self, output) {
-        output.with_square(function() {
-            var a = self.elements, len = a.length;
-            if (len > 0) output.space();
+    DEFPRINT(AST_Array, function(output) {
+        var a = this.elements, len = a.length;
+        output.with_square(len > 0 ? function() {
+            output.space();
             a.forEach(function(exp, i) {
                 if (i) output.comma();
                 exp.print(output);
@@ -1281,12 +1288,13 @@ function OutputStream(options) {
                 if (i === len - 1 && exp instanceof AST_Hole)
                   output.comma();
             });
-            if (len > 0) output.space();
-        });
+            output.space();
+        } : noop);
     });
-    DEFPRINT(AST_Object, function(self, output) {
-        if (self.properties.length > 0) output.with_block(function() {
-            self.properties.forEach(function(prop, i) {
+    DEFPRINT(AST_Object, function(output) {
+        var props = this.properties;
+        if (props.length > 0) output.with_block(function() {
+            props.forEach(function(prop, i) {
                 if (i) {
                     output.print(",");
                     output.newline();
@@ -1296,7 +1304,7 @@ function OutputStream(options) {
             });
             output.newline();
         });
-        else print_braced_empty(self, output);
+        else print_braced_empty(this, output);
     });
 
     function print_property_name(key, quote, output) {
@@ -1315,47 +1323,48 @@ function OutputStream(options) {
         }
     }
 
-    DEFPRINT(AST_ObjectKeyVal, function(self, output) {
+    DEFPRINT(AST_ObjectKeyVal, function(output) {
+        var self = this;
         print_property_name(self.key, self.quote, output);
         output.colon();
         self.value.print(output);
     });
-    AST_ObjectProperty.DEFMETHOD("_print_getter_setter", function(type, output) {
-        output.print(type);
-        output.space();
-        print_property_name(this.key.name, this.quote, output);
-        this.value._do_print(output, true);
-    });
-    DEFPRINT(AST_ObjectSetter, function(self, output) {
-        self._print_getter_setter("set", output);
-    });
-    DEFPRINT(AST_ObjectGetter, function(self, output) {
-        self._print_getter_setter("get", output);
-    });
-    DEFPRINT(AST_Symbol, function(self, output) {
-        var def = self.definition();
-        output.print_name(def && def.mangled_name || self.name);
+    function print_accessor(type) {
+        return function(output) {
+            var self = this;
+            output.print(type);
+            output.space();
+            print_property_name(self.key.name, self.quote, output);
+            self.value._codegen(output, true);
+        };
+    }
+    DEFPRINT(AST_ObjectGetter, print_accessor("get"));
+    DEFPRINT(AST_ObjectSetter, print_accessor("set"));
+    DEFPRINT(AST_Symbol, function(output) {
+        var def = this.definition();
+        output.print_name(def && def.mangled_name || this.name);
     });
     DEFPRINT(AST_Hole, noop);
-    DEFPRINT(AST_This, function(self, output) {
+    DEFPRINT(AST_This, function(output) {
         output.print("this");
     });
-    DEFPRINT(AST_Constant, function(self, output) {
-        output.print(self.value);
+    DEFPRINT(AST_Constant, function(output) {
+        output.print(this.value);
     });
-    DEFPRINT(AST_String, function(self, output) {
-        output.print_string(self.value, self.quote);
+    DEFPRINT(AST_String, function(output) {
+        output.print_string(this.value, this.quote);
     });
-    DEFPRINT(AST_Number, function(self, output) {
-        if (use_asm && self.start && self.start.raw != null) {
-            output.print(self.start.raw);
+    DEFPRINT(AST_Number, function(output) {
+        var start = this.start;
+        if (use_asm && start && start.raw != null) {
+            output.print(start.raw);
         } else {
-            output.print(make_num(self.value));
+            output.print(make_num(this.value));
         }
     });
 
-    DEFPRINT(AST_RegExp, function(self, output) {
-        var regexp = self.value;
+    DEFPRINT(AST_RegExp, function(output) {
+        var regexp = this.value;
         var str = regexp.toString();
         var end = str.lastIndexOf("/");
         if (regexp.raw_source) {
@@ -1389,7 +1398,7 @@ function OutputStream(options) {
             }
         }));
         var p = output.parent();
-        if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self)
+        if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === this)
             output.print(" ");
     });
 
index 0419439..e47497d 100644 (file)
@@ -110,7 +110,6 @@ function mangle_properties(ast, options) {
         cache: null,
         debug: false,
         keep_quoted: false,
-        only_cache: false,
         regex: null,
         reserved: null,
     }, true);
@@ -213,7 +212,6 @@ function mangle_properties(ast, options) {
 
     function can_mangle(name) {
         if (unmangleable[name]) return false;
-        if (options.only_cache) return cache.has(name);
         if (/^-?[0-9]+(\.[0-9]+)?(e[+-][0-9]+)?$/.test(name)) return false;
         return true;
     }
index 450c106..5d990c0 100644 (file)
@@ -96,8 +96,9 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
 
     // pass 1: setup scope chaining and handle definitions
     var self = this;
-    var scope = self.parent_scope = null;
     var defun = null;
+    var next_def_id = 0;
+    var scope = self.parent_scope = null;
     var tw = new TreeWalker(function(node, descend) {
         if (node instanceof AST_Catch) {
             var save_scope = scope;
@@ -149,7 +150,9 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
             scope.def_variable(node).defun = defun;
         }
     });
-    self.next_def_id = 0;
+    self.make_def = function(orig, init) {
+        return new SymbolDef(++next_def_id, this, orig, init);
+    };
     self.walk(tw);
 
     // pass 2: find back references and eval
@@ -240,12 +243,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
     }
 });
 
-AST_Scope.DEFMETHOD("make_def", function(orig, init) {
-    var top = this;
-    while (top.parent_scope) top = top.parent_scope;
-    return new SymbolDef(++top.next_def_id, this, orig, init);
-});
-
 AST_Toplevel.DEFMETHOD("def_global", function(node) {
     var globals = this.globals, name = node.name;
     if (globals.has(name)) {
@@ -259,23 +256,28 @@ AST_Toplevel.DEFMETHOD("def_global", function(node) {
     }
 });
 
+function init_scope_vars(scope, parent) {
+    scope.cname = -1;                               // the current index for mangling functions/variables
+    scope.enclosed = [];                            // variables from this or outer scope(s) that are referenced from this or inner scopes
+    scope.uses_eval = false;                        // will be set to true if this or nested scope uses the global `eval`
+    scope.uses_with = false;                        // will be set to true if this or some nested scope uses the `with` statement
+    scope.parent_scope = parent;                    // the parent scope (null if this is the top level)
+    scope.functions = new Dictionary();             // map name to AST_SymbolDefun (functions defined in this scope)
+    scope.variables = new Dictionary();             // map name to AST_SymbolVar (variables defined in this scope; includes functions)
+    if (parent) scope.make_def = parent.make_def;   // top-level tracking of SymbolDef instances
+}
+
 AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope) {
-    this.variables = new Dictionary();  // map name to AST_SymbolVar (variables defined in this scope; includes functions)
-    this.functions = new Dictionary();  // map name to AST_SymbolDefun (functions defined in this scope)
-    this.uses_with = false;             // will be set to true if this or some nested scope uses the `with` statement
-    this.uses_eval = false;             // will be set to true if this or nested scope uses the global `eval`
-    this.parent_scope = parent_scope;   // the parent scope
-    this.enclosed = [];                 // a list of variables from this or outer scope(s) that are referenced from this or inner scopes
-    this.cname = -1;                    // the current index for mangling functions/variables
+    init_scope_vars(this, parent_scope);
 });
 
-AST_Lambda.DEFMETHOD("init_scope_vars", function() {
-    AST_Scope.prototype.init_scope_vars.apply(this, arguments);
+AST_Lambda.DEFMETHOD("init_scope_vars", function(parent_scope) {
+    init_scope_vars(this, parent_scope);
     this.uses_arguments = false;
     this.def_variable(new AST_SymbolFunarg({
         name: "arguments",
         start: this.start,
-        end: this.end
+        end: this.end,
     }));
 });
 
@@ -387,18 +389,10 @@ AST_Symbol.DEFMETHOD("unmangleable", function(options) {
 // labels are always mangleable
 AST_Label.DEFMETHOD("unmangleable", return_false);
 
-AST_Symbol.DEFMETHOD("unreferenced", function() {
-    return !this.definition().references.length && !this.scope.pinned();
-});
-
 AST_Symbol.DEFMETHOD("definition", function() {
     return this.thedef;
 });
 
-AST_Symbol.DEFMETHOD("global", function() {
-    return this.definition().global;
-});
-
 function _default_mangler_options(options) {
     options = defaults(options, {
         eval        : false,
@@ -558,8 +552,8 @@ AST_Sequence.DEFMETHOD("tail_node", function() {
 AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options) {
     options = _default_mangler_options(options);
     base54.reset();
+    var fn = AST_Symbol.prototype.add_source_map;
     try {
-        var fn = AST_Symbol.prototype.add_source_map;
         AST_Symbol.prototype.add_source_map = function() {
             if (!this.unmangleable(options)) base54.consider(this.name, -1);
         };