unify logging functionality (#3392)
authorAlex Lam S.L <alexlamsl@gmail.com>
Mon, 29 Apr 2019 22:32:24 +0000 (06:32 +0800)
committerGitHub <noreply@github.com>
Mon, 29 Apr 2019 22:32:24 +0000 (06:32 +0800)
fixes #3253
fixes #3254

13 files changed:
bin/uglifyjs
lib/ast.js
lib/compress.js
lib/minify.js
lib/parse.js
lib/utils.js
test/compress/collapse_vars.js
test/compress/drop-unused.js
test/compress/ie8.js
test/compress/issue-1034.js
test/mocha/cli.js
test/mocha/sourcemaps.js
test/run-tests.js

index bee6b6a..35207bf 100755 (executable)
@@ -63,7 +63,7 @@ if (program.configFile) {
     }
 }
 if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
-    fatal("ERROR: cannot write source map to STDOUT");
+    fatal("cannot write source map to STDOUT");
 }
 [
     "compress",
@@ -78,6 +78,15 @@ if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
         options[name] = program[name];
     }
 });
+if (program.verbose) {
+    options.warnings = "verbose";
+} else if (program.warn) {
+    options.warnings = true;
+}
+if (options.warnings) {
+    UglifyJS.AST_Node.log_function(print_error, options.warnings == "verbose");
+    delete options.warnings;
+}
 if (program.beautify) {
     options.output = typeof program.beautify == "object" ? program.beautify : {};
     if (!("beautify" in options.output)) {
@@ -124,7 +133,7 @@ if (program.parse) {
     if (!program.parse.acorn && !program.parse.spidermonkey) {
         options.parse = program.parse;
     } else if (program.sourceMap && program.sourceMap.content == "inline") {
-        fatal("ERROR: inline source map only works with built-in parser");
+        fatal("inline source map only works with built-in parser");
     }
 }
 if (~program.rawArgs.indexOf("--rename")) {
@@ -144,15 +153,8 @@ if (typeof program.sourceMap == "object" && "base" in program.sourceMap) {
         };
     }();
 }
-if (program.verbose) {
-    options.warnings = "verbose";
-} else if (program.warn) {
-    options.warnings = true;
-}
 if (program.self) {
-    if (program.args.length) {
-        print_error("WARN: Ignoring input files since --self was passed");
-    }
+    if (program.args.length) UglifyJS.AST_Node.warn("Ignoring input files since --self was passed");
     if (!options.wrap) options.wrap = "UglifyJS";
     simple_glob(UglifyJS.FILES).forEach(function(name) {
         files[convert_path(name)] = read_file(name);
@@ -180,12 +182,9 @@ function convert_ast(fn) {
 }
 
 function run() {
-    UglifyJS.AST_Node.warn_function = function(msg) {
-        print_error("WARN: " + msg);
-    };
     var content = program.sourceMap && program.sourceMap.content;
     if (content && content != "inline") {
-        print_error("INFO: Using input source map: " + content);
+        UglifyJS.AST_Node.info("Using input source map: " + content);
         options.sourceMap.content = read_file(content, content);
     }
     if (program.timings) options.timings = true;
@@ -293,7 +292,11 @@ function run() {
 }
 
 function fatal(message) {
-    if (message instanceof Error) message = message.stack.replace(/^\S*?Error:/, "ERROR:")
+    if (message instanceof Error) {
+        message = message.stack.replace(/^\S*?Error:/, "ERROR:")
+    } else {
+        message = "ERROR: " + message;
+    }
     print_error(message);
     process.exit(1);
 }
@@ -370,9 +373,9 @@ function parse_js(flag) {
                     });
                 }
             }));
-        } catch(ex) {
+        } catch (ex) {
             if (flag) {
-                fatal("Error parsing arguments for '" + flag + "': " + value);
+                fatal("cannot parse arguments for '" + flag + "': " + value);
             } else {
                 options[value] = null;
             }
index f496095..f75670e 100644 (file)
@@ -118,9 +118,25 @@ var AST_Node = DEFNODE("Node", "start end", {
     }
 }, null);
 
-AST_Node.warn = function(txt, props) {
-    if (AST_Node.warn_function) AST_Node.warn_function(string_template(txt, props));
-};
+(AST_Node.log_function = function(fn, verbose) {
+    var printed = Object.create(null);
+    if (fn) {
+        AST_Node.info = verbose ? function(text, props) {
+            log("INFO: " + string_template(text, props));
+        } : noop;
+        AST_Node.warn = function(text, props) {
+            log("WARN: " + string_template(text, props));
+        };
+    } else {
+        AST_Node.info = AST_Node.warn = noop;
+    }
+
+    function log(msg) {
+        if (printed[msg]) return;
+        printed[msg] = true;
+        fn(msg);
+    }
+})();
 
 /* -----[ statements ]----- */
 
index 7d9a74d..4db202a 100644 (file)
@@ -94,7 +94,6 @@ function Compressor(options, false_by_default) {
         unsafe_regexp   : false,
         unsafe_undefined: false,
         unused          : !false_by_default,
-        warnings        : false,
     }, true);
     var global_defs = this.options["global_defs"];
     if (typeof global_defs == "object") for (var key in global_defs) {
@@ -144,7 +143,6 @@ function Compressor(options, false_by_default) {
     };
     var sequences = this.options["sequences"];
     this.sequences_limit = sequences == 1 ? 800 : sequences | 0;
-    this.warnings_produced = {};
 }
 
 Compressor.prototype = new TreeTransformer;
