From 77a2f0f77eafaa18cbe9587d040b82c3d846481a Mon Sep 17 00:00:00 2001 From: alexlamsl Date: Sun, 10 Jan 2021 00:05:15 +0800 Subject: [PATCH] support `async` test cases properly --- test/compress/awaits.js | 30 +++++++---- test/sandbox.js | 112 +++++++++++++++++++++++++--------------- 2 files changed, 90 insertions(+), 52 deletions(-) diff --git a/test/compress/awaits.js b/test/compress/awaits.js index 8caa60c066e..c6e5313ec0e 100644 --- a/test/compress/awaits.js +++ b/test/compress/awaits.js @@ -612,22 +612,32 @@ issue_4340: { call_expression: { input: { console.log(typeof async function(log) { - (await log)("FAIL"); + (await log)("foo"); }(console.log).then); + console.log("bar"); } - expect_exact: 'console.log(typeof async function(log){(await log)("FAIL")}(console.log).then);' - expect_stdout: "function" + expect_exact: 'console.log(typeof async function(log){(await log)("foo")}(console.log).then);console.log("bar");' + expect_stdout: [ + "function", + "bar", + "foo", + ] node_version: ">=8" } property_access_expression: { input: { console.log(typeof async function(con) { - (await con).log("FAIL"); + (await con).log("foo"); }(console).then); + console.log("bar"); } - expect_exact: 'console.log(typeof async function(con){(await con).log("FAIL")}(console).then);' - expect_stdout: "function" + expect_exact: 'console.log(typeof async function(con){(await con).log("foo")}(console).then);console.log("bar");' + expect_stdout: [ + "function", + "bar", + "foo", + ] node_version: ">=8" } @@ -685,20 +695,18 @@ reduce_iife_3: { input: { var a = "foo"; (async function() { - console.log(a); - console.log(await a); + console.log(a, await a, a, await a); })(); a = "bar"; } expect: { var a = "foo"; (async function() { - console.log(a); - console.log(await a); + console.log(a, await a, a, await a); })(); a = "bar"; } - expect_stdout: "foo" + expect_stdout: "foo foo bar bar" node_version: ">=8" } diff --git a/test/sandbox.js b/test/sandbox.js index 78a3435e78b..a464c0f1685 100644 --- a/test/sandbox.js +++ b/test/sandbox.js @@ -1,39 +1,42 @@ +var execSync = require("child_process").execSync; var semver = require("semver"); var vm = require("vm"); -var setupContext = new vm.Script([ - "[ 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";', -].concat(Object.getOwnPropertyDescriptor(Function.prototype, "name").configurable ? [ - ' Object.defineProperty(this, "name", {', - " get: function() {", - " return n;", - " }", - " });", -] : [], [ - " }", - ' return "function(){}";', - " };", - "}();", - "this;", -]).join("\n")); - -function createContext() { - var ctx = vm.createContext(Object.defineProperties({}, { - console: { value: { log: log } }, +function setupContext(global) { + [ Array, Boolean, Error, Function, Number, Object, RegExp, String ].forEach(function(f) { + f.toString = Function.prototype.toString; + }); + Function.prototype.toString = function() { + var configurable = Object.getOwnPropertyDescriptor(Function.prototype, "name").configurable; + var id = 100000; + return function() { + var n = this.name; + if (!/^F[0-9]{6}N$/.test(n)) { + n = "F" + ++id + "N"; + if (configurable) Object.defineProperty(this, "name", { + get: function() { + return n; + } + }); + } + return "function(){}"; + }; + }(); + if (typeof process != "undefined") process.on("unhandledRejection", function() {}); + Object.defineProperties(global, { global: { get: self }, self: { get: self }, window: { get: self }, - })); - var global = setupContext.runInContext(ctx); - return ctx; + }); + var log = console.log; + global.console = { + log: function(msg) { + if (arguments.length == 1 && typeof msg == "string") return log("%s", msg); + return log.apply(null, [].map.call(arguments, function(arg) { + return safe_log(arg, 3); + })); + }, + }; function self() { return this; @@ -55,16 +58,16 @@ function createContext() { } return arg; } +} - function log(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); - })); - } +function wrap_code(code, toplevel) { + if (toplevel) return "(" + setupContext + ")(this);(function(){" + code + "})();"; + return code.replace(/^(?:(["'])[^"']*\1;)?/, function(directive) { + return directive + "(" + setupContext + ")(this);"; + }); } -function run_code(code, toplevel, timeout) { +function run_code_vm(code, toplevel, timeout) { timeout = timeout || 5000; var stdout = ""; var original_write = process.stdout.write; @@ -72,7 +75,7 @@ function run_code(code, toplevel, timeout) { stdout += chunk; }; try { - vm.runInContext(toplevel ? "(function(){" + code + "})()" : code, createContext(), { timeout: timeout }); + vm.runInContext(wrap_code(code, toplevel), vm.createContext({ console: console }), { timeout: timeout }); return stdout; } catch (ex) { return ex; @@ -81,15 +84,42 @@ function run_code(code, toplevel, timeout) { } } +function run_code_exec(code, toplevel, timeout) { + try { + return execSync('"' + process.argv[0] + '"', { + encoding: "utf8", + input: wrap_code(code, toplevel), + stdio: "pipe", + timeout: timeout || 5000, + }); + } catch (ex) { + var msg = ex.message.replace(/\r\n/g, "\n"); + var match = /\n([^:\s]*Error)(?:: ([\s\S]+?))?\n( at [\s\S]+)\n$/.exec(msg); + if (match) { + ex = new global[match[1]](match[2]); + ex.stack = ex.stack.slice(0, ex.stack.indexOf(" at ")) + match[3]; + } else if (/ETIMEDOUT/.test(msg)) { + ex = new Error("Script execution timed out."); + } else if (match = /\n *\^\n(\n.+|[^{[].*)\n/.exec(msg)) try { + ex = vm.runInNewContext("(" + match[1].trim() + ")"); + } catch (e) { + ex = match[1]; + } + return ex; + } +} + exports.run_code = semver.satisfies(process.version, "0.8") ? function(code, toplevel, timeout) { - var stdout = run_code(code, toplevel, timeout); + var stdout = run_code_vm(code, toplevel, timeout); if (typeof stdout != "string" || !/arguments/.test(code)) return stdout; do { var prev = stdout; - stdout = run_code(code, toplevel, timeout); + stdout = run_code_vm(code, toplevel, timeout); } while (prev !== stdout); return stdout; -} : run_code; +} : semver.satisfies(process.version, "<8") ? run_code_vm : function(code, toplevel, timeout) { + return (/\b(async|setInterval|setTimeout)\b/.test(code) ? run_code_exec : run_code_vm)(code, toplevel, timeout); +}; function strip_func_ids(text) { return ("" + text).replace(/F[0-9]{6}N/g, "N>");