Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix corner case in arguments #3421

Merged
merged 1 commit into from May 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
55 changes: 35 additions & 20 deletions lib/compress.js
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -3832,6 +3829,7 @@ merge(Compressor.prototype, {
};
}
});
tt.push(compressor.parent());
self.transform(tt);

function verify_safe_usage(def, read, modified) {
Expand Down Expand Up @@ -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),
Expand All @@ -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) {
Expand Down Expand Up @@ -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() {
Expand Down
154 changes: 154 additions & 0 deletions test/compress/arguments.js
Expand Up @@ -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"
}
66 changes: 66 additions & 0 deletions test/compress/keep_fargs.js
Expand Up @@ -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"
}