improve performance (#3020)
authorAlex Lam S.L <alexlamsl@gmail.com>
Thu, 22 Mar 2018 19:43:52 +0000 (03:43 +0800)
committerGitHub <noreply@github.com>
Thu, 22 Mar 2018 19:43:52 +0000 (03:43 +0800)
- replace `find_if()` with `all()` wherever possible
- move ESTree-specific logic out of `figure_out_scope()`

lib/compress.js
lib/mozilla-ast.js
lib/parse.js
lib/scope.js
test/mocha/minify.js

index aeff904..972341b 100644 (file)
@@ -3525,8 +3525,9 @@ merge(Compressor.prototype, {
                 var defs = [];
                 vars.each(function(def, name){
                     if (self instanceof AST_Lambda
-                        && find_if(function(x){ return x.name == def.name.name },
-                                   self.argnames)) {
+                        && !all(self.argnames, function(argname) {
+                            return argname.name != name;
+                        })) {
                         vars.del(name);
                     } else {
                         def = def.clone();
index 8d7ee4b..b80afbb 100644 (file)
         FROM_MOZ_STACK = [];
         var ast = from_moz(node);
         FROM_MOZ_STACK = save_stack;
+        ast.walk(new TreeWalker(function(node) {
+            if (node instanceof AST_LabelRef) {
+                for (var level = 0, parent; parent = this.parent(level); level++) {
+                    if (parent instanceof AST_Scope) break;
+                    if (parent instanceof AST_LabeledStatement && parent.label.name == node.name) {
+                        node.thedef = parent.label;
+                        break;
+                    }
+                }
+                if (!node.thedef) {
+                    var s = node.start;
+                    js_error("Undefined label " + node.name, s.file, s.line, s.col, s.pos);
+                }
+            }
+        }));
         return ast;
     };
 
index af63114..f88d13e 100644 (file)
@@ -969,7 +969,9 @@ function parse($TEXT, options) {
 
     function labeled_statement() {
         var label = as_symbol(AST_Label);
-        if (find_if(function(l){ return l.name == label.name }, S.labels)) {
+        if (!all(S.labels, function(l) {
+            return l.name != label.name;
+        })) {
             // ECMA-262, 12.12: An ECMAScript program is considered
             // syntactically incorrect if it contains a
             // LabelledStatement that is enclosed by a
index baa3e8b..7cbd82c 100644 (file)
@@ -100,7 +100,6 @@ 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 labels = new Dictionary();
     var defun = null;
     var tw = new TreeWalker(function(node, descend){
         if (node instanceof AST_Catch) {
@@ -115,25 +114,12 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
             node.init_scope_vars(scope);
             var save_scope = scope;
             var save_defun = defun;
-            var save_labels = labels;
             defun = scope = node;
-            labels = new Dictionary();
             descend();
             scope = save_scope;
             defun = save_defun;
-            labels = save_labels;
             return true;        // don't descend again in TreeWalker
         }
-        if (node instanceof AST_LabeledStatement) {
-            var l = node.label;
-            if (labels.has(l.name)) {
-                throw new Error(string_template("Label {name} defined twice", l));
-            }
-            labels.set(l.name, l);
-            descend();
-            labels.del(l.name);
-            return true;        // no descend again
-        }
         if (node instanceof AST_With) {
             for (var s = scope; s; s = s.parent_scope)
                 s.uses_with = true;
@@ -171,15 +157,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
         else if (node instanceof AST_SymbolCatch) {
             scope.def_variable(node).defun = defun;
         }
-        else if (node instanceof AST_LabelRef) {
-            var sym = labels.get(node.name);
-            if (!sym) throw new Error(string_template("Undefined label {name} [{line},{col}]", {
-                name: node.name,
-                line: node.start.line,
-                col: node.start.col
-            }));
-            node.thedef = sym;
-        }
     });
     self.walk(tw);
 
index 02180a5..995897d 100644 (file)
@@ -312,6 +312,15 @@ describe("minify", function() {
             assert.strictEqual(err.line, 1);
             assert.strictEqual(err.col, 12);
         });
+        it("should reject duplicated label name", function() {
+            var result = Uglify.minify("L:{L:{}}");
+            var err = result.error;
+            assert.ok(err instanceof Error);
+            assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Label L defined twice");
+            assert.strictEqual(err.filename, "0");
+            assert.strictEqual(err.line, 1);
+            assert.strictEqual(err.col, 4);
+        });
     });
 
     describe("global_defs", function() {