aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2019-05-19 12:59:40 +0800
committerGitHub <noreply@github.com>2019-05-19 12:59:40 +0800
commitae77ebe5a5f1be4b2634036f48d8b570b569cb21 (patch)
tree754c0f68fd2ae5f06b3bd006a35c2b8eea22da0e
parent04439edceccfdc450901907cd248425b3ba384ae (diff)
downloadtracifyjs-ae77ebe5a5f1be4b2634036f48d8b570b569cb21.tar.gz
tracifyjs-ae77ebe5a5f1be4b2634036f48d8b570b569cb21.zip
fix corner case in `arguments` (#3421)
fixes #3420
-rw-r--r--lib/compress.js55
-rw-r--r--test/compress/arguments.js154
-rw-r--r--test/compress/keep_fargs.js66
3 files changed, 255 insertions, 20 deletions
diff --git a/lib/compress.js b/lib/compress.js
index b7e5b3d2..e1f0105c 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -105,10 +105,10 @@ function Compressor(options, false_by_default) {
}
if (this.options["inline"] === true) this.options["inline"] = 3;
var keep_fargs = this.options["keep_fargs"];
- this.drop_fargs = keep_fargs == "strict" ? function(lambda) {
+ this.drop_fargs = keep_fargs == "strict" ? function(lambda, parent) {
if (lambda.length_read) return false;
var name = lambda.name;
- if (!name) return true;
+ if (!name) return parent && parent.TYPE == "Call";
if (name.fixed_value() !== lambda) return false;
var def = name.definition();
if (def.direct_access) return false;
@@ -527,12 +527,9 @@ merge(Compressor.prototype, {
function mark_assignment_to_arguments(node) {
if (!(node instanceof AST_Sub)) return;
var expr = node.expression;
- var prop = node.property;
- if (expr instanceof AST_SymbolRef
- && is_arguments(expr.definition())
- && prop instanceof AST_Number) {
- expr.definition().reassigned = true;
- }
+ if (!(expr instanceof AST_SymbolRef)) return;
+ var def = expr.definition();
+ if (is_arguments(def) && node.property instanceof AST_Number) def.reassigned = true;
}
var suppressor = new TreeWalker(function(node) {
@@ -3641,7 +3638,7 @@ merge(Compressor.prototype, {
node.name = null;
}
if (node instanceof AST_Lambda && !(node instanceof AST_Accessor)) {
- var trim = compressor.drop_fargs(node);
+ var trim = compressor.drop_fargs(node, parent);
for (var a = node.argnames, i = a.length; --i >= 0;) {
var sym = a[i];
if (!(sym.definition().id in in_use_ids)) {
@@ -3832,6 +3829,7 @@ merge(Compressor.prototype, {
};
}
});
+ tt.push(compressor.parent());
self.transform(tt);
function verify_safe_usage(def, read, modified) {
@@ -6682,23 +6680,30 @@ merge(Compressor.prototype, {
}
}
}
- var fn;
+ var parent = compressor.parent();
+ var def, fn, fn_parent;
if (compressor.option("arguments")
&& expr instanceof AST_SymbolRef
- && is_arguments(expr.definition())
+ && is_arguments(def = expr.definition())
&& prop instanceof AST_Number
- && (fn = expr.scope) === compressor.find_parent(AST_Lambda)) {
+ && (fn = expr.scope) === find_lambda()) {
var index = prop.getValue();
+ if (parent instanceof AST_UnaryPrefix && parent.operator == "delete") {
+ if (!def.deleted) def.deleted = [];
+ def.deleted[index] = true;
+ }
var argname = fn.argnames[index];
- if (argname && compressor.has_directive("use strict")) {
- var def = argname.definition();
+ if (def.deleted && def.deleted[index]) {
+ argname = null;
+ } else if (argname && compressor.has_directive("use strict")) {
+ var arg_def = argname.definition();
if (!compressor.option("reduce_vars")
- || expr.definition().reassigned
- || def.assignments
- || def.orig.length > 1) {
+ || def.reassigned
+ || arg_def.assignments
+ || arg_def.orig.length > 1) {
argname = null;
}
- } else if (!argname && compressor.drop_fargs(fn) && index < fn.argnames.length + 5) {
+ } else if (!argname && index < fn.argnames.length + 5 && compressor.drop_fargs(fn, fn_parent)) {
while (index >= fn.argnames.length) {
argname = make_node(AST_SymbolFunarg, fn, {
name: fn.make_var_name("argument_" + fn.argnames.length),
@@ -6711,14 +6716,14 @@ merge(Compressor.prototype, {
if (argname && find_if(function(node) {
return node.name === argname.name;
}, fn.argnames) === argname) {
- expr.definition().reassigned = false;
+ def.reassigned = false;
var sym = make_node(AST_SymbolRef, self, argname);
sym.reference({});
delete argname.__unused;
return sym;
}
}
- if (is_lhs(compressor.self(), compressor.parent())) return self;
+ if (is_lhs(compressor.self(), parent)) return self;
if (key !== prop) {
var sub = self.flatten_object(property, compressor);
if (sub) {
@@ -6767,6 +6772,16 @@ merge(Compressor.prototype, {
return best_of(compressor, ev, self);
}
return self;
+
+ function find_lambda() {
+ var i = 0, p;
+ while (p = compressor.parent(i++)) {
+ if (p instanceof AST_Lambda) {
+ fn_parent = compressor.parent(i);
+ return p;
+ }
+ }
+ }
});
AST_Scope.DEFMETHOD("contains_this", function() {
diff --git a/test/compress/arguments.js b/test/compress/arguments.js
index eaff8119..119eaf2c 100644
--- a/test/compress/arguments.js
+++ b/test/compress/arguments.js
@@ -622,3 +622,157 @@ issue_3282_2_passes: {
}
expect_stdout: true
}
+
+issue_3420_1: {
+ options = {
+ arguments: true,
+ keep_fargs: "strict",
+ }
+ input: {
+ console.log(function() {
+ return function() {
+ return arguments[0];
+ };
+ }().length);
+ }
+ expect: {
+ console.log(function() {
+ return function() {
+ return arguments[0];
+ };
+ }().length);
+ }
+ expect_stdout: "0"
+}
+
+issue_3420_2: {
+ options = {
+ arguments: true,
+ keep_fargs: "strict",
+ }
+ input: {
+ var foo = function() {
+ delete arguments[0];
+ };
+ foo();
+ }
+ expect: {
+ var foo = function() {
+ delete arguments[0];
+ };
+ foo();
+ }
+ expect_stdout: true
+}
+
+issue_3420_3: {
+ options = {
+ arguments: true,
+ keep_fargs: "strict",
+ }
+ input: {
+ "use strict";
+ var foo = function() {
+ delete arguments[0];
+ };
+ foo();
+ }
+ expect: {
+ "use strict";
+ var foo = function() {
+ delete arguments[0];
+ };
+ foo();
+ }
+ expect_stdout: true
+}
+
+issue_3420_4: {
+ options = {
+ arguments: true,
+ keep_fargs: "strict",
+ }
+ input: {
+ !function() {
+ console.log(arguments[0]);
+ delete arguments[0];
+ console.log(arguments[0]);
+ }(42);
+ }
+ expect: {
+ !function(argument_0) {
+ console.log(argument_0);
+ delete arguments[0];
+ console.log(arguments[0]);
+ }(42);
+ }
+ expect_stdout: [
+ "42",
+ "undefined",
+ ]
+}
+
+issue_3420_5: {
+ options = {
+ arguments: true,
+ keep_fargs: "strict",
+ }
+ input: {
+ "use strict";
+ !function() {
+ console.log(arguments[0]);
+ delete arguments[0];
+ console.log(arguments[0]);
+ }(42);
+ }
+ expect: {
+ "use strict";
+ !function(argument_0) {
+ console.log(argument_0);
+ delete arguments[0];
+ console.log(arguments[0]);
+ }(42);
+ }
+ expect_stdout: [
+ "42",
+ "undefined",
+ ]
+}
+
+issue_3420_6: {
+ options = {
+ arguments: true,
+ keep_fargs: "strict",
+ }
+ input: {
+ console.log(function() {
+ return delete arguments[0];
+ }());
+ }
+ expect: {
+ console.log(function() {
+ return delete arguments[0];
+ }());
+ }
+ expect_stdout: "true"
+}
+
+issue_3420_7: {
+ options = {
+ arguments: true,
+ keep_fargs: "strict",
+ }
+ input: {
+ "use strict";
+ console.log(function() {
+ return delete arguments[0];
+ }());
+ }
+ expect: {
+ "use strict";
+ console.log(function() {
+ return delete arguments[0];
+ }());
+ }
+ expect_stdout: "true"
+}
diff --git a/test/compress/keep_fargs.js b/test/compress/keep_fargs.js
index b23e96f0..558b10bb 100644
--- a/test/compress/keep_fargs.js
+++ b/test/compress/keep_fargs.js
@@ -1051,3 +1051,69 @@ function_name_mangle_ie8: {
expect_exact: "(function(){console.log(typeof function o(){})})();"
expect_stdout: "function"
}
+
+issue_3420_1: {
+ options = {
+ keep_fargs: "strict",
+ unused: true,
+ }
+ input: {
+ console.log(function() {
+ return function(a, b, c, d) {
+ return a + b;
+ };
+ }().length);
+ }
+ expect: {
+ console.log(function() {
+ return function(a, b, c, d) {
+ return a + b;
+ };
+ }().length);
+ }
+ expect_stdout: "4"
+}
+
+issue_3420_2: {
+ options = {
+ inline: true,
+ keep_fargs: "strict",
+ unused: true,
+ }
+ input: {
+ console.log(function() {
+ return function(a, b, c, d) {
+ return a + b;
+ };
+ }().length);
+ }
+ expect: {
+ console.log(function(a, b, c, d) {
+ return a + b;
+ }.length);
+ }
+ expect_stdout: "4"
+}
+
+issue_3420_3: {
+ options = {
+ inline: true,
+ keep_fargs: "strict",
+ reduce_vars: true,
+ unused: true,
+ }
+ input: {
+ console.log(function() {
+ function f(a, b, c, d) {
+ return a + b;
+ }
+ return f;
+ }().length);
+ }
+ expect: {
+ console.log(function(a, b, c, d) {
+ return a + b;
+ }.length);
+ }
+ expect_stdout: "4"
+}