// https://github.com/terser/terser/blob/v5.37.0/test/sandbox.js import vm from 'vm'; // import { Console } from "console"; // global.console = new Console({ // stdout: process.stdout, // stderr: process.stderr, // colorMode: false // }); function safe_log(arg, level) { if (arg) { switch (typeof arg) { case 'function': return arg.toString(); case 'object': if (/Error$/.test(arg.name)) return arg.toString(); arg.constructor.toString(); if (level--) { for (var key in arg) { if (!Object.getOwnPropertyDescriptor(arg, key).get) { arg[key] = safe_log(arg[key], level); } } } } } return arg; } function strip_func_ids(text) { return text.toString().replace(/F[0-9]{6}N/g, 'N>'); } var FUNC_TOSTRING = ` [ Array, Boolean, Error, Function, Number, Object, RegExp, String].forEach(function(f) { f.toString = Function.prototype.toString; }); Function.prototype.toString = function() { var id = 100000; return function() { var n = this.name; if (!/^F[0-9]{6}N$/.test(n)) { n = "F" + ++id + "N"; ${ Object.getOwnPropertyDescriptor(Function.prototype, 'name').configurable ? 'Object.defineProperty(this, "name", { get: () => n });' : '' } } return "function " + n + "() {...}"; } }(); `; export function run_code(code, prepend_code = '') { var stdout = ''; var original_write = process.stdout.write; process.stdout.write = function(chunk) { stdout += chunk; }; try { const global = { console: { log: function(msg) { if (arguments.length == 1 && typeof msg == 'string') { return console.log(msg); } return console.log.apply( console, [].map.call(arguments, function(arg) { return safe_log(arg, 3); }), ); }, }, id: x => x, leak: () => {}, pass: () => { global.console.log('PASS'); }, fail: () => { global.console.log('FAIL'); }, }; global.global = global; vm.runInNewContext( [ FUNC_TOSTRING, '!function() {', prepend_code + code, '}();', ].join('\n'), global, ); return stdout; } catch (ex) { return ex; } finally { process.stdout.write = original_write; } } export function same_stdout(expected, actual) { return typeof expected == typeof actual && strip_func_ids(expected) == strip_func_ids(actual); }