Add Robot_JoyIt driver
This commit is contained in:
1
node_modules/jest-worker/LICENSE
generated
vendored
1
node_modules/jest-worker/LICENSE
generated
vendored
@@ -1,6 +1,7 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
Copyright Contributors to the Jest project.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
2
node_modules/jest-worker/README.md
generated
vendored
2
node_modules/jest-worker/README.md
generated
vendored
@@ -233,7 +233,7 @@ async function main() {
|
||||
console.log(await myWorker.transform('/tmp/foo.js'));
|
||||
|
||||
// Wait a bit.
|
||||
await sleep(10000);
|
||||
await sleep(10_000);
|
||||
|
||||
// Transform the same file again. Will immediately return because the
|
||||
// transformed file is cached in the worker, and `computeWorkerKey` ensures
|
||||
|
||||
152
node_modules/jest-worker/build/Farm.js
generated
vendored
152
node_modules/jest-worker/build/Farm.js
generated
vendored
@@ -1,152 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, '__esModule', {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
var _FifoQueue = _interopRequireDefault(require('./FifoQueue'));
|
||||
var _types = require('./types');
|
||||
function _interopRequireDefault(obj) {
|
||||
return obj && obj.__esModule ? obj : {default: obj};
|
||||
}
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
class Farm {
|
||||
_computeWorkerKey;
|
||||
_workerSchedulingPolicy;
|
||||
_cacheKeys = Object.create(null);
|
||||
_locks = [];
|
||||
_offset = 0;
|
||||
_taskQueue;
|
||||
constructor(_numOfWorkers, _callback, options = {}) {
|
||||
this._numOfWorkers = _numOfWorkers;
|
||||
this._callback = _callback;
|
||||
this._computeWorkerKey = options.computeWorkerKey;
|
||||
this._workerSchedulingPolicy =
|
||||
options.workerSchedulingPolicy ?? 'round-robin';
|
||||
this._taskQueue = options.taskQueue ?? new _FifoQueue.default();
|
||||
}
|
||||
doWork(method, ...args) {
|
||||
const customMessageListeners = new Set();
|
||||
const addCustomMessageListener = listener => {
|
||||
customMessageListeners.add(listener);
|
||||
return () => {
|
||||
customMessageListeners.delete(listener);
|
||||
};
|
||||
};
|
||||
const onCustomMessage = message => {
|
||||
customMessageListeners.forEach(listener => listener(message));
|
||||
};
|
||||
const promise = new Promise(
|
||||
// Bind args to this function so it won't reference to the parent scope.
|
||||
// This prevents a memory leak in v8, because otherwise the function will
|
||||
// retain args for the closure.
|
||||
((args, resolve, reject) => {
|
||||
const computeWorkerKey = this._computeWorkerKey;
|
||||
const request = [_types.CHILD_MESSAGE_CALL, false, method, args];
|
||||
let worker = null;
|
||||
let hash = null;
|
||||
if (computeWorkerKey) {
|
||||
hash = computeWorkerKey.call(this, method, ...args);
|
||||
worker = hash == null ? null : this._cacheKeys[hash];
|
||||
}
|
||||
const onStart = worker => {
|
||||
if (hash != null) {
|
||||
this._cacheKeys[hash] = worker;
|
||||
}
|
||||
};
|
||||
const onEnd = (error, result) => {
|
||||
customMessageListeners.clear();
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(result);
|
||||
}
|
||||
};
|
||||
const task = {
|
||||
onCustomMessage,
|
||||
onEnd,
|
||||
onStart,
|
||||
request
|
||||
};
|
||||
if (worker) {
|
||||
this._taskQueue.enqueue(task, worker.getWorkerId());
|
||||
this._process(worker.getWorkerId());
|
||||
} else {
|
||||
this._push(task);
|
||||
}
|
||||
}).bind(null, args)
|
||||
);
|
||||
promise.UNSTABLE_onCustomMessage = addCustomMessageListener;
|
||||
return promise;
|
||||
}
|
||||
_process(workerId) {
|
||||
if (this._isLocked(workerId)) {
|
||||
return this;
|
||||
}
|
||||
const task = this._taskQueue.dequeue(workerId);
|
||||
if (!task) {
|
||||
return this;
|
||||
}
|
||||
if (task.request[1]) {
|
||||
throw new Error('Queue implementation returned processed task');
|
||||
}
|
||||
|
||||
// Reference the task object outside so it won't be retained by onEnd,
|
||||
// and other properties of the task object, such as task.request can be
|
||||
// garbage collected.
|
||||
let taskOnEnd = task.onEnd;
|
||||
const onEnd = (error, result) => {
|
||||
if (taskOnEnd) {
|
||||
taskOnEnd(error, result);
|
||||
}
|
||||
taskOnEnd = null;
|
||||
this._unlock(workerId);
|
||||
this._process(workerId);
|
||||
};
|
||||
task.request[1] = true;
|
||||
this._lock(workerId);
|
||||
this._callback(
|
||||
workerId,
|
||||
task.request,
|
||||
task.onStart,
|
||||
onEnd,
|
||||
task.onCustomMessage
|
||||
);
|
||||
return this;
|
||||
}
|
||||
_push(task) {
|
||||
this._taskQueue.enqueue(task);
|
||||
const offset = this._getNextWorkerOffset();
|
||||
for (let i = 0; i < this._numOfWorkers; i++) {
|
||||
this._process((offset + i) % this._numOfWorkers);
|
||||
if (task.request[1]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
_getNextWorkerOffset() {
|
||||
switch (this._workerSchedulingPolicy) {
|
||||
case 'in-order':
|
||||
return 0;
|
||||
case 'round-robin':
|
||||
return this._offset++;
|
||||
}
|
||||
}
|
||||
_lock(workerId) {
|
||||
this._locks[workerId] = true;
|
||||
}
|
||||
_unlock(workerId) {
|
||||
this._locks[workerId] = false;
|
||||
}
|
||||
_isLocked(workerId) {
|
||||
return this._locks[workerId];
|
||||
}
|
||||
}
|
||||
exports.default = Farm;
|
||||
89
node_modules/jest-worker/build/FifoQueue.js
generated
vendored
89
node_modules/jest-worker/build/FifoQueue.js
generated
vendored
@@ -1,89 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, '__esModule', {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* First-in, First-out task queue that manages a dedicated pool
|
||||
* for each worker as well as a shared queue. The FIFO ordering is guaranteed
|
||||
* across the worker specific and shared queue.
|
||||
*/
|
||||
class FifoQueue {
|
||||
_workerQueues = [];
|
||||
_sharedQueue = new InternalQueue();
|
||||
enqueue(task, workerId) {
|
||||
if (workerId == null) {
|
||||
this._sharedQueue.enqueue(task);
|
||||
return;
|
||||
}
|
||||
let workerQueue = this._workerQueues[workerId];
|
||||
if (workerQueue == null) {
|
||||
workerQueue = this._workerQueues[workerId] = new InternalQueue();
|
||||
}
|
||||
const sharedTop = this._sharedQueue.peekLast();
|
||||
const item = {
|
||||
previousSharedTask: sharedTop,
|
||||
task
|
||||
};
|
||||
workerQueue.enqueue(item);
|
||||
}
|
||||
dequeue(workerId) {
|
||||
const workerTop = this._workerQueues[workerId]?.peek();
|
||||
const sharedTaskIsProcessed =
|
||||
workerTop?.previousSharedTask?.request[1] ?? true;
|
||||
|
||||
// Process the top task from the shared queue if
|
||||
// - there's no task in the worker specific queue or
|
||||
// - if the non-worker-specific task after which this worker specific task
|
||||
// has been queued wasn't processed yet
|
||||
if (workerTop != null && sharedTaskIsProcessed) {
|
||||
return this._workerQueues[workerId]?.dequeue()?.task ?? null;
|
||||
}
|
||||
return this._sharedQueue.dequeue();
|
||||
}
|
||||
}
|
||||
exports.default = FifoQueue;
|
||||
/**
|
||||
* FIFO queue for a single worker / shared queue.
|
||||
*/
|
||||
class InternalQueue {
|
||||
_head = null;
|
||||
_last = null;
|
||||
enqueue(value) {
|
||||
const item = {
|
||||
next: null,
|
||||
value
|
||||
};
|
||||
if (this._last == null) {
|
||||
this._head = item;
|
||||
} else {
|
||||
this._last.next = item;
|
||||
}
|
||||
this._last = item;
|
||||
}
|
||||
dequeue() {
|
||||
if (this._head == null) {
|
||||
return null;
|
||||
}
|
||||
const item = this._head;
|
||||
this._head = item.next;
|
||||
if (this._head == null) {
|
||||
this._last = null;
|
||||
}
|
||||
return item.value;
|
||||
}
|
||||
peek() {
|
||||
return this._head?.value ?? null;
|
||||
}
|
||||
peekLast() {
|
||||
return this._last?.value ?? null;
|
||||
}
|
||||
}
|
||||
137
node_modules/jest-worker/build/PriorityQueue.js
generated
vendored
137
node_modules/jest-worker/build/PriorityQueue.js
generated
vendored
@@ -1,137 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, '__esModule', {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Priority queue that processes tasks in natural ordering (lower priority first)
|
||||
* according to the priority computed by the function passed in the constructor.
|
||||
*
|
||||
* FIFO ordering isn't guaranteed for tasks with the same priority.
|
||||
*
|
||||
* Worker specific tasks with the same priority as a non-worker specific task
|
||||
* are always processed first.
|
||||
*/
|
||||
class PriorityQueue {
|
||||
_queue = [];
|
||||
_sharedQueue = new MinHeap();
|
||||
constructor(_computePriority) {
|
||||
this._computePriority = _computePriority;
|
||||
}
|
||||
enqueue(task, workerId) {
|
||||
if (workerId == null) {
|
||||
this._enqueue(task, this._sharedQueue);
|
||||
} else {
|
||||
const queue = this._getWorkerQueue(workerId);
|
||||
this._enqueue(task, queue);
|
||||
}
|
||||
}
|
||||
_enqueue(task, queue) {
|
||||
const item = {
|
||||
priority: this._computePriority(task.request[2], ...task.request[3]),
|
||||
task
|
||||
};
|
||||
queue.add(item);
|
||||
}
|
||||
dequeue(workerId) {
|
||||
const workerQueue = this._getWorkerQueue(workerId);
|
||||
const workerTop = workerQueue.peek();
|
||||
const sharedTop = this._sharedQueue.peek();
|
||||
|
||||
// use the task from the worker queue if there's no task in the shared queue
|
||||
// or if the priority of the worker queue is smaller or equal to the
|
||||
// priority of the top task in the shared queue. The tasks of the
|
||||
// worker specific queue are preferred because no other worker can pick this
|
||||
// specific task up.
|
||||
if (
|
||||
sharedTop == null ||
|
||||
(workerTop != null && workerTop.priority <= sharedTop.priority)
|
||||
) {
|
||||
return workerQueue.poll()?.task ?? null;
|
||||
}
|
||||
return this._sharedQueue.poll().task;
|
||||
}
|
||||
_getWorkerQueue(workerId) {
|
||||
let queue = this._queue[workerId];
|
||||
if (queue == null) {
|
||||
queue = this._queue[workerId] = new MinHeap();
|
||||
}
|
||||
return queue;
|
||||
}
|
||||
}
|
||||
exports.default = PriorityQueue;
|
||||
class MinHeap {
|
||||
_heap = [];
|
||||
peek() {
|
||||
return this._heap[0] ?? null;
|
||||
}
|
||||
add(item) {
|
||||
const nodes = this._heap;
|
||||
nodes.push(item);
|
||||
if (nodes.length === 1) {
|
||||
return;
|
||||
}
|
||||
let currentIndex = nodes.length - 1;
|
||||
|
||||
// Bubble up the added node as long as the parent is bigger
|
||||
while (currentIndex > 0) {
|
||||
const parentIndex = Math.floor((currentIndex + 1) / 2) - 1;
|
||||
const parent = nodes[parentIndex];
|
||||
if (parent.priority <= item.priority) {
|
||||
break;
|
||||
}
|
||||
nodes[currentIndex] = parent;
|
||||
nodes[parentIndex] = item;
|
||||
currentIndex = parentIndex;
|
||||
}
|
||||
}
|
||||
poll() {
|
||||
const nodes = this._heap;
|
||||
const result = nodes[0];
|
||||
const lastElement = nodes.pop();
|
||||
|
||||
// heap was empty or removed the last element
|
||||
if (result == null || nodes.length === 0) {
|
||||
return result ?? null;
|
||||
}
|
||||
let index = 0;
|
||||
nodes[0] = lastElement ?? null;
|
||||
const element = nodes[0];
|
||||
while (true) {
|
||||
let swapIndex = null;
|
||||
const rightChildIndex = (index + 1) * 2;
|
||||
const leftChildIndex = rightChildIndex - 1;
|
||||
const rightChild = nodes[rightChildIndex];
|
||||
const leftChild = nodes[leftChildIndex];
|
||||
|
||||
// if the left child is smaller, swap with the left
|
||||
if (leftChild != null && leftChild.priority < element.priority) {
|
||||
swapIndex = leftChildIndex;
|
||||
}
|
||||
|
||||
// If the right child is smaller or the right child is smaller than the left
|
||||
// then swap with the right child
|
||||
if (
|
||||
rightChild != null &&
|
||||
rightChild.priority < (swapIndex == null ? element : leftChild).priority
|
||||
) {
|
||||
swapIndex = rightChildIndex;
|
||||
}
|
||||
if (swapIndex == null) {
|
||||
break;
|
||||
}
|
||||
nodes[index] = nodes[swapIndex];
|
||||
nodes[swapIndex] = element;
|
||||
index = swapIndex;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
34
node_modules/jest-worker/build/WorkerPool.js
generated
vendored
34
node_modules/jest-worker/build/WorkerPool.js
generated
vendored
@@ -1,34 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, '__esModule', {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
var _BaseWorkerPool = _interopRequireDefault(require('./base/BaseWorkerPool'));
|
||||
function _interopRequireDefault(obj) {
|
||||
return obj && obj.__esModule ? obj : {default: obj};
|
||||
}
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
class WorkerPool extends _BaseWorkerPool.default {
|
||||
send(workerId, request, onStart, onEnd, onCustomMessage) {
|
||||
this.restartWorkerIfShutDown(workerId);
|
||||
this.getWorkerById(workerId).send(request, onStart, onEnd, onCustomMessage);
|
||||
}
|
||||
createWorker(workerOptions) {
|
||||
let Worker;
|
||||
if (this._options.enableWorkerThreads) {
|
||||
Worker = require('./workers/NodeThreadsWorker').default;
|
||||
} else {
|
||||
Worker = require('./workers/ChildProcessWorker').default;
|
||||
}
|
||||
return new Worker(workerOptions);
|
||||
}
|
||||
}
|
||||
var _default = WorkerPool;
|
||||
exports.default = _default;
|
||||
156
node_modules/jest-worker/build/base/BaseWorkerPool.js
generated
vendored
156
node_modules/jest-worker/build/base/BaseWorkerPool.js
generated
vendored
@@ -1,156 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, '__esModule', {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
function _mergeStream() {
|
||||
const data = _interopRequireDefault(require('merge-stream'));
|
||||
_mergeStream = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
var _types = require('../types');
|
||||
function _interopRequireDefault(obj) {
|
||||
return obj && obj.__esModule ? obj : {default: obj};
|
||||
}
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
// How long to wait for the child process to terminate
|
||||
// after CHILD_MESSAGE_END before sending force exiting.
|
||||
const FORCE_EXIT_DELAY = 500;
|
||||
|
||||
/* istanbul ignore next */
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
const emptyMethod = () => {};
|
||||
class BaseWorkerPool {
|
||||
_stderr;
|
||||
_stdout;
|
||||
_options;
|
||||
_workers;
|
||||
_workerPath;
|
||||
constructor(workerPath, options) {
|
||||
this._options = options;
|
||||
this._workerPath = workerPath;
|
||||
this._workers = new Array(options.numWorkers);
|
||||
const stdout = (0, _mergeStream().default)();
|
||||
const stderr = (0, _mergeStream().default)();
|
||||
const {forkOptions, maxRetries, resourceLimits, setupArgs} = options;
|
||||
for (let i = 0; i < options.numWorkers; i++) {
|
||||
const workerOptions = {
|
||||
forkOptions,
|
||||
idleMemoryLimit: this._options.idleMemoryLimit,
|
||||
maxRetries,
|
||||
resourceLimits,
|
||||
setupArgs,
|
||||
workerId: i,
|
||||
workerPath
|
||||
};
|
||||
const worker = this.createWorker(workerOptions);
|
||||
const workerStdout = worker.getStdout();
|
||||
const workerStderr = worker.getStderr();
|
||||
if (workerStdout) {
|
||||
stdout.add(workerStdout);
|
||||
}
|
||||
if (workerStderr) {
|
||||
stderr.add(workerStderr);
|
||||
}
|
||||
this._workers[i] = worker;
|
||||
}
|
||||
this._stdout = stdout;
|
||||
this._stderr = stderr;
|
||||
}
|
||||
getStderr() {
|
||||
return this._stderr;
|
||||
}
|
||||
getStdout() {
|
||||
return this._stdout;
|
||||
}
|
||||
getWorkers() {
|
||||
return this._workers;
|
||||
}
|
||||
getWorkerById(workerId) {
|
||||
return this._workers[workerId];
|
||||
}
|
||||
restartWorkerIfShutDown(workerId) {
|
||||
if (this._workers[workerId].state === _types.WorkerStates.SHUT_DOWN) {
|
||||
const {forkOptions, maxRetries, resourceLimits, setupArgs} =
|
||||
this._options;
|
||||
const workerOptions = {
|
||||
forkOptions,
|
||||
idleMemoryLimit: this._options.idleMemoryLimit,
|
||||
maxRetries,
|
||||
resourceLimits,
|
||||
setupArgs,
|
||||
workerId,
|
||||
workerPath: this._workerPath
|
||||
};
|
||||
const worker = this.createWorker(workerOptions);
|
||||
this._workers[workerId] = worker;
|
||||
}
|
||||
}
|
||||
createWorker(_workerOptions) {
|
||||
throw Error('Missing method createWorker in WorkerPool');
|
||||
}
|
||||
async start() {
|
||||
await Promise.all(
|
||||
this._workers.map(async worker => {
|
||||
await worker.waitForWorkerReady();
|
||||
await new Promise((resolve, reject) => {
|
||||
worker.send(
|
||||
[_types.CHILD_MESSAGE_CALL_SETUP],
|
||||
emptyMethod,
|
||||
error => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
},
|
||||
emptyMethod
|
||||
);
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
async end() {
|
||||
// We do not cache the request object here. If so, it would only be only
|
||||
// processed by one of the workers, and we want them all to close.
|
||||
const workerExitPromises = this._workers.map(async worker => {
|
||||
worker.send(
|
||||
[_types.CHILD_MESSAGE_END, false],
|
||||
emptyMethod,
|
||||
emptyMethod,
|
||||
emptyMethod
|
||||
);
|
||||
|
||||
// Schedule a force exit in case worker fails to exit gracefully so
|
||||
// await worker.waitForExit() never takes longer than FORCE_EXIT_DELAY
|
||||
let forceExited = false;
|
||||
const forceExitTimeout = setTimeout(() => {
|
||||
worker.forceExit();
|
||||
forceExited = true;
|
||||
}, FORCE_EXIT_DELAY);
|
||||
await worker.waitForExit();
|
||||
// Worker ideally exited gracefully, don't send force exit then
|
||||
clearTimeout(forceExitTimeout);
|
||||
return forceExited;
|
||||
});
|
||||
const workerExits = await Promise.all(workerExitPromises);
|
||||
return workerExits.reduce(
|
||||
(result, forceExited) => ({
|
||||
forceExited: result.forceExited || forceExited
|
||||
}),
|
||||
{
|
||||
forceExited: false
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
exports.default = BaseWorkerPool;
|
||||
259
node_modules/jest-worker/build/index.d.mts
generated
vendored
Normal file
259
node_modules/jest-worker/build/index.d.mts
generated
vendored
Normal file
@@ -0,0 +1,259 @@
|
||||
import { ResourceLimits } from "worker_threads";
|
||||
import { ForkOptions } from "child_process";
|
||||
|
||||
//#region src/types.d.ts
|
||||
|
||||
type ReservedKeys = 'end' | 'getStderr' | 'getStdout' | 'setup' | 'teardown';
|
||||
type ExcludeReservedKeys<K> = Exclude<K, ReservedKeys>;
|
||||
type FunctionLike = (...args: any) => unknown;
|
||||
type MethodLikeKeys<T> = { [K in keyof T]: T[K] extends FunctionLike ? K : never }[keyof T];
|
||||
type Promisify<T extends FunctionLike> = ReturnType<T> extends Promise<infer R> ? (...args: Parameters<T>) => Promise<R> : (...args: Parameters<T>) => Promise<ReturnType<T>>;
|
||||
type WorkerModule<T> = { [K in keyof T as Extract<ExcludeReservedKeys<K>, MethodLikeKeys<T>>]: T[K] extends FunctionLike ? Promisify<T[K]> : never };
|
||||
declare const CHILD_MESSAGE_INITIALIZE = 0;
|
||||
declare const CHILD_MESSAGE_CALL = 1;
|
||||
declare const CHILD_MESSAGE_END = 2;
|
||||
declare const CHILD_MESSAGE_MEM_USAGE = 3;
|
||||
declare const CHILD_MESSAGE_CALL_SETUP = 4;
|
||||
type WorkerCallback = (workerId: number, request: ChildMessage, onStart: OnStart, onEnd: OnEnd, onCustomMessage: OnCustomMessage) => void;
|
||||
interface WorkerPoolInterface {
|
||||
getStderr(): NodeJS.ReadableStream;
|
||||
getStdout(): NodeJS.ReadableStream;
|
||||
getWorkers(): Array<WorkerInterface>;
|
||||
createWorker(options: WorkerOptions): WorkerInterface;
|
||||
send: WorkerCallback;
|
||||
start(): Promise<void>;
|
||||
end(): Promise<PoolExitResult>;
|
||||
}
|
||||
interface WorkerInterface {
|
||||
get state(): WorkerStates;
|
||||
send(request: ChildMessage, onProcessStart: OnStart, onProcessEnd: OnEnd, onCustomMessage: OnCustomMessage): void;
|
||||
waitForExit(): Promise<void>;
|
||||
forceExit(): void;
|
||||
getWorkerId(): number;
|
||||
getStderr(): NodeJS.ReadableStream | null;
|
||||
getStdout(): NodeJS.ReadableStream | null;
|
||||
/**
|
||||
* Some system level identifier for the worker. IE, process id, thread id, etc.
|
||||
*/
|
||||
getWorkerSystemId(): number;
|
||||
getMemoryUsage(): Promise<number | null>;
|
||||
/**
|
||||
* Checks to see if the child worker is actually running.
|
||||
*/
|
||||
isWorkerRunning(): boolean;
|
||||
/**
|
||||
* When the worker child is started and ready to start handling requests.
|
||||
*
|
||||
* @remarks
|
||||
* This mostly exists to help with testing so that you don't check the status
|
||||
* of things like isWorkerRunning before it actually is.
|
||||
*/
|
||||
waitForWorkerReady(): Promise<void>;
|
||||
}
|
||||
type PoolExitResult = {
|
||||
forceExited: boolean;
|
||||
};
|
||||
interface PromiseWithCustomMessage<T> extends Promise<T> {
|
||||
UNSTABLE_onCustomMessage?: (listener: OnCustomMessage) => () => void;
|
||||
}
|
||||
interface TaskQueue {
|
||||
/**
|
||||
* Enqueues the task in the queue for the specified worker or adds it to the
|
||||
* queue shared by all workers
|
||||
* @param task the task to queue
|
||||
* @param workerId the id of the worker that should process this task or undefined
|
||||
* if there's no preference.
|
||||
*/
|
||||
enqueue(task: QueueChildMessage, workerId?: number): void;
|
||||
/**
|
||||
* Dequeues the next item from the queue for the specified worker
|
||||
* @param workerId the id of the worker for which the next task should be retrieved
|
||||
*/
|
||||
dequeue(workerId: number): QueueChildMessage | null;
|
||||
}
|
||||
type WorkerSchedulingPolicy = 'round-robin' | 'in-order';
|
||||
type WorkerFarmOptions = {
|
||||
computeWorkerKey?: (method: string, ...args: Array<unknown>) => string | null;
|
||||
enableWorkerThreads?: boolean;
|
||||
exposedMethods?: ReadonlyArray<string>;
|
||||
forkOptions?: ForkOptions;
|
||||
maxRetries?: number;
|
||||
numWorkers?: number;
|
||||
resourceLimits?: ResourceLimits;
|
||||
setupArgs?: Array<unknown>;
|
||||
taskQueue?: TaskQueue;
|
||||
WorkerPool?: new (workerPath: string, options?: WorkerPoolOptions) => WorkerPoolInterface;
|
||||
workerSchedulingPolicy?: WorkerSchedulingPolicy;
|
||||
idleMemoryLimit?: number;
|
||||
};
|
||||
type WorkerPoolOptions = {
|
||||
setupArgs: Array<unknown>;
|
||||
forkOptions: ForkOptions;
|
||||
resourceLimits: ResourceLimits;
|
||||
maxRetries: number;
|
||||
numWorkers: number;
|
||||
enableWorkerThreads: boolean;
|
||||
idleMemoryLimit?: number;
|
||||
};
|
||||
type WorkerOptions = {
|
||||
forkOptions: ForkOptions;
|
||||
resourceLimits: ResourceLimits;
|
||||
setupArgs: Array<unknown>;
|
||||
maxRetries: number;
|
||||
workerId: number;
|
||||
workerData?: unknown;
|
||||
workerPath: string;
|
||||
/**
|
||||
* After a job has executed the memory usage it should return to.
|
||||
*
|
||||
* @remarks
|
||||
* Note this is different from ResourceLimits in that it checks at idle, after
|
||||
* a job is complete. So you could have a resource limit of 500MB but an idle
|
||||
* limit of 50MB. The latter will only trigger if after a job has completed the
|
||||
* memory usage hasn't returned back down under 50MB.
|
||||
*/
|
||||
idleMemoryLimit?: number;
|
||||
/**
|
||||
* This mainly exists so the path can be changed during testing.
|
||||
* https://github.com/jestjs/jest/issues/9543
|
||||
*/
|
||||
childWorkerPath?: string;
|
||||
/**
|
||||
* This is useful for debugging individual tests allowing you to see
|
||||
* the raw output of the worker.
|
||||
*/
|
||||
silent?: boolean;
|
||||
/**
|
||||
* Used to immediately bind event handlers.
|
||||
*/
|
||||
on?: {
|
||||
[WorkerEvents.STATE_CHANGE]: OnStateChangeHandler | ReadonlyArray<OnStateChangeHandler>;
|
||||
};
|
||||
};
|
||||
type OnStateChangeHandler = (state: WorkerStates, oldState: WorkerStates) => void;
|
||||
type ChildMessageInitialize = [type: typeof CHILD_MESSAGE_INITIALIZE, isProcessed: boolean, fileName: string, setupArgs: Array<unknown>, workerId: string | undefined];
|
||||
type ChildMessageCall = [type: typeof CHILD_MESSAGE_CALL, isProcessed: boolean, methodName: string, args: Array<unknown>];
|
||||
type ChildMessageEnd = [type: typeof CHILD_MESSAGE_END, isProcessed: boolean];
|
||||
type ChildMessageMemUsage = [type: typeof CHILD_MESSAGE_MEM_USAGE];
|
||||
type ChildMessageCallSetup = [type: typeof CHILD_MESSAGE_CALL_SETUP];
|
||||
type ChildMessage = ChildMessageInitialize | ChildMessageCall | ChildMessageEnd | ChildMessageMemUsage | ChildMessageCallSetup;
|
||||
type OnStart = (worker: WorkerInterface) => void;
|
||||
type OnEnd = (err: Error | null, result: unknown) => void;
|
||||
type OnCustomMessage = (message: Array<unknown> | unknown) => void;
|
||||
type QueueChildMessage = {
|
||||
request: ChildMessageCall;
|
||||
onStart: OnStart;
|
||||
onEnd: OnEnd;
|
||||
onCustomMessage: OnCustomMessage;
|
||||
};
|
||||
declare enum WorkerStates {
|
||||
STARTING = "starting",
|
||||
OK = "ok",
|
||||
OUT_OF_MEMORY = "oom",
|
||||
RESTARTING = "restarting",
|
||||
SHUTTING_DOWN = "shutting-down",
|
||||
SHUT_DOWN = "shut-down",
|
||||
}
|
||||
declare enum WorkerEvents {
|
||||
STATE_CHANGE = "state-change",
|
||||
}
|
||||
//#endregion
|
||||
//#region src/PriorityQueue.d.ts
|
||||
type ComputeTaskPriorityCallback = (method: string, ...args: Array<unknown>) => number;
|
||||
type QueueItem = {
|
||||
task: QueueChildMessage;
|
||||
priority: number;
|
||||
};
|
||||
/**
|
||||
* Priority queue that processes tasks in natural ordering (lower priority first)
|
||||
* according to the priority computed by the function passed in the constructor.
|
||||
*
|
||||
* FIFO ordering isn't guaranteed for tasks with the same priority.
|
||||
*
|
||||
* Worker specific tasks with the same priority as a non-worker specific task
|
||||
* are always processed first.
|
||||
*/
|
||||
declare class PriorityQueue implements TaskQueue {
|
||||
private readonly _computePriority;
|
||||
private _queue;
|
||||
private readonly _sharedQueue;
|
||||
constructor(_computePriority: ComputeTaskPriorityCallback);
|
||||
enqueue(task: QueueChildMessage, workerId?: number): void;
|
||||
_enqueue(task: QueueChildMessage, queue: MinHeap<QueueItem>): void;
|
||||
dequeue(workerId: number): QueueChildMessage | null;
|
||||
_getWorkerQueue(workerId: number): MinHeap<QueueItem>;
|
||||
}
|
||||
type HeapItem = {
|
||||
priority: number;
|
||||
};
|
||||
declare class MinHeap<TItem extends HeapItem> {
|
||||
private readonly _heap;
|
||||
peek(): TItem | null;
|
||||
add(item: TItem): void;
|
||||
poll(): TItem | null;
|
||||
}
|
||||
//#endregion
|
||||
//#region src/FifoQueue.d.ts
|
||||
/**
|
||||
* First-in, First-out task queue that manages a dedicated pool
|
||||
* for each worker as well as a shared queue. The FIFO ordering is guaranteed
|
||||
* across the worker specific and shared queue.
|
||||
*/
|
||||
declare class FifoQueue implements TaskQueue {
|
||||
private _workerQueues;
|
||||
private readonly _sharedQueue;
|
||||
enqueue(task: QueueChildMessage, workerId?: number): void;
|
||||
dequeue(workerId: number): QueueChildMessage | null;
|
||||
}
|
||||
//#endregion
|
||||
//#region src/workers/messageParent.d.ts
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
declare function messageParent(message: unknown, parentProcess?: NodeJS.Process): void;
|
||||
//#endregion
|
||||
//#region src/index.d.ts
|
||||
type JestWorkerFarm<T extends Record<string, unknown>> = Worker & WorkerModule<T>;
|
||||
/**
|
||||
* The Jest farm (publicly called "Worker") is a class that allows you to queue
|
||||
* methods across multiple child processes, in order to parallelize work. This
|
||||
* is done by providing an absolute path to a module that will be loaded on each
|
||||
* of the child processes, and bridged to the main process.
|
||||
*
|
||||
* Bridged methods are specified by using the "exposedMethods" property of the
|
||||
* "options" object. This is an array of strings, where each of them corresponds
|
||||
* to the exported name in the loaded module.
|
||||
*
|
||||
* You can also control the amount of workers by using the "numWorkers" property
|
||||
* of the "options" object, and the settings passed to fork the process through
|
||||
* the "forkOptions" property. The amount of workers defaults to the amount of
|
||||
* CPUS minus one.
|
||||
*
|
||||
* Queueing calls can be done in two ways:
|
||||
* - Standard method: calls will be redirected to the first available worker,
|
||||
* so they will get executed as soon as they can.
|
||||
*
|
||||
* - Sticky method: if a "computeWorkerKey" method is provided within the
|
||||
* config, the resulting string of this method will be used as a key.
|
||||
* Every time this key is returned, it is guaranteed that your job will be
|
||||
* processed by the same worker. This is specially useful if your workers
|
||||
* are caching results.
|
||||
*/
|
||||
declare class Worker {
|
||||
private _ending;
|
||||
private readonly _farm;
|
||||
private readonly _options;
|
||||
private readonly _workerPool;
|
||||
constructor(workerPath: string | URL, options?: WorkerFarmOptions);
|
||||
private _bindExposedWorkerMethods;
|
||||
private _callFunctionWithArgs;
|
||||
getStderr(): NodeJS.ReadableStream;
|
||||
getStdout(): NodeJS.ReadableStream;
|
||||
start(): Promise<void>;
|
||||
end(): Promise<PoolExitResult>;
|
||||
}
|
||||
//#endregion
|
||||
export { FifoQueue, JestWorkerFarm, PriorityQueue, PromiseWithCustomMessage, TaskQueue, Worker, WorkerFarmOptions, WorkerPoolInterface, WorkerPoolOptions, messageParent };
|
||||
18
node_modules/jest-worker/build/index.d.ts
generated
vendored
18
node_modules/jest-worker/build/index.d.ts
generated
vendored
@@ -4,10 +4,9 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
/// <reference types="node" />
|
||||
|
||||
import type {ForkOptions} from 'child_process';
|
||||
import type {ResourceLimits} from 'worker_threads';
|
||||
import {ForkOptions} from 'child_process';
|
||||
import {ResourceLimits} from 'worker_threads';
|
||||
|
||||
declare const CHILD_MESSAGE_CALL = 1;
|
||||
|
||||
@@ -133,11 +132,10 @@ export declare interface PromiseWithCustomMessage<T> extends Promise<T> {
|
||||
UNSTABLE_onCustomMessage?: (listener: OnCustomMessage) => () => void;
|
||||
}
|
||||
|
||||
declare type Promisify<T extends FunctionLike> = ReturnType<T> extends Promise<
|
||||
infer R
|
||||
>
|
||||
? (...args: Parameters<T>) => Promise<R>
|
||||
: (...args: Parameters<T>) => Promise<ReturnType<T>>;
|
||||
declare type Promisify<T extends FunctionLike> =
|
||||
ReturnType<T> extends Promise<infer R>
|
||||
? (...args: Parameters<T>) => Promise<R>
|
||||
: (...args: Parameters<T>) => Promise<ReturnType<T>>;
|
||||
|
||||
declare type QueueChildMessage = {
|
||||
request: ChildMessageCall;
|
||||
@@ -299,6 +297,10 @@ declare type WorkerOptions_2 = {
|
||||
* a job is complete. So you could have a resource limit of 500MB but an idle
|
||||
* limit of 50MB. The latter will only trigger if after a job has completed the
|
||||
* memory usage hasn't returned back down under 50MB.
|
||||
*
|
||||
* Special case: setting this to 0 will restart the worker process after each
|
||||
* job completes, providing complete process isolation between test files
|
||||
* regardless of memory usage.
|
||||
*/
|
||||
idleMemoryLimit?: number;
|
||||
/**
|
||||
|
||||
1808
node_modules/jest-worker/build/index.js
generated
vendored
1808
node_modules/jest-worker/build/index.js
generated
vendored
File diff suppressed because it is too large
Load Diff
6
node_modules/jest-worker/build/index.mjs
generated
vendored
Normal file
6
node_modules/jest-worker/build/index.mjs
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import cjsModule from './index.js';
|
||||
|
||||
export const FifoQueue = cjsModule.FifoQueue;
|
||||
export const PriorityQueue = cjsModule.PriorityQueue;
|
||||
export const Worker = cjsModule.Worker;
|
||||
export const messageParent = cjsModule.messageParent;
|
||||
1
node_modules/jest-worker/build/processChild.d.mts
generated
vendored
Normal file
1
node_modules/jest-worker/build/processChild.d.mts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export { };
|
||||
310
node_modules/jest-worker/build/processChild.js
generated
vendored
Normal file
310
node_modules/jest-worker/build/processChild.js
generated
vendored
Normal file
@@ -0,0 +1,310 @@
|
||||
/*!
|
||||
* /**
|
||||
* * Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* *
|
||||
* * This source code is licensed under the MIT license found in the
|
||||
* * LICENSE file in the root directory of this source tree.
|
||||
* * /
|
||||
*/
|
||||
/******/ (() => { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
/******/ var __webpack_modules__ = ({
|
||||
|
||||
/***/ "./src/types.ts":
|
||||
/***/ ((__unused_webpack_module, exports) => {
|
||||
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
exports.WorkerStates = exports.WorkerEvents = exports.PARENT_MESSAGE_SETUP_ERROR = exports.PARENT_MESSAGE_OK = exports.PARENT_MESSAGE_MEM_USAGE = exports.PARENT_MESSAGE_CUSTOM = exports.PARENT_MESSAGE_CLIENT_ERROR = exports.CHILD_MESSAGE_MEM_USAGE = exports.CHILD_MESSAGE_INITIALIZE = exports.CHILD_MESSAGE_END = exports.CHILD_MESSAGE_CALL_SETUP = exports.CHILD_MESSAGE_CALL = void 0;
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
// Because of the dynamic nature of a worker communication process, all messages
|
||||
// coming from any of the other processes cannot be typed. Thus, many types
|
||||
// include "unknown" as a TS type, which is (unfortunately) correct here.
|
||||
|
||||
const CHILD_MESSAGE_INITIALIZE = exports.CHILD_MESSAGE_INITIALIZE = 0;
|
||||
const CHILD_MESSAGE_CALL = exports.CHILD_MESSAGE_CALL = 1;
|
||||
const CHILD_MESSAGE_END = exports.CHILD_MESSAGE_END = 2;
|
||||
const CHILD_MESSAGE_MEM_USAGE = exports.CHILD_MESSAGE_MEM_USAGE = 3;
|
||||
const CHILD_MESSAGE_CALL_SETUP = exports.CHILD_MESSAGE_CALL_SETUP = 4;
|
||||
const PARENT_MESSAGE_OK = exports.PARENT_MESSAGE_OK = 0;
|
||||
const PARENT_MESSAGE_CLIENT_ERROR = exports.PARENT_MESSAGE_CLIENT_ERROR = 1;
|
||||
const PARENT_MESSAGE_SETUP_ERROR = exports.PARENT_MESSAGE_SETUP_ERROR = 2;
|
||||
const PARENT_MESSAGE_CUSTOM = exports.PARENT_MESSAGE_CUSTOM = 3;
|
||||
const PARENT_MESSAGE_MEM_USAGE = exports.PARENT_MESSAGE_MEM_USAGE = 4;
|
||||
|
||||
// Option objects.
|
||||
|
||||
// Messages passed from the parent to the children.
|
||||
|
||||
// Messages passed from the children to the parent.
|
||||
|
||||
// Queue types.
|
||||
let WorkerStates = exports.WorkerStates = /*#__PURE__*/function (WorkerStates) {
|
||||
WorkerStates["STARTING"] = "starting";
|
||||
WorkerStates["OK"] = "ok";
|
||||
WorkerStates["OUT_OF_MEMORY"] = "oom";
|
||||
WorkerStates["RESTARTING"] = "restarting";
|
||||
WorkerStates["SHUTTING_DOWN"] = "shutting-down";
|
||||
WorkerStates["SHUT_DOWN"] = "shut-down";
|
||||
return WorkerStates;
|
||||
}({});
|
||||
let WorkerEvents = exports.WorkerEvents = /*#__PURE__*/function (WorkerEvents) {
|
||||
WorkerEvents["STATE_CHANGE"] = "state-change";
|
||||
return WorkerEvents;
|
||||
}({});
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./src/workers/safeMessageTransferring.ts":
|
||||
/***/ ((__unused_webpack_module, exports) => {
|
||||
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
exports.packMessage = packMessage;
|
||||
exports.unpackMessage = unpackMessage;
|
||||
function _structuredClone() {
|
||||
const data = require("@ungap/structured-clone");
|
||||
_structuredClone = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
function packMessage(message) {
|
||||
return {
|
||||
__STRUCTURED_CLONE_SERIALIZED__: true,
|
||||
/**
|
||||
* Use the `json: true` option to avoid errors
|
||||
* caused by `function` or `symbol` types.
|
||||
* It's not ideal to lose `function` and `symbol` types,
|
||||
* but reliability is more important.
|
||||
*/
|
||||
data: (0, _structuredClone().serialize)(message, {
|
||||
json: true
|
||||
})
|
||||
};
|
||||
}
|
||||
function isTransferringContainer(message) {
|
||||
return message != null && typeof message === 'object' && '__STRUCTURED_CLONE_SERIALIZED__' in message && 'data' in message;
|
||||
}
|
||||
function unpackMessage(message) {
|
||||
if (isTransferringContainer(message)) {
|
||||
return (0, _structuredClone().deserialize)(message.data);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
/***/ })
|
||||
|
||||
/******/ });
|
||||
/************************************************************************/
|
||||
/******/ // The module cache
|
||||
/******/ var __webpack_module_cache__ = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/ // Check if module is in cache
|
||||
/******/ var cachedModule = __webpack_module_cache__[moduleId];
|
||||
/******/ if (cachedModule !== undefined) {
|
||||
/******/ return cachedModule.exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = __webpack_module_cache__[moduleId] = {
|
||||
/******/ // no module.id needed
|
||||
/******/ // no module.loaded needed
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/************************************************************************/
|
||||
var __webpack_exports__ = {};
|
||||
|
||||
|
||||
function _nodeUtil() {
|
||||
const data = require("node:util");
|
||||
_nodeUtil = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _jestUtil() {
|
||||
const data = require("jest-util");
|
||||
_jestUtil = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
var _types = __webpack_require__("./src/types.ts");
|
||||
var _safeMessageTransferring = __webpack_require__("./src/workers/safeMessageTransferring.ts");
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
let file = null;
|
||||
let setupArgs = [];
|
||||
let initialized = false;
|
||||
|
||||
/**
|
||||
* This file is a small bootstrapper for workers. It sets up the communication
|
||||
* between the worker and the parent process, interpreting parent messages and
|
||||
* sending results back.
|
||||
*
|
||||
* The file loaded will be lazily initialized the first time any of the workers
|
||||
* is called. This is done for optimal performance: if the farm is initialized,
|
||||
* but no call is made to it, child Node processes will be consuming the least
|
||||
* possible amount of memory.
|
||||
*
|
||||
* If an invalid message is detected, the child will exit (by throwing) with a
|
||||
* non-zero exit code.
|
||||
*/
|
||||
const messageListener = request => {
|
||||
switch (request[0]) {
|
||||
case _types.CHILD_MESSAGE_INITIALIZE:
|
||||
const init = request;
|
||||
file = init[2];
|
||||
setupArgs = init[3];
|
||||
break;
|
||||
case _types.CHILD_MESSAGE_CALL:
|
||||
const call = request;
|
||||
execMethod(call[2], call[3]);
|
||||
break;
|
||||
case _types.CHILD_MESSAGE_END:
|
||||
end();
|
||||
break;
|
||||
case _types.CHILD_MESSAGE_MEM_USAGE:
|
||||
reportMemoryUsage();
|
||||
break;
|
||||
case _types.CHILD_MESSAGE_CALL_SETUP:
|
||||
if (initialized) {
|
||||
reportSuccess(void 0);
|
||||
} else {
|
||||
const main = require(file);
|
||||
initialized = true;
|
||||
if (main.setup) {
|
||||
execFunction(main.setup, main, setupArgs, reportSuccess, reportInitializeError);
|
||||
} else {
|
||||
reportSuccess(void 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new TypeError(`Unexpected request from parent process: ${request[0]}`);
|
||||
}
|
||||
};
|
||||
process.on('message', messageListener);
|
||||
function reportSuccess(result) {
|
||||
if (!process || !process.send) {
|
||||
throw new Error('Child can only be used on a forked process');
|
||||
}
|
||||
try {
|
||||
process.send([_types.PARENT_MESSAGE_OK, result]);
|
||||
} catch (error) {
|
||||
if (_nodeUtil().types.isNativeError(error) &&
|
||||
// if .send is a function, it's a serialization issue
|
||||
!error.message.includes('.send is not a function')) {
|
||||
// Apply specific serialization only in error cases
|
||||
// to avoid affecting performance in regular cases.
|
||||
process.send([_types.PARENT_MESSAGE_OK, (0, _safeMessageTransferring.packMessage)(result)]);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
function reportClientError(error) {
|
||||
return reportError(error, _types.PARENT_MESSAGE_CLIENT_ERROR);
|
||||
}
|
||||
function reportInitializeError(error) {
|
||||
return reportError(error, _types.PARENT_MESSAGE_SETUP_ERROR);
|
||||
}
|
||||
function reportMemoryUsage() {
|
||||
if (!process || !process.send) {
|
||||
throw new Error('Child can only be used on a forked process');
|
||||
}
|
||||
const msg = [_types.PARENT_MESSAGE_MEM_USAGE, process.memoryUsage().heapUsed];
|
||||
process.send(msg);
|
||||
}
|
||||
function reportError(error, type) {
|
||||
if (!process || !process.send) {
|
||||
throw new Error('Child can only be used on a forked process');
|
||||
}
|
||||
if (error == null) {
|
||||
error = new Error('"null" or "undefined" thrown');
|
||||
}
|
||||
process.send([type, error.constructor && error.constructor.name, error.message, error.stack, typeof error === 'object' ? {
|
||||
...error
|
||||
} : error]);
|
||||
}
|
||||
function end() {
|
||||
const main = require(file);
|
||||
if (!main.teardown) {
|
||||
exitProcess();
|
||||
return;
|
||||
}
|
||||
execFunction(main.teardown, main, [], exitProcess, exitProcess);
|
||||
}
|
||||
function exitProcess() {
|
||||
// Clean up open handles so the process ideally exits gracefully
|
||||
process.removeListener('message', messageListener);
|
||||
}
|
||||
function execMethod(method, args) {
|
||||
const main = require(file);
|
||||
let fn;
|
||||
if (method === 'default') {
|
||||
fn = main.__esModule ? main.default : main;
|
||||
} else {
|
||||
fn = main[method];
|
||||
}
|
||||
function execHelper() {
|
||||
execFunction(fn, main, args, reportSuccess, reportClientError);
|
||||
}
|
||||
if (initialized || !main.setup) {
|
||||
execHelper();
|
||||
return;
|
||||
}
|
||||
initialized = true;
|
||||
execFunction(main.setup, main, setupArgs, execHelper, reportInitializeError);
|
||||
}
|
||||
function execFunction(fn, ctx, args, onResult, onError) {
|
||||
let result;
|
||||
try {
|
||||
result = fn.apply(ctx, args);
|
||||
} catch (error) {
|
||||
onError(error);
|
||||
return;
|
||||
}
|
||||
if ((0, _jestUtil().isPromise)(result)) {
|
||||
result.then(onResult, onError);
|
||||
} else {
|
||||
onResult(result);
|
||||
}
|
||||
}
|
||||
module.exports = __webpack_exports__;
|
||||
/******/ })()
|
||||
;
|
||||
147
node_modules/jest-worker/build/processChild.mjs
generated
vendored
Normal file
147
node_modules/jest-worker/build/processChild.mjs
generated
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
import { createRequire } from "node:module";
|
||||
import { types } from "node:util";
|
||||
import { isPromise } from "jest-util";
|
||||
import { serialize } from "@ungap/structured-clone";
|
||||
|
||||
//#region rolldown:runtime
|
||||
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
||||
|
||||
//#endregion
|
||||
//#region src/types.ts
|
||||
const CHILD_MESSAGE_INITIALIZE = 0;
|
||||
const CHILD_MESSAGE_CALL = 1;
|
||||
const CHILD_MESSAGE_END = 2;
|
||||
const CHILD_MESSAGE_MEM_USAGE = 3;
|
||||
const CHILD_MESSAGE_CALL_SETUP = 4;
|
||||
const PARENT_MESSAGE_OK = 0;
|
||||
const PARENT_MESSAGE_CLIENT_ERROR = 1;
|
||||
const PARENT_MESSAGE_SETUP_ERROR = 2;
|
||||
const PARENT_MESSAGE_MEM_USAGE = 4;
|
||||
|
||||
//#endregion
|
||||
//#region src/workers/safeMessageTransferring.ts
|
||||
function packMessage(message) {
|
||||
return {
|
||||
__STRUCTURED_CLONE_SERIALIZED__: true,
|
||||
data: serialize(message, { json: true })
|
||||
};
|
||||
}
|
||||
|
||||
//#endregion
|
||||
//#region src/workers/processChild.ts
|
||||
let file = null;
|
||||
let setupArgs = [];
|
||||
let initialized = false;
|
||||
/**
|
||||
* This file is a small bootstrapper for workers. It sets up the communication
|
||||
* between the worker and the parent process, interpreting parent messages and
|
||||
* sending results back.
|
||||
*
|
||||
* The file loaded will be lazily initialized the first time any of the workers
|
||||
* is called. This is done for optimal performance: if the farm is initialized,
|
||||
* but no call is made to it, child Node processes will be consuming the least
|
||||
* possible amount of memory.
|
||||
*
|
||||
* If an invalid message is detected, the child will exit (by throwing) with a
|
||||
* non-zero exit code.
|
||||
*/
|
||||
const messageListener = (request) => {
|
||||
switch (request[0]) {
|
||||
case CHILD_MESSAGE_INITIALIZE:
|
||||
const init = request;
|
||||
file = init[2];
|
||||
setupArgs = init[3];
|
||||
break;
|
||||
case CHILD_MESSAGE_CALL:
|
||||
const call = request;
|
||||
execMethod(call[2], call[3]);
|
||||
break;
|
||||
case CHILD_MESSAGE_END:
|
||||
end();
|
||||
break;
|
||||
case CHILD_MESSAGE_MEM_USAGE:
|
||||
reportMemoryUsage();
|
||||
break;
|
||||
case CHILD_MESSAGE_CALL_SETUP:
|
||||
if (initialized) reportSuccess(void 0);
|
||||
else {
|
||||
const main = __require(file);
|
||||
initialized = true;
|
||||
if (main.setup) execFunction(main.setup, main, setupArgs, reportSuccess, reportInitializeError);
|
||||
else reportSuccess(void 0);
|
||||
}
|
||||
break;
|
||||
default: throw new TypeError(`Unexpected request from parent process: ${request[0]}`);
|
||||
}
|
||||
};
|
||||
process.on("message", messageListener);
|
||||
function reportSuccess(result) {
|
||||
if (!process || !process.send) throw new Error("Child can only be used on a forked process");
|
||||
try {
|
||||
process.send([PARENT_MESSAGE_OK, result]);
|
||||
} catch (error) {
|
||||
if (types.isNativeError(error) && !error.message.includes(".send is not a function")) process.send([PARENT_MESSAGE_OK, packMessage(result)]);
|
||||
else throw error;
|
||||
}
|
||||
}
|
||||
function reportClientError(error) {
|
||||
return reportError(error, PARENT_MESSAGE_CLIENT_ERROR);
|
||||
}
|
||||
function reportInitializeError(error) {
|
||||
return reportError(error, PARENT_MESSAGE_SETUP_ERROR);
|
||||
}
|
||||
function reportMemoryUsage() {
|
||||
if (!process || !process.send) throw new Error("Child can only be used on a forked process");
|
||||
const msg = [PARENT_MESSAGE_MEM_USAGE, process.memoryUsage().heapUsed];
|
||||
process.send(msg);
|
||||
}
|
||||
function reportError(error, type) {
|
||||
if (!process || !process.send) throw new Error("Child can only be used on a forked process");
|
||||
if (error == null) error = new Error("\"null\" or \"undefined\" thrown");
|
||||
process.send([
|
||||
type,
|
||||
error.constructor && error.constructor.name,
|
||||
error.message,
|
||||
error.stack,
|
||||
typeof error === "object" ? { ...error } : error
|
||||
]);
|
||||
}
|
||||
function end() {
|
||||
const main = __require(file);
|
||||
if (!main.teardown) {
|
||||
exitProcess();
|
||||
return;
|
||||
}
|
||||
execFunction(main.teardown, main, [], exitProcess, exitProcess);
|
||||
}
|
||||
function exitProcess() {
|
||||
process.removeListener("message", messageListener);
|
||||
}
|
||||
function execMethod(method, args) {
|
||||
const main = __require(file);
|
||||
let fn;
|
||||
if (method === "default") fn = main.__esModule ? main.default : main;
|
||||
else fn = main[method];
|
||||
function execHelper() {
|
||||
execFunction(fn, main, args, reportSuccess, reportClientError);
|
||||
}
|
||||
if (initialized || !main.setup) {
|
||||
execHelper();
|
||||
return;
|
||||
}
|
||||
initialized = true;
|
||||
execFunction(main.setup, main, setupArgs, execHelper, reportInitializeError);
|
||||
}
|
||||
function execFunction(fn, ctx, args, onResult, onError) {
|
||||
let result;
|
||||
try {
|
||||
result = fn.apply(ctx, args);
|
||||
} catch (error) {
|
||||
onError(error);
|
||||
return;
|
||||
}
|
||||
if (isPromise(result)) result.then(onResult, onError);
|
||||
else onResult(result);
|
||||
}
|
||||
|
||||
//#endregion
|
||||
1
node_modules/jest-worker/build/threadChild.d.mts
generated
vendored
Normal file
1
node_modules/jest-worker/build/threadChild.d.mts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export { };
|
||||
347
node_modules/jest-worker/build/threadChild.js
generated
vendored
Normal file
347
node_modules/jest-worker/build/threadChild.js
generated
vendored
Normal file
@@ -0,0 +1,347 @@
|
||||
/*!
|
||||
* /**
|
||||
* * Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* *
|
||||
* * This source code is licensed under the MIT license found in the
|
||||
* * LICENSE file in the root directory of this source tree.
|
||||
* * /
|
||||
*/
|
||||
/******/ (() => { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
/******/ var __webpack_modules__ = ({
|
||||
|
||||
/***/ "./src/types.ts":
|
||||
/***/ ((__unused_webpack_module, exports) => {
|
||||
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
exports.WorkerStates = exports.WorkerEvents = exports.PARENT_MESSAGE_SETUP_ERROR = exports.PARENT_MESSAGE_OK = exports.PARENT_MESSAGE_MEM_USAGE = exports.PARENT_MESSAGE_CUSTOM = exports.PARENT_MESSAGE_CLIENT_ERROR = exports.CHILD_MESSAGE_MEM_USAGE = exports.CHILD_MESSAGE_INITIALIZE = exports.CHILD_MESSAGE_END = exports.CHILD_MESSAGE_CALL_SETUP = exports.CHILD_MESSAGE_CALL = void 0;
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
// Because of the dynamic nature of a worker communication process, all messages
|
||||
// coming from any of the other processes cannot be typed. Thus, many types
|
||||
// include "unknown" as a TS type, which is (unfortunately) correct here.
|
||||
|
||||
const CHILD_MESSAGE_INITIALIZE = exports.CHILD_MESSAGE_INITIALIZE = 0;
|
||||
const CHILD_MESSAGE_CALL = exports.CHILD_MESSAGE_CALL = 1;
|
||||
const CHILD_MESSAGE_END = exports.CHILD_MESSAGE_END = 2;
|
||||
const CHILD_MESSAGE_MEM_USAGE = exports.CHILD_MESSAGE_MEM_USAGE = 3;
|
||||
const CHILD_MESSAGE_CALL_SETUP = exports.CHILD_MESSAGE_CALL_SETUP = 4;
|
||||
const PARENT_MESSAGE_OK = exports.PARENT_MESSAGE_OK = 0;
|
||||
const PARENT_MESSAGE_CLIENT_ERROR = exports.PARENT_MESSAGE_CLIENT_ERROR = 1;
|
||||
const PARENT_MESSAGE_SETUP_ERROR = exports.PARENT_MESSAGE_SETUP_ERROR = 2;
|
||||
const PARENT_MESSAGE_CUSTOM = exports.PARENT_MESSAGE_CUSTOM = 3;
|
||||
const PARENT_MESSAGE_MEM_USAGE = exports.PARENT_MESSAGE_MEM_USAGE = 4;
|
||||
|
||||
// Option objects.
|
||||
|
||||
// Messages passed from the parent to the children.
|
||||
|
||||
// Messages passed from the children to the parent.
|
||||
|
||||
// Queue types.
|
||||
let WorkerStates = exports.WorkerStates = /*#__PURE__*/function (WorkerStates) {
|
||||
WorkerStates["STARTING"] = "starting";
|
||||
WorkerStates["OK"] = "ok";
|
||||
WorkerStates["OUT_OF_MEMORY"] = "oom";
|
||||
WorkerStates["RESTARTING"] = "restarting";
|
||||
WorkerStates["SHUTTING_DOWN"] = "shutting-down";
|
||||
WorkerStates["SHUT_DOWN"] = "shut-down";
|
||||
return WorkerStates;
|
||||
}({});
|
||||
let WorkerEvents = exports.WorkerEvents = /*#__PURE__*/function (WorkerEvents) {
|
||||
WorkerEvents["STATE_CHANGE"] = "state-change";
|
||||
return WorkerEvents;
|
||||
}({});
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./src/workers/isDataCloneError.ts":
|
||||
/***/ ((__unused_webpack_module, exports) => {
|
||||
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
exports.isDataCloneError = isDataCloneError;
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
// https://webidl.spec.whatwg.org/#datacloneerror
|
||||
const DATA_CLONE_ERROR_CODE = 25;
|
||||
|
||||
/**
|
||||
* Unfortunately, [`util.types.isNativeError(value)`](https://nodejs.org/api/util.html#utiltypesisnativeerrorvalue)
|
||||
* return `false` for `DataCloneError` error.
|
||||
* For this reason, try to detect it in this way
|
||||
*/
|
||||
function isDataCloneError(error) {
|
||||
return error != null && typeof error === 'object' && 'name' in error && error.name === 'DataCloneError' && 'message' in error && typeof error.message === 'string' && 'code' in error && error.code === DATA_CLONE_ERROR_CODE;
|
||||
}
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./src/workers/safeMessageTransferring.ts":
|
||||
/***/ ((__unused_webpack_module, exports) => {
|
||||
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
exports.packMessage = packMessage;
|
||||
exports.unpackMessage = unpackMessage;
|
||||
function _structuredClone() {
|
||||
const data = require("@ungap/structured-clone");
|
||||
_structuredClone = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
function packMessage(message) {
|
||||
return {
|
||||
__STRUCTURED_CLONE_SERIALIZED__: true,
|
||||
/**
|
||||
* Use the `json: true` option to avoid errors
|
||||
* caused by `function` or `symbol` types.
|
||||
* It's not ideal to lose `function` and `symbol` types,
|
||||
* but reliability is more important.
|
||||
*/
|
||||
data: (0, _structuredClone().serialize)(message, {
|
||||
json: true
|
||||
})
|
||||
};
|
||||
}
|
||||
function isTransferringContainer(message) {
|
||||
return message != null && typeof message === 'object' && '__STRUCTURED_CLONE_SERIALIZED__' in message && 'data' in message;
|
||||
}
|
||||
function unpackMessage(message) {
|
||||
if (isTransferringContainer(message)) {
|
||||
return (0, _structuredClone().deserialize)(message.data);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
/***/ })
|
||||
|
||||
/******/ });
|
||||
/************************************************************************/
|
||||
/******/ // The module cache
|
||||
/******/ var __webpack_module_cache__ = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/ // Check if module is in cache
|
||||
/******/ var cachedModule = __webpack_module_cache__[moduleId];
|
||||
/******/ if (cachedModule !== undefined) {
|
||||
/******/ return cachedModule.exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = __webpack_module_cache__[moduleId] = {
|
||||
/******/ // no module.id needed
|
||||
/******/ // no module.loaded needed
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/************************************************************************/
|
||||
var __webpack_exports__ = {};
|
||||
|
||||
|
||||
function _worker_threads() {
|
||||
const data = require("worker_threads");
|
||||
_worker_threads = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _jestUtil() {
|
||||
const data = require("jest-util");
|
||||
_jestUtil = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
var _types = __webpack_require__("./src/types.ts");
|
||||
var _isDataCloneError = __webpack_require__("./src/workers/isDataCloneError.ts");
|
||||
var _safeMessageTransferring = __webpack_require__("./src/workers/safeMessageTransferring.ts");
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
let file = null;
|
||||
let setupArgs = [];
|
||||
let initialized = false;
|
||||
|
||||
/**
|
||||
* This file is a small bootstrapper for workers. It sets up the communication
|
||||
* between the worker and the parent process, interpreting parent messages and
|
||||
* sending results back.
|
||||
*
|
||||
* The file loaded will be lazily initialized the first time any of the workers
|
||||
* is called. This is done for optimal performance: if the farm is initialized,
|
||||
* but no call is made to it, child Node processes will be consuming the least
|
||||
* possible amount of memory.
|
||||
*
|
||||
* If an invalid message is detected, the child will exit (by throwing) with a
|
||||
* non-zero exit code.
|
||||
*/
|
||||
const messageListener = request => {
|
||||
switch (request[0]) {
|
||||
case _types.CHILD_MESSAGE_INITIALIZE:
|
||||
const init = request;
|
||||
file = init[2];
|
||||
setupArgs = init[3];
|
||||
process.env.JEST_WORKER_ID = init[4];
|
||||
break;
|
||||
case _types.CHILD_MESSAGE_CALL:
|
||||
const call = request;
|
||||
execMethod(call[2], call[3]);
|
||||
break;
|
||||
case _types.CHILD_MESSAGE_END:
|
||||
end();
|
||||
break;
|
||||
case _types.CHILD_MESSAGE_MEM_USAGE:
|
||||
reportMemoryUsage();
|
||||
break;
|
||||
case _types.CHILD_MESSAGE_CALL_SETUP:
|
||||
if (initialized) {
|
||||
reportSuccess(void 0);
|
||||
} else {
|
||||
const main = require(file);
|
||||
initialized = true;
|
||||
if (main.setup) {
|
||||
execFunction(main.setup, main, setupArgs, reportSuccess, reportInitializeError);
|
||||
} else {
|
||||
reportSuccess(void 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new TypeError(`Unexpected request from parent process: ${request[0]}`);
|
||||
}
|
||||
};
|
||||
_worker_threads().parentPort.on('message', messageListener);
|
||||
function reportMemoryUsage() {
|
||||
if (_worker_threads().isMainThread) {
|
||||
throw new Error('Child can only be used on a forked process');
|
||||
}
|
||||
const msg = [_types.PARENT_MESSAGE_MEM_USAGE, process.memoryUsage().heapUsed];
|
||||
_worker_threads().parentPort.postMessage(msg);
|
||||
}
|
||||
function reportSuccess(result) {
|
||||
if (_worker_threads().isMainThread) {
|
||||
throw new Error('Child can only be used on a forked process');
|
||||
}
|
||||
try {
|
||||
_worker_threads().parentPort.postMessage([_types.PARENT_MESSAGE_OK, result]);
|
||||
} catch (error) {
|
||||
let resolvedError = error;
|
||||
// Try to handle https://html.spec.whatwg.org/multipage/structured-data.html#structuredserializeinternal
|
||||
// for `symbols` and `functions`
|
||||
if ((0, _isDataCloneError.isDataCloneError)(error)) {
|
||||
try {
|
||||
_worker_threads().parentPort.postMessage([_types.PARENT_MESSAGE_OK, (0, _safeMessageTransferring.packMessage)(result)]);
|
||||
return;
|
||||
} catch (secondTryError) {
|
||||
resolvedError = secondTryError;
|
||||
}
|
||||
}
|
||||
// Handling it here to avoid unhandled rejection
|
||||
// which is hard to distinguish on the parent side
|
||||
reportClientError(resolvedError);
|
||||
}
|
||||
}
|
||||
function reportClientError(error) {
|
||||
return reportError(error, _types.PARENT_MESSAGE_CLIENT_ERROR);
|
||||
}
|
||||
function reportInitializeError(error) {
|
||||
return reportError(error, _types.PARENT_MESSAGE_SETUP_ERROR);
|
||||
}
|
||||
function reportError(error, type) {
|
||||
if (_worker_threads().isMainThread) {
|
||||
throw new Error('Child can only be used on a forked process');
|
||||
}
|
||||
if (error == null) {
|
||||
error = new Error('"null" or "undefined" thrown');
|
||||
}
|
||||
_worker_threads().parentPort.postMessage([type, error.constructor && error.constructor.name, error.message, error.stack, typeof error === 'object' ? {
|
||||
...error
|
||||
} : error]);
|
||||
}
|
||||
function end() {
|
||||
const main = require(file);
|
||||
if (!main.teardown) {
|
||||
exitProcess();
|
||||
return;
|
||||
}
|
||||
execFunction(main.teardown, main, [], exitProcess, exitProcess);
|
||||
}
|
||||
function exitProcess() {
|
||||
// Clean up open handles so the worker ideally exits gracefully
|
||||
_worker_threads().parentPort.removeListener('message', messageListener);
|
||||
}
|
||||
function execMethod(method, args) {
|
||||
const main = require(file);
|
||||
let fn;
|
||||
if (method === 'default') {
|
||||
fn = main.__esModule ? main.default : main;
|
||||
} else {
|
||||
fn = main[method];
|
||||
}
|
||||
function execHelper() {
|
||||
execFunction(fn, main, args, reportSuccess, reportClientError);
|
||||
}
|
||||
if (initialized || !main.setup) {
|
||||
execHelper();
|
||||
return;
|
||||
}
|
||||
initialized = true;
|
||||
execFunction(main.setup, main, setupArgs, execHelper, reportInitializeError);
|
||||
}
|
||||
function execFunction(fn, ctx, args, onResult, onError) {
|
||||
let result;
|
||||
try {
|
||||
result = fn.apply(ctx, args);
|
||||
} catch (error) {
|
||||
onError(error);
|
||||
return;
|
||||
}
|
||||
if ((0, _jestUtil().isPromise)(result)) {
|
||||
result.then(onResult, onError);
|
||||
} else {
|
||||
onResult(result);
|
||||
}
|
||||
}
|
||||
module.exports = __webpack_exports__;
|
||||
/******/ })()
|
||||
;
|
||||
172
node_modules/jest-worker/build/threadChild.mjs
generated
vendored
Normal file
172
node_modules/jest-worker/build/threadChild.mjs
generated
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
import { createRequire } from "node:module";
|
||||
import { isMainThread, parentPort } from "worker_threads";
|
||||
import { isPromise } from "jest-util";
|
||||
import { serialize } from "@ungap/structured-clone";
|
||||
|
||||
//#region rolldown:runtime
|
||||
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
||||
|
||||
//#endregion
|
||||
//#region src/types.ts
|
||||
const CHILD_MESSAGE_INITIALIZE = 0;
|
||||
const CHILD_MESSAGE_CALL = 1;
|
||||
const CHILD_MESSAGE_END = 2;
|
||||
const CHILD_MESSAGE_MEM_USAGE = 3;
|
||||
const CHILD_MESSAGE_CALL_SETUP = 4;
|
||||
const PARENT_MESSAGE_OK = 0;
|
||||
const PARENT_MESSAGE_CLIENT_ERROR = 1;
|
||||
const PARENT_MESSAGE_SETUP_ERROR = 2;
|
||||
const PARENT_MESSAGE_MEM_USAGE = 4;
|
||||
|
||||
//#endregion
|
||||
//#region src/workers/isDataCloneError.ts
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
const DATA_CLONE_ERROR_CODE = 25;
|
||||
/**
|
||||
* Unfortunately, [`util.types.isNativeError(value)`](https://nodejs.org/api/util.html#utiltypesisnativeerrorvalue)
|
||||
* return `false` for `DataCloneError` error.
|
||||
* For this reason, try to detect it in this way
|
||||
*/
|
||||
function isDataCloneError(error) {
|
||||
return error != null && typeof error === "object" && "name" in error && error.name === "DataCloneError" && "message" in error && typeof error.message === "string" && "code" in error && error.code === DATA_CLONE_ERROR_CODE;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
//#region src/workers/safeMessageTransferring.ts
|
||||
function packMessage(message) {
|
||||
return {
|
||||
__STRUCTURED_CLONE_SERIALIZED__: true,
|
||||
data: serialize(message, { json: true })
|
||||
};
|
||||
}
|
||||
|
||||
//#endregion
|
||||
//#region src/workers/threadChild.ts
|
||||
let file = null;
|
||||
let setupArgs = [];
|
||||
let initialized = false;
|
||||
/**
|
||||
* This file is a small bootstrapper for workers. It sets up the communication
|
||||
* between the worker and the parent process, interpreting parent messages and
|
||||
* sending results back.
|
||||
*
|
||||
* The file loaded will be lazily initialized the first time any of the workers
|
||||
* is called. This is done for optimal performance: if the farm is initialized,
|
||||
* but no call is made to it, child Node processes will be consuming the least
|
||||
* possible amount of memory.
|
||||
*
|
||||
* If an invalid message is detected, the child will exit (by throwing) with a
|
||||
* non-zero exit code.
|
||||
*/
|
||||
const messageListener = (request) => {
|
||||
switch (request[0]) {
|
||||
case CHILD_MESSAGE_INITIALIZE:
|
||||
const init = request;
|
||||
file = init[2];
|
||||
setupArgs = init[3];
|
||||
process.env.JEST_WORKER_ID = init[4];
|
||||
break;
|
||||
case CHILD_MESSAGE_CALL:
|
||||
const call = request;
|
||||
execMethod(call[2], call[3]);
|
||||
break;
|
||||
case CHILD_MESSAGE_END:
|
||||
end();
|
||||
break;
|
||||
case CHILD_MESSAGE_MEM_USAGE:
|
||||
reportMemoryUsage();
|
||||
break;
|
||||
case CHILD_MESSAGE_CALL_SETUP:
|
||||
if (initialized) reportSuccess(void 0);
|
||||
else {
|
||||
const main = __require(file);
|
||||
initialized = true;
|
||||
if (main.setup) execFunction(main.setup, main, setupArgs, reportSuccess, reportInitializeError);
|
||||
else reportSuccess(void 0);
|
||||
}
|
||||
break;
|
||||
default: throw new TypeError(`Unexpected request from parent process: ${request[0]}`);
|
||||
}
|
||||
};
|
||||
parentPort.on("message", messageListener);
|
||||
function reportMemoryUsage() {
|
||||
if (isMainThread) throw new Error("Child can only be used on a forked process");
|
||||
const msg = [PARENT_MESSAGE_MEM_USAGE, process.memoryUsage().heapUsed];
|
||||
parentPort.postMessage(msg);
|
||||
}
|
||||
function reportSuccess(result) {
|
||||
if (isMainThread) throw new Error("Child can only be used on a forked process");
|
||||
try {
|
||||
parentPort.postMessage([PARENT_MESSAGE_OK, result]);
|
||||
} catch (error) {
|
||||
let resolvedError = error;
|
||||
if (isDataCloneError(error)) try {
|
||||
parentPort.postMessage([PARENT_MESSAGE_OK, packMessage(result)]);
|
||||
return;
|
||||
} catch (secondTryError) {
|
||||
resolvedError = secondTryError;
|
||||
}
|
||||
reportClientError(resolvedError);
|
||||
}
|
||||
}
|
||||
function reportClientError(error) {
|
||||
return reportError(error, PARENT_MESSAGE_CLIENT_ERROR);
|
||||
}
|
||||
function reportInitializeError(error) {
|
||||
return reportError(error, PARENT_MESSAGE_SETUP_ERROR);
|
||||
}
|
||||
function reportError(error, type) {
|
||||
if (isMainThread) throw new Error("Child can only be used on a forked process");
|
||||
if (error == null) error = new Error("\"null\" or \"undefined\" thrown");
|
||||
parentPort.postMessage([
|
||||
type,
|
||||
error.constructor && error.constructor.name,
|
||||
error.message,
|
||||
error.stack,
|
||||
typeof error === "object" ? { ...error } : error
|
||||
]);
|
||||
}
|
||||
function end() {
|
||||
const main = __require(file);
|
||||
if (!main.teardown) {
|
||||
exitProcess();
|
||||
return;
|
||||
}
|
||||
execFunction(main.teardown, main, [], exitProcess, exitProcess);
|
||||
}
|
||||
function exitProcess() {
|
||||
parentPort.removeListener("message", messageListener);
|
||||
}
|
||||
function execMethod(method, args) {
|
||||
const main = __require(file);
|
||||
let fn;
|
||||
if (method === "default") fn = main.__esModule ? main.default : main;
|
||||
else fn = main[method];
|
||||
function execHelper() {
|
||||
execFunction(fn, main, args, reportSuccess, reportClientError);
|
||||
}
|
||||
if (initialized || !main.setup) {
|
||||
execHelper();
|
||||
return;
|
||||
}
|
||||
initialized = true;
|
||||
execFunction(main.setup, main, setupArgs, execHelper, reportInitializeError);
|
||||
}
|
||||
function execFunction(fn, ctx, args, onResult, onError) {
|
||||
let result;
|
||||
try {
|
||||
result = fn.apply(ctx, args);
|
||||
} catch (error) {
|
||||
onError(error);
|
||||
return;
|
||||
}
|
||||
if (isPromise(result)) result.then(onResult, onError);
|
||||
else onResult(result);
|
||||
}
|
||||
|
||||
//#endregion
|
||||
72
node_modules/jest-worker/build/types.js
generated
vendored
72
node_modules/jest-worker/build/types.js
generated
vendored
@@ -1,72 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, '__esModule', {
|
||||
value: true
|
||||
});
|
||||
exports.WorkerStates =
|
||||
exports.WorkerEvents =
|
||||
exports.PARENT_MESSAGE_SETUP_ERROR =
|
||||
exports.PARENT_MESSAGE_OK =
|
||||
exports.PARENT_MESSAGE_MEM_USAGE =
|
||||
exports.PARENT_MESSAGE_CUSTOM =
|
||||
exports.PARENT_MESSAGE_CLIENT_ERROR =
|
||||
exports.CHILD_MESSAGE_MEM_USAGE =
|
||||
exports.CHILD_MESSAGE_INITIALIZE =
|
||||
exports.CHILD_MESSAGE_END =
|
||||
exports.CHILD_MESSAGE_CALL_SETUP =
|
||||
exports.CHILD_MESSAGE_CALL =
|
||||
void 0;
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
// Because of the dynamic nature of a worker communication process, all messages
|
||||
// coming from any of the other processes cannot be typed. Thus, many types
|
||||
// include "unknown" as a TS type, which is (unfortunately) correct here.
|
||||
|
||||
const CHILD_MESSAGE_INITIALIZE = 0;
|
||||
exports.CHILD_MESSAGE_INITIALIZE = CHILD_MESSAGE_INITIALIZE;
|
||||
const CHILD_MESSAGE_CALL = 1;
|
||||
exports.CHILD_MESSAGE_CALL = CHILD_MESSAGE_CALL;
|
||||
const CHILD_MESSAGE_END = 2;
|
||||
exports.CHILD_MESSAGE_END = CHILD_MESSAGE_END;
|
||||
const CHILD_MESSAGE_MEM_USAGE = 3;
|
||||
exports.CHILD_MESSAGE_MEM_USAGE = CHILD_MESSAGE_MEM_USAGE;
|
||||
const CHILD_MESSAGE_CALL_SETUP = 4;
|
||||
exports.CHILD_MESSAGE_CALL_SETUP = CHILD_MESSAGE_CALL_SETUP;
|
||||
const PARENT_MESSAGE_OK = 0;
|
||||
exports.PARENT_MESSAGE_OK = PARENT_MESSAGE_OK;
|
||||
const PARENT_MESSAGE_CLIENT_ERROR = 1;
|
||||
exports.PARENT_MESSAGE_CLIENT_ERROR = PARENT_MESSAGE_CLIENT_ERROR;
|
||||
const PARENT_MESSAGE_SETUP_ERROR = 2;
|
||||
exports.PARENT_MESSAGE_SETUP_ERROR = PARENT_MESSAGE_SETUP_ERROR;
|
||||
const PARENT_MESSAGE_CUSTOM = 3;
|
||||
exports.PARENT_MESSAGE_CUSTOM = PARENT_MESSAGE_CUSTOM;
|
||||
const PARENT_MESSAGE_MEM_USAGE = 4;
|
||||
|
||||
// Option objects.
|
||||
|
||||
// Messages passed from the parent to the children.
|
||||
|
||||
// Messages passed from the children to the parent.
|
||||
|
||||
// Queue types.
|
||||
exports.PARENT_MESSAGE_MEM_USAGE = PARENT_MESSAGE_MEM_USAGE;
|
||||
let WorkerStates = /*#__PURE__*/ (function (WorkerStates) {
|
||||
WorkerStates['STARTING'] = 'starting';
|
||||
WorkerStates['OK'] = 'ok';
|
||||
WorkerStates['OUT_OF_MEMORY'] = 'oom';
|
||||
WorkerStates['RESTARTING'] = 'restarting';
|
||||
WorkerStates['SHUTTING_DOWN'] = 'shutting-down';
|
||||
WorkerStates['SHUT_DOWN'] = 'shut-down';
|
||||
return WorkerStates;
|
||||
})({});
|
||||
exports.WorkerStates = WorkerStates;
|
||||
let WorkerEvents = /*#__PURE__*/ (function (WorkerEvents) {
|
||||
WorkerEvents['STATE_CHANGE'] = 'state-change';
|
||||
return WorkerEvents;
|
||||
})({});
|
||||
exports.WorkerEvents = WorkerEvents;
|
||||
490
node_modules/jest-worker/build/workers/ChildProcessWorker.js
generated
vendored
490
node_modules/jest-worker/build/workers/ChildProcessWorker.js
generated
vendored
@@ -1,490 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, '__esModule', {
|
||||
value: true
|
||||
});
|
||||
exports.default = exports.SIGKILL_DELAY = void 0;
|
||||
function _child_process() {
|
||||
const data = require('child_process');
|
||||
_child_process = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _os() {
|
||||
const data = require('os');
|
||||
_os = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _mergeStream() {
|
||||
const data = _interopRequireDefault(require('merge-stream'));
|
||||
_mergeStream = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _supportsColor() {
|
||||
const data = require('supports-color');
|
||||
_supportsColor = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
var _types = require('../types');
|
||||
var _WorkerAbstract = _interopRequireDefault(require('./WorkerAbstract'));
|
||||
function _interopRequireDefault(obj) {
|
||||
return obj && obj.__esModule ? obj : {default: obj};
|
||||
}
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
const SIGNAL_BASE_EXIT_CODE = 128;
|
||||
const SIGKILL_EXIT_CODE = SIGNAL_BASE_EXIT_CODE + 9;
|
||||
const SIGTERM_EXIT_CODE = SIGNAL_BASE_EXIT_CODE + 15;
|
||||
|
||||
// How long to wait after SIGTERM before sending SIGKILL
|
||||
const SIGKILL_DELAY = 500;
|
||||
|
||||
/**
|
||||
* This class wraps the child process and provides a nice interface to
|
||||
* communicate with. It takes care of:
|
||||
*
|
||||
* - Re-spawning the process if it dies.
|
||||
* - Queues calls while the worker is busy.
|
||||
* - Re-sends the requests if the worker blew up.
|
||||
*
|
||||
* The reason for queueing them here (since childProcess.send also has an
|
||||
* internal queue) is because the worker could be doing asynchronous work, and
|
||||
* this would lead to the child process to read its receiving buffer and start a
|
||||
* second call. By queueing calls here, we don't send the next call to the
|
||||
* children until we receive the result of the previous one.
|
||||
*
|
||||
* As soon as a request starts to be processed by a worker, its "processed"
|
||||
* field is changed to "true", so that other workers which might encounter the
|
||||
* same call skip it.
|
||||
*/
|
||||
exports.SIGKILL_DELAY = SIGKILL_DELAY;
|
||||
class ChildProcessWorker extends _WorkerAbstract.default {
|
||||
_child;
|
||||
_options;
|
||||
_request;
|
||||
_retries;
|
||||
_onProcessEnd;
|
||||
_onCustomMessage;
|
||||
_stdout;
|
||||
_stderr;
|
||||
_stderrBuffer = [];
|
||||
_memoryUsagePromise;
|
||||
_resolveMemoryUsage;
|
||||
_childIdleMemoryUsage;
|
||||
_childIdleMemoryUsageLimit;
|
||||
_memoryUsageCheck = false;
|
||||
_childWorkerPath;
|
||||
constructor(options) {
|
||||
super(options);
|
||||
this._options = options;
|
||||
this._request = null;
|
||||
this._stdout = null;
|
||||
this._stderr = null;
|
||||
this._childIdleMemoryUsage = null;
|
||||
this._childIdleMemoryUsageLimit = options.idleMemoryLimit || null;
|
||||
this._childWorkerPath =
|
||||
options.childWorkerPath || require.resolve('./processChild');
|
||||
this.state = _types.WorkerStates.STARTING;
|
||||
this.initialize();
|
||||
}
|
||||
initialize() {
|
||||
if (
|
||||
this.state === _types.WorkerStates.OUT_OF_MEMORY ||
|
||||
this.state === _types.WorkerStates.SHUTTING_DOWN ||
|
||||
this.state === _types.WorkerStates.SHUT_DOWN
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (this._child && this._child.connected) {
|
||||
this._child.kill('SIGKILL');
|
||||
}
|
||||
this.state = _types.WorkerStates.STARTING;
|
||||
const forceColor = _supportsColor().stdout
|
||||
? {
|
||||
FORCE_COLOR: '1'
|
||||
}
|
||||
: {};
|
||||
const silent = this._options.silent ?? true;
|
||||
if (!silent) {
|
||||
// NOTE: Detecting an out of memory crash is independent of idle memory usage monitoring. We want to
|
||||
// monitor for a crash occurring so that it can be handled as required and so we can tell the difference
|
||||
// between an OOM crash and another kind of crash. We need to do this because if a worker crashes due to
|
||||
// an OOM event sometimes it isn't seen by the worker pool and it just sits there waiting for the worker
|
||||
// to respond and it never will.
|
||||
console.warn('Unable to detect out of memory event if silent === false');
|
||||
}
|
||||
this._stderrBuffer = [];
|
||||
const options = {
|
||||
cwd: process.cwd(),
|
||||
env: {
|
||||
...process.env,
|
||||
JEST_WORKER_ID: String(this._options.workerId + 1),
|
||||
// 0-indexed workerId, 1-indexed JEST_WORKER_ID
|
||||
...forceColor
|
||||
},
|
||||
// Suppress --debug / --inspect flags while preserving others (like --harmony).
|
||||
execArgv: process.execArgv.filter(v => !/^--(debug|inspect)/.test(v)),
|
||||
// default to advanced serialization in order to match worker threads
|
||||
serialization: 'advanced',
|
||||
silent,
|
||||
...this._options.forkOptions
|
||||
};
|
||||
this._child = (0, _child_process().fork)(
|
||||
this._childWorkerPath,
|
||||
[],
|
||||
options
|
||||
);
|
||||
if (this._child.stdout) {
|
||||
if (!this._stdout) {
|
||||
// We need to add a permanent stream to the merged stream to prevent it
|
||||
// from ending when the subprocess stream ends
|
||||
this._stdout = (0, _mergeStream().default)(this._getFakeStream());
|
||||
}
|
||||
this._stdout.add(this._child.stdout);
|
||||
}
|
||||
if (this._child.stderr) {
|
||||
if (!this._stderr) {
|
||||
// We need to add a permanent stream to the merged stream to prevent it
|
||||
// from ending when the subprocess stream ends
|
||||
this._stderr = (0, _mergeStream().default)(this._getFakeStream());
|
||||
}
|
||||
this._stderr.add(this._child.stderr);
|
||||
this._child.stderr.on('data', this.stderrDataHandler.bind(this));
|
||||
}
|
||||
this._child.on('message', this._onMessage.bind(this));
|
||||
this._child.on('exit', this._onExit.bind(this));
|
||||
this._child.on('disconnect', this._onDisconnect.bind(this));
|
||||
this._child.send([
|
||||
_types.CHILD_MESSAGE_INITIALIZE,
|
||||
false,
|
||||
this._options.workerPath,
|
||||
this._options.setupArgs
|
||||
]);
|
||||
this._retries++;
|
||||
|
||||
// If we exceeded the amount of retries, we will emulate an error reply
|
||||
// coming from the child. This avoids code duplication related with cleaning
|
||||
// the queue, and scheduling the next call.
|
||||
if (this._retries > this._options.maxRetries) {
|
||||
const error = new Error(
|
||||
`Jest worker encountered ${this._retries} child process exceptions, exceeding retry limit`
|
||||
);
|
||||
this._onMessage([
|
||||
_types.PARENT_MESSAGE_CLIENT_ERROR,
|
||||
error.name,
|
||||
error.message,
|
||||
error.stack,
|
||||
{
|
||||
type: 'WorkerError'
|
||||
}
|
||||
]);
|
||||
|
||||
// Clear the request so we don't keep executing it.
|
||||
this._request = null;
|
||||
}
|
||||
this.state = _types.WorkerStates.OK;
|
||||
if (this._resolveWorkerReady) {
|
||||
this._resolveWorkerReady();
|
||||
}
|
||||
}
|
||||
stderrDataHandler(chunk) {
|
||||
if (chunk) {
|
||||
this._stderrBuffer.push(Buffer.from(chunk));
|
||||
}
|
||||
this._detectOutOfMemoryCrash();
|
||||
if (this.state === _types.WorkerStates.OUT_OF_MEMORY) {
|
||||
this._workerReadyPromise = undefined;
|
||||
this._resolveWorkerReady = undefined;
|
||||
this.killChild();
|
||||
this._shutdown();
|
||||
}
|
||||
}
|
||||
_detectOutOfMemoryCrash() {
|
||||
try {
|
||||
const bufferStr = Buffer.concat(this._stderrBuffer).toString('utf8');
|
||||
if (
|
||||
bufferStr.includes('heap out of memory') ||
|
||||
bufferStr.includes('allocation failure;') ||
|
||||
bufferStr.includes('Last few GCs')
|
||||
) {
|
||||
if (
|
||||
this.state === _types.WorkerStates.OK ||
|
||||
this.state === _types.WorkerStates.STARTING
|
||||
) {
|
||||
this.state = _types.WorkerStates.OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error looking for out of memory crash', err);
|
||||
}
|
||||
}
|
||||
_onDisconnect() {
|
||||
this._workerReadyPromise = undefined;
|
||||
this._resolveWorkerReady = undefined;
|
||||
this._detectOutOfMemoryCrash();
|
||||
if (this.state === _types.WorkerStates.OUT_OF_MEMORY) {
|
||||
this.killChild();
|
||||
this._shutdown();
|
||||
}
|
||||
}
|
||||
_onMessage(response) {
|
||||
// Ignore messages not intended for us
|
||||
if (!Array.isArray(response)) return;
|
||||
|
||||
// TODO: Add appropriate type check
|
||||
let error;
|
||||
switch (response[0]) {
|
||||
case _types.PARENT_MESSAGE_OK:
|
||||
this._onProcessEnd(null, response[1]);
|
||||
break;
|
||||
case _types.PARENT_MESSAGE_CLIENT_ERROR:
|
||||
error = response[4];
|
||||
if (error != null && typeof error === 'object') {
|
||||
const extra = error;
|
||||
// @ts-expect-error: no index
|
||||
const NativeCtor = globalThis[response[1]];
|
||||
const Ctor = typeof NativeCtor === 'function' ? NativeCtor : Error;
|
||||
error = new Ctor(response[2]);
|
||||
error.type = response[1];
|
||||
error.stack = response[3];
|
||||
for (const key in extra) {
|
||||
error[key] = extra[key];
|
||||
}
|
||||
}
|
||||
this._onProcessEnd(error, null);
|
||||
break;
|
||||
case _types.PARENT_MESSAGE_SETUP_ERROR:
|
||||
error = new Error(`Error when calling setup: ${response[2]}`);
|
||||
error.type = response[1];
|
||||
error.stack = response[3];
|
||||
this._onProcessEnd(error, null);
|
||||
break;
|
||||
case _types.PARENT_MESSAGE_CUSTOM:
|
||||
this._onCustomMessage(response[1]);
|
||||
break;
|
||||
case _types.PARENT_MESSAGE_MEM_USAGE:
|
||||
this._childIdleMemoryUsage = response[1];
|
||||
if (this._resolveMemoryUsage) {
|
||||
this._resolveMemoryUsage(response[1]);
|
||||
this._resolveMemoryUsage = undefined;
|
||||
this._memoryUsagePromise = undefined;
|
||||
}
|
||||
this._performRestartIfRequired();
|
||||
break;
|
||||
default:
|
||||
// Ignore messages not intended for us
|
||||
break;
|
||||
}
|
||||
}
|
||||
_performRestartIfRequired() {
|
||||
if (this._memoryUsageCheck) {
|
||||
this._memoryUsageCheck = false;
|
||||
let limit = this._childIdleMemoryUsageLimit;
|
||||
|
||||
// TODO: At some point it would make sense to make use of
|
||||
// stringToBytes found in jest-config, however as this
|
||||
// package does not have any dependencies on an other jest
|
||||
// packages that can wait until some other time.
|
||||
if (limit && limit > 0 && limit <= 1) {
|
||||
limit = Math.floor((0, _os().totalmem)() * limit);
|
||||
} else if (limit) {
|
||||
limit = Math.floor(limit);
|
||||
}
|
||||
if (
|
||||
limit &&
|
||||
this._childIdleMemoryUsage &&
|
||||
this._childIdleMemoryUsage > limit
|
||||
) {
|
||||
this.state = _types.WorkerStates.RESTARTING;
|
||||
this.killChild();
|
||||
}
|
||||
}
|
||||
}
|
||||
_onExit(exitCode, signal) {
|
||||
this._workerReadyPromise = undefined;
|
||||
this._resolveWorkerReady = undefined;
|
||||
this._detectOutOfMemoryCrash();
|
||||
if (exitCode !== 0 && this.state === _types.WorkerStates.OUT_OF_MEMORY) {
|
||||
this._onProcessEnd(
|
||||
new Error('Jest worker ran out of memory and crashed'),
|
||||
null
|
||||
);
|
||||
this._shutdown();
|
||||
} else if (
|
||||
(exitCode !== 0 &&
|
||||
exitCode !== null &&
|
||||
exitCode !== SIGTERM_EXIT_CODE &&
|
||||
exitCode !== SIGKILL_EXIT_CODE &&
|
||||
this.state !== _types.WorkerStates.SHUTTING_DOWN) ||
|
||||
this.state === _types.WorkerStates.RESTARTING
|
||||
) {
|
||||
this.state = _types.WorkerStates.RESTARTING;
|
||||
this.initialize();
|
||||
if (this._request) {
|
||||
this._child.send(this._request);
|
||||
}
|
||||
} else {
|
||||
// At this point, it's not clear why the child process exited. There could
|
||||
// be several reasons:
|
||||
//
|
||||
// 1. The child process exited successfully after finishing its work.
|
||||
// This is the most likely case.
|
||||
// 2. The child process crashed in a manner that wasn't caught through
|
||||
// any of the heuristic-based checks above.
|
||||
// 3. The child process was killed by another process or daemon unrelated
|
||||
// to Jest. For example, oom-killer on Linux may have picked the child
|
||||
// process to kill because overall system memory is constrained.
|
||||
//
|
||||
// If there's a pending request to the child process in any of those
|
||||
// situations, the request still needs to be handled in some manner before
|
||||
// entering the shutdown phase. Otherwise the caller expecting a response
|
||||
// from the worker will never receive indication that something unexpected
|
||||
// happened and hang forever.
|
||||
//
|
||||
// In normal operation, the request is handled and cleared before the
|
||||
// child process exits. If it's still present, it's not clear what
|
||||
// happened and probably best to throw an error. In practice, this usually
|
||||
// happens when the child process is killed externally.
|
||||
//
|
||||
// There's a reasonable argument that the child process should be retried
|
||||
// with request re-sent in this scenario. However, if the problem was due
|
||||
// to situations such as oom-killer attempting to free up system
|
||||
// resources, retrying would exacerbate the problem.
|
||||
const isRequestStillPending = !!this._request;
|
||||
if (isRequestStillPending) {
|
||||
// If a signal is present, we can be reasonably confident the process
|
||||
// was killed externally. Log this fact so it's more clear to users that
|
||||
// something went wrong externally, rather than a bug in Jest itself.
|
||||
const error = new Error(
|
||||
signal != null
|
||||
? `A jest worker process (pid=${this._child.pid}) was terminated by another process: signal=${signal}, exitCode=${exitCode}. Operating system logs may contain more information on why this occurred.`
|
||||
: `A jest worker process (pid=${this._child.pid}) crashed for an unknown reason: exitCode=${exitCode}`
|
||||
);
|
||||
this._onProcessEnd(error, null);
|
||||
}
|
||||
this._shutdown();
|
||||
}
|
||||
}
|
||||
send(request, onProcessStart, onProcessEnd, onCustomMessage) {
|
||||
this._stderrBuffer = [];
|
||||
onProcessStart(this);
|
||||
this._onProcessEnd = (...args) => {
|
||||
const hasRequest = !!this._request;
|
||||
|
||||
// Clean the request to avoid sending past requests to workers that fail
|
||||
// while waiting for a new request (timers, unhandled rejections...)
|
||||
this._request = null;
|
||||
if (
|
||||
this._childIdleMemoryUsageLimit &&
|
||||
this._child.connected &&
|
||||
hasRequest
|
||||
) {
|
||||
this.checkMemoryUsage();
|
||||
}
|
||||
return onProcessEnd(...args);
|
||||
};
|
||||
this._onCustomMessage = (...arg) => onCustomMessage(...arg);
|
||||
this._request = request;
|
||||
this._retries = 0;
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
this._child.send(request, () => {});
|
||||
}
|
||||
waitForExit() {
|
||||
return this._exitPromise;
|
||||
}
|
||||
killChild() {
|
||||
// We store a reference so that there's no way we can accidentally
|
||||
// kill a new worker that has been spawned.
|
||||
const childToKill = this._child;
|
||||
childToKill.kill('SIGTERM');
|
||||
return setTimeout(() => childToKill.kill('SIGKILL'), SIGKILL_DELAY);
|
||||
}
|
||||
forceExit() {
|
||||
this.state = _types.WorkerStates.SHUTTING_DOWN;
|
||||
const sigkillTimeout = this.killChild();
|
||||
this._exitPromise.then(() => clearTimeout(sigkillTimeout));
|
||||
}
|
||||
getWorkerId() {
|
||||
return this._options.workerId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the process id of the worker.
|
||||
*
|
||||
* @returns Process id.
|
||||
*/
|
||||
getWorkerSystemId() {
|
||||
return this._child.pid;
|
||||
}
|
||||
getStdout() {
|
||||
return this._stdout;
|
||||
}
|
||||
getStderr() {
|
||||
return this._stderr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the last reported memory usage.
|
||||
*
|
||||
* @returns Memory usage in bytes.
|
||||
*/
|
||||
getMemoryUsage() {
|
||||
if (!this._memoryUsagePromise) {
|
||||
let rejectCallback;
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
this._resolveMemoryUsage = resolve;
|
||||
rejectCallback = reject;
|
||||
});
|
||||
this._memoryUsagePromise = promise;
|
||||
if (!this._child.connected && rejectCallback) {
|
||||
rejectCallback(new Error('Child process is not running.'));
|
||||
this._memoryUsagePromise = undefined;
|
||||
this._resolveMemoryUsage = undefined;
|
||||
return promise;
|
||||
}
|
||||
this._child.send([_types.CHILD_MESSAGE_MEM_USAGE], err => {
|
||||
if (err && rejectCallback) {
|
||||
this._memoryUsagePromise = undefined;
|
||||
this._resolveMemoryUsage = undefined;
|
||||
rejectCallback(err);
|
||||
}
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
return this._memoryUsagePromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets updated memory usage and restarts if required
|
||||
*/
|
||||
checkMemoryUsage() {
|
||||
if (this._childIdleMemoryUsageLimit) {
|
||||
this._memoryUsageCheck = true;
|
||||
this._child.send([_types.CHILD_MESSAGE_MEM_USAGE], err => {
|
||||
if (err) {
|
||||
console.error('Unable to check memory usage', err);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.warn(
|
||||
'Memory usage of workers can only be checked if a limit is set'
|
||||
);
|
||||
}
|
||||
}
|
||||
isWorkerRunning() {
|
||||
return this._child.connected && !this._child.killed;
|
||||
}
|
||||
}
|
||||
exports.default = ChildProcessWorker;
|
||||
359
node_modules/jest-worker/build/workers/NodeThreadsWorker.js
generated
vendored
359
node_modules/jest-worker/build/workers/NodeThreadsWorker.js
generated
vendored
@@ -1,359 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, '__esModule', {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
function _os() {
|
||||
const data = require('os');
|
||||
_os = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _worker_threads() {
|
||||
const data = require('worker_threads');
|
||||
_worker_threads = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _mergeStream() {
|
||||
const data = _interopRequireDefault(require('merge-stream'));
|
||||
_mergeStream = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
var _types = require('../types');
|
||||
var _WorkerAbstract = _interopRequireDefault(require('./WorkerAbstract'));
|
||||
function _interopRequireDefault(obj) {
|
||||
return obj && obj.__esModule ? obj : {default: obj};
|
||||
}
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
class ExperimentalWorker extends _WorkerAbstract.default {
|
||||
_worker;
|
||||
_options;
|
||||
_request;
|
||||
_retries;
|
||||
_onProcessEnd;
|
||||
_onCustomMessage;
|
||||
_stdout;
|
||||
_stderr;
|
||||
_memoryUsagePromise;
|
||||
_resolveMemoryUsage;
|
||||
_childWorkerPath;
|
||||
_childIdleMemoryUsage;
|
||||
_childIdleMemoryUsageLimit;
|
||||
_memoryUsageCheck = false;
|
||||
constructor(options) {
|
||||
super(options);
|
||||
this._options = options;
|
||||
this._request = null;
|
||||
this._stdout = null;
|
||||
this._stderr = null;
|
||||
this._childWorkerPath =
|
||||
options.childWorkerPath || require.resolve('./threadChild');
|
||||
this._childIdleMemoryUsage = null;
|
||||
this._childIdleMemoryUsageLimit = options.idleMemoryLimit || null;
|
||||
this.initialize();
|
||||
}
|
||||
initialize() {
|
||||
if (
|
||||
this.state === _types.WorkerStates.OUT_OF_MEMORY ||
|
||||
this.state === _types.WorkerStates.SHUTTING_DOWN ||
|
||||
this.state === _types.WorkerStates.SHUT_DOWN
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (this._worker) {
|
||||
this._worker.terminate();
|
||||
}
|
||||
this.state = _types.WorkerStates.STARTING;
|
||||
this._worker = new (_worker_threads().Worker)(this._childWorkerPath, {
|
||||
eval: false,
|
||||
resourceLimits: this._options.resourceLimits,
|
||||
stderr: true,
|
||||
stdout: true,
|
||||
workerData: this._options.workerData,
|
||||
...this._options.forkOptions
|
||||
});
|
||||
if (this._worker.stdout) {
|
||||
if (!this._stdout) {
|
||||
// We need to add a permanent stream to the merged stream to prevent it
|
||||
// from ending when the subprocess stream ends
|
||||
this._stdout = (0, _mergeStream().default)(this._getFakeStream());
|
||||
}
|
||||
this._stdout.add(this._worker.stdout);
|
||||
}
|
||||
if (this._worker.stderr) {
|
||||
if (!this._stderr) {
|
||||
// We need to add a permanent stream to the merged stream to prevent it
|
||||
// from ending when the subprocess stream ends
|
||||
this._stderr = (0, _mergeStream().default)(this._getFakeStream());
|
||||
}
|
||||
this._stderr.add(this._worker.stderr);
|
||||
}
|
||||
|
||||
// This can be useful for debugging.
|
||||
if (!(this._options.silent ?? true)) {
|
||||
this._worker.stdout.setEncoding('utf8');
|
||||
// eslint-disable-next-line no-console
|
||||
this._worker.stdout.on('data', console.log);
|
||||
this._worker.stderr.setEncoding('utf8');
|
||||
this._worker.stderr.on('data', console.error);
|
||||
}
|
||||
this._worker.on('message', this._onMessage.bind(this));
|
||||
this._worker.on('exit', this._onExit.bind(this));
|
||||
this._worker.on('error', this._onError.bind(this));
|
||||
this._worker.postMessage([
|
||||
_types.CHILD_MESSAGE_INITIALIZE,
|
||||
false,
|
||||
this._options.workerPath,
|
||||
this._options.setupArgs,
|
||||
String(this._options.workerId + 1) // 0-indexed workerId, 1-indexed JEST_WORKER_ID
|
||||
]);
|
||||
|
||||
this._retries++;
|
||||
|
||||
// If we exceeded the amount of retries, we will emulate an error reply
|
||||
// coming from the child. This avoids code duplication related with cleaning
|
||||
// the queue, and scheduling the next call.
|
||||
if (this._retries > this._options.maxRetries) {
|
||||
const error = new Error('Call retries were exceeded');
|
||||
this._onMessage([
|
||||
_types.PARENT_MESSAGE_CLIENT_ERROR,
|
||||
error.name,
|
||||
error.message,
|
||||
error.stack,
|
||||
{
|
||||
type: 'WorkerError'
|
||||
}
|
||||
]);
|
||||
}
|
||||
this.state = _types.WorkerStates.OK;
|
||||
if (this._resolveWorkerReady) {
|
||||
this._resolveWorkerReady();
|
||||
}
|
||||
}
|
||||
_onError(error) {
|
||||
if (error.message.includes('heap out of memory')) {
|
||||
this.state = _types.WorkerStates.OUT_OF_MEMORY;
|
||||
|
||||
// Threads don't behave like processes, they don't crash when they run out of
|
||||
// memory. But for consistency we want them to behave like processes so we call
|
||||
// terminate to simulate a crash happening that was not planned
|
||||
this._worker.terminate();
|
||||
}
|
||||
}
|
||||
_onMessage(response) {
|
||||
// Ignore messages not intended for us
|
||||
if (!Array.isArray(response)) return;
|
||||
let error;
|
||||
switch (response[0]) {
|
||||
case _types.PARENT_MESSAGE_OK:
|
||||
this._onProcessEnd(null, response[1]);
|
||||
break;
|
||||
case _types.PARENT_MESSAGE_CLIENT_ERROR:
|
||||
error = response[4];
|
||||
if (error != null && typeof error === 'object') {
|
||||
const extra = error;
|
||||
// @ts-expect-error: no index
|
||||
const NativeCtor = globalThis[response[1]];
|
||||
const Ctor = typeof NativeCtor === 'function' ? NativeCtor : Error;
|
||||
error = new Ctor(response[2]);
|
||||
error.type = response[1];
|
||||
error.stack = response[3];
|
||||
for (const key in extra) {
|
||||
// @ts-expect-error: no index
|
||||
error[key] = extra[key];
|
||||
}
|
||||
}
|
||||
this._onProcessEnd(error, null);
|
||||
break;
|
||||
case _types.PARENT_MESSAGE_SETUP_ERROR:
|
||||
error = new Error(`Error when calling setup: ${response[2]}`);
|
||||
|
||||
// @ts-expect-error: adding custom properties to errors.
|
||||
error.type = response[1];
|
||||
error.stack = response[3];
|
||||
this._onProcessEnd(error, null);
|
||||
break;
|
||||
case _types.PARENT_MESSAGE_CUSTOM:
|
||||
this._onCustomMessage(response[1]);
|
||||
break;
|
||||
case _types.PARENT_MESSAGE_MEM_USAGE:
|
||||
this._childIdleMemoryUsage = response[1];
|
||||
if (this._resolveMemoryUsage) {
|
||||
this._resolveMemoryUsage(response[1]);
|
||||
this._resolveMemoryUsage = undefined;
|
||||
this._memoryUsagePromise = undefined;
|
||||
}
|
||||
this._performRestartIfRequired();
|
||||
break;
|
||||
default:
|
||||
// Ignore messages not intended for us
|
||||
break;
|
||||
}
|
||||
}
|
||||
_onExit(exitCode) {
|
||||
this._workerReadyPromise = undefined;
|
||||
this._resolveWorkerReady = undefined;
|
||||
if (exitCode !== 0 && this.state === _types.WorkerStates.OUT_OF_MEMORY) {
|
||||
this._onProcessEnd(
|
||||
new Error('Jest worker ran out of memory and crashed'),
|
||||
null
|
||||
);
|
||||
this._shutdown();
|
||||
} else if (
|
||||
(exitCode !== 0 &&
|
||||
this.state !== _types.WorkerStates.SHUTTING_DOWN &&
|
||||
this.state !== _types.WorkerStates.SHUT_DOWN) ||
|
||||
this.state === _types.WorkerStates.RESTARTING
|
||||
) {
|
||||
this.initialize();
|
||||
if (this._request) {
|
||||
this._worker.postMessage(this._request);
|
||||
}
|
||||
} else {
|
||||
// If the worker thread exits while a request is still pending, throw an
|
||||
// error. This is unexpected and tests may not have run to completion.
|
||||
const isRequestStillPending = !!this._request;
|
||||
if (isRequestStillPending) {
|
||||
this._onProcessEnd(
|
||||
new Error(
|
||||
'A Jest worker thread exited unexpectedly before finishing tests for an unknown reason. One of the ways this can happen is if process.exit() was called in testing code.'
|
||||
),
|
||||
null
|
||||
);
|
||||
}
|
||||
this._shutdown();
|
||||
}
|
||||
}
|
||||
waitForExit() {
|
||||
return this._exitPromise;
|
||||
}
|
||||
forceExit() {
|
||||
this.state = _types.WorkerStates.SHUTTING_DOWN;
|
||||
this._worker.terminate();
|
||||
}
|
||||
send(request, onProcessStart, onProcessEnd, onCustomMessage) {
|
||||
onProcessStart(this);
|
||||
this._onProcessEnd = (...args) => {
|
||||
const hasRequest = !!this._request;
|
||||
|
||||
// Clean the request to avoid sending past requests to workers that fail
|
||||
// while waiting for a new request (timers, unhandled rejections...)
|
||||
this._request = null;
|
||||
if (this._childIdleMemoryUsageLimit && hasRequest) {
|
||||
this.checkMemoryUsage();
|
||||
}
|
||||
const res = onProcessEnd?.(...args);
|
||||
|
||||
// Clean up the reference so related closures can be garbage collected.
|
||||
onProcessEnd = null;
|
||||
return res;
|
||||
};
|
||||
this._onCustomMessage = (...arg) => onCustomMessage(...arg);
|
||||
this._request = request;
|
||||
this._retries = 0;
|
||||
this._worker.postMessage(request);
|
||||
}
|
||||
getWorkerId() {
|
||||
return this._options.workerId;
|
||||
}
|
||||
getStdout() {
|
||||
return this._stdout;
|
||||
}
|
||||
getStderr() {
|
||||
return this._stderr;
|
||||
}
|
||||
_performRestartIfRequired() {
|
||||
if (this._memoryUsageCheck) {
|
||||
this._memoryUsageCheck = false;
|
||||
let limit = this._childIdleMemoryUsageLimit;
|
||||
|
||||
// TODO: At some point it would make sense to make use of
|
||||
// stringToBytes found in jest-config, however as this
|
||||
// package does not have any dependencies on an other jest
|
||||
// packages that can wait until some other time.
|
||||
if (limit && limit > 0 && limit <= 1) {
|
||||
limit = Math.floor((0, _os().totalmem)() * limit);
|
||||
} else if (limit) {
|
||||
limit = Math.floor(limit);
|
||||
}
|
||||
if (
|
||||
limit &&
|
||||
this._childIdleMemoryUsage &&
|
||||
this._childIdleMemoryUsage > limit
|
||||
) {
|
||||
this.state = _types.WorkerStates.RESTARTING;
|
||||
this._worker.terminate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the last reported memory usage.
|
||||
*
|
||||
* @returns Memory usage in bytes.
|
||||
*/
|
||||
getMemoryUsage() {
|
||||
if (!this._memoryUsagePromise) {
|
||||
let rejectCallback;
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
this._resolveMemoryUsage = resolve;
|
||||
rejectCallback = reject;
|
||||
});
|
||||
this._memoryUsagePromise = promise;
|
||||
if (!this._worker.threadId) {
|
||||
rejectCallback(new Error('Child process is not running.'));
|
||||
this._memoryUsagePromise = undefined;
|
||||
this._resolveMemoryUsage = undefined;
|
||||
return promise;
|
||||
}
|
||||
try {
|
||||
this._worker.postMessage([_types.CHILD_MESSAGE_MEM_USAGE]);
|
||||
} catch (err) {
|
||||
this._memoryUsagePromise = undefined;
|
||||
this._resolveMemoryUsage = undefined;
|
||||
rejectCallback(err);
|
||||
}
|
||||
return promise;
|
||||
}
|
||||
return this._memoryUsagePromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets updated memory usage and restarts if required
|
||||
*/
|
||||
checkMemoryUsage() {
|
||||
if (this._childIdleMemoryUsageLimit) {
|
||||
this._memoryUsageCheck = true;
|
||||
this._worker.postMessage([_types.CHILD_MESSAGE_MEM_USAGE]);
|
||||
} else {
|
||||
console.warn(
|
||||
'Memory usage of workers can only be checked if a limit is set'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the thread id of the worker.
|
||||
*
|
||||
* @returns Thread id.
|
||||
*/
|
||||
getWorkerSystemId() {
|
||||
return this._worker.threadId;
|
||||
}
|
||||
isWorkerRunning() {
|
||||
return this._worker.threadId >= 0;
|
||||
}
|
||||
}
|
||||
exports.default = ExperimentalWorker;
|
||||
135
node_modules/jest-worker/build/workers/WorkerAbstract.js
generated
vendored
135
node_modules/jest-worker/build/workers/WorkerAbstract.js
generated
vendored
@@ -1,135 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, '__esModule', {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
function _stream() {
|
||||
const data = require('stream');
|
||||
_stream = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
var _types = require('../types');
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
class WorkerAbstract extends _stream().EventEmitter {
|
||||
/**
|
||||
* DO NOT WRITE TO THIS DIRECTLY.
|
||||
* Use this.state getter/setters so events are emitted correctly.
|
||||
*/
|
||||
#state = _types.WorkerStates.STARTING;
|
||||
_fakeStream = null;
|
||||
_exitPromise;
|
||||
_resolveExitPromise;
|
||||
_workerReadyPromise;
|
||||
_resolveWorkerReady;
|
||||
get state() {
|
||||
return this.#state;
|
||||
}
|
||||
set state(value) {
|
||||
if (this.#state !== value) {
|
||||
const oldState = this.#state;
|
||||
this.#state = value;
|
||||
this.emit(_types.WorkerEvents.STATE_CHANGE, value, oldState);
|
||||
}
|
||||
}
|
||||
constructor(options) {
|
||||
super();
|
||||
if (typeof options.on === 'object') {
|
||||
for (const [event, handlers] of Object.entries(options.on)) {
|
||||
// Can't do Array.isArray on a ReadonlyArray<T>.
|
||||
// https://github.com/microsoft/TypeScript/issues/17002
|
||||
if (typeof handlers === 'function') {
|
||||
super.on(event, handlers);
|
||||
} else {
|
||||
for (const handler of handlers) {
|
||||
super.on(event, handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this._exitPromise = new Promise(resolve => {
|
||||
this._resolveExitPromise = resolve;
|
||||
});
|
||||
this._exitPromise.then(() => {
|
||||
this.state = _types.WorkerStates.SHUT_DOWN;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the worker child process to be ready to handle requests.
|
||||
*
|
||||
* @returns Promise which resolves when ready.
|
||||
*/
|
||||
waitForWorkerReady() {
|
||||
if (!this._workerReadyPromise) {
|
||||
this._workerReadyPromise = new Promise((resolve, reject) => {
|
||||
let settled = false;
|
||||
let to;
|
||||
switch (this.state) {
|
||||
case _types.WorkerStates.OUT_OF_MEMORY:
|
||||
case _types.WorkerStates.SHUTTING_DOWN:
|
||||
case _types.WorkerStates.SHUT_DOWN:
|
||||
settled = true;
|
||||
reject(
|
||||
new Error(
|
||||
`Worker state means it will never be ready: ${this.state}`
|
||||
)
|
||||
);
|
||||
break;
|
||||
case _types.WorkerStates.STARTING:
|
||||
case _types.WorkerStates.RESTARTING:
|
||||
this._resolveWorkerReady = () => {
|
||||
settled = true;
|
||||
resolve();
|
||||
if (to) {
|
||||
clearTimeout(to);
|
||||
}
|
||||
};
|
||||
break;
|
||||
case _types.WorkerStates.OK:
|
||||
settled = true;
|
||||
resolve();
|
||||
break;
|
||||
}
|
||||
if (!settled) {
|
||||
to = setTimeout(() => {
|
||||
if (!settled) {
|
||||
reject(new Error('Timeout starting worker'));
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
});
|
||||
}
|
||||
return this._workerReadyPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to shut down the current working instance once the children have been
|
||||
* killed off.
|
||||
*/
|
||||
_shutdown() {
|
||||
this.state === _types.WorkerStates.SHUT_DOWN;
|
||||
|
||||
// End the permanent stream so the merged stream end too
|
||||
if (this._fakeStream) {
|
||||
this._fakeStream.end();
|
||||
this._fakeStream = null;
|
||||
}
|
||||
this._resolveExitPromise();
|
||||
}
|
||||
_getFakeStream() {
|
||||
if (!this._fakeStream) {
|
||||
this._fakeStream = new (_stream().PassThrough)();
|
||||
}
|
||||
return this._fakeStream;
|
||||
}
|
||||
}
|
||||
exports.default = WorkerAbstract;
|
||||
33
node_modules/jest-worker/build/workers/messageParent.js
generated
vendored
33
node_modules/jest-worker/build/workers/messageParent.js
generated
vendored
@@ -1,33 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, '__esModule', {
|
||||
value: true
|
||||
});
|
||||
exports.default = messageParent;
|
||||
function _worker_threads() {
|
||||
const data = require('worker_threads');
|
||||
_worker_threads = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
var _types = require('../types');
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
function messageParent(message, parentProcess = process) {
|
||||
if (!_worker_threads().isMainThread && _worker_threads().parentPort != null) {
|
||||
_worker_threads().parentPort.postMessage([
|
||||
_types.PARENT_MESSAGE_CUSTOM,
|
||||
message
|
||||
]);
|
||||
} else if (typeof parentProcess.send === 'function') {
|
||||
parentProcess.send([_types.PARENT_MESSAGE_CUSTOM, message]);
|
||||
} else {
|
||||
throw new Error('"messageParent" can only be used inside a worker');
|
||||
}
|
||||
}
|
||||
159
node_modules/jest-worker/build/workers/processChild.js
generated
vendored
159
node_modules/jest-worker/build/workers/processChild.js
generated
vendored
@@ -1,159 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
function _jestUtil() {
|
||||
const data = require('jest-util');
|
||||
_jestUtil = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
var _types = require('../types');
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
let file = null;
|
||||
let setupArgs = [];
|
||||
let initialized = false;
|
||||
|
||||
/**
|
||||
* This file is a small bootstrapper for workers. It sets up the communication
|
||||
* between the worker and the parent process, interpreting parent messages and
|
||||
* sending results back.
|
||||
*
|
||||
* The file loaded will be lazily initialized the first time any of the workers
|
||||
* is called. This is done for optimal performance: if the farm is initialized,
|
||||
* but no call is made to it, child Node processes will be consuming the least
|
||||
* possible amount of memory.
|
||||
*
|
||||
* If an invalid message is detected, the child will exit (by throwing) with a
|
||||
* non-zero exit code.
|
||||
*/
|
||||
const messageListener = request => {
|
||||
switch (request[0]) {
|
||||
case _types.CHILD_MESSAGE_INITIALIZE:
|
||||
const init = request;
|
||||
file = init[2];
|
||||
setupArgs = init[3];
|
||||
break;
|
||||
case _types.CHILD_MESSAGE_CALL:
|
||||
const call = request;
|
||||
execMethod(call[2], call[3]);
|
||||
break;
|
||||
case _types.CHILD_MESSAGE_END:
|
||||
end();
|
||||
break;
|
||||
case _types.CHILD_MESSAGE_MEM_USAGE:
|
||||
reportMemoryUsage();
|
||||
break;
|
||||
case _types.CHILD_MESSAGE_CALL_SETUP:
|
||||
if (initialized) {
|
||||
reportSuccess(void 0);
|
||||
} else {
|
||||
const main = require(file);
|
||||
initialized = true;
|
||||
if (main.setup) {
|
||||
execFunction(
|
||||
main.setup,
|
||||
main,
|
||||
setupArgs,
|
||||
reportSuccess,
|
||||
reportInitializeError
|
||||
);
|
||||
} else {
|
||||
reportSuccess(void 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new TypeError(
|
||||
`Unexpected request from parent process: ${request[0]}`
|
||||
);
|
||||
}
|
||||
};
|
||||
process.on('message', messageListener);
|
||||
function reportSuccess(result) {
|
||||
if (!process || !process.send) {
|
||||
throw new Error('Child can only be used on a forked process');
|
||||
}
|
||||
process.send([_types.PARENT_MESSAGE_OK, result]);
|
||||
}
|
||||
function reportClientError(error) {
|
||||
return reportError(error, _types.PARENT_MESSAGE_CLIENT_ERROR);
|
||||
}
|
||||
function reportInitializeError(error) {
|
||||
return reportError(error, _types.PARENT_MESSAGE_SETUP_ERROR);
|
||||
}
|
||||
function reportMemoryUsage() {
|
||||
if (!process || !process.send) {
|
||||
throw new Error('Child can only be used on a forked process');
|
||||
}
|
||||
const msg = [_types.PARENT_MESSAGE_MEM_USAGE, process.memoryUsage().heapUsed];
|
||||
process.send(msg);
|
||||
}
|
||||
function reportError(error, type) {
|
||||
if (!process || !process.send) {
|
||||
throw new Error('Child can only be used on a forked process');
|
||||
}
|
||||
if (error == null) {
|
||||
error = new Error('"null" or "undefined" thrown');
|
||||
}
|
||||
process.send([
|
||||
type,
|
||||
error.constructor && error.constructor.name,
|
||||
error.message,
|
||||
error.stack,
|
||||
typeof error === 'object'
|
||||
? {
|
||||
...error
|
||||
}
|
||||
: error
|
||||
]);
|
||||
}
|
||||
function end() {
|
||||
const main = require(file);
|
||||
if (!main.teardown) {
|
||||
exitProcess();
|
||||
return;
|
||||
}
|
||||
execFunction(main.teardown, main, [], exitProcess, exitProcess);
|
||||
}
|
||||
function exitProcess() {
|
||||
// Clean up open handles so the process ideally exits gracefully
|
||||
process.removeListener('message', messageListener);
|
||||
}
|
||||
function execMethod(method, args) {
|
||||
const main = require(file);
|
||||
let fn;
|
||||
if (method === 'default') {
|
||||
fn = main.__esModule ? main.default : main;
|
||||
} else {
|
||||
fn = main[method];
|
||||
}
|
||||
function execHelper() {
|
||||
execFunction(fn, main, args, reportSuccess, reportClientError);
|
||||
}
|
||||
if (initialized || !main.setup) {
|
||||
execHelper();
|
||||
return;
|
||||
}
|
||||
initialized = true;
|
||||
execFunction(main.setup, main, setupArgs, execHelper, reportInitializeError);
|
||||
}
|
||||
function execFunction(fn, ctx, args, onResult, onError) {
|
||||
let result;
|
||||
try {
|
||||
result = fn.apply(ctx, args);
|
||||
} catch (err) {
|
||||
onError(err);
|
||||
return;
|
||||
}
|
||||
if ((0, _jestUtil().isPromise)(result)) {
|
||||
result.then(onResult, onError);
|
||||
} else {
|
||||
onResult(result);
|
||||
}
|
||||
}
|
||||
177
node_modules/jest-worker/build/workers/threadChild.js
generated
vendored
177
node_modules/jest-worker/build/workers/threadChild.js
generated
vendored
@@ -1,177 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
function _worker_threads() {
|
||||
const data = require('worker_threads');
|
||||
_worker_threads = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _jestUtil() {
|
||||
const data = require('jest-util');
|
||||
_jestUtil = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
var _types = require('../types');
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
let file = null;
|
||||
let setupArgs = [];
|
||||
let initialized = false;
|
||||
|
||||
/**
|
||||
* This file is a small bootstrapper for workers. It sets up the communication
|
||||
* between the worker and the parent process, interpreting parent messages and
|
||||
* sending results back.
|
||||
*
|
||||
* The file loaded will be lazily initialized the first time any of the workers
|
||||
* is called. This is done for optimal performance: if the farm is initialized,
|
||||
* but no call is made to it, child Node processes will be consuming the least
|
||||
* possible amount of memory.
|
||||
*
|
||||
* If an invalid message is detected, the child will exit (by throwing) with a
|
||||
* non-zero exit code.
|
||||
*/
|
||||
const messageListener = request => {
|
||||
switch (request[0]) {
|
||||
case _types.CHILD_MESSAGE_INITIALIZE:
|
||||
const init = request;
|
||||
file = init[2];
|
||||
setupArgs = init[3];
|
||||
process.env.JEST_WORKER_ID = init[4];
|
||||
break;
|
||||
case _types.CHILD_MESSAGE_CALL:
|
||||
const call = request;
|
||||
execMethod(call[2], call[3]);
|
||||
break;
|
||||
case _types.CHILD_MESSAGE_END:
|
||||
end();
|
||||
break;
|
||||
case _types.CHILD_MESSAGE_MEM_USAGE:
|
||||
reportMemoryUsage();
|
||||
break;
|
||||
case _types.CHILD_MESSAGE_CALL_SETUP:
|
||||
if (initialized) {
|
||||
reportSuccess(void 0);
|
||||
} else {
|
||||
const main = require(file);
|
||||
initialized = true;
|
||||
if (main.setup) {
|
||||
execFunction(
|
||||
main.setup,
|
||||
main,
|
||||
setupArgs,
|
||||
reportSuccess,
|
||||
reportInitializeError
|
||||
);
|
||||
} else {
|
||||
reportSuccess(void 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new TypeError(
|
||||
`Unexpected request from parent process: ${request[0]}`
|
||||
);
|
||||
}
|
||||
};
|
||||
_worker_threads().parentPort.on('message', messageListener);
|
||||
function reportMemoryUsage() {
|
||||
if (_worker_threads().isMainThread) {
|
||||
throw new Error('Child can only be used on a forked process');
|
||||
}
|
||||
const msg = [_types.PARENT_MESSAGE_MEM_USAGE, process.memoryUsage().heapUsed];
|
||||
_worker_threads().parentPort.postMessage(msg);
|
||||
}
|
||||
function reportSuccess(result) {
|
||||
if (_worker_threads().isMainThread) {
|
||||
throw new Error('Child can only be used on a forked process');
|
||||
}
|
||||
try {
|
||||
_worker_threads().parentPort.postMessage([
|
||||
_types.PARENT_MESSAGE_OK,
|
||||
result
|
||||
]);
|
||||
} catch (err) {
|
||||
// Handling it here to avoid unhandled `DataCloneError` rejection
|
||||
// which is hard to distinguish on the parent side
|
||||
// (such error doesn't have any message or stack trace)
|
||||
reportClientError(err);
|
||||
}
|
||||
}
|
||||
function reportClientError(error) {
|
||||
return reportError(error, _types.PARENT_MESSAGE_CLIENT_ERROR);
|
||||
}
|
||||
function reportInitializeError(error) {
|
||||
return reportError(error, _types.PARENT_MESSAGE_SETUP_ERROR);
|
||||
}
|
||||
function reportError(error, type) {
|
||||
if (_worker_threads().isMainThread) {
|
||||
throw new Error('Child can only be used on a forked process');
|
||||
}
|
||||
if (error == null) {
|
||||
error = new Error('"null" or "undefined" thrown');
|
||||
}
|
||||
_worker_threads().parentPort.postMessage([
|
||||
type,
|
||||
error.constructor && error.constructor.name,
|
||||
error.message,
|
||||
error.stack,
|
||||
typeof error === 'object'
|
||||
? {
|
||||
...error
|
||||
}
|
||||
: error
|
||||
]);
|
||||
}
|
||||
function end() {
|
||||
const main = require(file);
|
||||
if (!main.teardown) {
|
||||
exitProcess();
|
||||
return;
|
||||
}
|
||||
execFunction(main.teardown, main, [], exitProcess, exitProcess);
|
||||
}
|
||||
function exitProcess() {
|
||||
// Clean up open handles so the worker ideally exits gracefully
|
||||
_worker_threads().parentPort.removeListener('message', messageListener);
|
||||
}
|
||||
function execMethod(method, args) {
|
||||
const main = require(file);
|
||||
let fn;
|
||||
if (method === 'default') {
|
||||
fn = main.__esModule ? main.default : main;
|
||||
} else {
|
||||
fn = main[method];
|
||||
}
|
||||
function execHelper() {
|
||||
execFunction(fn, main, args, reportSuccess, reportClientError);
|
||||
}
|
||||
if (initialized || !main.setup) {
|
||||
execHelper();
|
||||
return;
|
||||
}
|
||||
initialized = true;
|
||||
execFunction(main.setup, main, setupArgs, execHelper, reportInitializeError);
|
||||
}
|
||||
function execFunction(fn, ctx, args, onResult, onError) {
|
||||
let result;
|
||||
try {
|
||||
result = fn.apply(ctx, args);
|
||||
} catch (err) {
|
||||
onError(err);
|
||||
return;
|
||||
}
|
||||
if ((0, _jestUtil().isPromise)(result)) {
|
||||
result.then(onResult, onError);
|
||||
} else {
|
||||
onResult(result);
|
||||
}
|
||||
}
|
||||
26
node_modules/jest-worker/package.json
generated
vendored
26
node_modules/jest-worker/package.json
generated
vendored
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jest-worker",
|
||||
"version": "29.7.0",
|
||||
"version": "30.2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jestjs/jest.git",
|
||||
@@ -12,31 +12,33 @@
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./build/index.d.ts",
|
||||
"require": "./build/index.js",
|
||||
"import": "./build/index.mjs",
|
||||
"default": "./build/index.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"jest-util": "^29.7.0",
|
||||
"@ungap/structured-clone": "^1.3.0",
|
||||
"jest-util": "30.2.0",
|
||||
"merge-stream": "^2.0.0",
|
||||
"supports-color": "^8.0.0"
|
||||
"supports-color": "^8.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.11.6",
|
||||
"@tsd/typescript": "^5.0.4",
|
||||
"@types/merge-stream": "^1.1.2",
|
||||
"@types/supports-color": "^8.1.0",
|
||||
"@babel/core": "^7.27.4",
|
||||
"@types/merge-stream": "^2.0.0",
|
||||
"@types/supports-color": "^8.1.3",
|
||||
"@types/ungap__structured-clone": "^1.2.0",
|
||||
"get-stream": "^6.0.0",
|
||||
"jest-leak-detector": "^29.7.0",
|
||||
"tsd-lite": "^0.7.0",
|
||||
"worker-farm": "^1.6.0"
|
||||
"jest-leak-detector": "30.2.0",
|
||||
"worker-farm": "^1.7.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
||||
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"gitHead": "4e56991693da7cd4c3730dc3579a1dd1403ee630"
|
||||
"gitHead": "855864e3f9751366455246790be2bf912d4d0dac"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user