improve handling of eval (#3776)

closes #3768
This commit is contained in:
Alex Lam S.L
2020-04-10 23:36:17 +01:00
committed by GitHub
parent dce9dfce0e
commit c810ecd081
5 changed files with 90 additions and 24 deletions

View File

@@ -996,9 +996,7 @@ merge(Compressor.prototype, {
function needs_unbinding(compressor, val) { function needs_unbinding(compressor, val) {
return val instanceof AST_PropAccess return val instanceof AST_PropAccess
|| compressor.has_directive("use strict") || is_undeclared_ref(val) && val.name == "eval";
&& is_undeclared_ref(val)
&& val.name == "eval";
} }
// we shouldn't compress (1,func)(something) to // we shouldn't compress (1,func)(something) to

View File

@@ -162,17 +162,22 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
} }
if (node instanceof AST_SymbolRef) { if (node instanceof AST_SymbolRef) {
var name = node.name; var name = node.name;
if (name == "eval" && tw.parent() instanceof AST_Call) {
for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) {
s.uses_eval = true;
}
}
var sym = node.scope.find_variable(name); var sym = node.scope.find_variable(name);
if (!sym) { if (!sym) {
sym = self.def_global(node); sym = self.def_global(node);
} else if (sym.scope instanceof AST_Lambda && name == "arguments") { } else if (sym.scope instanceof AST_Lambda && name == "arguments") {
sym.scope.uses_arguments = true; sym.scope.uses_arguments = true;
} }
if (name == "eval") {
var parent = tw.parent();
if (parent.TYPE == "Call" && parent.expression === node) {
for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) {
s.uses_eval = true;
}
} else if (sym.undeclared) {
self.uses_eval = true;
}
}
node.thedef = sym; node.thedef = sym;
node.reference(options); node.reference(options);
return true; return true;

View File

@@ -9,12 +9,12 @@ mangle: {
})(); })();
} }
expect: { expect: {
var o = eval, e = 42; var e = eval, x = 42;
(function() { (function() {
console.log(o("typeof x")); console.log(e("typeof x"));
})(); })();
} }
expect_stdout: "undefined" expect_stdout: true
} }
compress: { compress: {
@@ -49,7 +49,7 @@ compress: {
console.log(function() { console.log(function() {
var a = 42; var a = 42;
return eval("typeof a"); return eval("typeof a");
}(), eval("typeof a"), function(eval) { }(), (0, eval)("typeof a"), function(eval) {
var a = false; var a = false;
return eval("typeof a"); return eval("typeof a");
}(eval), function(f) { }(eval), function(f) {
@@ -66,3 +66,63 @@ compress: {
} }
expect_stdout: "number undefined boolean string undefined" expect_stdout: "number undefined boolean string undefined"
} }
call_arg_1: {
mangle = {
toplevel: true,
}
input: {
var z = "foo";
(function() {
var z = false;
(function(e) {
var z = 42;
e("console.log(typeof z)");
})(eval);
})();
}
expect: {
var z = "foo";
(function() {
var o = false;
(function(o) {
var a = 42;
o("console.log(typeof z)");
})(eval);
})();
}
expect_stdout: true
}
call_arg_2: {
mangle = {
toplevel: true,
}
input: {
function eval() {
console.log("PASS");
}
var z = "foo";
(function() {
var z = false;
(function(e) {
var z = 42;
e("console.log(typeof z)");
})(eval);
})();
}
expect: {
function n() {
console.log("PASS");
}
var o = "foo";
(function() {
var o = false;
(function(o) {
var n = 42;
o("console.log(typeof z)");
})(n);
})();
}
expect_stdout: "PASS"
}

View File

@@ -8,7 +8,7 @@ remove_sequence: {
(0, 1, _decorators.logThis)(); (0, 1, _decorators.logThis)();
} }
expect: { expect: {
eval(); (0, eval)();
logThis(); logThis();
(0, _decorators.logThis)(); (0, _decorators.logThis)();
} }

View File

@@ -53,20 +53,23 @@ this_binding_conditionals: {
this_binding_collapse_vars: { this_binding_collapse_vars: {
options = { options = {
collapse_vars: true, collapse_vars: true,
toplevel: true,
unused: true, unused: true,
} }
input: { input: {
"use strict"; function f() {
var c = a; c(); "use strict";
var d = a.b; d(); var c = a; c();
var e = eval; e(); var d = a.b; d();
var e = eval; e();
}
} }
expect: { expect: {
"use strict"; function f() {
a(); "use strict";
(0, a.b)(); a();
(0, eval)(); (0, a.b)();
(0, eval)();
}
} }
} }
@@ -97,7 +100,7 @@ this_binding_side_effects: {
(function(foo) { (function(foo) {
foo(); foo();
(0, foo.bar)(); (0, foo.bar)();
eval("console.log(foo);"); (0, eval)("console.log(foo);");
}()); }());
(function(foo) { (function(foo) {
"use strict"; "use strict";
@@ -144,7 +147,7 @@ this_binding_sequences: {
return eval("this"); return eval("this");
}()), }()),
console.log(typeof function() { console.log(typeof function() {
return eval("this"); return (0, eval)("this");
}()), }()),
console.log(typeof function() { console.log(typeof function() {
"use strict"; "use strict";