mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-01 07:33:12 +08:00
process.emitWarning checks its arguments in Node's order: an options object replaces type with `options.type || "Warning"` and code with `options.code`, type and code are checked before the warning and for Error warnings too, an empty type names the warning "Warning", and a DeprecationWarning type returns at once under process.noDeprecation. Wrong kinds throw ERR_INVALID_ARG_TYPE with Node's "Received ..." tail. An instance of an Error subclass is an Error warning, and a typed record in the options position is read as the options object. The default report reads the warning's message, code and detail as property reads do, so an Error subclass's own code is reported. A deprecation thrown under process.throwDeprecation is thrown as the Error it encodes, so the uncaught report names it. process.kill throws ERR_UNKNOWN_SIGNAL for an unknown signal name, as subprocess.kill does, and a failed kill(2) is Node's errnoException with errno, code and syscall. A failed process.chdir names the working directory as path and the target as dest. os.userInfo() reads the passwd entry of the effective uid: uid and gid are the entry's pw_uid and pw_gid (-1 on Windows), not the process ids. os.homedir() answers $HOME whenever it is set, an empty value included. The minimal test/common for Node's test/parallel files gains isAIX, isIBMi and isSunOS.
139 lines
4.0 KiB
JavaScript
139 lines
4.0 KiB
JavaScript
"use strict";
|
|
// A minimal test/common for building Node's test/parallel files with scriptc:
|
|
// the helpers those files use, with the semantics of Node's
|
|
// test/common/index.js. Add a helper here, with Node's semantics, when a
|
|
// lane's files need it.
|
|
const assert = require("assert");
|
|
const os = require("os");
|
|
const { inspect } = require("util");
|
|
|
|
const hasIntl = true;
|
|
const isDebug = false;
|
|
const isWindows = process.platform === "win32";
|
|
const isAIX = os.type() === "AIX";
|
|
const isIBMi = os.type() === "OS400";
|
|
const isSunOS = process.platform === "sunos";
|
|
const mustCallChecks = [];
|
|
|
|
function runCallChecks(exitCode) {
|
|
if (exitCode !== 0) return;
|
|
const failed = mustCallChecks.filter((context) => {
|
|
if ("minimum" in context) return context.actual < context.minimum;
|
|
return context.actual !== context.exact;
|
|
});
|
|
for (const context of failed) {
|
|
console.log(
|
|
"Mismatched %s function calls. Expected %s, actual %d.",
|
|
context.name,
|
|
String(context.exact ?? context.minimum),
|
|
context.actual,
|
|
);
|
|
}
|
|
if (failed.length) process.exit(1);
|
|
}
|
|
|
|
function noop() {}
|
|
|
|
function mustCallInner(fn, criteria, field) {
|
|
if (typeof fn === "number") {
|
|
criteria = fn;
|
|
fn = noop;
|
|
} else if (fn === undefined) {
|
|
fn = noop;
|
|
}
|
|
if (criteria === undefined) criteria = 1;
|
|
const context = { actual: 0, name: fn.name || "<anonymous>" };
|
|
context[field] = criteria;
|
|
if (mustCallChecks.length === 0) process.on("exit", runCallChecks);
|
|
mustCallChecks.push(context);
|
|
return function (...args) {
|
|
context.actual++;
|
|
return fn.apply(this, args);
|
|
};
|
|
}
|
|
|
|
function mustCall(fn, exact) {
|
|
return mustCallInner(fn, exact, "exact");
|
|
}
|
|
|
|
function mustCallAtLeast(fn, minimum) {
|
|
return mustCallInner(fn, minimum, "minimum");
|
|
}
|
|
|
|
function mustNotCall(msg) {
|
|
return function mustNotCall() {
|
|
assert.fail(msg || "function should not have been called");
|
|
};
|
|
}
|
|
|
|
function skip(msg) {
|
|
console.log(`1..0 # Skipped: ${msg}`);
|
|
process.exit(0);
|
|
}
|
|
|
|
function expectWarning(name, expected, code) {
|
|
if (typeof expected === "string") expected = [[expected, code]];
|
|
else if (expected.length !== 0 && !Array.isArray(expected[0]))
|
|
expected = [[expected[0], expected[1]]];
|
|
const check = mustCall((warning) => {
|
|
const [message, warningCode] = expected.shift();
|
|
assert.strictEqual(warning.name, name);
|
|
if (typeof message === "string") assert.strictEqual(warning.message, message);
|
|
else assert.match(warning.message, message);
|
|
assert.strictEqual(warning.code, warningCode);
|
|
}, expected.length);
|
|
process.on("warning", (warning) => {
|
|
if (warning.name !== name)
|
|
throw new TypeError(`"${warning.name}" was triggered without being expected.`);
|
|
check(warning);
|
|
});
|
|
}
|
|
|
|
function invalidArgTypeHelper(input) {
|
|
if (input == null) return ` Received ${input}`;
|
|
if (typeof input === "function") return ` Received function ${input.name}`;
|
|
if (typeof input === "object") {
|
|
const name = input.constructor?.name;
|
|
if (typeof name === "string" && name !== "") return ` Received an instance of ${name}`;
|
|
return ` Received ${inspect(input, { depth: -1 })}`;
|
|
}
|
|
let inspected = inspect(input, { colors: false });
|
|
if (inspected.length > 28) inspected = `${inspected.slice(inspected, 0, 25)}...`;
|
|
return ` Received type ${typeof input} (${inspected})`;
|
|
}
|
|
|
|
function spawnPromisified(...args) {
|
|
const { spawn } = require("child_process");
|
|
let stderr = "";
|
|
let stdout = "";
|
|
const child = spawn(...args);
|
|
child.stderr.setEncoding("utf8");
|
|
child.stderr.on("data", (data) => {
|
|
stderr += data;
|
|
});
|
|
child.stdout.setEncoding("utf8");
|
|
child.stdout.on("data", (data) => {
|
|
stdout += data;
|
|
});
|
|
return new Promise((resolve, reject) => {
|
|
child.on("close", (code, signal) => resolve({ code, signal, stderr, stdout }));
|
|
child.on("error", (code, signal) => reject({ code, signal, stderr, stdout }));
|
|
});
|
|
}
|
|
|
|
module.exports = {
|
|
hasIntl,
|
|
isAIX,
|
|
isDebug,
|
|
isIBMi,
|
|
isSunOS,
|
|
isWindows,
|
|
mustCall,
|
|
mustCallAtLeast,
|
|
mustNotCall,
|
|
skip,
|
|
expectWarning,
|
|
invalidArgTypeHelper,
|
|
spawnPromisified,
|
|
};
|