improve test/run-test.js performance (#2971)
- allow reuse of contextified sandbox - minimise bottleneck from `vm.createContext()`
This commit is contained in:
@@ -182,7 +182,7 @@ function run_compress_tests() {
|
|||||||
}
|
}
|
||||||
if (test.expect_stdout
|
if (test.expect_stdout
|
||||||
&& (!test.node_version || semver.satisfies(process.version, test.node_version))) {
|
&& (!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) {
|
if (test.expect_stdout === true) {
|
||||||
test.expect_stdout = stdout;
|
test.expect_stdout = stdout;
|
||||||
}
|
}
|
||||||
@@ -196,7 +196,7 @@ function run_compress_tests() {
|
|||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
stdout = sandbox.run_code(output);
|
stdout = sandbox.run_code(output, true);
|
||||||
if (!sandbox.same_stdout(test.expect_stdout, stdout)) {
|
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", {
|
log("!!! failed\n---INPUT---\n{input}\n---EXPECTED {expected_type}---\n{expected}\n---ACTUAL {actual_type}---\n{actual}\n\n", {
|
||||||
input: input_formatted,
|
input: input_formatted,
|
||||||
@@ -378,7 +378,7 @@ function reminify(orig_options, input_code, input_formatted, expect_stdout) {
|
|||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} 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) {
|
if (typeof expect_stdout != "string" && typeof stdout != "string" && expect_stdout.name == stdout.name) {
|
||||||
stdout = expect_stdout;
|
stdout = expect_stdout;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,27 @@
|
|||||||
var semver = require("semver");
|
var semver = require("semver");
|
||||||
var vm = require("vm");
|
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) {
|
function safe_log(arg, level) {
|
||||||
if (arg) switch (typeof arg) {
|
if (arg) switch (typeof arg) {
|
||||||
case "function":
|
case "function":
|
||||||
@@ -9,7 +30,8 @@ function safe_log(arg, level) {
|
|||||||
if (/Error$/.test(arg.name)) return arg.toString();
|
if (/Error$/.test(arg.name)) return arg.toString();
|
||||||
arg.constructor.toString();
|
arg.constructor.toString();
|
||||||
if (level--) for (var key in arg) {
|
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);
|
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, "<F<>N>");
|
return text.toString().replace(/F[0-9]{6}N/g, "<F<>N>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var context;
|
||||||
var FUNC_TOSTRING = [
|
var FUNC_TOSTRING = [
|
||||||
"[ Array, Boolean, Error, Function, Number, Object, RegExp, String].forEach(function(f) {",
|
"[ Array, Boolean, Error, Function, Number, Object, RegExp, String].forEach(function(f) {",
|
||||||
" f.toString = Function.prototype.toString;",
|
" f.toString = Function.prototype.toString;",
|
||||||
@@ -43,35 +66,30 @@ var FUNC_TOSTRING = [
|
|||||||
" };",
|
" };",
|
||||||
"}();",
|
"}();",
|
||||||
]).join("\n");
|
]).join("\n");
|
||||||
exports.run_code = function(code) {
|
exports.run_code = function(code, reuse) {
|
||||||
var stdout = "";
|
var stdout = "";
|
||||||
var original_write = process.stdout.write;
|
var original_write = process.stdout.write;
|
||||||
process.stdout.write = function(chunk) {
|
process.stdout.write = function(chunk) {
|
||||||
stdout += chunk;
|
stdout += chunk;
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
vm.runInNewContext([
|
if (!reuse || !context) context = createContext();
|
||||||
|
vm.runInContext([
|
||||||
FUNC_TOSTRING,
|
FUNC_TOSTRING,
|
||||||
"!function() {",
|
"!function() {",
|
||||||
code,
|
code,
|
||||||
"}();",
|
"}();",
|
||||||
].join("\n"), {
|
].join("\n"), context, { timeout: 5000 });
|
||||||
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 });
|
|
||||||
return stdout;
|
return stdout;
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
return ex;
|
return ex;
|
||||||
} finally {
|
} finally {
|
||||||
process.stdout.write = original_write;
|
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) {
|
exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expected, actual) {
|
||||||
|
|||||||
Reference in New Issue
Block a user