@scelar/nodepod 1.0.7 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +252 -240
- package/dist/__sw__.js +31 -5
- package/dist/{child_process-bGGe8mTj.cjs → child_process-DldQfPd9.cjs} +7431 -7435
- package/dist/child_process-DldQfPd9.cjs.map +1 -0
- package/dist/{child_process-CgnmoilU.js → child_process-eiM1_nmq.js} +8231 -8234
- package/dist/child_process-eiM1_nmq.js.map +1 -0
- package/dist/cross-origin.d.ts +2 -0
- package/dist/{index-DZpqX03n.js → index-CK6KRbI1.js} +37316 -36899
- package/dist/index-CK6KRbI1.js.map +1 -0
- package/dist/{index-NinyWmnj.cjs → index-DfyUKyNH.cjs} +39254 -38824
- package/dist/index-DfyUKyNH.cjs.map +1 -0
- package/dist/index.cjs +67 -67
- package/dist/index.mjs +61 -61
- package/dist/isolation-helpers.d.ts +3 -0
- package/dist/packages/archive-extractor.d.ts +2 -0
- package/dist/packages/version-resolver.d.ts +1 -0
- package/dist/request-proxy.d.ts +3 -0
- package/dist/script-engine.d.ts +1 -1
- package/dist/sdk/nodepod.d.ts +58 -58
- package/dist/sdk/types.d.ts +3 -0
- package/dist/threading/offload-types.d.ts +1 -0
- package/package.json +97 -97
- package/src/cross-origin.ts +75 -26
- package/src/iframe-sandbox.ts +145 -141
- package/src/isolation-helpers.ts +154 -148
- package/src/packages/archive-extractor.ts +251 -248
- package/src/packages/installer.ts +1 -0
- package/src/packages/version-resolver.ts +2 -0
- package/src/polyfills/net.ts +353 -353
- package/src/polyfills/util.ts +559 -559
- package/src/polyfills/worker_threads.ts +326 -326
- package/src/request-proxy.ts +43 -9
- package/src/script-engine.ts +3733 -3722
- package/src/sdk/nodepod.ts +8 -0
- package/src/sdk/types.ts +3 -0
- package/src/shell/shell-builtins.ts +19 -19
- package/src/threading/offload-types.ts +113 -112
- package/src/threading/offload-worker.ts +15 -0
- package/dist/child_process-CgnmoilU.js.map +0 -1
- package/dist/child_process-bGGe8mTj.cjs.map +0 -1
- package/dist/index-DZpqX03n.js.map +0 -1
- package/dist/index-NinyWmnj.cjs.map +0 -1
|
@@ -1,326 +1,326 @@
|
|
|
1
|
-
// worker_threads polyfill using fork infrastructure for real Web Workers
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import { EventEmitter } from "./events";
|
|
5
|
-
import { ref as eventLoopRef, unref as eventLoopUnref } from "../helpers/event-loop";
|
|
6
|
-
|
|
7
|
-
// shared defaults for main thread; child workers get per-engine overrides via buildResolver
|
|
8
|
-
export let isMainThread = true;
|
|
9
|
-
export let parentPort: MessagePort | null = null;
|
|
10
|
-
export let workerData: unknown = null;
|
|
11
|
-
export let threadId = 0;
|
|
12
|
-
|
|
13
|
-
// fork callback, set by process-worker-entry.ts
|
|
14
|
-
|
|
15
|
-
export type WorkerThreadForkFn = (
|
|
16
|
-
modulePath: string,
|
|
17
|
-
opts: {
|
|
18
|
-
workerData: unknown;
|
|
19
|
-
threadId: number;
|
|
20
|
-
isEval?: boolean;
|
|
21
|
-
cwd: string;
|
|
22
|
-
env: Record<string, string>;
|
|
23
|
-
onMessage: (data: unknown) => void;
|
|
24
|
-
onError: (err: Error) => void;
|
|
25
|
-
onExit: (code: number) => void;
|
|
26
|
-
onStdout?: (data: string) => void;
|
|
27
|
-
onStderr?: (data: string) => void;
|
|
28
|
-
},
|
|
29
|
-
) => {
|
|
30
|
-
postMessage: (data: unknown) => void;
|
|
31
|
-
terminate: () => void;
|
|
32
|
-
requestId: number;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
let _workerThreadForkFn: WorkerThreadForkFn | null = null;
|
|
36
|
-
|
|
37
|
-
export function setWorkerThreadForkCallback(fn: WorkerThreadForkFn): void {
|
|
38
|
-
_workerThreadForkFn = fn;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
let _nextThreadId = 1;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
export interface MessagePort extends EventEmitter {
|
|
45
|
-
postMessage(_val: unknown, _transfer?: unknown[]): void;
|
|
46
|
-
start(): void;
|
|
47
|
-
close(): void;
|
|
48
|
-
ref(): void;
|
|
49
|
-
unref(): void;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
interface MessagePortConstructor {
|
|
53
|
-
new (): MessagePort;
|
|
54
|
-
(this: any): void;
|
|
55
|
-
prototype: any;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export const MessagePort = function MessagePort(this: any) {
|
|
59
|
-
if (!this) return;
|
|
60
|
-
EventEmitter.call(this);
|
|
61
|
-
} as unknown as MessagePortConstructor;
|
|
62
|
-
|
|
63
|
-
Object.setPrototypeOf(MessagePort.prototype, EventEmitter.prototype);
|
|
64
|
-
|
|
65
|
-
MessagePort.prototype.postMessage = function postMessage(_val: unknown, _transfer?: unknown[]): void {};
|
|
66
|
-
MessagePort.prototype.start = function start(): void {};
|
|
67
|
-
MessagePort.prototype.close = function close(): void {};
|
|
68
|
-
MessagePort.prototype.ref = function ref(): void {};
|
|
69
|
-
MessagePort.prototype.unref = function unref(): void {};
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
export interface MessageChannel {
|
|
73
|
-
port1: MessagePort;
|
|
74
|
-
port2: MessagePort;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
interface MessageChannelConstructor {
|
|
78
|
-
new (): MessageChannel;
|
|
79
|
-
(this: any): void;
|
|
80
|
-
prototype: any;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export const MessageChannel = function MessageChannel(this: any) {
|
|
84
|
-
if (!this) return;
|
|
85
|
-
this.port1 = new MessagePort();
|
|
86
|
-
this.port2 = new MessagePort();
|
|
87
|
-
|
|
88
|
-
// wire the two ports together
|
|
89
|
-
const p1 = this.port1;
|
|
90
|
-
const p2 = this.port2;
|
|
91
|
-
p1.postMessage = (val: unknown) => {
|
|
92
|
-
queueMicrotask(() => p2.emit("message", val));
|
|
93
|
-
};
|
|
94
|
-
p2.postMessage = (val: unknown) => {
|
|
95
|
-
queueMicrotask(() => p1.emit("message", val));
|
|
96
|
-
};
|
|
97
|
-
} as unknown as MessageChannelConstructor;
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
export interface Worker extends EventEmitter {
|
|
101
|
-
threadId: number;
|
|
102
|
-
resourceLimits: object;
|
|
103
|
-
_handle: ReturnType<WorkerThreadForkFn> | null;
|
|
104
|
-
_terminated: boolean;
|
|
105
|
-
_isReffed: boolean;
|
|
106
|
-
postMessage(value: unknown, _transferListOrOptions?: unknown): void;
|
|
107
|
-
terminate(): Promise<number>;
|
|
108
|
-
ref(): this;
|
|
109
|
-
unref(): this;
|
|
110
|
-
getHeapSnapshot(): Promise<unknown>;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
interface WorkerConstructor {
|
|
114
|
-
new (
|
|
115
|
-
script: string | URL,
|
|
116
|
-
opts?: {
|
|
117
|
-
workerData?: unknown;
|
|
118
|
-
eval?: boolean;
|
|
119
|
-
env?: Record<string, string> | symbol;
|
|
120
|
-
argv?: string[];
|
|
121
|
-
execArgv?: string[];
|
|
122
|
-
resourceLimits?: Record<string, number>;
|
|
123
|
-
name?: string;
|
|
124
|
-
transferList?: unknown[];
|
|
125
|
-
},
|
|
126
|
-
): Worker;
|
|
127
|
-
(this: any, script: string | URL, opts?: any): void;
|
|
128
|
-
prototype: any;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
export const Worker = function Worker(
|
|
132
|
-
this: any,
|
|
133
|
-
script: string | URL,
|
|
134
|
-
opts?: {
|
|
135
|
-
workerData?: unknown;
|
|
136
|
-
eval?: boolean;
|
|
137
|
-
env?: Record<string, string> | symbol;
|
|
138
|
-
argv?: string[];
|
|
139
|
-
execArgv?: string[];
|
|
140
|
-
resourceLimits?: Record<string, number>;
|
|
141
|
-
name?: string;
|
|
142
|
-
transferList?: unknown[];
|
|
143
|
-
},
|
|
144
|
-
) {
|
|
145
|
-
if (!this) return;
|
|
146
|
-
EventEmitter.call(this);
|
|
147
|
-
|
|
148
|
-
this.threadId = _nextThreadId++;
|
|
149
|
-
this.resourceLimits = {};
|
|
150
|
-
this._handle = null;
|
|
151
|
-
this._terminated = false;
|
|
152
|
-
this._isReffed = false;
|
|
153
|
-
|
|
154
|
-
const scriptStr = typeof script === "string" ? script : script.href;
|
|
155
|
-
const self = this;
|
|
156
|
-
|
|
157
|
-
if (!_workerThreadForkFn) {
|
|
158
|
-
// no fork callback wired
|
|
159
|
-
queueMicrotask(() => {
|
|
160
|
-
self.emit(
|
|
161
|
-
"error",
|
|
162
|
-
new Error(
|
|
163
|
-
"[Nodepod] worker_threads.Worker requires worker mode. " +
|
|
164
|
-
"Ensure the process is running in a worker context.",
|
|
165
|
-
),
|
|
166
|
-
);
|
|
167
|
-
});
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
const workerDataVal = opts?.workerData ?? null;
|
|
172
|
-
const isEval = !!opts?.eval;
|
|
173
|
-
const env =
|
|
174
|
-
opts?.env && typeof opts.env !== "symbol"
|
|
175
|
-
? (opts.env as Record<string, string>)
|
|
176
|
-
: {};
|
|
177
|
-
|
|
178
|
-
const handle = _workerThreadForkFn(scriptStr, {
|
|
179
|
-
workerData: workerDataVal,
|
|
180
|
-
threadId: this.threadId,
|
|
181
|
-
isEval,
|
|
182
|
-
cwd: (globalThis as any).process?.cwd?.() ?? "/",
|
|
183
|
-
env,
|
|
184
|
-
onMessage: (data: unknown) => {
|
|
185
|
-
self.emit("message", data);
|
|
186
|
-
},
|
|
187
|
-
onError: (err: Error) => {
|
|
188
|
-
self.emit("error", err);
|
|
189
|
-
},
|
|
190
|
-
onExit: (code: number) => {
|
|
191
|
-
if (self._isReffed) {
|
|
192
|
-
self._isReffed = false;
|
|
193
|
-
eventLoopUnref();
|
|
194
|
-
}
|
|
195
|
-
self._terminated = true;
|
|
196
|
-
self.emit("exit", code);
|
|
197
|
-
},
|
|
198
|
-
onStdout: (data: string) => {
|
|
199
|
-
const sink = (globalThis as any).process?.stdout?.write;
|
|
200
|
-
if (typeof sink === "function") sink.call((globalThis as any).process.stdout, data);
|
|
201
|
-
},
|
|
202
|
-
onStderr: (data: string) => {
|
|
203
|
-
const sink = (globalThis as any).process?.stderr?.write;
|
|
204
|
-
if (typeof sink === "function") sink.call((globalThis as any).process.stderr, data);
|
|
205
|
-
},
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
this._handle = handle;
|
|
209
|
-
|
|
210
|
-
// keep parent alive while worker runs (Node.js default)
|
|
211
|
-
this._isReffed = true;
|
|
212
|
-
eventLoopRef();
|
|
213
|
-
|
|
214
|
-
queueMicrotask(() => {
|
|
215
|
-
if (!self._terminated) self.emit("online");
|
|
216
|
-
});
|
|
217
|
-
} as unknown as WorkerConstructor;
|
|
218
|
-
|
|
219
|
-
Object.setPrototypeOf(Worker.prototype, EventEmitter.prototype);
|
|
220
|
-
|
|
221
|
-
Worker.prototype.postMessage = function postMessage(this: any, value: unknown, _transferListOrOptions?: unknown): void {
|
|
222
|
-
if (this._handle && !this._terminated) {
|
|
223
|
-
this._handle.postMessage(value);
|
|
224
|
-
}
|
|
225
|
-
};
|
|
226
|
-
|
|
227
|
-
Worker.prototype.terminate = function terminate(this: any): Promise<number> {
|
|
228
|
-
if (this._handle && !this._terminated) {
|
|
229
|
-
if (this._isReffed) {
|
|
230
|
-
this._isReffed = false;
|
|
231
|
-
eventLoopUnref();
|
|
232
|
-
}
|
|
233
|
-
this._terminated = true;
|
|
234
|
-
this._handle.terminate();
|
|
235
|
-
}
|
|
236
|
-
return Promise.resolve(0);
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
Worker.prototype.ref = function ref(this: any): any {
|
|
240
|
-
if (!this._isReffed && !this._terminated) {
|
|
241
|
-
this._isReffed = true;
|
|
242
|
-
eventLoopRef();
|
|
243
|
-
}
|
|
244
|
-
return this;
|
|
245
|
-
};
|
|
246
|
-
|
|
247
|
-
Worker.prototype.unref = function unref(this: any): any {
|
|
248
|
-
if (this._isReffed) {
|
|
249
|
-
this._isReffed = false;
|
|
250
|
-
eventLoopUnref();
|
|
251
|
-
}
|
|
252
|
-
return this;
|
|
253
|
-
};
|
|
254
|
-
|
|
255
|
-
Worker.prototype.getHeapSnapshot = function getHeapSnapshot(): Promise<unknown> {
|
|
256
|
-
return Promise.resolve({});
|
|
257
|
-
};
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
export interface BroadcastChannel extends EventEmitter {
|
|
261
|
-
name: string;
|
|
262
|
-
postMessage(_msg: unknown): void;
|
|
263
|
-
close(): void;
|
|
264
|
-
ref(): void;
|
|
265
|
-
unref(): void;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
interface BroadcastChannelConstructor {
|
|
269
|
-
new (label: string): BroadcastChannel;
|
|
270
|
-
(this: any, label: string): void;
|
|
271
|
-
prototype: any;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
export const BroadcastChannel = function BroadcastChannel(this: any, label: string) {
|
|
275
|
-
if (!this) return;
|
|
276
|
-
EventEmitter.call(this);
|
|
277
|
-
this.name = label;
|
|
278
|
-
} as unknown as BroadcastChannelConstructor;
|
|
279
|
-
|
|
280
|
-
Object.setPrototypeOf(BroadcastChannel.prototype, EventEmitter.prototype);
|
|
281
|
-
|
|
282
|
-
BroadcastChannel.prototype.postMessage = function postMessage(_msg: unknown): void {};
|
|
283
|
-
BroadcastChannel.prototype.close = function close(): void {};
|
|
284
|
-
BroadcastChannel.prototype.ref = function ref(): void {};
|
|
285
|
-
BroadcastChannel.prototype.unref = function unref(): void {};
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
export function moveMessagePortToContext(
|
|
289
|
-
port: MessagePort,
|
|
290
|
-
_ctx: unknown,
|
|
291
|
-
): MessagePort {
|
|
292
|
-
return port;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
export function receiveMessageOnPort(
|
|
296
|
-
_port: MessagePort,
|
|
297
|
-
): { message: unknown } | undefined {
|
|
298
|
-
return undefined;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
export const SHARE_ENV = Symbol.for("nodejs.worker_threads.SHARE_ENV");
|
|
302
|
-
|
|
303
|
-
export function markAsUntransferable(_obj: unknown): void {}
|
|
304
|
-
export function getEnvironmentData(_key: unknown): unknown {
|
|
305
|
-
return undefined;
|
|
306
|
-
}
|
|
307
|
-
export function setEnvironmentData(_key: unknown, _val: unknown): void {}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
export default {
|
|
311
|
-
isMainThread,
|
|
312
|
-
parentPort,
|
|
313
|
-
workerData,
|
|
314
|
-
threadId,
|
|
315
|
-
Worker,
|
|
316
|
-
MessageChannel,
|
|
317
|
-
MessagePort,
|
|
318
|
-
BroadcastChannel,
|
|
319
|
-
moveMessagePortToContext,
|
|
320
|
-
receiveMessageOnPort,
|
|
321
|
-
SHARE_ENV,
|
|
322
|
-
markAsUntransferable,
|
|
323
|
-
getEnvironmentData,
|
|
324
|
-
setEnvironmentData,
|
|
325
|
-
setWorkerThreadForkCallback,
|
|
326
|
-
};
|
|
1
|
+
// worker_threads polyfill using fork infrastructure for real Web Workers
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import { EventEmitter } from "./events";
|
|
5
|
+
import { ref as eventLoopRef, unref as eventLoopUnref } from "../helpers/event-loop";
|
|
6
|
+
|
|
7
|
+
// shared defaults for main thread; child workers get per-engine overrides via buildResolver
|
|
8
|
+
export let isMainThread = true;
|
|
9
|
+
export let parentPort: MessagePort | null = null;
|
|
10
|
+
export let workerData: unknown = null;
|
|
11
|
+
export let threadId = 0;
|
|
12
|
+
|
|
13
|
+
// fork callback, set by process-worker-entry.ts
|
|
14
|
+
|
|
15
|
+
export type WorkerThreadForkFn = (
|
|
16
|
+
modulePath: string,
|
|
17
|
+
opts: {
|
|
18
|
+
workerData: unknown;
|
|
19
|
+
threadId: number;
|
|
20
|
+
isEval?: boolean;
|
|
21
|
+
cwd: string;
|
|
22
|
+
env: Record<string, string>;
|
|
23
|
+
onMessage: (data: unknown) => void;
|
|
24
|
+
onError: (err: Error) => void;
|
|
25
|
+
onExit: (code: number) => void;
|
|
26
|
+
onStdout?: (data: string) => void;
|
|
27
|
+
onStderr?: (data: string) => void;
|
|
28
|
+
},
|
|
29
|
+
) => {
|
|
30
|
+
postMessage: (data: unknown) => void;
|
|
31
|
+
terminate: () => void;
|
|
32
|
+
requestId: number;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
let _workerThreadForkFn: WorkerThreadForkFn | null = null;
|
|
36
|
+
|
|
37
|
+
export function setWorkerThreadForkCallback(fn: WorkerThreadForkFn): void {
|
|
38
|
+
_workerThreadForkFn = fn;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
let _nextThreadId = 1;
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
export interface MessagePort extends EventEmitter {
|
|
45
|
+
postMessage(_val: unknown, _transfer?: unknown[]): void;
|
|
46
|
+
start(): void;
|
|
47
|
+
close(): void;
|
|
48
|
+
ref(): void;
|
|
49
|
+
unref(): void;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
interface MessagePortConstructor {
|
|
53
|
+
new (): MessagePort;
|
|
54
|
+
(this: any): void;
|
|
55
|
+
prototype: any;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const MessagePort = function MessagePort(this: any) {
|
|
59
|
+
if (!this) return;
|
|
60
|
+
EventEmitter.call(this);
|
|
61
|
+
} as unknown as MessagePortConstructor;
|
|
62
|
+
|
|
63
|
+
Object.setPrototypeOf(MessagePort.prototype, EventEmitter.prototype);
|
|
64
|
+
|
|
65
|
+
MessagePort.prototype.postMessage = function postMessage(_val: unknown, _transfer?: unknown[]): void {};
|
|
66
|
+
MessagePort.prototype.start = function start(): void {};
|
|
67
|
+
MessagePort.prototype.close = function close(): void {};
|
|
68
|
+
MessagePort.prototype.ref = function ref(): void {};
|
|
69
|
+
MessagePort.prototype.unref = function unref(): void {};
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
export interface MessageChannel {
|
|
73
|
+
port1: MessagePort;
|
|
74
|
+
port2: MessagePort;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
interface MessageChannelConstructor {
|
|
78
|
+
new (): MessageChannel;
|
|
79
|
+
(this: any): void;
|
|
80
|
+
prototype: any;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export const MessageChannel = function MessageChannel(this: any) {
|
|
84
|
+
if (!this) return;
|
|
85
|
+
this.port1 = new MessagePort();
|
|
86
|
+
this.port2 = new MessagePort();
|
|
87
|
+
|
|
88
|
+
// wire the two ports together
|
|
89
|
+
const p1 = this.port1;
|
|
90
|
+
const p2 = this.port2;
|
|
91
|
+
p1.postMessage = (val: unknown) => {
|
|
92
|
+
queueMicrotask(() => p2.emit("message", val));
|
|
93
|
+
};
|
|
94
|
+
p2.postMessage = (val: unknown) => {
|
|
95
|
+
queueMicrotask(() => p1.emit("message", val));
|
|
96
|
+
};
|
|
97
|
+
} as unknown as MessageChannelConstructor;
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
export interface Worker extends EventEmitter {
|
|
101
|
+
threadId: number;
|
|
102
|
+
resourceLimits: object;
|
|
103
|
+
_handle: ReturnType<WorkerThreadForkFn> | null;
|
|
104
|
+
_terminated: boolean;
|
|
105
|
+
_isReffed: boolean;
|
|
106
|
+
postMessage(value: unknown, _transferListOrOptions?: unknown): void;
|
|
107
|
+
terminate(): Promise<number>;
|
|
108
|
+
ref(): this;
|
|
109
|
+
unref(): this;
|
|
110
|
+
getHeapSnapshot(): Promise<unknown>;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
interface WorkerConstructor {
|
|
114
|
+
new (
|
|
115
|
+
script: string | URL,
|
|
116
|
+
opts?: {
|
|
117
|
+
workerData?: unknown;
|
|
118
|
+
eval?: boolean;
|
|
119
|
+
env?: Record<string, string> | symbol;
|
|
120
|
+
argv?: string[];
|
|
121
|
+
execArgv?: string[];
|
|
122
|
+
resourceLimits?: Record<string, number>;
|
|
123
|
+
name?: string;
|
|
124
|
+
transferList?: unknown[];
|
|
125
|
+
},
|
|
126
|
+
): Worker;
|
|
127
|
+
(this: any, script: string | URL, opts?: any): void;
|
|
128
|
+
prototype: any;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export const Worker = function Worker(
|
|
132
|
+
this: any,
|
|
133
|
+
script: string | URL,
|
|
134
|
+
opts?: {
|
|
135
|
+
workerData?: unknown;
|
|
136
|
+
eval?: boolean;
|
|
137
|
+
env?: Record<string, string> | symbol;
|
|
138
|
+
argv?: string[];
|
|
139
|
+
execArgv?: string[];
|
|
140
|
+
resourceLimits?: Record<string, number>;
|
|
141
|
+
name?: string;
|
|
142
|
+
transferList?: unknown[];
|
|
143
|
+
},
|
|
144
|
+
) {
|
|
145
|
+
if (!this) return;
|
|
146
|
+
EventEmitter.call(this);
|
|
147
|
+
|
|
148
|
+
this.threadId = _nextThreadId++;
|
|
149
|
+
this.resourceLimits = {};
|
|
150
|
+
this._handle = null;
|
|
151
|
+
this._terminated = false;
|
|
152
|
+
this._isReffed = false;
|
|
153
|
+
|
|
154
|
+
const scriptStr = typeof script === "string" ? script : script.href;
|
|
155
|
+
const self = this;
|
|
156
|
+
|
|
157
|
+
if (!_workerThreadForkFn) {
|
|
158
|
+
// no fork callback wired
|
|
159
|
+
queueMicrotask(() => {
|
|
160
|
+
self.emit(
|
|
161
|
+
"error",
|
|
162
|
+
new Error(
|
|
163
|
+
"[Nodepod] worker_threads.Worker requires worker mode. " +
|
|
164
|
+
"Ensure the process is running in a worker context.",
|
|
165
|
+
),
|
|
166
|
+
);
|
|
167
|
+
});
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const workerDataVal = opts?.workerData ?? null;
|
|
172
|
+
const isEval = !!opts?.eval;
|
|
173
|
+
const env =
|
|
174
|
+
opts?.env && typeof opts.env !== "symbol"
|
|
175
|
+
? (opts.env as Record<string, string>)
|
|
176
|
+
: {};
|
|
177
|
+
|
|
178
|
+
const handle = _workerThreadForkFn(scriptStr, {
|
|
179
|
+
workerData: workerDataVal,
|
|
180
|
+
threadId: this.threadId,
|
|
181
|
+
isEval,
|
|
182
|
+
cwd: (globalThis as any).process?.cwd?.() ?? "/",
|
|
183
|
+
env,
|
|
184
|
+
onMessage: (data: unknown) => {
|
|
185
|
+
self.emit("message", data);
|
|
186
|
+
},
|
|
187
|
+
onError: (err: Error) => {
|
|
188
|
+
self.emit("error", err);
|
|
189
|
+
},
|
|
190
|
+
onExit: (code: number) => {
|
|
191
|
+
if (self._isReffed) {
|
|
192
|
+
self._isReffed = false;
|
|
193
|
+
eventLoopUnref();
|
|
194
|
+
}
|
|
195
|
+
self._terminated = true;
|
|
196
|
+
self.emit("exit", code);
|
|
197
|
+
},
|
|
198
|
+
onStdout: (data: string) => {
|
|
199
|
+
const sink = (globalThis as any).process?.stdout?.write;
|
|
200
|
+
if (typeof sink === "function") sink.call((globalThis as any).process.stdout, data);
|
|
201
|
+
},
|
|
202
|
+
onStderr: (data: string) => {
|
|
203
|
+
const sink = (globalThis as any).process?.stderr?.write;
|
|
204
|
+
if (typeof sink === "function") sink.call((globalThis as any).process.stderr, data);
|
|
205
|
+
},
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
this._handle = handle;
|
|
209
|
+
|
|
210
|
+
// keep parent alive while worker runs (Node.js default)
|
|
211
|
+
this._isReffed = true;
|
|
212
|
+
eventLoopRef();
|
|
213
|
+
|
|
214
|
+
queueMicrotask(() => {
|
|
215
|
+
if (!self._terminated) self.emit("online");
|
|
216
|
+
});
|
|
217
|
+
} as unknown as WorkerConstructor;
|
|
218
|
+
|
|
219
|
+
Object.setPrototypeOf(Worker.prototype, EventEmitter.prototype);
|
|
220
|
+
|
|
221
|
+
Worker.prototype.postMessage = function postMessage(this: any, value: unknown, _transferListOrOptions?: unknown): void {
|
|
222
|
+
if (this._handle && !this._terminated) {
|
|
223
|
+
this._handle.postMessage(value);
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
Worker.prototype.terminate = function terminate(this: any): Promise<number> {
|
|
228
|
+
if (this._handle && !this._terminated) {
|
|
229
|
+
if (this._isReffed) {
|
|
230
|
+
this._isReffed = false;
|
|
231
|
+
eventLoopUnref();
|
|
232
|
+
}
|
|
233
|
+
this._terminated = true;
|
|
234
|
+
this._handle.terminate();
|
|
235
|
+
}
|
|
236
|
+
return Promise.resolve(0);
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
Worker.prototype.ref = function ref(this: any): any {
|
|
240
|
+
if (!this._isReffed && !this._terminated) {
|
|
241
|
+
this._isReffed = true;
|
|
242
|
+
eventLoopRef();
|
|
243
|
+
}
|
|
244
|
+
return this;
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
Worker.prototype.unref = function unref(this: any): any {
|
|
248
|
+
if (this._isReffed) {
|
|
249
|
+
this._isReffed = false;
|
|
250
|
+
eventLoopUnref();
|
|
251
|
+
}
|
|
252
|
+
return this;
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
Worker.prototype.getHeapSnapshot = function getHeapSnapshot(): Promise<unknown> {
|
|
256
|
+
return Promise.resolve({});
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
export interface BroadcastChannel extends EventEmitter {
|
|
261
|
+
name: string;
|
|
262
|
+
postMessage(_msg: unknown): void;
|
|
263
|
+
close(): void;
|
|
264
|
+
ref(): void;
|
|
265
|
+
unref(): void;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
interface BroadcastChannelConstructor {
|
|
269
|
+
new (label: string): BroadcastChannel;
|
|
270
|
+
(this: any, label: string): void;
|
|
271
|
+
prototype: any;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
export const BroadcastChannel = function BroadcastChannel(this: any, label: string) {
|
|
275
|
+
if (!this) return;
|
|
276
|
+
EventEmitter.call(this);
|
|
277
|
+
this.name = label;
|
|
278
|
+
} as unknown as BroadcastChannelConstructor;
|
|
279
|
+
|
|
280
|
+
Object.setPrototypeOf(BroadcastChannel.prototype, EventEmitter.prototype);
|
|
281
|
+
|
|
282
|
+
BroadcastChannel.prototype.postMessage = function postMessage(_msg: unknown): void {};
|
|
283
|
+
BroadcastChannel.prototype.close = function close(): void {};
|
|
284
|
+
BroadcastChannel.prototype.ref = function ref(): void {};
|
|
285
|
+
BroadcastChannel.prototype.unref = function unref(): void {};
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
export function moveMessagePortToContext(
|
|
289
|
+
port: MessagePort,
|
|
290
|
+
_ctx: unknown,
|
|
291
|
+
): MessagePort {
|
|
292
|
+
return port;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export function receiveMessageOnPort(
|
|
296
|
+
_port: MessagePort,
|
|
297
|
+
): { message: unknown } | undefined {
|
|
298
|
+
return undefined;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
export const SHARE_ENV = Symbol.for("nodejs.worker_threads.SHARE_ENV");
|
|
302
|
+
|
|
303
|
+
export function markAsUntransferable(_obj: unknown): void {}
|
|
304
|
+
export function getEnvironmentData(_key: unknown): unknown {
|
|
305
|
+
return undefined;
|
|
306
|
+
}
|
|
307
|
+
export function setEnvironmentData(_key: unknown, _val: unknown): void {}
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
export default {
|
|
311
|
+
isMainThread,
|
|
312
|
+
parentPort,
|
|
313
|
+
workerData,
|
|
314
|
+
threadId,
|
|
315
|
+
Worker,
|
|
316
|
+
MessageChannel,
|
|
317
|
+
MessagePort,
|
|
318
|
+
BroadcastChannel,
|
|
319
|
+
moveMessagePortToContext,
|
|
320
|
+
receiveMessageOnPort,
|
|
321
|
+
SHARE_ENV,
|
|
322
|
+
markAsUntransferable,
|
|
323
|
+
getEnvironmentData,
|
|
324
|
+
setEnvironmentData,
|
|
325
|
+
setWorkerThreadForkCallback,
|
|
326
|
+
};
|