uglify-js
Advanced tools
Comparing version
@@ -88,3 +88,3 @@ /*********************************************************************** | ||
var AST_Token = DEFNODE("Token", "type value line col pos endline endcol endpos nlb comments_before file", { | ||
var AST_Token = DEFNODE("Token", "type value line col pos endline endcol endpos nlb comments_before file raw", { | ||
}, null); | ||
@@ -931,6 +931,7 @@ | ||
this.stack = []; | ||
this.directives = Object.create(null); | ||
}; | ||
TreeWalker.prototype = { | ||
_visit: function(node, descend) { | ||
this.stack.push(node); | ||
this.push(node); | ||
var ret = this.visit(node, descend ? function(){ | ||
@@ -942,3 +943,3 @@ descend.call(node); | ||
} | ||
this.stack.pop(); | ||
this.pop(node); | ||
return ret; | ||
@@ -950,6 +951,14 @@ }, | ||
push: function (node) { | ||
if (node instanceof AST_Lambda) { | ||
this.directives = Object.create(this.directives); | ||
} else if (node instanceof AST_Directive) { | ||
this.directives[node.value] = this.directives[node.value] ? "up" : true; | ||
} | ||
this.stack.push(node); | ||
}, | ||
pop: function() { | ||
return this.stack.pop(); | ||
pop: function(node) { | ||
this.stack.pop(); | ||
if (node instanceof AST_Lambda) { | ||
this.directives = Object.getPrototypeOf(this.directives); | ||
} | ||
}, | ||
@@ -967,3 +976,12 @@ self: function() { | ||
has_directive: function(type) { | ||
return this.find_parent(AST_Scope).has_directive(type); | ||
var dir = this.directives[type]; | ||
if (dir) return dir; | ||
var node = this.stack[this.stack.length - 1]; | ||
if (node instanceof AST_Scope) { | ||
for (var i = 0; i < node.body.length; ++i) { | ||
var st = node.body[i]; | ||
if (!(st instanceof AST_Directive)) break; | ||
if (st.value == type) return true; | ||
} | ||
} | ||
}, | ||
@@ -970,0 +988,0 @@ in_boolean_context: function() { |
@@ -149,3 +149,10 @@ /*********************************************************************** | ||
default: | ||
args.value = val; | ||
var rx = M.regex; | ||
if (rx && rx.pattern) { | ||
// RegExpLiteral as per ESTree AST spec | ||
args.value = new RegExp(rx.pattern, rx.flags).toString(); | ||
} else { | ||
// support legacy RegExp | ||
args.value = M.regex && M.raw ? M.raw : val; | ||
} | ||
return new AST_RegExp(args); | ||
@@ -338,2 +345,15 @@ } | ||
def_to_moz(AST_RegExp, function To_Moz_RegExpLiteral(M) { | ||
var value = M.value; | ||
return { | ||
type: "Literal", | ||
value: value, | ||
raw: value.toString(), | ||
regex: { | ||
pattern: value.source, | ||
flags: value.toString().match(/[gimuy]*$/)[0] | ||
} | ||
}; | ||
}); | ||
def_to_moz(AST_Constant, function To_Moz_Literal(M) { | ||
@@ -348,3 +368,4 @@ var value = M.value; | ||
type: "Literal", | ||
value: -value | ||
value: -value, | ||
raw: M.start.raw | ||
} | ||
@@ -355,3 +376,4 @@ }; | ||
type: "Literal", | ||
value: value | ||
value: value, | ||
raw: M.start.raw | ||
}; | ||
@@ -376,2 +398,8 @@ }); | ||
function raw_token(moznode) { | ||
if (moznode.type == "Literal") { | ||
return moznode.raw != null ? moznode.raw : moznode.value + ""; | ||
} | ||
} | ||
function my_start_token(moznode) { | ||
@@ -387,3 +415,4 @@ var loc = moznode.loc, start = loc && loc.start; | ||
endcol : start && start.column, | ||
endpos : range ? range[0] : moznode.start | ||
endpos : range ? range[0] : moznode.start, | ||
raw : raw_token(moznode), | ||
}); | ||
@@ -402,3 +431,4 @@ }; | ||
endcol : end && end.column, | ||
endpos : range ? range[1] : moznode.end | ||
endpos : range ? range[1] : moznode.end, | ||
raw : raw_token(moznode), | ||
}); | ||
@@ -405,0 +435,0 @@ }; |
@@ -91,3 +91,3 @@ /*********************************************************************** | ||
var dq = 0, sq = 0; | ||
str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0\ufeff]/g, function(s){ | ||
str = str.replace(/[\\\b\f\n\r\v\t\x22\x27\u2028\u2029\0\ufeff]/g, function(s){ | ||
switch (s) { | ||
@@ -99,2 +99,3 @@ case "\\": return "\\\\"; | ||
case "\r": return "\\r"; | ||
case "\x0B": return options.screw_ie8 ? "\\v" : "\\x0B"; | ||
case "\u2028": return "\\u2028"; | ||
@@ -130,4 +131,7 @@ case "\u2029": return "\\u2029"; | ||
var ret = make_string(str, quote); | ||
if (options.inline_script) | ||
if (options.inline_script) { | ||
ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1"); | ||
ret = ret.replace(/\x3c!--/g, "\\x3c!--"); | ||
ret = ret.replace(/--\x3e/g, "--\\x3e"); | ||
} | ||
return ret; | ||
@@ -384,4 +388,9 @@ }; | ||
var use_asm = false; | ||
AST_Node.DEFMETHOD("print", function(stream, force_parens){ | ||
var self = this, generator = self._codegen; | ||
var self = this, generator = self._codegen, prev_use_asm = use_asm; | ||
if (self instanceof AST_Directive && self.value == "use asm") { | ||
use_asm = true; | ||
} | ||
function doit() { | ||
@@ -399,2 +408,5 @@ self.add_comments(stream); | ||
stream.pop_node(); | ||
if (self instanceof AST_Lambda) { | ||
use_asm = prev_use_asm; | ||
} | ||
}); | ||
@@ -1053,6 +1065,15 @@ | ||
DEFPRINT(AST_Binary, function(self, output){ | ||
var op = self.operator; | ||
self.left.print(output); | ||
output.space(); | ||
output.print(self.operator); | ||
if (self.operator == "<" | ||
if (op[0] == ">" /* ">>" ">>>" ">" ">=" */ | ||
&& self.left instanceof AST_UnaryPostfix | ||
&& self.left.operator == "--") { | ||
// space is mandatory to avoid outputting --> | ||
output.print(" "); | ||
} else { | ||
// the space is optional depending on "beautify" | ||
output.space(); | ||
} | ||
output.print(op); | ||
if ((op == "<" || op == "<<") | ||
&& self.right instanceof AST_UnaryPrefix | ||
@@ -1063,3 +1084,2 @@ && self.right.operator == "!" | ||
// space is mandatory to avoid outputting <!-- | ||
// http://javascript.spec.whatwg.org/#comment-syntax | ||
output.print(" "); | ||
@@ -1168,6 +1188,4 @@ } else { | ||
DEFPRINT(AST_Number, function(self, output){ | ||
if (self.literal !== undefined | ||
&& +self.literal === self.value /* paranoid check */ | ||
&& self.scope && self.scope.has_directive('use asm')) { | ||
output.print(self.literal); | ||
if (use_asm && self.start.raw != null) { | ||
output.print(self.start.raw); | ||
} else { | ||
@@ -1351,2 +1369,8 @@ output.print(make_num(self.getValue())); | ||
DEFMAP(AST_Constant, basic_sourcemap_gen); | ||
DEFMAP(AST_ObjectSetter, function(self, output){ | ||
output.add_mapping(self.start, self.key.name); | ||
}); | ||
DEFMAP(AST_ObjectGetter, function(self, output){ | ||
output.add_mapping(self.start, self.key.name); | ||
}); | ||
DEFMAP(AST_ObjectProperty, function(self, output){ | ||
@@ -1353,0 +1377,0 @@ output.add_mapping(self.start, self.key); |
@@ -62,3 +62,2 @@ /*********************************************************************** | ||
var RE_OCT_NUMBER = /^0[0-7]+$/; | ||
var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i; | ||
@@ -186,4 +185,5 @@ var OPERATORS = makePredicate([ | ||
return parseInt(num.substr(1), 8); | ||
} else if (RE_DEC_NUMBER.test(num)) { | ||
return parseFloat(num); | ||
} else { | ||
var val = parseFloat(num); | ||
if (val == num) return val; | ||
} | ||
@@ -290,2 +290,5 @@ }; | ||
}; | ||
if (/^(?:num|string|regexp)$/i.test(type)) { | ||
ret.raw = $TEXT.substring(ret.pos, ret.endpos); | ||
} | ||
if (!is_comment) { | ||
@@ -341,7 +344,3 @@ ret.comments_before = S.comments_before; | ||
if (!isNaN(valid)) { | ||
var tok = token("num", valid); | ||
if (num.indexOf('.') >= 0) { | ||
tok.literal = num; | ||
} | ||
return tok; | ||
return token("num", valid); | ||
} else { | ||
@@ -1159,3 +1158,3 @@ parse_error("Invalid syntax: " + num); | ||
case "num": | ||
ret = new AST_Number({ start: tok, end: tok, value: tok.value, literal: tok.literal }); | ||
ret = new AST_Number({ start: tok, end: tok, value: tok.value }); | ||
break; | ||
@@ -1162,0 +1161,0 @@ case "string": |
@@ -95,2 +95,3 @@ /*********************************************************************** | ||
var scope = self.parent_scope = null; | ||
var labels = new Dictionary(); | ||
var defun = null; | ||
@@ -112,17 +113,21 @@ var nesting = 0; | ||
var save_defun = defun; | ||
var save_labels = labels; | ||
defun = scope = node; | ||
labels = new Dictionary(); | ||
++nesting; descend(); --nesting; | ||
scope = save_scope; | ||
defun = save_defun; | ||
labels = save_labels; | ||
return true; // don't descend again in TreeWalker | ||
} | ||
if (node instanceof AST_Directive) { | ||
node.scope = scope; | ||
push_uniq(scope.directives, node.value); | ||
return true; | ||
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_Number) { | ||
node.scope = scope; | ||
return true; | ||
} | ||
if (node instanceof AST_With) { | ||
@@ -136,2 +141,6 @@ for (var s = scope; s; s = s.parent_scope) | ||
} | ||
if (node instanceof AST_Label) { | ||
node.thedef = node; | ||
node.references = []; | ||
} | ||
if (node instanceof AST_SymbolLambda) { | ||
@@ -158,2 +167,11 @@ defun.def_function(node); | ||
} | ||
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; | ||
} | ||
}); | ||
@@ -173,2 +191,6 @@ self.walk(tw); | ||
} | ||
if (node instanceof AST_LoopControl && node.label) { | ||
node.label.thedef.references.push(node); | ||
return true; | ||
} | ||
if (node instanceof AST_SymbolRef) { | ||
@@ -210,3 +232,2 @@ var name = node.name; | ||
AST_Scope.DEFMETHOD("init_scope_vars", function(nesting){ | ||
this.directives = []; // contains the directives defined in this scope, i.e. "use strict" | ||
this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions) | ||
@@ -222,6 +243,2 @@ this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope) | ||
AST_Scope.DEFMETHOD("strict", function(){ | ||
return this.has_directive("use strict"); | ||
}); | ||
AST_Lambda.DEFMETHOD("init_scope_vars", function(){ | ||
@@ -250,7 +267,2 @@ AST_Scope.prototype.init_scope_vars.apply(this, arguments); | ||
AST_Scope.DEFMETHOD("has_directive", function(value){ | ||
return this.parent_scope && this.parent_scope.has_directive(value) | ||
|| (this.directives.indexOf(value) >= 0 ? this : null); | ||
}); | ||
AST_Scope.DEFMETHOD("def_function", function(symbol){ | ||
@@ -257,0 +269,0 @@ this.functions.set(symbol.name, this.def_variable(symbol)); |
@@ -73,3 +73,3 @@ /*********************************************************************** | ||
} | ||
tw.pop(); | ||
tw.pop(this); | ||
return x; | ||
@@ -76,0 +76,0 @@ }); |
@@ -7,3 +7,3 @@ { | ||
"license": "BSD-2-Clause", | ||
"version": "2.5.0", | ||
"version": "2.6.0", | ||
"engines": { | ||
@@ -36,3 +36,3 @@ "node": ">=0.8.0" | ||
"uglify-to-browserify": "~1.0.0", | ||
"yargs": "~3.5.4" | ||
"yargs": "~3.10.0" | ||
}, | ||
@@ -39,0 +39,0 @@ "devDependencies": { |
@@ -137,2 +137,4 @@ UglifyJS 2 | ||
--name-cache File to hold mangled names mappings | ||
--pure-funcs List of functions that can be safely removed if | ||
their return value is not used [array] | ||
``` | ||
@@ -139,0 +141,0 @@ |
@@ -48,3 +48,2 @@ var path = require("path"); | ||
// 1. parse | ||
var haveScope = false; | ||
var toplevel = null, | ||
@@ -78,3 +77,2 @@ sourcesContent = {}; | ||
toplevel.figure_out_scope(); | ||
haveScope = true; | ||
var sq = UglifyJS.Compressor(compress); | ||
@@ -87,3 +85,2 @@ toplevel = toplevel.transform(sq); | ||
toplevel.figure_out_scope(options.mangle); | ||
haveScope = true; | ||
toplevel.compute_char_frequency(options.mangle); | ||
@@ -93,8 +90,3 @@ toplevel.mangle_names(options.mangle); | ||
// 4. scope (if needed) | ||
if (!haveScope) { | ||
toplevel.figure_out_scope(); | ||
} | ||
// 5. output | ||
// 4. output | ||
var inMap = options.inSourceMap; | ||
@@ -101,0 +93,0 @@ var output = {}; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
520180
0.75%13652
0.6%792
0.25%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
Updated