aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2020-04-23 23:50:53 +0100
committerGitHub <noreply@github.com>2020-04-24 06:50:53 +0800
commit3ee13cae02174e565ca40462d7b15c4974265871 (patch)
tree1a7a9b09da324ff3cb238ac101637696e02cb781
parent99cf3a38c53d4a8e4ac937962df4a0fdc600c070 (diff)
downloadtracifyjs-3ee13cae02174e565ca40462d7b15c4974265871.tar.gz
tracifyjs-3ee13cae02174e565ca40462d7b15c4974265871.zip
improve `compress` (#3814)
- avoid identifier overflow through consecutive API calls - simplify `reduce_vars` - enhance `unsafe` `evaluate`
-rw-r--r--lib/compress.js17
-rw-r--r--lib/scope.js29
-rw-r--r--test/compress/reduce_vars.js19
3 files changed, 43 insertions, 22 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 7c2077b7..9420d8d2 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -460,7 +460,7 @@ merge(Compressor.prototype, {
return def.fixed instanceof AST_Defun;
}
- function safe_to_assign(tw, def, scope, value) {
+ function safe_to_assign(tw, def, value) {
if (def.fixed === undefined) return true;
if (def.fixed === null && def.safe_ids) {
def.safe_ids[def.id] = false;
@@ -471,11 +471,8 @@ merge(Compressor.prototype, {
if (!safe_to_read(tw, def)) return false;
if (def.fixed === false) return false;
if (def.fixed != null && (!value || def.references.length > def.assignments)) return false;
- if (def.fixed instanceof AST_Defun) {
- return value instanceof AST_Node && def.fixed.parent_scope === scope;
- }
return all(def.orig, function(sym) {
- return !(sym instanceof AST_SymbolDefun || sym instanceof AST_SymbolLambda);
+ return !(sym instanceof AST_SymbolLambda);
});
}
@@ -557,7 +554,7 @@ merge(Compressor.prototype, {
}
if (sym.fixed) delete sym.fixed;
var d = sym.definition();
- var safe = safe_to_assign(tw, d, sym.scope, node.right);
+ var safe = safe_to_assign(tw, d, node.right);
d.assignments++;
var fixed = d.fixed;
if (!fixed && node.operator != "=") return;
@@ -820,7 +817,7 @@ merge(Compressor.prototype, {
}
if (exp.fixed) delete exp.fixed;
var d = exp.definition();
- var safe = safe_to_assign(tw, d, exp.scope, true);
+ var safe = safe_to_assign(tw, d, true);
d.assignments++;
var fixed = d.fixed;
if (!fixed) return;
@@ -846,7 +843,7 @@ merge(Compressor.prototype, {
var node = this;
var d = node.name.definition();
if (node.value) {
- if (safe_to_assign(tw, d, node.name.scope, node.value)) {
+ if (safe_to_assign(tw, d, node.value)) {
d.fixed = function() {
return node.value;
};
@@ -3195,7 +3192,7 @@ merge(Compressor.prototype, {
def(AST_Statement, function() {
throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start));
});
- def(AST_Lambda, return_this);
+ def(AST_Accessor, return_this);
def(AST_Node, return_this);
def(AST_Constant, function() {
return this.value;
@@ -3213,7 +3210,7 @@ merge(Compressor.prototype, {
var value = node._eval(compressor, ignore_side_effects, cached, depth);
return value === node ? this : value;
});
- def(AST_Function, function(compressor) {
+ def(AST_Lambda, function(compressor) {
if (compressor.option("unsafe")) {
var fn = function() {};
fn.node = this;
diff --git a/lib/scope.js b/lib/scope.js
index ad33c5e0..adbfe4ac 100644
--- a/lib/scope.js
+++ b/lib/scope.js
@@ -43,23 +43,21 @@
"use strict";
-function SymbolDef(scope, orig, init) {
+function SymbolDef(id, scope, orig, init) {
+ this.eliminated = 0;
+ this.global = false;
+ this.id = id;
+ this.init = init;
+ this.lambda = orig instanceof AST_SymbolLambda;
+ this.mangled_name = null;
this.name = orig.name;
this.orig = [ orig ];
- this.init = init;
- this.eliminated = 0;
- this.scope = scope;
this.references = [];
this.replaced = 0;
- this.global = false;
- this.mangled_name = null;
+ this.scope = scope;
this.undeclared = false;
- this.id = SymbolDef.next_id++;
- this.lambda = orig instanceof AST_SymbolLambda;
}
-SymbolDef.next_id = 1;
-
SymbolDef.prototype = {
unmangleable: function(options) {
return this.global && !options.toplevel
@@ -151,6 +149,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
scope.def_variable(node).defun = defun;
}
});
+ self.next_def_id = 0;
self.walk(tw);
// pass 2: find back references and eval
@@ -240,12 +239,18 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
}
});
+AST_Scope.DEFMETHOD("make_def", function(orig, init) {
+ var top = this;
+ while (top.parent_scope) top = top.parent_scope;
+ return new SymbolDef(++top.next_def_id, this, orig, init);
+});
+
AST_Toplevel.DEFMETHOD("def_global", function(node) {
var globals = this.globals, name = node.name;
if (globals.has(name)) {
return globals.get(name);
} else {
- var g = new SymbolDef(this, node);
+ var g = this.make_def(node);
g.undeclared = true;
g.global = true;
globals.set(name, g);
@@ -310,7 +315,7 @@ AST_Scope.DEFMETHOD("def_variable", function(symbol, init) {
def.orig.push(symbol);
if (def.init instanceof AST_Function) def.init = init;
} else {
- def = new SymbolDef(this, symbol, init);
+ def = this.make_def(symbol, init);
this.variables.set(symbol.name, def);
def.global = !this.parent_scope;
}
diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js
index 6be1171f..25108cae 100644
--- a/test/compress/reduce_vars.js
+++ b/test/compress/reduce_vars.js
@@ -223,6 +223,25 @@ unsafe_evaluate: {
expect_stdout: true
}
+unsafe_evaluate_defun: {
+ options = {
+ evaluate: true,
+ reduce_vars: true,
+ unsafe: true,
+ unused: true,
+ }
+ input: {
+ console.log(function() {
+ function f() {}
+ return ++f;
+ }());
+ }
+ expect: {
+ console.log(NaN);
+ }
+ expect_stdout: "NaN"
+}
+
unsafe_evaluate_side_effect_free_1: {
options = {
evaluate: true,