From 49bfc6b555ca3be3084c0819391eabf2839e6f1b Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Fri, 23 Mar 2018 03:43:52 +0800 Subject: [PATCH] improve performance (#3020) - replace `find_if()` with `all()` wherever possible - move ESTree-specific logic out of `figure_out_scope()` --- lib/compress.js | 5 +++-- lib/mozilla-ast.js | 15 +++++++++++++++ lib/parse.js | 4 +++- lib/scope.js | 23 ----------------------- test/mocha/minify.js | 9 +++++++++ 5 files changed, 30 insertions(+), 26 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index aeff904e..972341bb 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -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(); diff --git a/lib/mozilla-ast.js b/lib/mozilla-ast.js index 8d7ee4b8..b80afbbb 100644 --- a/lib/mozilla-ast.js +++ b/lib/mozilla-ast.js @@ -564,6 +564,21 @@ 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; }; diff --git a/lib/parse.js b/lib/parse.js index af631149..f88d13ec 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -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 diff --git a/lib/scope.js b/lib/scope.js index baa3e8bd..7cbd82c1 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -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); diff --git a/test/mocha/minify.js b/test/mocha/minify.js index 02180a59..995897da 100644 --- a/test/mocha/minify.js +++ b/test/mocha/minify.js @@ -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() { -- 2.34.1