Merge branch 'master' into harmony

This commit is contained in:
Richard van Velzen
2016-05-04 20:13:35 +02:00
13 changed files with 263 additions and 49 deletions

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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;