From: Alex Lam S.L Date: Sat, 3 Mar 2018 20:50:00 +0000 (+0800) Subject: improve `test/run-test.js` performance (#2971) X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=798fc21530cf15049767af1e38aeae04f81ec5e2;p=UglifyJS.git improve `test/run-test.js` performance (#2971) - allow reuse of contextified sandbox - minimise bottleneck from `vm.createContext()` --- diff --git a/test/run-tests.js b/test/run-tests.js index d3238370..dcc7cc1e 100755 --- a/test/run-tests.js +++ b/test/run-tests.js @@ -182,7 +182,7 @@ function run_compress_tests() { } if (test.expect_stdout && (!test.node_version || semver.satisfies(process.version, test.node_version))) { - var stdout = sandbox.run_code(input_code); + var stdout = sandbox.run_code(input_code, true); if (test.expect_stdout === true) { test.expect_stdout = stdout; } @@ -196,7 +196,7 @@ function run_compress_tests() { }); return false; } - stdout = sandbox.run_code(output); + stdout = sandbox.run_code(output, true); if (!sandbox.same_stdout(test.expect_stdout, stdout)) { log("!!! failed\n---INPUT---\n{input}\n---EXPECTED {expected_type}---\n{expected}\n---ACTUAL {actual_type}---\n{actual}\n\n", { input: input_formatted, @@ -378,7 +378,7 @@ function reminify(orig_options, input_code, input_formatted, expect_stdout) { }); return false; } else { - var stdout = sandbox.run_code(result.code); + var stdout = sandbox.run_code(result.code, true); if (typeof expect_stdout != "string" && typeof stdout != "string" && expect_stdout.name == stdout.name) { stdout = expect_stdout; } diff --git a/test/sandbox.js b/test/sandbox.js index bef63df0..13cfe088 100644 --- a/test/sandbox.js +++ b/test/sandbox.js @@ -1,6 +1,27 @@ var semver = require("semver"); var vm = require("vm"); +function createContext() { + var context = Object.create(null); + Object.defineProperty(context, "console", { + value: function() { + var con = Object.create(null); + Object.defineProperty(con, "log", { + value: function(msg) { + if (arguments.length == 1 && typeof msg == "string") { + return console.log("%s", msg); + } + return console.log.apply(console, [].map.call(arguments, function(arg) { + return safe_log(arg, 3); + })); + } + }); + return con; + }() + }); + return vm.createContext(context); +} + function safe_log(arg, level) { if (arg) switch (typeof arg) { case "function": @@ -9,7 +30,8 @@ function safe_log(arg, level) { if (/Error$/.test(arg.name)) return arg.toString(); arg.constructor.toString(); if (level--) for (var key in arg) { - if (!Object.getOwnPropertyDescriptor(arg, key).get) { + var desc = Object.getOwnPropertyDescriptor(arg, key); + if (!desc || !desc.get) { arg[key] = safe_log(arg[key], level); } } @@ -21,6 +43,7 @@ function strip_func_ids(text) { return text.toString().replace(/F[0-9]{6}N/g, "N>"); } +var context; var FUNC_TOSTRING = [ "[ Array, Boolean, Error, Function, Number, Object, RegExp, String].forEach(function(f) {", " f.toString = Function.prototype.toString;", @@ -43,35 +66,30 @@ var FUNC_TOSTRING = [ " };", "}();", ]).join("\n"); -exports.run_code = function(code) { +exports.run_code = function(code, reuse) { var stdout = ""; var original_write = process.stdout.write; process.stdout.write = function(chunk) { stdout += chunk; }; try { - vm.runInNewContext([ + if (!reuse || !context) context = createContext(); + vm.runInContext([ FUNC_TOSTRING, "!function() {", code, "}();", - ].join("\n"), { - console: { - log: function(msg) { - if (arguments.length == 1 && typeof msg == "string") { - return console.log("%s", msg); - } - return console.log.apply(console, [].map.call(arguments, function(arg) { - return safe_log(arg, 3); - })); - } - } - }, { timeout: 5000 }); + ].join("\n"), context, { timeout: 5000 }); return stdout; } catch (ex) { return ex; } finally { process.stdout.write = original_write; + if (!reuse || /prototype/.test(code)) { + context = null; + } else for (var key in context) { + delete context[key]; + } } }; exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expected, actual) {