@cloudflare/vitest-pool-workers
Version:
Workers Vitest integration for writing Vitest unit and integration tests that run inside the Workers runtime
843 lines (834 loc) • 27 kB
JavaScript
import assert from "node:assert";
import * as vm from "node:vm";
import defines from "__VITEST_POOL_WORKERS_DEFINES";
import { createWorkerEntrypointWrapper, maybeHandleRunRequest, registerHandlerAndGlobalWaitUntil, runInRunnerObject } from "cloudflare:test-internal";
import { DurableObject } from "cloudflare:workers";
import { Buffer } from "node:buffer";
export * from "__VITEST_POOL_WORKERS_USER_OBJECT"
//#region ../../node_modules/.pnpm/devalue@5.6.3/node_modules/devalue/src/utils.js
var DevalueError = class extends Error {
/**
* @param {string} message
* @param {string[]} keys
* @param {any} [value] - The value that failed to be serialized
* @param {any} [root] - The root value being serialized
*/
constructor(message, keys, value, root) {
super(message);
this.name = "DevalueError";
this.path = keys.join("");
this.value = value;
this.root = root;
}
};
/** @param {any} thing */
function is_primitive(thing) {
return Object(thing) !== thing;
}
const object_proto_names = /* @__PURE__ */ Object.getOwnPropertyNames(Object.prototype).sort().join("\0");
/** @param {any} thing */
function is_plain_object(thing) {
const proto = Object.getPrototypeOf(thing);
return proto === Object.prototype || proto === null || Object.getPrototypeOf(proto) === null || Object.getOwnPropertyNames(proto).sort().join("\0") === object_proto_names;
}
/** @param {any} thing */
function get_type(thing) {
return Object.prototype.toString.call(thing).slice(8, -1);
}
/** @param {string} char */
function get_escaped_char(char) {
switch (char) {
case "\"": return "\\\"";
case "<": return "\\u003C";
case "\\": return "\\\\";
case "\n": return "\\n";
case "\r": return "\\r";
case " ": return "\\t";
case "\b": return "\\b";
case "\f": return "\\f";
case "\u2028": return "\\u2028";
case "\u2029": return "\\u2029";
default: return char < " " ? `\\u${char.charCodeAt(0).toString(16).padStart(4, "0")}` : "";
}
}
/** @param {string} str */
function stringify_string(str) {
let result = "";
let last_pos = 0;
const len = str.length;
for (let i = 0; i < len; i += 1) {
const char = str[i];
const replacement = get_escaped_char(char);
if (replacement) {
result += str.slice(last_pos, i) + replacement;
last_pos = i + 1;
}
}
return `"${last_pos === 0 ? str : result + str.slice(last_pos)}"`;
}
/** @param {Record<string | symbol, any>} object */
function enumerable_symbols(object) {
return Object.getOwnPropertySymbols(object).filter((symbol) => Object.getOwnPropertyDescriptor(object, symbol).enumerable);
}
const is_identifier = /^[a-zA-Z_$][a-zA-Z_$0-9]*$/;
/** @param {string} key */
function stringify_key(key) {
return is_identifier.test(key) ? "." + key : "[" + JSON.stringify(key) + "]";
}
/** @param {string} s */
function is_valid_array_index(s) {
if (s.length === 0) return false;
if (s.length > 1 && s.charCodeAt(0) === 48) return false;
for (let i = 0; i < s.length; i++) {
const c = s.charCodeAt(i);
if (c < 48 || c > 57) return false;
}
const n = +s;
if (n >= 2 ** 32 - 1) return false;
if (n < 0) return false;
return true;
}
/**
* Finds the populated indices of an array.
* @param {unknown[]} array
*/
function valid_array_indices(array) {
const keys = Object.keys(array);
for (var i = keys.length - 1; i >= 0; i--) if (is_valid_array_index(keys[i])) break;
keys.length = i + 1;
return keys;
}
//#endregion
//#region ../../node_modules/.pnpm/devalue@5.6.3/node_modules/devalue/src/base64.js
/**
* Base64 Encodes an arraybuffer
* @param {ArrayBuffer} arraybuffer
* @returns {string}
*/
function encode64(arraybuffer) {
const dv = new DataView(arraybuffer);
let binaryString = "";
for (let i = 0; i < arraybuffer.byteLength; i++) binaryString += String.fromCharCode(dv.getUint8(i));
return binaryToAscii(binaryString);
}
/**
* Decodes a base64 string into an arraybuffer
* @param {string} string
* @returns {ArrayBuffer}
*/
function decode64(string) {
const binaryString = asciiToBinary(string);
const arraybuffer = new ArrayBuffer(binaryString.length);
const dv = new DataView(arraybuffer);
for (let i = 0; i < arraybuffer.byteLength; i++) dv.setUint8(i, binaryString.charCodeAt(i));
return arraybuffer;
}
const KEY_STRING = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/**
* Substitute for atob since it's deprecated in node.
* Does not do any input validation.
*
* @see https://github.com/jsdom/abab/blob/master/lib/atob.js
*
* @param {string} data
* @returns {string}
*/
function asciiToBinary(data) {
if (data.length % 4 === 0) data = data.replace(/==?$/, "");
let output = "";
let buffer = 0;
let accumulatedBits = 0;
for (let i = 0; i < data.length; i++) {
buffer <<= 6;
buffer |= KEY_STRING.indexOf(data[i]);
accumulatedBits += 6;
if (accumulatedBits === 24) {
output += String.fromCharCode((buffer & 16711680) >> 16);
output += String.fromCharCode((buffer & 65280) >> 8);
output += String.fromCharCode(buffer & 255);
buffer = accumulatedBits = 0;
}
}
if (accumulatedBits === 12) {
buffer >>= 4;
output += String.fromCharCode(buffer);
} else if (accumulatedBits === 18) {
buffer >>= 2;
output += String.fromCharCode((buffer & 65280) >> 8);
output += String.fromCharCode(buffer & 255);
}
return output;
}
/**
* Substitute for btoa since it's deprecated in node.
* Does not do any input validation.
*
* @see https://github.com/jsdom/abab/blob/master/lib/btoa.js
*
* @param {string} str
* @returns {string}
*/
function binaryToAscii(str) {
let out = "";
for (let i = 0; i < str.length; i += 3) {
/** @type {[number, number, number, number]} */
const groupsOfSix = [
void 0,
void 0,
void 0,
void 0
];
groupsOfSix[0] = str.charCodeAt(i) >> 2;
groupsOfSix[1] = (str.charCodeAt(i) & 3) << 4;
if (str.length > i + 1) {
groupsOfSix[1] |= str.charCodeAt(i + 1) >> 4;
groupsOfSix[2] = (str.charCodeAt(i + 1) & 15) << 2;
}
if (str.length > i + 2) {
groupsOfSix[2] |= str.charCodeAt(i + 2) >> 6;
groupsOfSix[3] = str.charCodeAt(i + 2) & 63;
}
for (let j = 0; j < groupsOfSix.length; j++) if (typeof groupsOfSix[j] === "undefined") out += "=";
else out += KEY_STRING[groupsOfSix[j]];
}
return out;
}
//#endregion
//#region ../../node_modules/.pnpm/devalue@5.6.3/node_modules/devalue/src/constants.js
const UNDEFINED = -1;
const HOLE = -2;
const NAN = -3;
const POSITIVE_INFINITY = -4;
const NEGATIVE_INFINITY = -5;
const NEGATIVE_ZERO = -6;
const SPARSE = -7;
//#endregion
//#region ../../node_modules/.pnpm/devalue@5.6.3/node_modules/devalue/src/parse.js
/**
* Revive a value serialized with `devalue.stringify`
* @param {string} serialized
* @param {Record<string, (value: any) => any>} [revivers]
*/
function parse(serialized, revivers) {
return unflatten(JSON.parse(serialized), revivers);
}
/**
* Revive a value flattened with `devalue.stringify`
* @param {number | any[]} parsed
* @param {Record<string, (value: any) => any>} [revivers]
*/
function unflatten(parsed, revivers) {
if (typeof parsed === "number") return hydrate(parsed, true);
if (!Array.isArray(parsed) || parsed.length === 0) throw new Error("Invalid input");
const values = parsed;
const hydrated = Array(values.length);
/**
* A set of values currently being hydrated with custom revivers,
* used to detect invalid cyclical dependencies
* @type {Set<number> | null}
*/
let hydrating = null;
/**
* @param {number} index
* @returns {any}
*/
function hydrate(index, standalone = false) {
if (index === UNDEFINED) return void 0;
if (index === NAN) return NaN;
if (index === POSITIVE_INFINITY) return Infinity;
if (index === NEGATIVE_INFINITY) return -Infinity;
if (index === NEGATIVE_ZERO) return -0;
if (standalone || typeof index !== "number") throw new Error(`Invalid input`);
if (index in hydrated) return hydrated[index];
const value = values[index];
if (!value || typeof value !== "object") hydrated[index] = value;
else if (Array.isArray(value)) if (typeof value[0] === "string") {
const type = value[0];
const reviver = revivers && Object.hasOwn(revivers, type) ? revivers[type] : void 0;
if (reviver) {
let i = value[1];
if (typeof i !== "number") i = values.push(value[1]) - 1;
hydrating ??= /* @__PURE__ */ new Set();
if (hydrating.has(i)) throw new Error("Invalid circular reference");
hydrating.add(i);
hydrated[index] = reviver(hydrate(i));
hydrating.delete(i);
return hydrated[index];
}
switch (type) {
case "Date":
hydrated[index] = new Date(value[1]);
break;
case "Set":
const set = /* @__PURE__ */ new Set();
hydrated[index] = set;
for (let i = 1; i < value.length; i += 1) set.add(hydrate(value[i]));
break;
case "Map":
const map = /* @__PURE__ */ new Map();
hydrated[index] = map;
for (let i = 1; i < value.length; i += 2) map.set(hydrate(value[i]), hydrate(value[i + 1]));
break;
case "RegExp":
hydrated[index] = new RegExp(value[1], value[2]);
break;
case "Object":
hydrated[index] = Object(value[1]);
break;
case "BigInt":
hydrated[index] = BigInt(value[1]);
break;
case "null":
const obj = Object.create(null);
hydrated[index] = obj;
for (let i = 1; i < value.length; i += 2) obj[value[i]] = hydrate(value[i + 1]);
break;
case "Int8Array":
case "Uint8Array":
case "Uint8ClampedArray":
case "Int16Array":
case "Uint16Array":
case "Int32Array":
case "Uint32Array":
case "Float32Array":
case "Float64Array":
case "BigInt64Array":
case "BigUint64Array": {
if (values[value[1]][0] !== "ArrayBuffer") throw new Error("Invalid data");
const TypedArrayConstructor = globalThis[type];
const typedArray = new TypedArrayConstructor(hydrate(value[1]));
hydrated[index] = value[2] !== void 0 ? typedArray.subarray(value[2], value[3]) : typedArray;
break;
}
case "ArrayBuffer": {
const base64 = value[1];
if (typeof base64 !== "string") throw new Error("Invalid ArrayBuffer encoding");
hydrated[index] = decode64(base64);
break;
}
case "Temporal.Duration":
case "Temporal.Instant":
case "Temporal.PlainDate":
case "Temporal.PlainTime":
case "Temporal.PlainDateTime":
case "Temporal.PlainMonthDay":
case "Temporal.PlainYearMonth":
case "Temporal.ZonedDateTime": {
const temporalName = type.slice(9);
hydrated[index] = Temporal[temporalName].from(value[1]);
break;
}
case "URL":
hydrated[index] = new URL(value[1]);
break;
case "URLSearchParams":
hydrated[index] = new URLSearchParams(value[1]);
break;
default: throw new Error(`Unknown type ${type}`);
}
} else if (value[0] === SPARSE) {
const len = value[1];
const array = new Array(len);
hydrated[index] = array;
for (let i = 2; i < value.length; i += 2) {
const idx = value[i];
array[idx] = hydrate(value[i + 1]);
}
} else {
const array = new Array(value.length);
hydrated[index] = array;
for (let i = 0; i < value.length; i += 1) {
const n = value[i];
if (n === HOLE) continue;
array[i] = hydrate(n);
}
}
else {
/** @type {Record<string, any>} */
const object = {};
hydrated[index] = object;
for (const key of Object.keys(value)) {
if (key === "__proto__") throw new Error("Cannot parse an object with a `__proto__` property");
const n = value[key];
object[key] = hydrate(n);
}
}
return hydrated[index];
}
return hydrate(0);
}
//#endregion
//#region ../../node_modules/.pnpm/devalue@5.6.3/node_modules/devalue/src/stringify.js
/**
* Turn a value into a JSON string that can be parsed with `devalue.parse`
* @param {any} value
* @param {Record<string, (value: any) => any>} [reducers]
*/
function stringify(value, reducers) {
/** @type {any[]} */
const stringified = [];
/** @type {Map<any, number>} */
const indexes = /* @__PURE__ */ new Map();
/** @type {Array<{ key: string, fn: (value: any) => any }>} */
const custom = [];
if (reducers) for (const key of Object.getOwnPropertyNames(reducers)) custom.push({
key,
fn: reducers[key]
});
/** @type {string[]} */
const keys = [];
let p = 0;
/** @param {any} thing */
function flatten(thing) {
if (thing === void 0) return UNDEFINED;
if (Number.isNaN(thing)) return NAN;
if (thing === Infinity) return POSITIVE_INFINITY;
if (thing === -Infinity) return NEGATIVE_INFINITY;
if (thing === 0 && 1 / thing < 0) return NEGATIVE_ZERO;
if (indexes.has(thing)) return indexes.get(thing);
const index$1 = p++;
indexes.set(thing, index$1);
for (const { key, fn } of custom) {
const value$1 = fn(thing);
if (value$1) {
stringified[index$1] = `["${key}",${flatten(value$1)}]`;
return index$1;
}
}
if (typeof thing === "function") throw new DevalueError(`Cannot stringify a function`, keys, thing, value);
let str = "";
if (is_primitive(thing)) str = stringify_primitive(thing);
else {
const type = get_type(thing);
switch (type) {
case "Number":
case "String":
case "Boolean":
str = `["Object",${stringify_primitive(thing)}]`;
break;
case "BigInt":
str = `["BigInt",${thing}]`;
break;
case "Date":
str = `["Date","${!isNaN(thing.getDate()) ? thing.toISOString() : ""}"]`;
break;
case "URL":
str = `["URL",${stringify_string(thing.toString())}]`;
break;
case "URLSearchParams":
str = `["URLSearchParams",${stringify_string(thing.toString())}]`;
break;
case "RegExp":
const { source, flags } = thing;
str = flags ? `["RegExp",${stringify_string(source)},"${flags}"]` : `["RegExp",${stringify_string(source)}]`;
break;
case "Array": {
let mostly_dense = false;
str = "[";
for (let i = 0; i < thing.length; i += 1) {
if (i > 0) str += ",";
if (Object.hasOwn(thing, i)) {
keys.push(`[${i}]`);
str += flatten(thing[i]);
keys.pop();
} else if (mostly_dense) str += HOLE;
else {
const populated_keys = valid_array_indices(thing);
const population = populated_keys.length;
const d = String(thing.length).length;
if ((thing.length - population) * 3 > 4 + d + population * (d + 1)) {
str = "[" + SPARSE + "," + thing.length;
for (let j = 0; j < populated_keys.length; j++) {
const key = populated_keys[j];
keys.push(`[${key}]`);
str += "," + key + "," + flatten(thing[key]);
keys.pop();
}
break;
} else {
mostly_dense = true;
str += HOLE;
}
}
}
str += "]";
break;
}
case "Set":
str = "[\"Set\"";
for (const value$1 of thing) str += `,${flatten(value$1)}`;
str += "]";
break;
case "Map":
str = "[\"Map\"";
for (const [key, value$1] of thing) {
keys.push(`.get(${is_primitive(key) ? stringify_primitive(key) : "..."})`);
str += `,${flatten(key)},${flatten(value$1)}`;
keys.pop();
}
str += "]";
break;
case "Int8Array":
case "Uint8Array":
case "Uint8ClampedArray":
case "Int16Array":
case "Uint16Array":
case "Int32Array":
case "Uint32Array":
case "Float32Array":
case "Float64Array":
case "BigInt64Array":
case "BigUint64Array": {
/** @type {import("./types.js").TypedArray} */
const typedArray = thing;
str = "[\"" + type + "\"," + flatten(typedArray.buffer);
const a = thing.byteOffset;
const b = a + thing.byteLength;
if (a > 0 || b !== typedArray.buffer.byteLength) {
const m = +/(\d+)/.exec(type)[1] / 8;
str += `,${a / m},${b / m}`;
}
str += "]";
break;
}
case "ArrayBuffer":
str = `["ArrayBuffer","${encode64(thing)}"]`;
break;
case "Temporal.Duration":
case "Temporal.Instant":
case "Temporal.PlainDate":
case "Temporal.PlainTime":
case "Temporal.PlainDateTime":
case "Temporal.PlainMonthDay":
case "Temporal.PlainYearMonth":
case "Temporal.ZonedDateTime":
str = `["${type}",${stringify_string(thing.toString())}]`;
break;
default:
if (!is_plain_object(thing)) throw new DevalueError(`Cannot stringify arbitrary non-POJOs`, keys, thing, value);
if (enumerable_symbols(thing).length > 0) throw new DevalueError(`Cannot stringify POJOs with symbolic keys`, keys, thing, value);
if (Object.getPrototypeOf(thing) === null) {
str = "[\"null\"";
for (const key of Object.keys(thing)) {
if (key === "__proto__") throw new DevalueError(`Cannot stringify objects with __proto__ keys`, keys, thing, value);
keys.push(stringify_key(key));
str += `,${stringify_string(key)},${flatten(thing[key])}`;
keys.pop();
}
str += "]";
} else {
str = "{";
let started = false;
for (const key of Object.keys(thing)) {
if (key === "__proto__") throw new DevalueError(`Cannot stringify objects with __proto__ keys`, keys, thing, value);
if (started) str += ",";
started = true;
keys.push(stringify_key(key));
str += `${stringify_string(key)}:${flatten(thing[key])}`;
keys.pop();
}
str += "}";
}
}
}
stringified[index$1] = str;
return index$1;
}
const index = flatten(value);
if (index < 0) return `${index}`;
return `[${stringified.join(",")}]`;
}
/**
* @param {any} thing
* @returns {string}
*/
function stringify_primitive(thing) {
const type = typeof thing;
if (type === "string") return stringify_string(thing);
if (thing instanceof String) return stringify_string(thing.toString());
if (thing === void 0) return UNDEFINED.toString();
if (thing === 0 && 1 / thing < 0) return NEGATIVE_ZERO.toString();
if (type === "bigint") return `["BigInt","${thing}"]`;
return String(thing);
}
//#endregion
//#region ../miniflare/src/workers/core/devalue.ts
const ALLOWED_ARRAY_BUFFER_VIEW_CONSTRUCTORS = [
DataView,
Int8Array,
Uint8Array,
Uint8ClampedArray,
Int16Array,
Uint16Array,
Int32Array,
Uint32Array,
Float32Array,
Float64Array,
BigInt64Array,
BigUint64Array
];
const ALLOWED_ERROR_CONSTRUCTORS = [
EvalError,
RangeError,
ReferenceError,
SyntaxError,
TypeError,
URIError,
Error
];
const structuredSerializableReducers = {
ArrayBuffer(value) {
if (value instanceof ArrayBuffer) return [Buffer.from(value).toString("base64")];
},
ArrayBufferView(value) {
if (ArrayBuffer.isView(value)) {
let name = value.constructor.name;
if (!ALLOWED_ARRAY_BUFFER_VIEW_CONSTRUCTORS.some((c) => c.name === name)) {
for (const ctor of ALLOWED_ARRAY_BUFFER_VIEW_CONSTRUCTORS) if (value instanceof ctor) {
name = ctor.name;
break;
}
}
let buf = value.buffer;
let off = value.byteOffset;
if (off !== 0 || buf.byteLength !== value.byteLength) {
buf = buf.slice(off, off + value.byteLength);
off = 0;
}
return [
name,
buf,
off,
value.byteLength
];
}
},
RegExp(value) {
if (value instanceof RegExp) {
const { source, flags } = value;
const encoded = Buffer.from(source).toString("base64");
return flags ? [
"RegExp",
encoded,
flags
] : ["RegExp", encoded];
}
},
Error(value) {
for (const ctor of ALLOWED_ERROR_CONSTRUCTORS) if (value instanceof ctor && value.name === ctor.name) return [
value.name,
value.message,
value.stack,
value.cause
];
if (value instanceof Error) return [
"Error",
value.message,
value.stack,
value.cause
];
}
};
const structuredSerializableRevivers = {
ArrayBuffer(value) {
assert(Array.isArray(value));
const [encoded] = value;
assert(typeof encoded === "string");
const view = Buffer.from(encoded, "base64");
return view.buffer.slice(view.byteOffset, view.byteOffset + view.byteLength);
},
ArrayBufferView(value) {
assert(Array.isArray(value));
const [name, buffer, byteOffset, byteLength] = value;
assert(typeof name === "string");
assert(buffer instanceof ArrayBuffer);
assert(typeof byteOffset === "number");
assert(typeof byteLength === "number");
const ctor = globalThis[name];
assert(ALLOWED_ARRAY_BUFFER_VIEW_CONSTRUCTORS.includes(ctor));
let length = byteLength;
if ("BYTES_PER_ELEMENT" in ctor) length /= ctor.BYTES_PER_ELEMENT;
return new ctor(buffer, byteOffset, length);
},
RegExp(value) {
assert(Array.isArray(value));
const [name, encoded, flags] = value;
assert(typeof name === "string");
assert(typeof encoded === "string");
const source = Buffer.from(encoded, "base64").toString("utf-8");
return new RegExp(source, flags);
},
Error(value) {
assert(Array.isArray(value));
const [name, message, stack, cause] = value;
assert(typeof name === "string");
assert(typeof message === "string");
assert(stack === void 0 || typeof stack === "string");
const ctor = globalThis[name];
assert(ALLOWED_ERROR_CONSTRUCTORS.includes(ctor));
const error = new ctor(message, { cause });
error.stack = stack;
return error;
}
};
//#endregion
//#region src/worker/index.ts
function structuredSerializableStringify(value) {
return stringify(value, structuredSerializableReducers);
}
function structuredSerializableParse(value) {
return parse(value, structuredSerializableRevivers);
}
globalThis.BroadcastChannel = class {
constructor(name) {
this.name = name;
}
postMessage(_message) {}
close() {}
addEventListener(_type, _listener) {}
removeEventListener(_type, _listener) {}
onmessage = null;
onmessageerror = null;
};
let cwd;
process.cwd = () => {
assert(cwd !== void 0, "Expected cwd to be set");
return cwd;
};
globalThis.__console = console;
function getCallerFileName(of) {
const originalStackTraceLimit = Error.stackTraceLimit;
const originalPrepareStackTrace = Error.prepareStackTrace;
try {
let fileName = null;
Error.stackTraceLimit = 1;
Error.prepareStackTrace = (_error, callSites) => {
fileName = callSites[0]?.getFileName();
return "";
};
const error = {};
Error.captureStackTrace(error, of);
error.stack;
return fileName;
} finally {
Error.stackTraceLimit = originalStackTraceLimit;
Error.prepareStackTrace = originalPrepareStackTrace;
}
}
const originalSetTimeout = globalThis.setTimeout;
const originalClearTimeout = globalThis.clearTimeout;
const timeoutPromiseResolves = /* @__PURE__ */ new Map();
const monkeypatchedSetTimeout = (...args) => {
const [callback, delay, ...restArgs] = args;
const callbackName = args[0]?.name ?? "";
const callerFileName = getCallerFileName(monkeypatchedSetTimeout);
if (!(/\/node_modules\/(\.pnpm\/|\.store\/)?vitest/.test(callerFileName ?? "") || /\/packages\/vitest\/dist/.test(callerFileName ?? "") || /\/node_modules\/(\.pnpm\/|\.store\/)?@voidzero-dev[+/]vite-plus-test/.test(callerFileName ?? "")) || delay) return originalSetTimeout.apply(globalThis, args);
if (callbackName === "NOOP") return -.5;
let promiseResolve;
const promise = new Promise((resolve) => {
promiseResolve = resolve;
});
assert(promiseResolve !== void 0);
registerHandlerAndGlobalWaitUntil(promise);
const id = originalSetTimeout.call(globalThis, () => {
promiseResolve?.();
callback?.(...restArgs);
});
timeoutPromiseResolves.set(id, promiseResolve);
return id;
};
globalThis.setTimeout = monkeypatchedSetTimeout;
globalThis.clearTimeout = (...args) => {
const id = args[0];
if (id === -.5) return;
const maybePromiseResolve = timeoutPromiseResolves.get(id);
timeoutPromiseResolves.delete(id);
maybePromiseResolve?.();
return originalClearTimeout.apply(globalThis, args);
};
function isDifferentIOContextError(e) {
return e instanceof Error && e.message.startsWith("Cannot perform I/O on behalf of a different");
}
let patchedFunction = false;
function ensurePatchedFunction(unsafeEval) {
if (patchedFunction) return;
patchedFunction = true;
globalThis.Function = new Proxy(globalThis.Function, { construct(_target, args, _newTarget) {
const script = args.pop();
return unsafeEval.newFunction(script, "anonymous", ...args);
} });
}
function applyDefines() {
for (const [key, value] of Object.entries(defines)) {
const segments = key.split(".");
let target = globalThis;
for (let i = 0; i < segments.length; i++) {
const segment = segments[i];
if (i === segments.length - 1) target[segment] = value;
else target = target[segment] ??= {};
}
}
}
var __VITEST_POOL_WORKERS_RUNNER_DURABLE_OBJECT__ = class extends DurableObject {
constructor(_state, doEnv) {
super(_state, doEnv);
vm._setUnsafeEval(doEnv.__VITEST_POOL_WORKERS_UNSAFE_EVAL);
ensurePatchedFunction(doEnv.__VITEST_POOL_WORKERS_UNSAFE_EVAL);
applyDefines();
}
async handleVitestRunRequest(request) {
assert.strictEqual(request.headers.get("Upgrade"), "websocket");
const { 0: poolSocket, 1: poolResponseSocket } = new WebSocketPair();
const workerDataHeader = request.headers.get("MF-Vitest-Worker-Data");
assert(workerDataHeader);
const wd = structuredSerializableParse(workerDataHeader);
assert(wd && typeof wd === "object" && "cwd" in wd && typeof wd.cwd === "string");
cwd = wd.cwd;
const { init, runBaseTests, setupEnvironment } = await import("vitest/worker");
poolSocket.accept();
init({
post: (response) => {
try {
poolSocket.send(structuredSerializableStringify(response));
} catch (error) {
if (isDifferentIOContextError(error)) registerHandlerAndGlobalWaitUntil(runInRunnerObject(() => {
poolSocket.send(structuredSerializableStringify(response));
}).catch((e) => {
__console.error("Error sending to pool inside runner:", e, response);
}));
else __console.error("Error sending to pool:", error, response);
}
},
on: (callback) => {
poolSocket.addEventListener("message", (m) => {
callback(structuredSerializableParse(m.data));
});
},
runTests: (state, traces) => runBaseTests("run", state, traces),
collectTests: (state, traces) => runBaseTests("collect", state, traces),
setup: setupEnvironment,
onModuleRunner(moduleRunner) {
const runner = moduleRunner;
if (runner.transport?.invoke) {
const originalInvoke = runner.transport.invoke.bind(runner.transport);
runner.transport.invoke = (...args) => {
return runInRunnerObject(() => originalInvoke(...args));
};
} else __console.warn("[vitest-pool-workers] Could not patch module runner transport. Dynamic import() inside entrypoint/DO handlers may fail.");
}
});
return new Response(null, {
status: 101,
webSocket: poolResponseSocket
});
}
async fetch(request) {
const response = await maybeHandleRunRequest(request, this);
if (response !== void 0) return response;
return this.handleVitestRunRequest(request);
}
};
var worker_default = createWorkerEntrypointWrapper("default");
//#endregion
export { __VITEST_POOL_WORKERS_RUNNER_DURABLE_OBJECT__, worker_default as default };
//# sourceMappingURL=index.mjs.map