Add proper support for "use asm"; blocks. Disable -c optimization within "use asm"; sections and preserve floating point literals in their original form. Non-asm.js sections are optimized as before. Asm.js sections can still be mangled and minified of whitespace. No special command line flags are required.

This commit is contained in:
kzc
2015-10-05 19:51:09 -04:00
committed by Richard van Velzen
parent c69294c449
commit 593677d2ff
5 changed files with 27 additions and 14 deletions

View File

@@ -401,7 +401,7 @@ async.eachLimit(files, 1, function (file, cb) {
writeNameCache("props", cache); writeNameCache("props", cache);
})(); })();
var SCOPE_IS_NEEDED = COMPRESS || MANGLE || ARGS.lint; var SCOPE_IS_NEEDED = COMPRESS || MANGLE || BEAUTIFY || ARGS.lint;
var TL_CACHE = readNameCache("vars"); var TL_CACHE = readNameCache("vars");
if (SCOPE_IS_NEEDED) { if (SCOPE_IS_NEEDED) {

View File

@@ -111,6 +111,7 @@ merge(Compressor.prototype, {
node.DEFMETHOD("optimize", function(compressor){ node.DEFMETHOD("optimize", function(compressor){
var self = this; var self = this;
if (self._optimized) return self; if (self._optimized) return self;
if (compressor.has_directive("use asm")) return self;
var opt = optimizer(self, compressor); var opt = optimizer(self, compressor);
opt._optimized = true; opt._optimized = true;
if (opt === self) return opt; if (opt === self) return opt;
@@ -1026,6 +1027,7 @@ merge(Compressor.prototype, {
AST_Scope.DEFMETHOD("drop_unused", function(compressor){ AST_Scope.DEFMETHOD("drop_unused", function(compressor){
var self = this; var self = this;
if (compressor.has_directive("use asm")) return self;
if (compressor.option("unused") if (compressor.option("unused")
&& !(self instanceof AST_Toplevel) && !(self instanceof AST_Toplevel)
&& !self.uses_eval && !self.uses_eval
@@ -1205,9 +1207,10 @@ merge(Compressor.prototype, {
}); });
AST_Scope.DEFMETHOD("hoist_declarations", function(compressor){ AST_Scope.DEFMETHOD("hoist_declarations", function(compressor){
var self = this;
if (compressor.has_directive("use asm")) return self;
var hoist_funs = compressor.option("hoist_funs"); var hoist_funs = compressor.option("hoist_funs");
var hoist_vars = compressor.option("hoist_vars"); var hoist_vars = compressor.option("hoist_vars");
var self = this;
if (hoist_funs || hoist_vars) { if (hoist_funs || hoist_vars) {
var dirs = []; var dirs = [];
var hoisted = []; var hoisted = [];
@@ -2028,15 +2031,14 @@ merge(Compressor.prototype, {
var commutativeOperators = makePredicate("== === != !== * & | ^"); var commutativeOperators = makePredicate("== === != !== * & | ^");
OPT(AST_Binary, function(self, compressor){ OPT(AST_Binary, function(self, compressor){
var reverse = compressor.has_directive("use asm") ? noop function reverse(op, force) {
: function(op, force) { if (force || !(self.left.has_side_effects(compressor) || self.right.has_side_effects(compressor))) {
if (force || !(self.left.has_side_effects(compressor) || self.right.has_side_effects(compressor))) { if (op) self.operator = op;
if (op) self.operator = op; var tmp = self.left;
var tmp = self.left; self.left = self.right;
self.left = self.right; self.right = tmp;
self.right = tmp; }
} }
};
if (commutativeOperators(self.operator)) { if (commutativeOperators(self.operator)) {
if (self.right instanceof AST_Constant if (self.right instanceof AST_Constant
&& !(self.left instanceof AST_Constant)) { && !(self.left instanceof AST_Constant)) {
@@ -2104,10 +2106,10 @@ merge(Compressor.prototype, {
if (compressor.option("conditionals")) { if (compressor.option("conditionals")) {
if (self.operator == "&&") { if (self.operator == "&&") {
var ll = self.left.evaluate(compressor); var ll = self.left.evaluate(compressor);
var rr = self.right.evaluate(compressor);
if (ll.length > 1) { if (ll.length > 1) {
if (ll[1]) { if (ll[1]) {
compressor.warn("Condition left of && always true [{file}:{line},{col}]", self.start); compressor.warn("Condition left of && always true [{file}:{line},{col}]", self.start);
var rr = self.right.evaluate(compressor);
return rr[0]; return rr[0];
} else { } else {
compressor.warn("Condition left of && always false [{file}:{line},{col}]", self.start); compressor.warn("Condition left of && always false [{file}:{line},{col}]", self.start);
@@ -2117,13 +2119,13 @@ merge(Compressor.prototype, {
} }
else if (self.operator == "||") { else if (self.operator == "||") {
var ll = self.left.evaluate(compressor); var ll = self.left.evaluate(compressor);
var rr = self.right.evaluate(compressor);
if (ll.length > 1) { if (ll.length > 1) {
if (ll[1]) { if (ll[1]) {
compressor.warn("Condition left of || always true [{file}:{line},{col}]", self.start); compressor.warn("Condition left of || always true [{file}:{line},{col}]", self.start);
return ll[0]; return ll[0];
} else { } else {
compressor.warn("Condition left of || always false [{file}:{line},{col}]", self.start); compressor.warn("Condition left of || always false [{file}:{line},{col}]", self.start);
var rr = self.right.evaluate(compressor);
return rr[0]; return rr[0];
} }
} }

View File

@@ -1158,7 +1158,11 @@ function OutputStream(options) {
output.print_string(self.getValue(), self.quote); output.print_string(self.getValue(), self.quote);
}); });
DEFPRINT(AST_Number, function(self, output){ DEFPRINT(AST_Number, function(self, output){
output.print(make_num(self.getValue())); if (self.value_string !== undefined && self.scope && self.scope.has_directive('use asm')) {
output.print(self.value_string);
} else {
output.print(make_num(self.getValue()));
}
}); });
function regexp_safe_literal(code) { function regexp_safe_literal(code) {

View File

@@ -1149,6 +1149,9 @@ function parse($TEXT, options) {
break; break;
case "num": case "num":
ret = new AST_Number({ start: tok, end: tok, value: tok.value }); ret = new AST_Number({ start: tok, end: tok, value: tok.value });
var value_string = $TEXT.substring(tok.pos, tok.endpos);
if (value_string.indexOf('.') >= 0)
ret.value_string = value_string;
break; break;
case "string": case "string":
ret = new AST_String({ ret = new AST_String({

View File

@@ -119,6 +119,10 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
push_uniq(scope.directives, node.value); push_uniq(scope.directives, node.value);
return true; return true;
} }
if (node instanceof AST_Number) {
node.scope = scope;
return true;
}
if (node instanceof AST_With) { if (node instanceof AST_With) {
for (var s = scope; s; s = s.parent_scope) for (var s = scope; s; s = s.parent_scope)
s.uses_with = true; s.uses_with = true;