This commit is contained in:
Alex Lam S.L 2017-03-01 08:25:11 +00:00 committed by GitHub
commit 70dc5ab990
3 changed files with 75 additions and 54 deletions

View File

@ -2472,55 +2472,31 @@ merge(Compressor.prototype, {
argnames: [], argnames: [],
body: [] body: []
}); });
if (all(self.args, function(x){ return x instanceof AST_String })) { // new Function("x", "return x") => function(x){return x}
// quite a corner-case, but we can handle it:
// https://github.com/mishoo/UglifyJS2/issues/203
// if the code argument is a constant, then we can minify it.
try { try {
var code = "(function(" + self.args.slice(0, -1).map(function(arg){ var args = self.args.map(function(arg) {
if (!(arg instanceof AST_String)) throw self;
return arg.value; return arg.value;
}).join(",") + "){" + self.args[self.args.length - 1].value + "})()";
var ast = parse(code);
ast.figure_out_scope({ screw_ie8: compressor.option("screw_ie8") });
var comp = new Compressor(compressor.options);
ast = ast.transform(comp);
ast.figure_out_scope({ screw_ie8: compressor.option("screw_ie8") });
ast.mangle_names();
var fun;
try {
ast.walk(new TreeWalker(function(node){
if (node instanceof AST_Lambda) {
fun = node;
throw ast;
}
}));
} catch(ex) {
if (ex !== ast) throw ex;
};
if (!fun) return self;
var args = fun.argnames.map(function(arg, i){
return make_node(AST_String, self.args[i], {
value: arg.print_to_string()
}); });
var code = args.pop();
var ast = parse("(function(" + args.join() + "){" + code + "})");
ast.figure_out_scope({ screw_ie8: compressor.option("screw_ie8") });
var scope = compressor.find_parent(AST_Scope);
ast.globals.each(function(g) {
var def = scope.find_variable(g.name);
if (def && !(def.scope instanceof AST_Toplevel)) throw self;
}); });
var code = OutputStream(); var fun = ast.body[0].body;
AST_BlockStatement.prototype._codegen.call(fun, fun, code); fun.parent_scope = scope;
code = code.toString().replace(/^\{|\}$/g, ""); return fun;
args.push(make_node(AST_String, self.args[self.args.length - 1], {
value: code
}));
self.args = args;
return self;
} catch(ex) { } catch(ex) {
if (ex instanceof JS_Parse_Error) { if (ex instanceof JS_Parse_Error) {
compressor.warn("Error parsing code passed to new Function [{file}:{line},{col}]", self.args[self.args.length - 1].start); compressor.warn("Error parsing code passed to new Function [{file}:{line},{col}]", self.args[self.args.length - 1].start);
compressor.warn(ex.toString()); compressor.warn(ex.toString());
} else { } else if (ex !== self) {
console.log(ex);
throw ex; throw ex;
} }
} }
}
break; break;
} }
} }

View File

@ -277,13 +277,6 @@ function makePredicate(words) {
return new Function("str", f); return new Function("str", f);
}; };
function all(array, predicate) {
for (var i = array.length; --i >= 0;)
if (!predicate(array[i]))
return false;
return true;
};
function Dictionary() { function Dictionary() {
this._values = Object.create(null); this._values = Object.create(null);
this._size = 0; this._size = 0;

View File

@ -6,3 +6,55 @@ non_ascii_function_identifier_name: {
} }
expect_exact: "function fooλ(δλ){}function λ(δλ){}(function λ(δλ){})();" expect_exact: "function fooλ(δλ){}function λ(δλ){}(function λ(δλ){})();"
} }
unsafe_eval: {
options = {
unsafe: true,
}
input: {
var a = Function("x", "return x");
function e() {
var a;
return Function("return a");
}
function f() {
return Function("return a");
}
function g(a) {
return Function("b", "return [ a, b ]");
}
function h(b) {
return Function("b", "c", "return [ a, b, c ]");
}
}
expect: {
var a = function(x) {
return x;
};
function e() {
var a;
return Function("return a");
}
function f() {
return function() {
return a;
};
}
function g(a) {
return Function("b", "return [ a, b ]");
}
function h(b) {
return function(b, c) {
return [ a, b, c ];
};
}
}
}