diff options
Diffstat (limited to 'node_modules/uglify-js/lib')
-rw-r--r-- | node_modules/uglify-js/lib/ast.js | 6 | ||||
-rw-r--r-- | node_modules/uglify-js/lib/compress.js | 53 | ||||
-rw-r--r-- | node_modules/uglify-js/lib/output.js | 20 | ||||
-rw-r--r-- | node_modules/uglify-js/lib/parse.js | 2 | ||||
-rw-r--r-- | node_modules/uglify-js/lib/scope.js | 1 |
5 files changed, 53 insertions, 29 deletions
diff --git a/node_modules/uglify-js/lib/ast.js b/node_modules/uglify-js/lib/ast.js index 0918574d1..9b243f16b 100644 --- a/node_modules/uglify-js/lib/ast.js +++ b/node_modules/uglify-js/lib/ast.js @@ -134,11 +134,10 @@ var AST_Debugger = DEFNODE("Debugger", null, { $documentation: "Represents a debugger statement", }, AST_Statement); -var AST_Directive = DEFNODE("Directive", "value scope quote", { +var AST_Directive = DEFNODE("Directive", "value quote", { $documentation: "Represents a directive, like \"use strict\";", $propdoc: { value: "[string] The value of this directive as a plain string (it's not an AST_String!)", - scope: "[AST_Scope/S] The scope that this directive affects", quote: "[string] the original quote character" }, }, AST_Statement); @@ -299,10 +298,9 @@ var AST_With = DEFNODE("With", "expression", { /* -----[ scope and functions ]----- */ -var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", { +var AST_Scope = DEFNODE("Scope", "variables functions uses_with uses_eval parent_scope enclosed cname", { $documentation: "Base class for all statements introducing a lexical scope", $propdoc: { - directives: "[string*/S] an array of directives declared in this scope", 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", diff --git a/node_modules/uglify-js/lib/compress.js b/node_modules/uglify-js/lib/compress.js index 7a16ba86b..d4a72d749 100644 --- a/node_modules/uglify-js/lib/compress.js +++ b/node_modules/uglify-js/lib/compress.js @@ -285,6 +285,10 @@ merge(Compressor.prototype, { AST_Node.DEFMETHOD("reset_opt_flags", function(compressor, rescan) { var reduce_vars = rescan && compressor.option("reduce_vars"); + // Stack of look-up tables to keep track of whether a `SymbolDef` has been + // properly assigned before use: + // - `push()` & `pop()` when visiting conditional branches + // - backup & restore via `save_ids` when visiting out-of-order sections var safe_ids = Object.create(null); var suppressor = new TreeWalker(function(node) { if (!(node instanceof AST_Symbol)) return; @@ -391,10 +395,9 @@ merge(Compressor.prototype, { return true; } if (node instanceof AST_Accessor) { - var save_ids = safe_ids; - safe_ids = Object.create(null); + push(); descend(); - safe_ids = save_ids; + pop(); return true; } if (node instanceof AST_Binary @@ -561,6 +564,7 @@ merge(Compressor.prototype, { }); function is_lhs_read_only(lhs) { + if (lhs instanceof AST_This) return true; if (lhs instanceof AST_SymbolRef) return lhs.definition().orig[0] instanceof AST_SymbolLambda; if (lhs instanceof AST_PropAccess) { lhs = lhs.expression; @@ -693,7 +697,7 @@ merge(Compressor.prototype, { return node instanceof AST_SymbolRef && node.definition().undeclared; } - var global_names = makePredicate("Array Boolean console Error Function Math Number RegExp Object String"); + var global_names = makePredicate("Array Boolean clearInterval clearTimeout console Date decodeURI decodeURIComponent encodeURI encodeURIComponent Error escape eval EvalError Function isFinite isNaN JSON Math Number parseFloat parseInt RangeError ReferenceError RegExp Object setInterval setTimeout String SyntaxError TypeError unescape URIError"); AST_SymbolRef.DEFMETHOD("is_declared", function(compressor) { return !this.definition().undeclared || compressor.option("unsafe") && global_names(this.name); @@ -745,7 +749,7 @@ merge(Compressor.prototype, { while (candidates.length > 0) { var candidate = candidates.pop(); var lhs = get_lhs(candidate); - if (!lhs || is_lhs_read_only(lhs)) continue; + if (!lhs || is_lhs_read_only(lhs) || lhs.has_side_effects(compressor)) continue; // Locate symbols which may execute code outside of scanning range var lvalues = get_lvalues(candidate); if (lhs instanceof AST_SymbolRef) lvalues[lhs.name] = false; @@ -841,13 +845,15 @@ merge(Compressor.prototype, { && !fn.uses_eval && (iife = compressor.parent()) instanceof AST_Call && iife.expression === fn) { + var fn_strict = compressor.has_directive("use strict"); + if (fn_strict && fn.body.indexOf(fn_strict) < 0) fn_strict = false; var names = Object.create(null); for (var i = fn.argnames.length; --i >= 0;) { var sym = fn.argnames[i]; if (sym.name in names) continue; names[sym.name] = true; var arg = iife.args[i]; - if (!arg) arg = make_node(AST_Undefined, sym); + if (!arg) arg = make_node(AST_Undefined, sym).transform(compressor); else { var tw = new TreeWalker(function(node) { if (!arg) return true; @@ -858,7 +864,7 @@ merge(Compressor.prototype, { } arg = null; } - if (node instanceof AST_This && !tw.find_parent(AST_Scope)) { + if (node instanceof AST_This && (fn_strict || !tw.find_parent(AST_Scope))) { arg = null; return true; } @@ -1980,16 +1986,27 @@ merge(Compressor.prototype, { if (!compressor.option("side_effects")) return false; if (this.pure !== undefined) return this.pure; var pure = false; - var comments, last_comment; + var comments, pure_comment; if (this.start && (comments = this.start.comments_before) && comments.length - && /[@#]__PURE__/.test((last_comment = comments[comments.length - 1]).value)) { - pure = last_comment; + && (pure_comment = find_if(function (comment) { + return /[@#]__PURE__/.test(comment.value); + }, comments))) { + pure = pure_comment; } return this.pure = pure; }); + var global_pure_fns = makePredicate("Boolean decodeURI decodeURIComponent Date encodeURI encodeURIComponent Error escape EvalError isFinite isNaN Number Object parseFloat parseInt RangeError ReferenceError String SyntaxError TypeError unescape URIError"); + AST_Call.DEFMETHOD("is_expr_pure", function(compressor) { + if (compressor.option("unsafe")) { + var expr = this.expression; + if (is_undeclared_ref(expr) && global_pure_fns(expr.name)) return true; + } + return this.has_pure_annotation(compressor) || !compressor.pure_funcs(this); + }); + // determine if expression has side effects (function(def){ def(AST_Node, return_true); @@ -1999,7 +2016,7 @@ merge(Compressor.prototype, { def(AST_This, return_false); def(AST_Call, function(compressor){ - if (!this.has_pure_annotation(compressor) && compressor.pure_funcs(this)) return true; + if (!this.is_expr_pure(compressor)) return true; for (var i = this.args.length; --i >= 0;) { if (this.args[i].has_side_effects(compressor)) return true; @@ -2423,17 +2440,18 @@ merge(Compressor.prototype, { // We fix it at this stage by moving the `var` outside the `for`. if (node instanceof AST_For) { descend(node, this); + var block; if (node.init instanceof AST_BlockStatement) { - var block = node.init; + block = node.init; node.init = block.body.pop(); block.body.push(node); - return in_list ? MAP.splice(block.body) : block; - } else if (node.init instanceof AST_SimpleStatement) { + } + if (node.init instanceof AST_SimpleStatement) { node.init = node.init.body; } else if (is_empty(node.init)) { node.init = null; } - return node; + return !block ? node : in_list ? MAP.splice(block.body) : block; } if (node instanceof AST_LabeledStatement && node.body instanceof AST_For) { descend(node, this); @@ -2617,7 +2635,7 @@ merge(Compressor.prototype, { def(AST_Constant, return_null); def(AST_This, return_null); def(AST_Call, function(compressor, first_in_statement){ - if (!this.has_pure_annotation(compressor) && compressor.pure_funcs(this)) { + if (!this.is_expr_pure(compressor)) { if (this.expression instanceof AST_Function && (!this.expression.name || !this.expression.name.definition().references.length)) { var node = this.clone(); @@ -3112,6 +3130,7 @@ merge(Compressor.prototype, { })); if (reduce_vars) name.definition().fixed = false; } + remove(def.name.definition().orig, def.name); return a; }, []); if (assignments.length == 0) return null; @@ -3483,7 +3502,7 @@ merge(Compressor.prototype, { && (left.operator == "++" || left.operator == "--")) { left = left.expression; } else left = null; - if (!left || is_lhs_read_only(left)) { + if (!left || is_lhs_read_only(left) || left.has_side_effects(compressor)) { expressions[++i] = cdr; continue; } diff --git a/node_modules/uglify-js/lib/output.js b/node_modules/uglify-js/lib/output.js index 4c873f10d..1aa634501 100644 --- a/node_modules/uglify-js/lib/output.js +++ b/node_modules/uglify-js/lib/output.js @@ -146,7 +146,7 @@ function OutputStream(options) { case "\u2029": return "\\u2029"; case "\ufeff": return "\\ufeff"; case "\0": - return /[0-7]/.test(str.charAt(i+1)) ? "\\x00" : "\\0"; + return /[0-9]/.test(str.charAt(i+1)) ? "\\x00" : "\\0"; } return s; }); @@ -482,13 +482,17 @@ function OutputStream(options) { nodetype.DEFMETHOD("_codegen", generator); }; - var use_asm = false; var in_directive = false; + var active_scope = null; + var use_asm = null; AST_Node.DEFMETHOD("print", function(stream, force_parens){ - var self = this, generator = self._codegen, prev_use_asm = use_asm; - if (self instanceof AST_Directive && self.value == "use asm" && stream.parent() instanceof AST_Scope) { - use_asm = true; + var self = this, generator = self._codegen; + if (self instanceof AST_Scope) { + active_scope = self; + } + else if (!use_asm && self instanceof AST_Directive && self.value == "use asm") { + use_asm = active_scope; } function doit() { self.add_comments(stream); @@ -502,8 +506,8 @@ function OutputStream(options) { doit(); } stream.pop_node(); - if (self instanceof AST_Scope) { - use_asm = prev_use_asm; + if (self === use_asm) { + use_asm = null; } }); AST_Node.DEFMETHOD("_print", AST_Node.prototype.print); @@ -1109,7 +1113,7 @@ function OutputStream(options) { self.expression.print(output); if (self instanceof AST_New && !need_constructor_parens(self, output)) return; - if (self.expression instanceof AST_Lambda) { + if (self.expression instanceof AST_Call || self.expression instanceof AST_Lambda) { output.add_mapping(self.start); } output.with_parens(function(){ diff --git a/node_modules/uglify-js/lib/parse.js b/node_modules/uglify-js/lib/parse.js index e2dd04b6c..099fc49a8 100644 --- a/node_modules/uglify-js/lib/parse.js +++ b/node_modules/uglify-js/lib/parse.js @@ -1054,6 +1054,8 @@ function parse($TEXT, options) { var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null; if (in_statement && !name) unexpected(); + if (name && ctor !== AST_Accessor && !(name instanceof AST_SymbolDeclaration)) + unexpected(prev()); expect("("); var argnames = []; for (var first = true; !is("punc", ")");) { diff --git a/node_modules/uglify-js/lib/scope.js b/node_modules/uglify-js/lib/scope.js index df7b2076c..8e766a567 100644 --- a/node_modules/uglify-js/lib/scope.js +++ b/node_modules/uglify-js/lib/scope.js @@ -235,6 +235,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){ ref.reference(options); }); node.thedef = def; + node.reference(options); return true; } })); |