@@ -175,7 +173,7 @@ merge(Compressor.prototype, {
                 node.walk(new TreeWalker(function() {
                     count++;
                 }));
-                this.info("pass " + pass + ": last_count: " + min_count + ", count: " + count);
+                AST_Node.info("pass " + pass + ": last_count: " + min_count + ", count: " + count);
                 if (count < min_count) {
                     min_count = count;
                     stopping = false;
@@ -191,24 +189,6 @@ merge(Compressor.prototype, {
         }
         return node;
     },
-    info: function() {
-        if (this.options.warnings == "verbose") {
-            AST_Node.warn.apply(AST_Node, arguments);
-        }
-    },
-    warn: function(text, props) {
-        if (this.options.warnings) {
-            // only emit unique warnings
-            var message = string_template(text, props);
-            if (!(message in this.warnings_produced)) {
-                this.warnings_produced[message] = true;
-                AST_Node.warn.apply(AST_Node, arguments);
-            }
-        }
-    },
-    clear_warnings: function() {
-        this.warnings_produced = {};
-    },
     before: function(node, descend, in_list) {
         if (node._squeezed) return node;
         var is_scope = node instanceof AST_Scope;
@@ -1138,7 +1118,7 @@ merge(Compressor.prototype, {
                         if (value_def && candidate instanceof AST_VarDef) return node;
                     }
                     CHANGED = abort = true;
-                    compressor.info("Collapsing {name} [{file}:{line},{col}]", {
+                    AST_Node.info("Collapsing {name} [{file}:{line},{col}]", {
                         name: node.print_to_string(),
                         file: node.start.file,
                         line: node.start.line,
@@ -1963,7 +1943,7 @@ merge(Compressor.prototype, {
             statements.length = n;
             CHANGED = n != len;
             if (has_quit) has_quit.forEach(function(stat) {
-                extract_declarations_from_unreachable_code(compressor, stat, statements);
+                extract_declarations_from_unreachable_code(stat, statements);
             });
         }
 
@@ -2216,13 +2196,13 @@ merge(Compressor.prototype, {
         }
     }
 
-    function extract_declarations_from_unreachable_code(compressor, stat, target) {
+    function extract_declarations_from_unreachable_code(stat, target) {
         if (!(stat instanceof AST_Defun)) {
-            compressor.warn("Dropping unreachable code [{file}:{line},{col}]", stat.start);
+            AST_Node.warn("Dropping unreachable code [{file}:{line},{col}]", stat.start);
         }
         stat.walk(new TreeWalker(function(node) {
             if (node instanceof AST_Definitions) {
-                compressor.warn("Declarations in unreachable code! [{file}:{line},{col}]", node.start);
+                AST_Node.warn("Declarations in unreachable code! [{file}:{line},{col}]", node.start);
                 node.remove_initializers();
                 target.push(node);
                 return true;
@@ -2599,8 +2579,8 @@ merge(Compressor.prototype, {
             return make_node_from_constant(value, orig);
         }
 
-        function warn(compressor, node) {
-            compressor.warn("global_defs " + node.print_to_string() + " redefined [{file}:{line},{col}]", node.start);
+        function warn(node) {
+            AST_Node.warn("global_defs " + node.print_to_string() + " redefined [{file}:{line},{col}]", node.start);
         }
 
         AST_Toplevel.DEFMETHOD("resolve_defines", function(compressor) {
@@ -2616,7 +2596,7 @@ merge(Compressor.prototype, {
                     child = parent;
                 }
                 if (is_lhs(child, parent)) {
-                    warn(compressor, node);
+                    warn(node);
                     return;
                 }
                 return def;
@@ -2628,7 +2608,7 @@ merge(Compressor.prototype, {
         });
         def(AST_SymbolDeclaration, function(compressor) {
             if (!this.global()) return;
-            if (HOP(compressor.option("global_defs"), this.name)) warn(compressor, this);
+            if (HOP(compressor.option("global_defs"), this.name)) warn(this);
         });
         def(AST_SymbolRef, function(compressor, suffix) {
             if (!this.global()) return;
@@ -3037,7 +3017,7 @@ merge(Compressor.prototype, {
                 try {
                     return val[key].apply(val, args);
                 } catch (ex) {
-                    compressor.warn("Error evaluating {code} [{file}:{line},{col}]", {
+                    AST_Node.warn("Error evaluating {code} [{file}:{line},{col}]", {
                         code: this.print_to_string(),
                         file: this.start.file,
                         line: this.start.line,
@@ -3648,7 +3628,7 @@ merge(Compressor.prototype, {
                         sym.__unused = true;
                         if (trim) {
                             a.pop();
-                            compressor[sym.unreferenced() ? "warn" : "info"]("Dropping unused function argument {name} [{file}:{line},{col}]", template(sym));
+                            AST_Node[sym.unreferenced() ? "warn" : "info"]("Dropping unused function argument {name} [{file}:{line},{col}]", template(sym));
                         }
                     } else {
                         trim = false;
@@ -3658,7 +3638,7 @@ merge(Compressor.prototype, {
             if (drop_funcs && node instanceof AST_Defun && node !== self) {
                 var def = node.name.definition();
                 if (!(def.id in in_use_ids)) {
-                    compressor[node.name.unreferenced() ? "warn" : "info"]("Dropping unused function {name} [{file}:{line},{col}]", template(node.name));
+                    AST_Node[node.name.unreferenced() ? "warn" : "info"]("Dropping unused function {name} [{file}:{line},{col}]", template(node.name));
                     def.eliminated++;
                     return make_node(AST_EmptyStatement, node);
                 }
@@ -3679,7 +3659,7 @@ merge(Compressor.prototype, {
                         }
                         var var_defs = var_defs_by_id.get(sym.id);
                         if (var_defs.length > 1 && (!def.value || sym.orig.indexOf(def.name) > sym.eliminated)) {
-                            compressor.warn("Dropping duplicated definition of variable {name} [{file}:{line},{col}]", template(def.name));
+                            AST_Node.warn("Dropping duplicated definition of variable {name} [{file}:{line},{col}]", template(def.name));
                             if (def.value) {
                                 var ref = make_node(AST_SymbolRef, def.name, def.name);
                                 sym.references.push(ref);
@@ -3704,7 +3684,7 @@ merge(Compressor.prototype, {
                             && def.value instanceof AST_Function
                             && can_rename(def.value, def.name.name)
                             && (!compressor.has_directive("use strict") || parent instanceof AST_Scope)) {
-                            compressor.warn("Declaring {name} as function [{file}:{line},{col}]", template(def.name));
+                            AST_Node.warn("Declaring {name} as function [{file}:{line},{col}]", template(def.name));
                             var defun = make_node(AST_Defun, def, def.value);
                             defun.name = make_node(AST_SymbolDefun, def.name, def.name);
                             var name_def = def.name.scope.resolve().def_function(defun.name);
@@ -3741,10 +3721,10 @@ merge(Compressor.prototype, {
                     } else {
                         var value = def.value && def.value.drop_side_effect_free(compressor);
                         if (value) {
-                            compressor.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", template(def.name));
+                            AST_Node.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", template(def.name));
                             side_effects.push(value);
                         } else {
-                            compressor[def.name.unreferenced() ? "warn" : "info"]("Dropping unused variable {name} [{file}:{line},{col}]", template(def.name));
+                            AST_Node[def.name.unreferenced() ? "warn" : "info"]("Dropping unused variable {name} [{file}:{line},{col}]", template(def.name));
                         }
                         sym.eliminated++;
                     }
@@ -4209,9 +4189,7 @@ merge(Compressor.prototype, {
                 }
                 return this;
             }
-            if (this.pure) {
-                compressor.warn("Dropping __PURE__ call [{file}:{line},{col}]", this.start);
-            }
+            if (this.pure) AST_Node.warn("Dropping __PURE__ call [{file}:{line},{col}]", this.start);
             var args = trim(this.args, compressor, first_in_statement);
             return args && make_sequence(this, args);
         });
@@ -4294,7 +4272,7 @@ merge(Compressor.prototype, {
             var body = self.body;
             var node = body.drop_side_effect_free(compressor, true);
             if (!node) {
-                compressor.warn("Dropping side-effect-free statement [{file}:{line},{col}]", self.start);
+                AST_Node.warn("Dropping side-effect-free statement [{file}:{line},{col}]", self.start);
                 return make_node(AST_EmptyStatement, self);
             }
             if (node !== body) {
@@ -4373,7 +4351,7 @@ merge(Compressor.prototype, {
                     body: self.condition
                 }));
             }
-            extract_declarations_from_unreachable_code(compressor, self.body, body);
+            extract_declarations_from_unreachable_code(self.body, body);
             return make_node(AST_BlockStatement, self, {
                 body: body
             });
@@ -4446,7 +4424,7 @@ merge(Compressor.prototype, {
             if (!cond) {
                 if (compressor.option("dead_code")) {
                     var body = [];
-                    extract_declarations_from_unreachable_code(compressor, self.body, body);
+                    extract_declarations_from_unreachable_code(self.body, body);
                     if (self.init instanceof AST_Statement) {
                         body.push(self.init);
                     } else if (self.init) {
@@ -4493,20 +4471,18 @@ merge(Compressor.prototype, {
                 cond = self.condition.is_truthy() || self.condition.tail_node().evaluate(compressor);
             }
             if (!cond) {
-                compressor.warn("Condition always false [{file}:{line},{col}]", self.condition.start);
+                AST_Node.warn("Condition always false [{file}:{line},{col}]", self.condition.start);
                 var body = [];
-                extract_declarations_from_unreachable_code(compressor, self.body, body);
+                extract_declarations_from_unreachable_code(self.body, body);
                 body.push(make_node(AST_SimpleStatement, self.condition, {
                     body: self.condition
                 }));
                 if (self.alternative) body.push(self.alternative);
                 return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
             } else if (!(cond instanceof AST_Node)) {
-                compressor.warn("Condition always true [{file}:{line},{col}]", self.condition.start);
+                AST_Node.warn("Condition always true [{file}:{line},{col}]", self.condition.start);
                 var body = [];
-                if (self.alternative) {
-                    extract_declarations_from_unreachable_code(compressor, self.alternative, body);
-                }
+                if (self.alternative) extract_declarations_from_unreachable_code(self.alternative, body);
                 body.push(make_node(AST_SimpleStatement, self.condition, {
                     body: self.condition
                 }));
@@ -4721,7 +4697,7 @@ merge(Compressor.prototype, {
             if (prev && !aborts(prev)) {
                 prev.body = prev.body.concat(branch.body);
             } else {
-                extract_declarations_from_unreachable_code(compressor, branch, decl);
+                extract_declarations_from_unreachable_code(branch, decl);
             }
         }
     });
@@ -4732,7 +4708,7 @@ merge(Compressor.prototype, {
         if (compressor.option("dead_code") && all(self.body, is_empty)) {
             var body = [];
             if (self.bcatch) {
-                extract_declarations_from_unreachable_code(compressor, self.bcatch, body);
+                extract_declarations_from_unreachable_code(self.bcatch, body);
                 body.forEach(function(stat) {
                     if (!(stat instanceof AST_Definitions)) return;
                     stat.definitions.forEach(function(var_def) {
@@ -4844,7 +4820,7 @@ merge(Compressor.prototype, {
                             elements: elements
                         });
                     } catch (ex) {
-                        compressor.warn("Invalid array length: {length} [{file}:{line},{col}]", {
+                        AST_Node.warn("Invalid array length: {length} [{file}:{line},{col}]", {
                             length: length,
                             file: self.start.file,
                             line: self.start.line,
@@ -4904,7 +4880,7 @@ merge(Compressor.prototype, {
                             value: RegExp.apply(RegExp, params),
                         }));
                     } catch (ex) {
-                        compressor.warn("Error converting {expr} [{file}:{line},{col}]", {
+                        AST_Node.warn("Error converting {expr} [{file}:{line},{col}]", {
                             expr: self.print_to_string(),
                             file: self.start.file,
                             line: self.start.line,
@@ -5087,8 +5063,8 @@ merge(Compressor.prototype, {
                     return self;
                 } catch (ex) {
                     if (ex instanceof JS_Parse_Error) {
-                        compressor.warn("Error parsing code passed to new Function [{file}:{line},{col}]", self.args[self.args.length - 1].start);
-                        compressor.warn(ex.toString());
+                        AST_Node.warn("Error parsing code passed to new Function [{file}:{line},{col}]", self.args[self.args.length - 1].start);
+                        AST_Node.warn(ex.toString());
                     } else {
                         throw ex;
                     }
@@ -5458,7 +5434,7 @@ merge(Compressor.prototype, {
               case "typeof":
                 // typeof always returns a non-empty string, thus it's
                 // always true in booleans
-                compressor.warn("Boolean expression always true [{file}:{line},{col}]", self.start);
+                AST_Node.warn("Boolean expression always true [{file}:{line},{col}]", self.start);
                 return (e instanceof AST_SymbolRef ? make_node(AST_True, self) : make_sequence(self, [
                     e,
                     make_node(AST_True, self)
@@ -5567,7 +5543,7 @@ merge(Compressor.prototype, {
           case "===":
           case "!==":
             if (is_undefined(self.left, compressor) && self.right.is_defined(compressor)) {
-                compressor.warn("Expression always defined [{file}:{line},{col}]", self.start);
+                AST_Node.warn("Expression always defined [{file}:{line},{col}]", self.start);
                 return make_sequence(self, [
                     self.right,
                     make_node(self.operator == "===" ? AST_False : AST_True, self)
@@ -5646,14 +5622,14 @@ merge(Compressor.prototype, {
             var ll = self.left.evaluate(compressor);
             var rr = self.right.evaluate(compressor);
             if (ll && typeof ll == "string") {
-                compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start);
+                AST_Node.warn("+ in boolean context always true [{file}:{line},{col}]", self.start);
                 return make_sequence(self, [
                     self.right,
                     make_node(AST_True, self)
                 ]).optimize(compressor);
             }
             if (rr && typeof rr == "string") {
-                compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start);
+                AST_Node.warn("+ in boolean context always true [{file}:{line},{col}]", self.start);
                 return make_sequence(self, [
                     self.left,
                     make_node(AST_True, self)
@@ -5713,16 +5689,16 @@ merge(Compressor.prototype, {
               case "&&":
                 var ll = fuzzy_eval(self.left);
                 if (!ll) {
-                    compressor.warn("Condition left of && always false [{file}:{line},{col}]", self.start);
+                    AST_Node.warn("Condition left of && always false [{file}:{line},{col}]", self.start);
                     return maintain_this_binding(compressor, compressor.parent(), compressor.self(), self.left).optimize(compressor);
                 } else if (!(ll instanceof AST_Node)) {
-                    compressor.warn("Condition left of && always true [{file}:{line},{col}]", self.start);
+                    AST_Node.warn("Condition left of && always true [{file}:{line},{col}]", self.start);
                     return make_sequence(self, [ self.left, self.right ]).optimize(compressor);
                 }
                 var rr = self.right.evaluate(compressor);
                 if (!rr) {
                     if (compressor.option("booleans") && compressor.in_boolean_context()) {
-                        compressor.warn("Boolean && always false [{file}:{line},{col}]", self.start);
+                        AST_Node.warn("Boolean && always false [{file}:{line},{col}]", self.start);
                         return make_sequence(self, [
                             self.left,
                             make_node(AST_False, self)
@@ -5732,7 +5708,7 @@ merge(Compressor.prototype, {
                     var parent = compressor.parent();
                     if (parent.operator == "&&" && parent.left === compressor.self()
                         || compressor.option("booleans") && compressor.in_boolean_context()) {
-                        compressor.warn("Dropping side-effect-free && [{file}:{line},{col}]", self.start);
+                        AST_Node.warn("Dropping side-effect-free && [{file}:{line},{col}]", self.start);
                         return self.left.optimize(compressor);
                     }
                 }
@@ -5749,10 +5725,10 @@ merge(Compressor.prototype, {
               case "||":
                 var ll = fuzzy_eval(self.left);
                 if (!ll) {
-                    compressor.warn("Condition left of || always false [{file}:{line},{col}]", self.start);
+                    AST_Node.warn("Condition left of || always false [{file}:{line},{col}]", self.start);
                     return make_sequence(self, [ self.left, self.right ]).optimize(compressor);
                 } else if (!(ll instanceof AST_Node)) {
-                    compressor.warn("Condition left of || always true [{file}:{line},{col}]", self.start);
+                    AST_Node.warn("Condition left of || always true [{file}:{line},{col}]", self.start);
                     return maintain_this_binding(compressor, compressor.parent(), compressor.self(), self.left).optimize(compressor);
                 }
                 var rr = self.right.evaluate(compressor);
@@ -5760,12 +5736,12 @@ merge(Compressor.prototype, {
                     var parent = compressor.parent();
                     if (parent.operator == "||" && parent.left === compressor.self()
                         || compressor.option("booleans") && compressor.in_boolean_context()) {
-                        compressor.warn("Dropping side-effect-free || [{file}:{line},{col}]", self.start);
+                        AST_Node.warn("Dropping side-effect-free || [{file}:{line},{col}]", self.start);
                         return self.left.optimize(compressor);
                     }
                 } else if (!(rr instanceof AST_Node)) {
                     if (compressor.option("booleans") && compressor.in_boolean_context()) {
-                        compressor.warn("Boolean || always true [{file}:{line},{col}]", self.start);
+                        AST_Node.warn("Boolean || always true [{file}:{line},{col}]", self.start);
                         return make_sequence(self, [
                             self.left,
                             make_node(AST_True, self)
@@ -6355,10 +6331,10 @@ merge(Compressor.prototype, {
         }
         var cond = self.condition.is_truthy() || self.condition.tail_node().evaluate(compressor);
         if (!cond) {
-            compressor.warn("Condition always false [{file}:{line},{col}]", self.start);
+            AST_Node.warn("Condition always false [{file}:{line},{col}]", self.start);
             return make_sequence(self, [ self.condition, self.alternative ]).optimize(compressor);
         } else if (!(cond instanceof AST_Node)) {
-            compressor.warn("Condition always true [{file}:{line},{col}]", self.start);
+            AST_Node.warn("Condition always true [{file}:{line},{col}]", self.start);
             return make_sequence(self, [ self.condition, self.consequent ]).optimize(compressor);
         }
         var negated = cond.negate(compressor, first_in_statement(compressor));
@@ -6597,7 +6573,7 @@ merge(Compressor.prototype, {
         });
         var p = compressor.parent();
         if (p instanceof AST_Binary && (p.operator == "==" || p.operator == "!=")) {
-            compressor.warn("Non-strict equality against boolean: {operator} {value} [{file}:{line},{col}]", {
+            AST_Node.warn("Non-strict equality against boolean: {operator} {value} [{file}:{line},{col}]", {
                 operator : p.operator,
                 value    : self.value,
                 file     : p.start.file,
@@ -6780,7 +6756,7 @@ merge(Compressor.prototype, {
 
     OPT(AST_Dot, function(self, compressor) {
         if (self.property == "arguments" || self.property == "caller") {
-            compressor.warn("Function.prototype.{prop} not supported [{file}:{line},{col}]", {
+            AST_Node.warn("Function.prototype.{prop} not supported [{file}:{line},{col}]", {
                 prop: self.property,
                 file: self.start.file,
                 line: self.start.line,
index d84f682..5f865c6 100644 (file)
@@ -51,7 +51,6 @@ function to_json(cache) {
 }
 
 function minify(files, options) {
-    var warn_function = AST_Node.warn_function;
     try {
         options = defaults(options, {
             compress: {},
@@ -78,7 +77,6 @@ function minify(files, options) {
         set_shorthand("ie8", options, [ "compress", "mangle", "output" ]);
         set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
         set_shorthand("toplevel", options, [ "compress", "mangle" ]);
-        set_shorthand("warnings", options, [ "compress" ]);
         var quoted_props;
         if (options.mangle) {
             options.mangle = defaults(options.mangle, {
@@ -116,11 +114,9 @@ function minify(files, options) {
             }, true);
         }
         var warnings = [];
-        if (options.warnings && !AST_Node.warn_function) {
-            AST_Node.warn_function = function(warning) {
-                warnings.push(warning);
-            };
-        }
+        if (options.warnings) AST_Node.log_function(function(warning) {
+            warnings.push(warning);
+        }, options.warnings == "verbose");
         if (timings) timings.parse = Date.now();
         var source_maps, toplevel;
         if (files instanceof AST_Toplevel) {
@@ -240,7 +236,5 @@ function minify(files, options) {
         return result;
     } catch (ex) {
         return { error: ex };
-    } finally {
-        AST_Node.warn_function = warn_function;
     }
 }
index 1a373a1..b7639df 100644 (file)
@@ -504,7 +504,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
             var regexp = new RegExp(source, mods);
             regexp.raw_source = source;
             return token("regexp", regexp);
-        } catch(e) {
+        } catch (e) {
             parse_error(e.message);
         }
     });
@@ -556,7 +556,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
         return function(x) {
             try {
                 return cont(x);
-            } catch(ex) {
+            } catch (ex) {
                 if (ex === EX_EOF) parse_error(eof_error);
                 else throw ex;
             }
index 40b65e2..6dcb631 100644 (file)
@@ -70,7 +70,7 @@ function configure_error_stack(fn) {
             err.name = this.name;
             try {
                 throw err;
-            } catch(e) {
+            } catch (e) {
                 return e.stack;
             }
         }
index 470f3b7..6e0afc6 100644 (file)
@@ -4194,7 +4194,7 @@ may_throw_2: {
                 var a = x();
                 ++b;
                 return b(a);
-            } catch(e) {}
+            } catch (e) {}
             console.log(b);
         }
         f(0);
@@ -4204,7 +4204,7 @@ may_throw_2: {
             try {
                 var a = x();
                 return (++b)(a);
-            } catch(e) {}
+            } catch (e) {}
             console.log(b);
         }
         f(0);
index 74fe369..9286532 100644 (file)
@@ -144,7 +144,7 @@ unused_var_in_catch: {
         function foo() {
             try {
                 foo();
-            } catch(ex) {
+            } catch (ex) {
                 var x = 10;
             }
         }
@@ -153,7 +153,7 @@ unused_var_in_catch: {
         function foo() {
             try {
                 foo();
-            } catch(ex) {}
+            } catch (ex) {}
         }
     }
 }
@@ -166,7 +166,7 @@ used_var_in_catch: {
         function foo() {
             try {
                 foo();
-            } catch(ex) {
+            } catch (ex) {
                 var x = 10;
             }
             return x;
@@ -176,7 +176,7 @@ used_var_in_catch: {
         function foo() {
             try {
                 foo();
-            } catch(ex) {
+            } catch (ex) {
                 var x = 10;
             }
             return x;
@@ -1156,7 +1156,7 @@ var_catch_toplevel: {
             try {
                 a++;
                 x();
-            } catch(a) {
+            } catch (a) {
                 if (a) var a;
                 var a = 10;
             }
@@ -1167,7 +1167,7 @@ var_catch_toplevel: {
         !function() {
             try {
                 x();
-            } catch(a) {
+            } catch (a) {
                 var a;
             }
         }();
index f98033e..e81e1a0 100644 (file)
@@ -59,9 +59,9 @@ do_screw_try_catch: {
     input: {
         good = function(e){
             return function(error){
-                try{
+                try {
                     e()
-                } catch(e) {
+                } catch (e) {
                     error(e)
                 }
             }
@@ -70,9 +70,9 @@ do_screw_try_catch: {
     expect: {
         good = function(n){
             return function(t){
-                try{
+                try {
                     n()
-                } catch(n) {
+                } catch (n) {
                     t(n)
                 }
             }
@@ -93,9 +93,9 @@ dont_screw_try_catch: {
     input: {
         bad = function(e){
             return function(error){
-                try{
+                try {
                     e()
-                } catch(e) {
+                } catch (e) {
                     error(e)
                 }
             }
@@ -104,9 +104,9 @@ dont_screw_try_catch: {
     expect: {
         bad = function(t){
             return function(n){
-                try{
+                try {
                     t()
-                } catch(t) {
+                } catch (t) {
                     n(t)
                 }
             }
@@ -137,7 +137,7 @@ do_screw_try_catch_undefined: {
     }
     expect: {
         function a(o){
-            try{
+            try {
                 throw "Stuff"
             } catch (o) {
                 console.log("caught: "+o)
@@ -172,7 +172,7 @@ dont_screw_try_catch_undefined: {
     }
     expect: {
         function a(n){
-            try{
+            try {
                 throw "Stuff"
             } catch (undefined) {
                 console.log("caught: " + undefined)
index f2a89e3..e8b6918 100644 (file)
@@ -59,7 +59,6 @@ non_hoisted_function_after_return_2a: {
         passes: 2,
         side_effects: true,
         unused: true,
-        warnings: "verbose",
     }
     input: {
         function foo(x) {
@@ -91,13 +90,13 @@ non_hoisted_function_after_return_2a: {
         "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:7,16]",
         "WARN: Dropping unused variable a [test/compress/issue-1034.js:4,20]",
         "WARN: Dropping unused function nope [test/compress/issue-1034.js:11,21]",
-        "WARN: pass 0: last_count: Infinity, count: 37",
+        "INFO: pass 0: last_count: Infinity, count: 37",
         "WARN: Dropping unreachable code [test/compress/issue-1034.js:9,12]",
         "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:9,12]",
         "WARN: Dropping unreachable code [test/compress/issue-1034.js:12,12]",
-        "WARN: Dropping unused variable b [test/compress/issue-1034.js:7,20]",
-        "WARN: Dropping unused variable c [test/compress/issue-1034.js:9,16]",
-        "WARN: pass 1: last_count: 37, count: 18",
+        "INFO: Dropping unused variable b [test/compress/issue-1034.js:7,20]",
+        "INFO: Dropping unused variable c [test/compress/issue-1034.js:9,16]",
+        "INFO: pass 1: last_count: 37, count: 18",
     ]
 }
 
@@ -213,7 +212,6 @@ non_hoisted_function_after_return_2a_strict: {
         passes: 2,
         side_effects: true,
         unused: true,
-        warnings: "verbose",
     }
     input: {
         "use strict";
@@ -250,13 +248,13 @@ non_hoisted_function_after_return_2a_strict: {
         "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:8,16]",
         "WARN: Dropping unused variable a [test/compress/issue-1034.js:5,20]",
         "WARN: Dropping unused function nope [test/compress/issue-1034.js:12,21]",
-        "WARN: pass 0: last_count: Infinity, count: 48",
+        "INFO: pass 0: last_count: Infinity, count: 48",
         "WARN: Dropping unreachable code [test/compress/issue-1034.js:10,12]",
         "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:10,12]",
         "WARN: Dropping unreachable code [test/compress/issue-1034.js:13,12]",
-        "WARN: Dropping unused variable b [test/compress/issue-1034.js:8,20]",
-        "WARN: Dropping unused variable c [test/compress/issue-1034.js:10,16]",
-        "WARN: pass 1: last_count: 48, count: 29",
+        "INFO: Dropping unused variable b [test/compress/issue-1034.js:8,20]",
+        "INFO: Dropping unused variable c [test/compress/issue-1034.js:10,16]",
+        "INFO: pass 1: last_count: 48, count: 29",
     ]
 }
 
index 811c493..6d6e1e8 100644 (file)
@@ -47,7 +47,7 @@ describe("bin/uglifyjs", function() {
         });
     });
     it("Should give sensible error against invalid input source map", function(done) {
-        var command = uglifyjscmd + " test/mocha.js --source-map content=blah,url=inline";
+        var command = uglifyjscmd + " test/mocha.js --source-map content=blah,url=inline --verbose";
         exec(command, function(err, stdout, stderr) {
             assert.ok(err);
             assert.deepEqual(stderr.split(/\n/).slice(0, 2), [
@@ -83,6 +83,7 @@ describe("bin/uglifyjs", function() {
             "test/input/issue-2082/sample.js",
             "--source-map", "content=test/input/issue-2082/sample.js.map",
             "--source-map", "url=inline",
+            "--verbose",
         ].join(" ");
         exec(command, function(err, stdout, stderr) {
             if (err) throw err;
@@ -202,7 +203,7 @@ describe("bin/uglifyjs", function() {
         });
     });
     it("Should warn for missing inline source map", function(done) {
-        var command = uglifyjscmd + " test/input/issue-1323/sample.js --source-map content=inline,url=inline";
+        var command = uglifyjscmd + " test/input/issue-1323/sample.js --source-map content=inline,url=inline --warn";
         exec(command, function(err, stdout, stderr) {
             if (err) throw err;
             assert.strictEqual(stdout, [
@@ -221,6 +222,7 @@ describe("bin/uglifyjs", function() {
             "test/input/issue-520/input.js",
             "test/input/issue-1323/sample.js",
             "--source-map", "content=inline,url=inline",
+            "--warn",
         ].join(" ");
         exec(command, function(err, stdout, stderr) {
             if (err) throw err;
@@ -466,7 +468,7 @@ describe("bin/uglifyjs", function() {
             done();
         });
     });
-    it("Should throw syntax error (catch(eval))", function(done) {
+    it("Should throw syntax error (catch (eval))", function(done) {
         var command = uglifyjscmd + ' test/input/invalid/try.js';
         exec(command, function(err, stdout, stderr) {
             assert.ok(err);
@@ -647,7 +649,7 @@ describe("bin/uglifyjs", function() {
         exec(command, function(err, stdout, stderr) {
             assert.ok(err);
             assert.strictEqual(stdout, "");
-            assert.strictEqual(stderr, "Error parsing arguments for 'define': a-b\n");
+            assert.strictEqual(stderr, "ERROR: cannot parse arguments for 'define': a-b\n");
             done();
         });
     });
index ccaa68e..f625b22 100644 (file)
@@ -118,51 +118,33 @@ describe("sourcemaps", function() {
             assert.strictEqual(result.code + "\n", readFileSync("test/input/issue-520/output.js", "utf8"));
         });
         it("Should warn for missing inline source map", function() {
-            var warn_function = UglifyJS.AST_Node.warn_function;
-            var warnings = [];
-            UglifyJS.AST_Node.warn_function = function(txt) {
-                warnings.push(txt);
-            };
-            try {
-                var result = UglifyJS.minify(read("./test/input/issue-1323/sample.js"), {
-                    mangle: false,
-                    sourceMap: {
-                        content: "inline"
-                    }
-                });
-                assert.strictEqual(result.code, "var bar=function(bar){return bar};");
-                assert.strictEqual(warnings.length, 1);
-                assert.strictEqual(warnings[0], "inline source map not found: 0");
-            } finally {
-                UglifyJS.AST_Node.warn_function = warn_function;
-            }
+            var result = UglifyJS.minify(read("./test/input/issue-1323/sample.js"), {
+                mangle: false,
+                sourceMap: {
+                    content: "inline"
+                },
+                warnings: true,
+            });
+            assert.strictEqual(result.code, "var bar=function(bar){return bar};");
+            assert.deepEqual(result.warnings, [ "WARN: inline source map not found: 0" ]);
         });
         it("Should handle multiple input and inline source map", function() {
-            var warn_function = UglifyJS.AST_Node.warn_function;
-            var warnings = [];
-            UglifyJS.AST_Node.warn_function = function(txt) {
-                warnings.push(txt);
-            };
-            try {
-                var result = UglifyJS.minify([
-                    read("./test/input/issue-520/input.js"),
-                    read("./test/input/issue-1323/sample.js"),
-                ], {
-                    sourceMap: {
-                        content: "inline",
-                        url: "inline",
-                    }
-                });
-                if (result.error) throw result.error;
-                assert.strictEqual(result.code, [
-                    "var Foo=function(){console.log(3)};new Foo;var bar=function(o){return o};",
-                    "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwiMSJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFdBQWdCQyxRQUFRQyxJQUFJLElBQVMsSUFBSUYsSUNBbkQsSUFBSUcsSUFDQSxTQUFjQSxHQUNWLE9BQU9BIn0=",
-                ].join("\n"));
-                assert.strictEqual(warnings.length, 1);
-                assert.strictEqual(warnings[0], "inline source map not found: 1");
-            } finally {
-                UglifyJS.AST_Node.warn_function = warn_function;
-            }
+            var result = UglifyJS.minify([
+                read("./test/input/issue-520/input.js"),
+                read("./test/input/issue-1323/sample.js"),
+            ], {
+                sourceMap: {
+                    content: "inline",
+                    url: "inline",
+                },
+                warnings: true,
+            });
+            if (result.error) throw result.error;
+            assert.strictEqual(result.code, [
+                "var Foo=function(){console.log(3)};new Foo;var bar=function(o){return o};",
+                "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwiMSJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFdBQWdCQyxRQUFRQyxJQUFJLElBQVMsSUFBSUYsSUNBbkQsSUFBSUcsSUFDQSxTQUFjQSxHQUNWLE9BQU9BIn0=",
+            ].join("\n"));
+            assert.deepEqual(result.warnings, [ "WARN: inline source map not found: 1" ]);
         });
         it("Should drop source contents for includeSources=false", function() {
             var result = UglifyJS.minify(read("./test/input/issue-520/input.js"), {
index f78deb3..aa415ec 100755 (executable)
@@ -231,16 +231,15 @@ function run_compress_tests() {
                 });
                 return false;
             }
-            var options = U.defaults(test.options, {
-                warnings: false
-            });
             var warnings_emitted = [];
-            var original_warn_function = U.AST_Node.warn_function;
             if (test.expect_warnings) {
-                U.AST_Node.warn_function = function(text) {
-                    warnings_emitted.push("WARN: " + text);
-                };
-                if (!options.warnings) options.warnings = true;
+                var expected_warnings = make_code(test.expect_warnings, {
+                    beautify: false,
+                    quote_style: 2, // force double quote to match JSON
+                });
+                U.AST_Node.log_function(function(text) {
+                    warnings_emitted.push(text);
+                }, /"INFO: /.test(expected_warnings));
             }
             if (test.mangle && test.mangle.properties && test.mangle.properties.keep_quoted) {
                 var quoted_props = test.mangle.properties.reserved;
@@ -252,7 +251,7 @@ function run_compress_tests() {
                 input.figure_out_scope(test.mangle);
                 input.expand_names(test.mangle);
             }
-            var cmp = new U.Compressor(options, true);
+            var cmp = new U.Compressor(test.options, true);
             var output = cmp.compress(input);
             output.figure_out_scope(test.mangle);
             if (test.mangle) {
@@ -283,11 +282,6 @@ function run_compress_tests() {
                 return false;
             }
             if (test.expect_warnings) {
-                U.AST_Node.warn_function = original_warn_function;
-                var expected_warnings = make_code(test.expect_warnings, {
-                    beautify: false,
-                    quote_style: 2, // force double quote to match JSON
-                });
                 warnings_emitted = warnings_emitted.map(function(input) {
                     return input.split(process.cwd() + path.sep).join("").split(path.sep).join("/");
                 });