}
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;
}
});
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,
});
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;
}
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":
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);
}
}
return text.toString().replace(/F[0-9]{6}N/g, "<F<>N>");
}
+var context;
var FUNC_TOSTRING = [
"[ Array, Boolean, Error, Function, Number, Object, RegExp, String].forEach(function(f) {",
" f.toString = Function.prototype.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) {