@wordpress/worker-threads 1.0.1-next.v.202602200903.0

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 ADDED
@@ -0,0 +1,132 @@
1
+ # Worker Threads
2
+
3
+ Utilities for type-safe Web Worker communication with RPC (Remote Procedure Call).
4
+
5
+ This package provides a simple and efficient way to communicate between the main thread and Web Workers, automatically handling:
6
+
7
+ - Promise-based async method calls
8
+ - Automatic transferable detection (ArrayBuffer, etc.)
9
+ - Type-safe API with full TypeScript support
10
+ - Error propagation from worker to main thread
11
+
12
+ ## Installation
13
+
14
+ Install the module:
15
+
16
+ ```bash
17
+ npm install @wordpress/worker-threads
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ ### Worker Thread
23
+
24
+ Create a worker file that exposes methods to the main thread:
25
+
26
+ ```typescript
27
+ // worker.ts
28
+ import { expose } from '@wordpress/worker-threads/worker';
29
+
30
+ const api = {
31
+ async processImage( buffer: ArrayBuffer, quality: number ): Promise<ArrayBuffer> {
32
+ // ... image processing logic
33
+ return resultBuffer;
34
+ },
35
+
36
+ async calculateSum( a: number, b: number ): Promise<number> {
37
+ return a + b;
38
+ },
39
+ };
40
+
41
+ expose( api );
42
+
43
+ // Export the type for use with wrap() on the main thread
44
+ export type WorkerAPI = typeof api;
45
+ ```
46
+
47
+ ### Main Thread
48
+
49
+ Wrap the worker to get a type-safe proxy:
50
+
51
+ ```typescript
52
+ // main.ts
53
+ import { wrap, terminate } from '@wordpress/worker-threads';
54
+ import type { WorkerAPI } from './worker';
55
+
56
+ // Create the worker
57
+ const worker = new Worker( new URL( './worker.js', import.meta.url ), {
58
+ type: 'module',
59
+ } );
60
+
61
+ // Wrap it to get the RPC proxy
62
+ const api = wrap<WorkerAPI>( worker );
63
+
64
+ // Call methods as async functions
65
+ const result = await api.processImage( imageBuffer, 0.82 );
66
+ const sum = await api.calculateSum( 1, 2 );
67
+
68
+ // Clean up when done
69
+ terminate( api );
70
+ ```
71
+
72
+ ## API Reference
73
+
74
+ ### Main Thread API
75
+
76
+ #### `wrap<T>( worker: Worker ): Remote<T>`
77
+
78
+ Wraps a Worker to provide a type-safe RPC interface. The returned proxy object allows calling methods on the worker as if they were local async functions.
79
+
80
+ #### `terminate( remote: Remote<unknown> ): void`
81
+
82
+ Terminates a wrapped worker and cleans up resources. Any pending calls will be rejected.
83
+
84
+ ### Worker Thread API
85
+
86
+ #### `expose<T>( target: T ): void`
87
+
88
+ Exposes an object's methods to be called from the main thread. Should be called once in the worker script.
89
+
90
+ ### Types
91
+
92
+ #### `Remote<T>`
93
+
94
+ A type that converts all methods of `T` to their async versions. Each method returns `Promise<Awaited<ReturnType>>`.
95
+
96
+ ## Features
97
+
98
+ ### Automatic Transferable Detection
99
+
100
+ The package automatically detects and transfers `ArrayBuffer` and other transferable objects, providing zero-copy performance for large data:
101
+
102
+ ```typescript
103
+ // ArrayBuffers are automatically transferred, not copied
104
+ const result = await api.processImage( largeImageBuffer );
105
+ ```
106
+
107
+ ### Error Handling
108
+
109
+ Errors thrown in the worker are properly propagated to the main thread:
110
+
111
+ ```typescript
112
+ try {
113
+ await api.riskyOperation();
114
+ } catch ( error ) {
115
+ console.error( 'Worker error:', error.message );
116
+ }
117
+ ```
118
+
119
+ ### TypeScript Support
120
+
121
+ Full type inference for method signatures:
122
+
123
+ ```typescript
124
+ // TypeScript knows the return type and parameter types
125
+ const result: ArrayBuffer = await api.processImage( buffer, 0.82 );
126
+ ```
127
+
128
+ ## Contributing to this package
129
+
130
+ This is an individual package that's part of the Gutenberg project. The project is organized as a monorepo. It's made up of multiple self-contained software packages, each with a specific purpose. The packages in this monorepo are published to [npm](https://www.npmjs.com/) and used by [WordPress](https://make.wordpress.org/core/) as well as other software projects.
131
+
132
+ To find out more about contributing to this package or Gutenberg as a whole, please read the project's main [contributor guide](https://github.com/WordPress/gutenberg/tree/HEAD/CONTRIBUTING.md).
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // packages/worker-threads/src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ expose: () => import_worker_thread.expose,
24
+ terminate: () => import_main_thread2.terminate,
25
+ wrap: () => import_main_thread.wrap
26
+ });
27
+ module.exports = __toCommonJS(index_exports);
28
+ var import_main_thread = require("./main-thread.cjs");
29
+ var import_main_thread2 = require("./main-thread.cjs");
30
+ var import_worker_thread = require("./worker-thread.cjs");
31
+ // Annotate the CommonJS export names for ESM import in node:
32
+ 0 && (module.exports = {
33
+ expose,
34
+ terminate,
35
+ wrap
36
+ });
37
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/index.ts"],
4
+ "sourcesContent": ["/**\n * Main entry point for @wordpress/worker-threads.\n *\n * This module provides utilities for type-safe Web Worker communication\n * using an RPC (Remote Procedure Call) pattern. It allows you to call\n * methods on a worker as if they were local async functions.\n *\n * @example\n * Main thread usage:\n * ```typescript\n * import { wrap, terminate } from '@wordpress/worker-threads';\n * import type { WorkerAPI } from './worker';\n *\n * const worker = new Worker(new URL('./worker.js', import.meta.url));\n * const api = wrap<WorkerAPI>(worker);\n *\n * const result = await api.processData(data);\n *\n * terminate(api);\n * ```\n *\n * Worker thread usage:\n * ```typescript\n * import { expose } from '@wordpress/worker-threads';\n *\n * const api = {\n * async processData(data: ArrayBuffer): Promise<ArrayBuffer> {\n * // ... processing\n * return result;\n * }\n * };\n *\n * expose(api);\n * export type WorkerAPI = typeof api;\n * ```\n */\n\n/**\n * Wraps a Worker to provide a type-safe RPC interface.\n */\nexport { wrap } from './main-thread';\n\n/**\n * Terminates a wrapped worker and cleans up resources.\n */\nexport { terminate } from './main-thread';\n\n/**\n * Exposes an object's methods to be called from the main thread.\n * This should be called in the worker script.\n */\nexport { expose } from './worker-thread';\n\n/**\n * Type that converts all methods to async versions.\n */\nexport type { Remote } from './types';\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAwCA,yBAAqB;AAKrB,IAAAA,sBAA0B;AAM1B,2BAAuB;",
6
+ "names": ["import_main_thread"]
7
+ }
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // packages/worker-threads/src/main-thread.ts
21
+ var main_thread_exports = {};
22
+ __export(main_thread_exports, {
23
+ terminate: () => terminate,
24
+ wrap: () => wrap
25
+ });
26
+ module.exports = __toCommonJS(main_thread_exports);
27
+ var import_comctx = require("comctx");
28
+ var import_types = require("./types.cjs");
29
+ var WorkerInjectAdapter = class {
30
+ worker;
31
+ constructor(worker) {
32
+ this.worker = worker;
33
+ }
34
+ sendMessage = (message, transfer) => {
35
+ this.worker.postMessage(message, transfer);
36
+ };
37
+ onMessage = (callback) => {
38
+ const handler = (event) => callback(event.data);
39
+ this.worker.addEventListener("message", handler);
40
+ return () => this.worker.removeEventListener("message", handler);
41
+ };
42
+ };
43
+ var remoteWorkers = /* @__PURE__ */ new WeakMap();
44
+ function wrap(worker) {
45
+ const [, inject] = (0, import_comctx.defineProxy)(() => ({}), {
46
+ namespace: "__wordpress_worker__",
47
+ heartbeatCheck: false,
48
+ transfer: true
49
+ });
50
+ const comctxRemote = inject(new WorkerInjectAdapter(worker));
51
+ remoteWorkers.set(comctxRemote, worker);
52
+ const proxy = new Proxy(comctxRemote, {
53
+ get(target, prop) {
54
+ if (prop === import_types.WORKER_SYMBOL) {
55
+ return worker;
56
+ }
57
+ return Reflect.get(target, prop);
58
+ }
59
+ });
60
+ remoteWorkers.set(proxy, worker);
61
+ return proxy;
62
+ }
63
+ function terminate(remote) {
64
+ const worker = remote[import_types.WORKER_SYMBOL];
65
+ if (!worker) {
66
+ return;
67
+ }
68
+ remoteWorkers.delete(remote);
69
+ worker.terminate();
70
+ }
71
+ // Annotate the CommonJS export names for ESM import in node:
72
+ 0 && (module.exports = {
73
+ terminate,
74
+ wrap
75
+ });
76
+ //# sourceMappingURL=main-thread.cjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/main-thread.ts"],
4
+ "sourcesContent": ["/**\n * External dependencies\n */\nimport {\n\tdefineProxy,\n\ttype Adapter,\n\ttype SendMessage,\n\ttype OnMessage,\n} from 'comctx';\n\n/**\n * Internal dependencies\n */\nimport { WORKER_SYMBOL, type Remote, type WithWorker } from './types';\n\n/**\n * Adapter for injecting (main thread calling worker).\n */\nclass WorkerInjectAdapter implements Adapter {\n\tprivate worker: Worker;\n\n\tconstructor( worker: Worker ) {\n\t\tthis.worker = worker;\n\t}\n\n\tsendMessage: SendMessage = ( message, transfer ) => {\n\t\tthis.worker.postMessage( message, transfer );\n\t};\n\n\tonMessage: OnMessage = ( callback ) => {\n\t\tconst handler = ( event: MessageEvent ) => callback( event.data );\n\t\tthis.worker.addEventListener( 'message', handler );\n\t\treturn () => this.worker.removeEventListener( 'message', handler );\n\t};\n}\n\n/**\n * WeakMap to store workers for each remote proxy.\n */\nconst remoteWorkers = new WeakMap< object, Worker >();\n\n/**\n * Wraps a Worker to provide a type-safe RPC interface.\n *\n * The returned proxy object allows calling methods on the worker as if they\n * were local async functions. Each method call is automatically serialized,\n * sent to the worker, and the result is returned as a Promise.\n *\n * @example\n * ```typescript\n * const worker = new Worker(new URL('./worker.js', import.meta.url));\n * const api = wrap<MyWorkerAPI>(worker);\n *\n * // Call worker methods as async functions\n * const result = await api.processData(data);\n * ```\n *\n * @param worker - The Worker instance to wrap.\n * @return A proxy object with all exposed methods as async functions.\n */\nexport function wrap< T extends object >( worker: Worker ): Remote< T > {\n\t// Create the inject function using defineProxy with an empty object\n\t// (the actual implementation is on the worker side).\n\tconst [ , inject ] = defineProxy( () => ( {} ) as T, {\n\t\tnamespace: '__wordpress_worker__',\n\t\theartbeatCheck: false,\n\t\ttransfer: true,\n\t} );\n\n\t// Create the proxy using the injector.\n\tconst comctxRemote = inject( new WorkerInjectAdapter( worker ) );\n\n\t// Store the worker reference.\n\tremoteWorkers.set( comctxRemote as object, worker );\n\n\t// Create a wrapper proxy that adds WORKER_SYMBOL support.\n\tconst proxy = new Proxy( comctxRemote as Remote< T > & WithWorker, {\n\t\tget( target, prop: string | symbol ) {\n\t\t\t// Return the worker for the WORKER_SYMBOL.\n\t\t\tif ( prop === WORKER_SYMBOL ) {\n\t\t\t\treturn worker;\n\t\t\t}\n\n\t\t\t// Delegate all other property access to the comctx remote.\n\t\t\treturn Reflect.get( target, prop );\n\t\t},\n\t} );\n\n\t// Store the worker for the proxy as well.\n\tremoteWorkers.set( proxy, worker );\n\n\treturn proxy;\n}\n\n/**\n * Terminates a wrapped worker and cleans up resources.\n *\n * After calling terminate, any pending calls will be rejected and the\n * worker will be stopped.\n *\n * @example\n * ```typescript\n * const api = wrap<MyWorkerAPI>(worker);\n * // ... use the API ...\n * terminate(api); // Clean up when done\n * ```\n *\n * @param remote - The wrapped worker proxy returned by wrap().\n */\nexport function terminate( remote: Remote< unknown > ): void {\n\t// Get the worker from the proxy.\n\tconst worker = ( remote as unknown as WithWorker )[ WORKER_SYMBOL ];\n\n\tif ( ! worker ) {\n\t\treturn;\n\t}\n\n\t// Clean up the worker reference.\n\tremoteWorkers.delete( remote as object );\n\n\t// Terminate the worker.\n\tworker.terminate();\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,oBAKO;AAKP,mBAA4D;AAK5D,IAAM,sBAAN,MAA6C;AAAA,EACpC;AAAA,EAER,YAAa,QAAiB;AAC7B,SAAK,SAAS;AAAA,EACf;AAAA,EAEA,cAA2B,CAAE,SAAS,aAAc;AACnD,SAAK,OAAO,YAAa,SAAS,QAAS;AAAA,EAC5C;AAAA,EAEA,YAAuB,CAAE,aAAc;AACtC,UAAM,UAAU,CAAE,UAAyB,SAAU,MAAM,IAAK;AAChE,SAAK,OAAO,iBAAkB,WAAW,OAAQ;AACjD,WAAO,MAAM,KAAK,OAAO,oBAAqB,WAAW,OAAQ;AAAA,EAClE;AACD;AAKA,IAAM,gBAAgB,oBAAI,QAA0B;AAqB7C,SAAS,KAA0B,QAA8B;AAGvE,QAAM,CAAE,EAAE,MAAO,QAAI,2BAAa,OAAQ,CAAC,IAAU;AAAA,IACpD,WAAW;AAAA,IACX,gBAAgB;AAAA,IAChB,UAAU;AAAA,EACX,CAAE;AAGF,QAAM,eAAe,OAAQ,IAAI,oBAAqB,MAAO,CAAE;AAG/D,gBAAc,IAAK,cAAwB,MAAO;AAGlD,QAAM,QAAQ,IAAI,MAAO,cAA0C;AAAA,IAClE,IAAK,QAAQ,MAAwB;AAEpC,UAAK,SAAS,4BAAgB;AAC7B,eAAO;AAAA,MACR;AAGA,aAAO,QAAQ,IAAK,QAAQ,IAAK;AAAA,IAClC;AAAA,EACD,CAAE;AAGF,gBAAc,IAAK,OAAO,MAAO;AAEjC,SAAO;AACR;AAiBO,SAAS,UAAW,QAAkC;AAE5D,QAAM,SAAW,OAAmC,0BAAc;AAElE,MAAK,CAAE,QAAS;AACf;AAAA,EACD;AAGA,gBAAc,OAAQ,MAAiB;AAGvC,SAAO,UAAU;AAClB;",
6
+ "names": []
7
+ }
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // packages/worker-threads/src/types.ts
21
+ var types_exports = {};
22
+ __export(types_exports, {
23
+ WORKER_SYMBOL: () => WORKER_SYMBOL
24
+ });
25
+ module.exports = __toCommonJS(types_exports);
26
+ var WORKER_SYMBOL = /* @__PURE__ */ Symbol("worker");
27
+ // Annotate the CommonJS export names for ESM import in node:
28
+ 0 && (module.exports = {
29
+ WORKER_SYMBOL
30
+ });
31
+ //# sourceMappingURL=types.cjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/types.ts"],
4
+ "sourcesContent": ["/**\n * Converts a type to its \"remote\" version where all methods become async.\n *\n * This type transformation ensures that when calling methods on a wrapped\n * worker, the return types are properly wrapped in Promises.\n */\nexport type Remote< T > = {\n\t[ K in keyof T ]: T[ K ] extends ( ...args: infer A ) => infer R\n\t\t? ( ...args: A ) => Promise< Awaited< R > >\n\t\t: never;\n};\n\n/**\n * Internal symbol used to store the worker reference on the proxy.\n */\nexport const WORKER_SYMBOL = Symbol( 'worker' );\n\n/**\n * Interface for objects that have an associated worker.\n */\nexport interface WithWorker {\n\t[ WORKER_SYMBOL ]: Worker;\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAeO,IAAM,gBAAgB,uBAAQ,QAAS;",
6
+ "names": []
7
+ }
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // packages/worker-threads/src/worker-thread.ts
21
+ var worker_thread_exports = {};
22
+ __export(worker_thread_exports, {
23
+ expose: () => expose
24
+ });
25
+ module.exports = __toCommonJS(worker_thread_exports);
26
+ var import_comctx = require("comctx");
27
+ var WorkerProvideAdapter = class {
28
+ sendMessage = (message, transfer) => {
29
+ self.postMessage(message, { transfer });
30
+ };
31
+ onMessage = (callback) => {
32
+ const handler = (event) => callback(event.data);
33
+ self.addEventListener("message", handler);
34
+ return () => self.removeEventListener("message", handler);
35
+ };
36
+ };
37
+ function expose(target) {
38
+ const [provide] = (0, import_comctx.defineProxy)(() => target, {
39
+ namespace: "__wordpress_worker__",
40
+ heartbeatCheck: false,
41
+ transfer: true
42
+ });
43
+ provide(new WorkerProvideAdapter());
44
+ }
45
+ // Annotate the CommonJS export names for ESM import in node:
46
+ 0 && (module.exports = {
47
+ expose
48
+ });
49
+ //# sourceMappingURL=worker-thread.cjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/worker-thread.ts"],
4
+ "sourcesContent": ["/**\n * External dependencies\n */\nimport {\n\tdefineProxy,\n\ttype Adapter,\n\ttype SendMessage,\n\ttype OnMessage,\n} from 'comctx';\n\n/**\n * Adapter for providing (worker exposing methods to main thread).\n */\nclass WorkerProvideAdapter implements Adapter {\n\tsendMessage: SendMessage = ( message, transfer ) => {\n\t\tself.postMessage( message, { transfer } );\n\t};\n\n\tonMessage: OnMessage = ( callback ) => {\n\t\tconst handler = ( event: MessageEvent ) => callback( event.data );\n\t\tself.addEventListener( 'message', handler );\n\t\treturn () => self.removeEventListener( 'message', handler );\n\t};\n}\n\n/**\n * Exposes an object's methods to be called from the main thread.\n *\n * This function should be called in the worker script to make methods\n * available for RPC calls. Only methods (functions) on the object will\n * be exposed; other properties are ignored.\n *\n * @example\n * ```typescript\n * // worker.ts\n * import { expose } from '@wordpress/worker-threads/worker';\n *\n * const api = {\n * async processImage(buffer: ArrayBuffer): Promise<ArrayBuffer> {\n * // ... processing logic\n * return resultBuffer;\n * },\n *\n * async calculateSum(a: number, b: number): Promise<number> {\n * return a + b;\n * }\n * };\n *\n * expose(api);\n *\n * // Export the type for use with wrap() on main thread\n * export type WorkerAPI = typeof api;\n * ```\n *\n * @param target - Object containing methods to expose to the main thread.\n */\nexport function expose< T extends object >( target: T ): void {\n\t// Create the provide function using defineProxy with the target.\n\tconst [ provide ] = defineProxy( () => target, {\n\t\tnamespace: '__wordpress_worker__',\n\t\theartbeatCheck: false,\n\t\ttransfer: true,\n\t} );\n\n\t// Start providing the target through the adapter.\n\tprovide( new WorkerProvideAdapter() );\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,oBAKO;AAKP,IAAM,uBAAN,MAA8C;AAAA,EAC7C,cAA2B,CAAE,SAAS,aAAc;AACnD,SAAK,YAAa,SAAS,EAAE,SAAS,CAAE;AAAA,EACzC;AAAA,EAEA,YAAuB,CAAE,aAAc;AACtC,UAAM,UAAU,CAAE,UAAyB,SAAU,MAAM,IAAK;AAChE,SAAK,iBAAkB,WAAW,OAAQ;AAC1C,WAAO,MAAM,KAAK,oBAAqB,WAAW,OAAQ;AAAA,EAC3D;AACD;AAiCO,SAAS,OAA4B,QAAkB;AAE7D,QAAM,CAAE,OAAQ,QAAI,2BAAa,MAAM,QAAQ;AAAA,IAC9C,WAAW;AAAA,IACX,gBAAgB;AAAA,IAChB,UAAU;AAAA,EACX,CAAE;AAGF,UAAS,IAAI,qBAAqB,CAAE;AACrC;",
6
+ "names": []
7
+ }
@@ -0,0 +1,10 @@
1
+ // packages/worker-threads/src/index.ts
2
+ import { wrap } from "./main-thread.mjs";
3
+ import { terminate } from "./main-thread.mjs";
4
+ import { expose } from "./worker-thread.mjs";
5
+ export {
6
+ expose,
7
+ terminate,
8
+ wrap
9
+ };
10
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/index.ts"],
4
+ "sourcesContent": ["/**\n * Main entry point for @wordpress/worker-threads.\n *\n * This module provides utilities for type-safe Web Worker communication\n * using an RPC (Remote Procedure Call) pattern. It allows you to call\n * methods on a worker as if they were local async functions.\n *\n * @example\n * Main thread usage:\n * ```typescript\n * import { wrap, terminate } from '@wordpress/worker-threads';\n * import type { WorkerAPI } from './worker';\n *\n * const worker = new Worker(new URL('./worker.js', import.meta.url));\n * const api = wrap<WorkerAPI>(worker);\n *\n * const result = await api.processData(data);\n *\n * terminate(api);\n * ```\n *\n * Worker thread usage:\n * ```typescript\n * import { expose } from '@wordpress/worker-threads';\n *\n * const api = {\n * async processData(data: ArrayBuffer): Promise<ArrayBuffer> {\n * // ... processing\n * return result;\n * }\n * };\n *\n * expose(api);\n * export type WorkerAPI = typeof api;\n * ```\n */\n\n/**\n * Wraps a Worker to provide a type-safe RPC interface.\n */\nexport { wrap } from './main-thread';\n\n/**\n * Terminates a wrapped worker and cleans up resources.\n */\nexport { terminate } from './main-thread';\n\n/**\n * Exposes an object's methods to be called from the main thread.\n * This should be called in the worker script.\n */\nexport { expose } from './worker-thread';\n\n/**\n * Type that converts all methods to async versions.\n */\nexport type { Remote } from './types';\n"],
5
+ "mappings": ";AAwCA,SAAS,YAAY;AAKrB,SAAS,iBAAiB;AAM1B,SAAS,cAAc;",
6
+ "names": []
7
+ }
@@ -0,0 +1,52 @@
1
+ // packages/worker-threads/src/main-thread.ts
2
+ import {
3
+ defineProxy
4
+ } from "comctx";
5
+ import { WORKER_SYMBOL } from "./types.mjs";
6
+ var WorkerInjectAdapter = class {
7
+ worker;
8
+ constructor(worker) {
9
+ this.worker = worker;
10
+ }
11
+ sendMessage = (message, transfer) => {
12
+ this.worker.postMessage(message, transfer);
13
+ };
14
+ onMessage = (callback) => {
15
+ const handler = (event) => callback(event.data);
16
+ this.worker.addEventListener("message", handler);
17
+ return () => this.worker.removeEventListener("message", handler);
18
+ };
19
+ };
20
+ var remoteWorkers = /* @__PURE__ */ new WeakMap();
21
+ function wrap(worker) {
22
+ const [, inject] = defineProxy(() => ({}), {
23
+ namespace: "__wordpress_worker__",
24
+ heartbeatCheck: false,
25
+ transfer: true
26
+ });
27
+ const comctxRemote = inject(new WorkerInjectAdapter(worker));
28
+ remoteWorkers.set(comctxRemote, worker);
29
+ const proxy = new Proxy(comctxRemote, {
30
+ get(target, prop) {
31
+ if (prop === WORKER_SYMBOL) {
32
+ return worker;
33
+ }
34
+ return Reflect.get(target, prop);
35
+ }
36
+ });
37
+ remoteWorkers.set(proxy, worker);
38
+ return proxy;
39
+ }
40
+ function terminate(remote) {
41
+ const worker = remote[WORKER_SYMBOL];
42
+ if (!worker) {
43
+ return;
44
+ }
45
+ remoteWorkers.delete(remote);
46
+ worker.terminate();
47
+ }
48
+ export {
49
+ terminate,
50
+ wrap
51
+ };
52
+ //# sourceMappingURL=main-thread.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/main-thread.ts"],
4
+ "sourcesContent": ["/**\n * External dependencies\n */\nimport {\n\tdefineProxy,\n\ttype Adapter,\n\ttype SendMessage,\n\ttype OnMessage,\n} from 'comctx';\n\n/**\n * Internal dependencies\n */\nimport { WORKER_SYMBOL, type Remote, type WithWorker } from './types';\n\n/**\n * Adapter for injecting (main thread calling worker).\n */\nclass WorkerInjectAdapter implements Adapter {\n\tprivate worker: Worker;\n\n\tconstructor( worker: Worker ) {\n\t\tthis.worker = worker;\n\t}\n\n\tsendMessage: SendMessage = ( message, transfer ) => {\n\t\tthis.worker.postMessage( message, transfer );\n\t};\n\n\tonMessage: OnMessage = ( callback ) => {\n\t\tconst handler = ( event: MessageEvent ) => callback( event.data );\n\t\tthis.worker.addEventListener( 'message', handler );\n\t\treturn () => this.worker.removeEventListener( 'message', handler );\n\t};\n}\n\n/**\n * WeakMap to store workers for each remote proxy.\n */\nconst remoteWorkers = new WeakMap< object, Worker >();\n\n/**\n * Wraps a Worker to provide a type-safe RPC interface.\n *\n * The returned proxy object allows calling methods on the worker as if they\n * were local async functions. Each method call is automatically serialized,\n * sent to the worker, and the result is returned as a Promise.\n *\n * @example\n * ```typescript\n * const worker = new Worker(new URL('./worker.js', import.meta.url));\n * const api = wrap<MyWorkerAPI>(worker);\n *\n * // Call worker methods as async functions\n * const result = await api.processData(data);\n * ```\n *\n * @param worker - The Worker instance to wrap.\n * @return A proxy object with all exposed methods as async functions.\n */\nexport function wrap< T extends object >( worker: Worker ): Remote< T > {\n\t// Create the inject function using defineProxy with an empty object\n\t// (the actual implementation is on the worker side).\n\tconst [ , inject ] = defineProxy( () => ( {} ) as T, {\n\t\tnamespace: '__wordpress_worker__',\n\t\theartbeatCheck: false,\n\t\ttransfer: true,\n\t} );\n\n\t// Create the proxy using the injector.\n\tconst comctxRemote = inject( new WorkerInjectAdapter( worker ) );\n\n\t// Store the worker reference.\n\tremoteWorkers.set( comctxRemote as object, worker );\n\n\t// Create a wrapper proxy that adds WORKER_SYMBOL support.\n\tconst proxy = new Proxy( comctxRemote as Remote< T > & WithWorker, {\n\t\tget( target, prop: string | symbol ) {\n\t\t\t// Return the worker for the WORKER_SYMBOL.\n\t\t\tif ( prop === WORKER_SYMBOL ) {\n\t\t\t\treturn worker;\n\t\t\t}\n\n\t\t\t// Delegate all other property access to the comctx remote.\n\t\t\treturn Reflect.get( target, prop );\n\t\t},\n\t} );\n\n\t// Store the worker for the proxy as well.\n\tremoteWorkers.set( proxy, worker );\n\n\treturn proxy;\n}\n\n/**\n * Terminates a wrapped worker and cleans up resources.\n *\n * After calling terminate, any pending calls will be rejected and the\n * worker will be stopped.\n *\n * @example\n * ```typescript\n * const api = wrap<MyWorkerAPI>(worker);\n * // ... use the API ...\n * terminate(api); // Clean up when done\n * ```\n *\n * @param remote - The wrapped worker proxy returned by wrap().\n */\nexport function terminate( remote: Remote< unknown > ): void {\n\t// Get the worker from the proxy.\n\tconst worker = ( remote as unknown as WithWorker )[ WORKER_SYMBOL ];\n\n\tif ( ! worker ) {\n\t\treturn;\n\t}\n\n\t// Clean up the worker reference.\n\tremoteWorkers.delete( remote as object );\n\n\t// Terminate the worker.\n\tworker.terminate();\n}\n"],
5
+ "mappings": ";AAGA;AAAA,EACC;AAAA,OAIM;AAKP,SAAS,qBAAmD;AAK5D,IAAM,sBAAN,MAA6C;AAAA,EACpC;AAAA,EAER,YAAa,QAAiB;AAC7B,SAAK,SAAS;AAAA,EACf;AAAA,EAEA,cAA2B,CAAE,SAAS,aAAc;AACnD,SAAK,OAAO,YAAa,SAAS,QAAS;AAAA,EAC5C;AAAA,EAEA,YAAuB,CAAE,aAAc;AACtC,UAAM,UAAU,CAAE,UAAyB,SAAU,MAAM,IAAK;AAChE,SAAK,OAAO,iBAAkB,WAAW,OAAQ;AACjD,WAAO,MAAM,KAAK,OAAO,oBAAqB,WAAW,OAAQ;AAAA,EAClE;AACD;AAKA,IAAM,gBAAgB,oBAAI,QAA0B;AAqB7C,SAAS,KAA0B,QAA8B;AAGvE,QAAM,CAAE,EAAE,MAAO,IAAI,YAAa,OAAQ,CAAC,IAAU;AAAA,IACpD,WAAW;AAAA,IACX,gBAAgB;AAAA,IAChB,UAAU;AAAA,EACX,CAAE;AAGF,QAAM,eAAe,OAAQ,IAAI,oBAAqB,MAAO,CAAE;AAG/D,gBAAc,IAAK,cAAwB,MAAO;AAGlD,QAAM,QAAQ,IAAI,MAAO,cAA0C;AAAA,IAClE,IAAK,QAAQ,MAAwB;AAEpC,UAAK,SAAS,eAAgB;AAC7B,eAAO;AAAA,MACR;AAGA,aAAO,QAAQ,IAAK,QAAQ,IAAK;AAAA,IAClC;AAAA,EACD,CAAE;AAGF,gBAAc,IAAK,OAAO,MAAO;AAEjC,SAAO;AACR;AAiBO,SAAS,UAAW,QAAkC;AAE5D,QAAM,SAAW,OAAmC,aAAc;AAElE,MAAK,CAAE,QAAS;AACf;AAAA,EACD;AAGA,gBAAc,OAAQ,MAAiB;AAGvC,SAAO,UAAU;AAClB;",
6
+ "names": []
7
+ }
@@ -0,0 +1,6 @@
1
+ // packages/worker-threads/src/types.ts
2
+ var WORKER_SYMBOL = /* @__PURE__ */ Symbol("worker");
3
+ export {
4
+ WORKER_SYMBOL
5
+ };
6
+ //# sourceMappingURL=types.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/types.ts"],
4
+ "sourcesContent": ["/**\n * Converts a type to its \"remote\" version where all methods become async.\n *\n * This type transformation ensures that when calling methods on a wrapped\n * worker, the return types are properly wrapped in Promises.\n */\nexport type Remote< T > = {\n\t[ K in keyof T ]: T[ K ] extends ( ...args: infer A ) => infer R\n\t\t? ( ...args: A ) => Promise< Awaited< R > >\n\t\t: never;\n};\n\n/**\n * Internal symbol used to store the worker reference on the proxy.\n */\nexport const WORKER_SYMBOL = Symbol( 'worker' );\n\n/**\n * Interface for objects that have an associated worker.\n */\nexport interface WithWorker {\n\t[ WORKER_SYMBOL ]: Worker;\n}\n"],
5
+ "mappings": ";AAeO,IAAM,gBAAgB,uBAAQ,QAAS;",
6
+ "names": []
7
+ }
@@ -0,0 +1,26 @@
1
+ // packages/worker-threads/src/worker-thread.ts
2
+ import {
3
+ defineProxy
4
+ } from "comctx";
5
+ var WorkerProvideAdapter = class {
6
+ sendMessage = (message, transfer) => {
7
+ self.postMessage(message, { transfer });
8
+ };
9
+ onMessage = (callback) => {
10
+ const handler = (event) => callback(event.data);
11
+ self.addEventListener("message", handler);
12
+ return () => self.removeEventListener("message", handler);
13
+ };
14
+ };
15
+ function expose(target) {
16
+ const [provide] = defineProxy(() => target, {
17
+ namespace: "__wordpress_worker__",
18
+ heartbeatCheck: false,
19
+ transfer: true
20
+ });
21
+ provide(new WorkerProvideAdapter());
22
+ }
23
+ export {
24
+ expose
25
+ };
26
+ //# sourceMappingURL=worker-thread.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/worker-thread.ts"],
4
+ "sourcesContent": ["/**\n * External dependencies\n */\nimport {\n\tdefineProxy,\n\ttype Adapter,\n\ttype SendMessage,\n\ttype OnMessage,\n} from 'comctx';\n\n/**\n * Adapter for providing (worker exposing methods to main thread).\n */\nclass WorkerProvideAdapter implements Adapter {\n\tsendMessage: SendMessage = ( message, transfer ) => {\n\t\tself.postMessage( message, { transfer } );\n\t};\n\n\tonMessage: OnMessage = ( callback ) => {\n\t\tconst handler = ( event: MessageEvent ) => callback( event.data );\n\t\tself.addEventListener( 'message', handler );\n\t\treturn () => self.removeEventListener( 'message', handler );\n\t};\n}\n\n/**\n * Exposes an object's methods to be called from the main thread.\n *\n * This function should be called in the worker script to make methods\n * available for RPC calls. Only methods (functions) on the object will\n * be exposed; other properties are ignored.\n *\n * @example\n * ```typescript\n * // worker.ts\n * import { expose } from '@wordpress/worker-threads/worker';\n *\n * const api = {\n * async processImage(buffer: ArrayBuffer): Promise<ArrayBuffer> {\n * // ... processing logic\n * return resultBuffer;\n * },\n *\n * async calculateSum(a: number, b: number): Promise<number> {\n * return a + b;\n * }\n * };\n *\n * expose(api);\n *\n * // Export the type for use with wrap() on main thread\n * export type WorkerAPI = typeof api;\n * ```\n *\n * @param target - Object containing methods to expose to the main thread.\n */\nexport function expose< T extends object >( target: T ): void {\n\t// Create the provide function using defineProxy with the target.\n\tconst [ provide ] = defineProxy( () => target, {\n\t\tnamespace: '__wordpress_worker__',\n\t\theartbeatCheck: false,\n\t\ttransfer: true,\n\t} );\n\n\t// Start providing the target through the adapter.\n\tprovide( new WorkerProvideAdapter() );\n}\n"],
5
+ "mappings": ";AAGA;AAAA,EACC;AAAA,OAIM;AAKP,IAAM,uBAAN,MAA8C;AAAA,EAC7C,cAA2B,CAAE,SAAS,aAAc;AACnD,SAAK,YAAa,SAAS,EAAE,SAAS,CAAE;AAAA,EACzC;AAAA,EAEA,YAAuB,CAAE,aAAc;AACtC,UAAM,UAAU,CAAE,UAAyB,SAAU,MAAM,IAAK;AAChE,SAAK,iBAAkB,WAAW,OAAQ;AAC1C,WAAO,MAAM,KAAK,oBAAqB,WAAW,OAAQ;AAAA,EAC3D;AACD;AAiCO,SAAS,OAA4B,QAAkB;AAE7D,QAAM,CAAE,OAAQ,IAAI,YAAa,MAAM,QAAQ;AAAA,IAC9C,WAAW;AAAA,IACX,gBAAgB;AAAA,IAChB,UAAU;AAAA,EACX,CAAE;AAGF,UAAS,IAAI,qBAAqB,CAAE;AACrC;",
6
+ "names": []
7
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Main entry point for @wordpress/worker-threads.
3
+ *
4
+ * This module provides utilities for type-safe Web Worker communication
5
+ * using an RPC (Remote Procedure Call) pattern. It allows you to call
6
+ * methods on a worker as if they were local async functions.
7
+ *
8
+ * @example
9
+ * Main thread usage:
10
+ * ```typescript
11
+ * import { wrap, terminate } from '@wordpress/worker-threads';
12
+ * import type { WorkerAPI } from './worker';
13
+ *
14
+ * const worker = new Worker(new URL('./worker.js', import.meta.url));
15
+ * const api = wrap<WorkerAPI>(worker);
16
+ *
17
+ * const result = await api.processData(data);
18
+ *
19
+ * terminate(api);
20
+ * ```
21
+ *
22
+ * Worker thread usage:
23
+ * ```typescript
24
+ * import { expose } from '@wordpress/worker-threads';
25
+ *
26
+ * const api = {
27
+ * async processData(data: ArrayBuffer): Promise<ArrayBuffer> {
28
+ * // ... processing
29
+ * return result;
30
+ * }
31
+ * };
32
+ *
33
+ * expose(api);
34
+ * export type WorkerAPI = typeof api;
35
+ * ```
36
+ */
37
+ /**
38
+ * Wraps a Worker to provide a type-safe RPC interface.
39
+ */
40
+ export { wrap } from './main-thread';
41
+ /**
42
+ * Terminates a wrapped worker and cleans up resources.
43
+ */
44
+ export { terminate } from './main-thread';
45
+ /**
46
+ * Exposes an object's methods to be called from the main thread.
47
+ * This should be called in the worker script.
48
+ */
49
+ export { expose } from './worker-thread';
50
+ /**
51
+ * Type that converts all methods to async versions.
52
+ */
53
+ export type { Remote } from './types';
54
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH;;GAEG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC;;GAEG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C;;;GAGG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC;;GAEG;AACH,YAAY,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import { type Remote } from './types';
5
+ /**
6
+ * Wraps a Worker to provide a type-safe RPC interface.
7
+ *
8
+ * The returned proxy object allows calling methods on the worker as if they
9
+ * were local async functions. Each method call is automatically serialized,
10
+ * sent to the worker, and the result is returned as a Promise.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const worker = new Worker(new URL('./worker.js', import.meta.url));
15
+ * const api = wrap<MyWorkerAPI>(worker);
16
+ *
17
+ * // Call worker methods as async functions
18
+ * const result = await api.processData(data);
19
+ * ```
20
+ *
21
+ * @param worker - The Worker instance to wrap.
22
+ * @return A proxy object with all exposed methods as async functions.
23
+ */
24
+ export declare function wrap<T extends object>(worker: Worker): Remote<T>;
25
+ /**
26
+ * Terminates a wrapped worker and cleans up resources.
27
+ *
28
+ * After calling terminate, any pending calls will be rejected and the
29
+ * worker will be stopped.
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * const api = wrap<MyWorkerAPI>(worker);
34
+ * // ... use the API ...
35
+ * terminate(api); // Clean up when done
36
+ * ```
37
+ *
38
+ * @param remote - The wrapped worker proxy returned by wrap().
39
+ */
40
+ export declare function terminate(remote: Remote<unknown>): void;
41
+ //# sourceMappingURL=main-thread.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main-thread.d.ts","sourceRoot":"","sources":["../src/main-thread.ts"],"names":[],"mappings":"AAUA;;GAEG;AACH,OAAO,EAAiB,KAAK,MAAM,EAAmB,MAAM,SAAS,CAAC;AA4BtE;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,IAAI,CAAE,CAAC,SAAS,MAAM,EAAI,MAAM,EAAE,MAAM,GAAI,MAAM,CAAE,CAAC,CAAE,CAgCtE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CAAE,MAAM,EAAE,MAAM,CAAE,OAAO,CAAE,GAAI,IAAI,CAa3D"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Converts a type to its "remote" version where all methods become async.
3
+ *
4
+ * This type transformation ensures that when calling methods on a wrapped
5
+ * worker, the return types are properly wrapped in Promises.
6
+ */
7
+ export type Remote<T> = {
8
+ [K in keyof T]: T[K] extends (...args: infer A) => infer R ? (...args: A) => Promise<Awaited<R>> : never;
9
+ };
10
+ /**
11
+ * Internal symbol used to store the worker reference on the proxy.
12
+ */
13
+ export declare const WORKER_SYMBOL: unique symbol;
14
+ /**
15
+ * Interface for objects that have an associated worker.
16
+ */
17
+ export interface WithWorker {
18
+ [WORKER_SYMBOL]: Worker;
19
+ }
20
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,MAAM,MAAM,CAAE,CAAC,IAAK;KACvB,CAAC,IAAI,MAAM,CAAC,GAAI,CAAC,CAAE,CAAC,CAAE,SAAS,CAAE,GAAG,IAAI,EAAE,MAAM,CAAC,KAAM,MAAM,CAAC,GAC7D,CAAE,GAAG,IAAI,EAAE,CAAC,KAAM,OAAO,CAAE,OAAO,CAAE,CAAC,CAAE,CAAE,GACzC,KAAK;CACR,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,eAAqB,CAAC;AAEhD;;GAEG;AACH,MAAM,WAAW,UAAU;IAC1B,CAAE,aAAa,CAAE,EAAE,MAAM,CAAC;CAC1B"}