diff --git a/lib/compress.js b/lib/compress.js index 2bc1c5a5..6e125e47 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -138,13 +138,15 @@ merge(Compressor.prototype, { }, before: function(node, descend, in_list) { if (node._squeezed) return node; - var was_scope = false; + // asm.js: drop unused only, leave everything else as is inside "use asm" scope + var asm = this.has_directive("use asm"), + was_scope = false; if (node instanceof AST_Scope) { - node = node.hoist_declarations(this); + if (!asm) node = node.hoist_declarations(this); was_scope = true; } descend(node, this); - node = node.optimize(this); + if (!asm) node = node.optimize(this); if (was_scope && node instanceof AST_Scope) { node.drop_unused(this); descend(node, this); @@ -1384,6 +1386,15 @@ merge(Compressor.prototype, { def(AST_Constant, return_false); def(AST_This, return_false); + // asm.js: `new stdlib.XYZ` inside "use asm" scope are always pure + def(AST_New, function(compressor){ + if (compressor.has_directive("use asm")) return false; + // AST_Call fallback + var pure = compressor.option("pure_funcs"); + if (!pure) return true; + return pure.indexOf(this.expression.print_to_string()) < 0; + }); + def(AST_Call, function(compressor){ if (!this.has_pure_annotation(compressor) && compressor.pure_funcs(this)) return true; for (var i = this.args.length; --i >= 0;) { diff --git a/lib/scope.js b/lib/scope.js index 29e4103a..7c083a69 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -289,6 +289,14 @@ AST_Scope.DEFMETHOD("def_variable", function(symbol){ AST_Scope.DEFMETHOD("next_mangled", function(options){ var ext = this.enclosed; + + // asm.js: don't mask module-scope names + var asm = this.has_directive("use asm"), + pasm = this.parent_scope ? this.parent_scope.has_directive("use asm") : false; + if (pasm) { + this.cname = this.parent_scope.cname; + } + out: while (true) { var m = base54(++this.cname); if (!is_identifier(m)) continue; // skip over "do" @@ -297,6 +305,21 @@ AST_Scope.DEFMETHOD("next_mangled", function(options){ // shadow a name excepted from mangling. if (options.except.indexOf(m) >= 0) continue; + // asm.js: don't reuse module name although it is out of the current scope + if (asm) { + var sym = this.name; + var penc = this.parent_scope.enclosed; + if (sym && penc.length) { + for (var i = 0; i < penc.length; i++) { + var psym = penc[i]; + if (sym.name == psym.name) { + var name = psym.mangled_name || (psym.unmangleable(options) && psym.name); + if (m == name) continue out; + } + } + } + } + // we must ensure that the mangled name does not shadow a name // from some parent scope that is referenced in this or in // inner scopes.