Merge branch 'master' into harmony
This commit is contained in:
@@ -75,18 +75,36 @@ function Compressor(options, false_by_default) {
|
||||
screw_ie8 : false,
|
||||
drop_console : false,
|
||||
angular : false,
|
||||
|
||||
warnings : true,
|
||||
global_defs : {}
|
||||
global_defs : {},
|
||||
passes : 1,
|
||||
}, true);
|
||||
this.warnings_produced = {};
|
||||
};
|
||||
|
||||
Compressor.prototype = new TreeTransformer;
|
||||
merge(Compressor.prototype, {
|
||||
option: function(key) { return this.options[key] },
|
||||
warn: function() {
|
||||
if (this.options.warnings)
|
||||
AST_Node.warn.apply(AST_Node, arguments);
|
||||
compress: function(node) {
|
||||
var passes = +this.options.passes || 1;
|
||||
for (var pass = 0; pass < passes && pass < 3; ++pass) {
|
||||
if (pass > 0) node.clear_opt_flags();
|
||||
node = node.transform(this);
|
||||
}
|
||||
return node;
|
||||
},
|
||||
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;
|
||||
@@ -129,6 +147,15 @@ merge(Compressor.prototype, {
|
||||
return this.print_to_string() == node.print_to_string();
|
||||
});
|
||||
|
||||
AST_Node.DEFMETHOD("clear_opt_flags", function(){
|
||||
this.walk(new TreeWalker(function(node){
|
||||
if (!(node instanceof AST_Directive || node instanceof AST_Constant)) {
|
||||
node._squeezed = false;
|
||||
node._optimized = false;
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
function make_node(ctor, orig, props) {
|
||||
if (!props) props = {};
|
||||
if (orig) {
|
||||
@@ -400,10 +427,7 @@ merge(Compressor.prototype, {
|
||||
var_defs_removed = true;
|
||||
}
|
||||
// Further optimize statement after substitution.
|
||||
stat.walk(new TreeWalker(function(node){
|
||||
delete node._squeezed;
|
||||
delete node._optimized;
|
||||
}));
|
||||
stat.clear_opt_flags();
|
||||
|
||||
compressor.warn("Replacing " + (is_constant ? "constant" : "variable") +
|
||||
" " + var_name + " [{file}:{line},{col}]", node.start);
|
||||
@@ -570,11 +594,13 @@ merge(Compressor.prototype, {
|
||||
CHANGED = true;
|
||||
stat = stat.clone();
|
||||
stat.condition = stat.condition.negate(compressor);
|
||||
var body = as_statement_array(stat.alternative).concat(ret);
|
||||
var funs = extract_functions_from_statement_array(body);
|
||||
stat.body = make_node(AST_BlockStatement, stat, {
|
||||
body: as_statement_array(stat.alternative).concat(ret)
|
||||
body: body
|
||||
});
|
||||
stat.alternative = null;
|
||||
ret = [ stat.transform(compressor) ];
|
||||
ret = funs.concat([ stat.transform(compressor) ]);
|
||||
continue loop;
|
||||
}
|
||||
//---
|
||||
@@ -832,6 +858,18 @@ merge(Compressor.prototype, {
|
||||
|
||||
};
|
||||
|
||||
function extract_functions_from_statement_array(statements) {
|
||||
var funs = [];
|
||||
for (var i = statements.length - 1; i >= 0; --i) {
|
||||
var stat = statements[i];
|
||||
if (stat instanceof AST_Defun) {
|
||||
statements.splice(i, 1);
|
||||
funs.unshift(stat);
|
||||
}
|
||||
}
|
||||
return funs;
|
||||
}
|
||||
|
||||
function extract_declarations_from_unreachable_code(compressor, stat, target) {
|
||||
if (!(stat instanceof AST_Defun)) {
|
||||
compressor.warn("Dropping unreachable code [{file}:{line},{col}]", stat.start);
|
||||
|
||||
@@ -414,6 +414,7 @@ function OutputStream(options) {
|
||||
|
||||
AST_Node.DEFMETHOD("print_to_string", function(options){
|
||||
var s = OutputStream(options);
|
||||
if (!options) s._readonly = true;
|
||||
this.print(s);
|
||||
return s.get();
|
||||
});
|
||||
@@ -421,6 +422,7 @@ function OutputStream(options) {
|
||||
/* -----[ comments ]----- */
|
||||
|
||||
AST_Node.DEFMETHOD("add_comments", function(output){
|
||||
if (output._readonly) return;
|
||||
var c = output.option("comments"), self = this;
|
||||
var start = self.start;
|
||||
if (start && !start._comments_dumped) {
|
||||
|
||||
14
lib/parse.js
14
lib/parse.js
@@ -265,6 +265,16 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
return S.text.substr(S.pos, str.length) == str;
|
||||
};
|
||||
|
||||
function find_eol() {
|
||||
var text = S.text;
|
||||
for (var i = S.pos, n = S.text.length; i < n; ++i) {
|
||||
var ch = text[i];
|
||||
if (ch == '\n' || ch == '\r')
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
function find(what, signal_eof) {
|
||||
var pos = S.text.indexOf(what, S.pos);
|
||||
if (signal_eof && pos == -1) throw EX_EOF;
|
||||
@@ -420,7 +430,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
|
||||
function skip_line_comment(type) {
|
||||
var regex_allowed = S.regex_allowed;
|
||||
var i = find("\n"), ret;
|
||||
var i = find_eol(), ret;
|
||||
if (i == -1) {
|
||||
ret = S.text.substr(S.pos);
|
||||
S.pos = S.text.length;
|
||||
@@ -437,7 +447,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
var skip_multiline_comment = with_eof_error("Unterminated multiline comment", function(){
|
||||
var regex_allowed = S.regex_allowed;
|
||||
var i = find("*/", true);
|
||||
var text = S.text.substring(S.pos, i);
|
||||
var text = S.text.substring(S.pos, i).replace(/\r\n|\r/g, '\n');
|
||||
var a = text.split("\n"), n = a.length;
|
||||
// update stream position
|
||||
S.pos = i + 2;
|
||||
|
||||
Reference in New Issue
Block a user