vivth 1.1.1 → 1.2.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.
Files changed (108) hide show
  1. package/.vivth-temp/README.src.md +35 -0
  2. package/README.md +1243 -441
  3. package/README.src.md +5 -2
  4. package/bun.lock +228 -0
  5. package/index.mjs +22 -9
  6. package/package.json +6 -3
  7. package/src/bundler/CompileJS.mjs +258 -0
  8. package/src/bundler/CreateESPlugin.mjs +24 -0
  9. package/src/bundler/EsBundler.mjs +27 -13
  10. package/src/bundler/FSInline.mjs +57 -0
  11. package/src/bundler/FSInlineAnalyzer.mjs +197 -0
  12. package/src/bundler/FSInlineBundled.mjs +34 -0
  13. package/src/bundler/adds/ToBundledJSPlugin.mjs +77 -0
  14. package/src/bundler/adds/externals.mjs +8 -0
  15. package/src/bundler/adds/pluginVivthBundle.mjs +5 -0
  16. package/src/class/Console.mjs +48 -27
  17. package/src/class/Derived.mjs +55 -7
  18. package/src/class/Effect.mjs +100 -39
  19. package/src/class/EnvSignal.mjs +5 -5
  20. package/src/class/EventSignal.mjs +55 -5
  21. package/src/class/FileSafe.mjs +124 -0
  22. package/src/class/ListDerived.mjs +6 -3
  23. package/src/class/ListSignal.mjs +11 -11
  24. package/src/class/LitExp.mjs +405 -0
  25. package/src/class/Paths.mjs +39 -4
  26. package/src/class/QChannel.mjs +79 -28
  27. package/src/class/SafeExit.mjs +31 -11
  28. package/src/class/Setup.mjs +12 -7
  29. package/src/class/Signal.mjs +26 -24
  30. package/src/class/WorkerMainThread.mjs +108 -135
  31. package/src/class/WorkerMainThreadBundled.mjs +216 -0
  32. package/src/class/WorkerThread.mjs +40 -31
  33. package/src/common/Base64URL.mjs +10 -5
  34. package/src/common/Base64URLFromFile.mjs +24 -0
  35. package/src/common/keys.mjs +3 -0
  36. package/src/doc/JSautoDOC.mjs +32 -56
  37. package/src/doc/parsedFile.mjs +37 -36
  38. package/src/function/CreateImmutable.mjs +9 -9
  39. package/src/function/EventCheck.mjs +2 -2
  40. package/src/function/EventObject.mjs +5 -5
  41. package/src/function/GetRuntime.mjs +38 -0
  42. package/src/function/IsAsync.mjs +2 -2
  43. package/src/function/LazyFactory.mjs +13 -13
  44. package/src/function/Timeout.mjs +2 -2
  45. package/src/function/Try.mjs +17 -12
  46. package/src/function/TryAsync.mjs +5 -5
  47. package/src/function/TrySync.mjs +5 -5
  48. package/src/function/TsToMjs.mjs +5 -4
  49. package/src/types/LitExpKeyType.mjs +5 -0
  50. package/src/types/QCBReturn.mjs +1 -1
  51. package/src/types/Runtime.mjs +7 -0
  52. package/types/dev/fsInline.d.mts +1 -0
  53. package/types/dev/test.d.mts +1 -0
  54. package/types/dev/testWorker.d.mts +7 -0
  55. package/types/dev/testbundle.d.mts +1 -0
  56. package/types/dev/workerThreadClass.d.mts +13 -0
  57. package/types/index.d.mts +18 -9
  58. package/types/src/bundler/CompileJS.d.mts +78 -0
  59. package/types/src/bundler/CreateESPlugin.d.mts +17 -0
  60. package/types/src/bundler/EsBundler.d.mts +33 -4
  61. package/types/src/bundler/FSInline.d.mts +43 -0
  62. package/types/src/bundler/FSInlineAnalyzer.d.mts +36 -0
  63. package/types/src/bundler/FSInlineBundled.d.mts +22 -0
  64. package/types/src/bundler/adds/ToBundledJSPlugin.d.mts +16 -0
  65. package/types/src/bundler/adds/externals.d.mts +1 -0
  66. package/types/src/bundler/adds/pluginVivthBundle.d.mts +1 -0
  67. package/types/src/class/Console.d.mts +36 -5
  68. package/types/src/class/Derived.d.mts +132 -5
  69. package/types/src/class/Effect.d.mts +106 -7
  70. package/types/src/class/EnvSignal.d.mts +8 -8
  71. package/types/src/class/EventSignal.d.mts +151 -7
  72. package/types/src/class/FileSafe.d.mts +90 -0
  73. package/types/src/class/ListDerived.d.mts +8 -5
  74. package/types/src/class/ListSignal.d.mts +123 -18
  75. package/types/src/class/LitExp.d.mts +361 -0
  76. package/types/src/class/Paths.d.mts +30 -4
  77. package/types/src/class/QChannel.d.mts +69 -22
  78. package/types/src/class/SafeExit.d.mts +24 -9
  79. package/types/src/class/Setup.d.mts +13 -10
  80. package/types/src/class/Signal.d.mts +73 -17
  81. package/types/src/class/WorkerMainThread.d.mts +47 -39
  82. package/types/src/class/WorkerMainThreadBundled.d.mts +85 -0
  83. package/types/src/class/WorkerThread.d.mts +34 -26
  84. package/types/src/common/Base64URL.d.mts +22 -1
  85. package/types/src/common/Base64URLFromFile.d.mts +16 -0
  86. package/types/src/common/keys.d.mts +1 -0
  87. package/types/src/doc/JSautoDOC.d.mts +3 -19
  88. package/types/src/doc/parsedFile.d.mts +72 -13
  89. package/types/src/function/CreateImmutable.d.mts +27 -2
  90. package/types/src/function/EventCheck.d.mts +15 -0
  91. package/types/src/function/EventObject.d.mts +17 -2
  92. package/types/src/function/GetRuntime.d.mts +2 -0
  93. package/types/src/function/IsAsync.d.mts +18 -0
  94. package/types/src/function/LazyFactory.d.mts +35 -2
  95. package/types/src/function/Timeout.d.mts +16 -0
  96. package/types/src/function/Try.d.mts +52 -1
  97. package/types/src/function/TryAsync.d.mts +22 -1
  98. package/types/src/function/TrySync.d.mts +16 -1
  99. package/types/src/function/TsToMjs.d.mts +19 -0
  100. package/types/src/types/LitExpKeyType.d.mts +1 -0
  101. package/types/src/types/QCBReturn.d.mts +1 -1
  102. package/types/src/types/Runtime.d.mts +1 -0
  103. package/dev/index.mjs +0 -28
  104. package/src/bundler/CompileMJS.mjs +0 -110
  105. package/src/function/WriteFileSafe.mjs +0 -37
  106. package/types/src/bundler/A.d.mts +0 -1
  107. package/types/src/bundler/CompileMJS.d.mts +0 -8
  108. package/types/src/function/WriteFileSafe.d.mts +0 -2
@@ -1,7 +1,7 @@
1
1
  // @ts-check
2
2
 
3
- import { Base64URL } from '../common/Base64URL.mjs';
4
3
  import { closeWorkerThreadEventObject } from '../common/eventObjects.mjs';
4
+ import { GetRuntime } from '../function/GetRuntime.mjs';
5
5
  import { Try } from '../function/Try.mjs';
6
6
  import { TryAsync } from '../function/TryAsync.mjs';
7
7
  import { Console } from './Console.mjs';
@@ -12,40 +12,53 @@ import { SafeExit } from './SafeExit.mjs';
12
12
  import { Signal } from './Signal.mjs';
13
13
 
14
14
  /**
15
- * @template A
16
- * @typedef {import('./WorkerResult.mjs').WorkerResult<A>} WorkerResult
15
+ * @template POST
16
+ * @typedef {import('./WorkerResult.mjs').WorkerResult<POST>} WorkerResult
17
17
  */
18
18
  /**
19
19
  * @typedef {import('./WorkerThread.mjs').WorkerThread} WorkerThread
20
+ * @typedef {import('../common/lazie.mjs').unwrapLazy} unwrapLazy
20
21
  */
21
22
 
22
23
  /**
23
24
  * @description
24
25
  * - class helper to create `Worker` instance;
26
+ * - before any `Worker` functionaily to be used, you need to setup it with `WorkerThread.setup` and `WorkerMainThread.setup` before runing anytyhing;
25
27
  * @template {WorkerThread} WT
26
28
  */
27
29
  export class WorkerMainThread {
30
+ /**
31
+ * @type {boolean}
32
+ */
28
33
  static #isRegistered = false;
29
34
  /**
30
35
  * @description
31
36
  * - need to be called first, before any `WorkerMainThread` instantiation:
32
37
  * @param {Object} param0
33
38
  * @param {typeof WorkerMainThread["workerClass"]} param0.workerClass
39
+ * - example:
40
+ * ```js
41
+ * import { Worker } from 'node:worker_threads';
42
+ * ```
34
43
  * @param {typeof WorkerMainThread["pathValidator"]} param0.pathValidator
44
+ * - example:
35
45
  * ```js
36
- * async(relativePath) => {
37
- * // verify whether relativePath exist, then return the full path
38
- * // use fetch | fs, chained with Paths.instance.root + WorkerMainThread.basePath;
39
- * }
46
+ * async (workerPath, root, base) => {
47
+ * const truePathCheck = `${root}/${base}/${workerPath}`;
48
+ * const res = await fetch(truePathCheck);
49
+ * // might also check wheter it need base or not
50
+ * return await res.ok;
51
+ * }
40
52
  * ```
41
53
  * @param {typeof WorkerMainThread["basePath"]} [param0.basePath]
42
54
  * - additonal realtivePath from rootPath;
43
55
  * - default: '';
44
56
  * @example
57
+ * import { Worker } from 'node:worker_threads';
45
58
  * import { WorkerMainThread } from 'vivth';
46
59
  *
47
60
  * WorkerMainThread.setup({
48
- * workerClass: async () => await (import('worker_threads')).Worker,
61
+ * workerClass: Worker,
49
62
  * basePath: 'public/assets/js/workers',
50
63
  * pathValidator: async (workerPath, root, base) => {
51
64
  * const res = await fetch(`${root}/${base}/${workerPath}`);
@@ -71,7 +84,7 @@ export class WorkerMainThread {
71
84
  * @description
72
85
  * - reference for `Worker` class;
73
86
  * - edit via `setup`;
74
- * @type {()=>Promise<typeof Worker|typeof import('worker_threads').Worker>}
87
+ * @type {typeof Worker|typeof import('worker_threads').Worker}
75
88
  */
76
89
  static workerClass;
77
90
  /**
@@ -92,31 +105,38 @@ export class WorkerMainThread {
92
105
  type: 'module',
93
106
  });
94
107
  /**
108
+ * @template {WorkerThread} WT
95
109
  * @description
96
110
  * - create Worker_instance;
97
111
  * @param {string} handler
98
- * - if `isInline` === `false`, `handler` should be:
99
- * >- pointing to worker thread file; WHICH
100
- * >- the path must be relative to `projectRoot`;
101
- * - if `isInline` === `true`, `handler` should be
102
- * >- string literal of prebundled worker thread script; OR
103
- * >- manually made string literal of worker thread script;
104
112
  * @param {Omit<WorkerOptions|import('worker_threads').WorkerOptions, 'eval'|'type'>} [options]
105
- * @param {boolean} [isInline]
113
+ * @returns {WorkerMainThread<WT>}
114
+ * @example
115
+ * import { WorkerMainThread } from 'vivth';
116
+ *
117
+ * export const myDoubleWorker = WorkerMainThread.newVivthWorker('./doubleWorkerThread.mjs');
118
+ */
119
+ static newVivthWorker = (handler, options = {}) => {
120
+ return new WorkerMainThread(handler, options);
121
+ };
122
+ /**
123
+ * @private
124
+ * @param {Parameters<typeof WorkerMainThread<WT>["newVivthWorker"]>[0]} handler
125
+ * @param {Parameters<typeof WorkerMainThread<WT>["newVivthWorker"]>[1]} [options]
106
126
  * @example
107
127
  * import { WorkerMainThread } from 'vivth';
108
128
  *
109
- * export const myDoubleWorker = new WorkerMainThread('./doubleWorkerThread.mjs');
129
+ * export const myDoubleWorker = WorkerMainThread.newVivthWorker('./doubleWorkerThread.mjs');
110
130
  */
111
- constructor(handler, options = {}, isInline = false) {
131
+ constructor(handler, options = {}) {
112
132
  /**
113
- * @param {WT["Receive"]} ev
133
+ * @param {WT["RECEIVE"]} ev
114
134
  * @returns {void}
115
135
  */
116
136
  const listener = (ev) => {
117
137
  this.#proxyReceiver.value = ev;
118
138
  };
119
- WorkerMainThread.#workerFilehandler(handler, options, this, listener, isInline);
139
+ WorkerMainThread.#workerFilehandler(handler, options, this, listener);
120
140
  }
121
141
  /**
122
142
  * @type {import('./Signal.mjs').Signal<import('./WorkerResult.mjs').WorkerResult<WT["Post"]>|MessageEvent<import('./WorkerResult.mjs').WorkerResult<WT["Post"]>>>}
@@ -128,144 +148,97 @@ export class WorkerMainThread {
128
148
  * | import('worker_threads').WorkerOptions} options
129
149
  * @param {WorkerMainThread} worker
130
150
  * @param {(any:any)=>void} listener
131
- * @param {boolean} isInline
132
151
  * @returns {Promise<void>}
133
152
  */
134
- static #workerFilehandler = async (handler, options, worker, listener, isInline) => {
153
+ static #workerFilehandler = async (handler, options, worker, listener) => {
135
154
  let resolvedPath;
136
- if (!isInline) {
137
- const pathValidator = WorkerMainThread.pathValidator;
138
- const [resolvedPath_, error] = await TryAsync(async () => {
139
- return await pathValidator({
140
- worker: handler,
141
- root: Paths.root,
142
- base: WorkerMainThread.basePath,
143
- });
155
+ const pathValidator = WorkerMainThread.pathValidator;
156
+ const [resolvedPath_, error] = await TryAsync(async () => {
157
+ return await pathValidator({
158
+ worker: handler,
159
+ root: Paths.root,
160
+ base: WorkerMainThread.basePath,
144
161
  });
145
- if (error) {
146
- Console.error({
147
- error,
148
- pathValidator,
149
- message: 'invalid pathValidator inputed to `WorkerMainThread`;',
150
- });
151
- return;
152
- }
153
- resolvedPath = resolvedPath_;
154
- } else {
155
- WorkerMainThread.#options.eval = true;
156
- resolvedPath = handler;
162
+ });
163
+ if (error) {
164
+ Console.error({
165
+ error,
166
+ pathValidator,
167
+ message: 'invalid pathValidator inputed to `WorkerMainThread`;',
168
+ });
169
+ return;
170
+ }
171
+ resolvedPath = resolvedPath_;
172
+ const runtime = GetRuntime();
173
+ const workerClass = WorkerMainThread.workerClass;
174
+ if (!workerClass) {
175
+ Console.error('invalid `Worker` inputed to `WorkerMainThread`;');
176
+ return;
157
177
  }
158
- const [_1, error1] = await Try({
159
- universal: async () => {
160
- const WorkerClass = await WorkerMainThread.workerClass();
161
- if (!WorkerClass) {
162
- throw new Error('invalid `Worker` inputed to `WorkerMainThread`;');
178
+ const [, errorCreatingWorker] = await Try({
179
+ browser: async () => {
180
+ if (runtime !== 'browser') {
181
+ throw new Error('not a browser');
163
182
  }
164
- const [_2, error2] = await Try({
165
- browser: async () => {
166
- if (!WorkerMainThread.isBrowser) {
167
- throw new Error('not a browser');
168
- }
169
- let worker_;
170
- if (!isInline) {
171
- worker_ = worker.#worker.value = new WorkerClass(resolvedPath, {
172
- ...options,
173
- ...WorkerMainThread.#options,
174
- });
175
- } else {
176
- const inlineURL = Base64URL(handler, 'application/javascript', btoa);
177
- worker_ = worker.#worker.value = new WorkerClass(inlineURL, {
178
- ...options,
179
- ...WorkerMainThread.#options,
180
- });
181
- }
182
- if (!('onmessage' in worker_)) {
183
- throw new Error();
184
- }
185
- worker_.onmessage = listener;
186
- if (SafeExit.instance) {
187
- SafeExit.instance.addCallback(async () => {
188
- worker_.onmessage = null;
189
- });
190
- }
191
- },
192
- nonBrowser: async () => {
193
- const worker_ = (worker.#worker.value = new WorkerClass(resolvedPath, {
194
- ...options,
195
- ...WorkerMainThread.#options,
196
- }));
197
- if (!('addEventListener' in worker_)) {
198
- throw new Error();
199
- }
200
- worker_.addEventListener('message', listener);
201
- if (SafeExit.instance) {
202
- SafeExit.instance.addCallback(async () => {
203
- worker_.removeEventListener('message', listener);
204
- });
205
- }
206
- },
183
+ let worker_;
184
+ worker_ = worker.#worker.value = new workerClass(resolvedPath, {
185
+ ...options,
186
+ ...WorkerMainThread.#options,
207
187
  });
208
- if (error2) {
209
- throw new Error();
188
+ if (!('onmessage' in worker_)) {
189
+ throw new Error('not a browser');
210
190
  }
191
+ worker_.onmessage = listener;
211
192
  if (SafeExit.instance) {
212
193
  SafeExit.instance.addCallback(async () => {
213
- worker.#worker.value.postMessage(closeWorkerThreadEventObject);
214
- worker.terminate();
194
+ worker_.onmessage = null;
215
195
  });
216
196
  }
217
197
  },
218
- nodeOrBun: async () => {
219
- if (!worker.#worker.value) {
220
- const { Worker } = await import('node:worker_threads');
221
- worker.#worker.value = new Worker(resolvedPath, {
222
- ...options,
223
- ...WorkerMainThread.#options,
224
- });
225
- }
226
- const worker_ = worker.#worker.value;
227
- // @ts-expect-error
228
- worker_.addListener('message', listener);
229
- if (SafeExit.instance) {
230
- SafeExit.instance.addCallback(async () => {
231
- // @ts-expect-error
232
- worker_.removeListener('message', listener);
233
- worker_.postMessage(closeWorkerThreadEventObject);
234
- worker.terminate();
235
- });
198
+ nonBrowser: async () => {
199
+ const worker_ = (worker.#worker.value = new workerClass(resolvedPath, {
200
+ ...options,
201
+ ...WorkerMainThread.#options,
202
+ }));
203
+ if ('addEventListener' in worker_) {
204
+ worker_.addEventListener('message', listener);
205
+ if (SafeExit.instance) {
206
+ SafeExit.instance.addCallback(async () => {
207
+ worker_.removeEventListener('message', listener);
208
+ });
209
+ }
210
+ } else if ('addListener' in worker_) {
211
+ worker_.addListener('message', listener);
212
+ if (SafeExit.instance) {
213
+ SafeExit.instance.addCallback(async () => {
214
+ worker_.removeListener('message', listener);
215
+ });
216
+ }
217
+ } else {
218
+ throw new Error('not a standard non browser');
236
219
  }
237
220
  },
238
221
  });
239
- if (error1) {
240
- Console.error(error1);
222
+ if (errorCreatingWorker) {
223
+ Console.error(errorCreatingWorker);
241
224
  return;
242
225
  }
243
- };
244
- /**
245
- * @type {boolean}
246
- */
247
- static #isBrowser = undefined;
248
- /**
249
- * @description
250
- * - check whether js run in browser
251
- * @type {boolean}
252
- */
253
- static get isBrowser() {
254
- if (WorkerMainThread.#isBrowser === undefined) {
255
- WorkerMainThread.#isBrowser =
256
- typeof window !== 'undefined' &&
257
- typeof location === 'object' &&
258
- typeof location.origin === 'string';
226
+ if (SafeExit.instance) {
227
+ SafeExit.instance.addCallback(async () => {
228
+ if (worker.#worker.value) {
229
+ worker.#worker.value.postMessage(closeWorkerThreadEventObject);
230
+ }
231
+ worker.terminate();
232
+ });
259
233
  }
260
- return WorkerMainThread.#isBrowser;
261
- }
234
+ };
262
235
  /**
263
236
  * lazyly generated because node version need to await
264
237
  * @type {Signal<Worker | import('worker_threads').Worker>}
265
238
  */
266
239
  #worker = new Signal(undefined);
267
240
  /**
268
- * @type {Signal<WT["Receive"]>}
241
+ * @type {Signal<WT["RECEIVE"]>}
269
242
  */
270
243
  #proxyPost = new Signal(undefined);
271
244
  #handler = new Effect(async ({ subscribe }) => {
@@ -295,7 +268,7 @@ export class WorkerMainThread {
295
268
  /**
296
269
  * @description
297
270
  * - result signal of the processed message;
298
- * @type {Derived<WorkerResult<WT["Post"]>>}
271
+ * @type {Derived<WorkerResult<WT["POST"]>>}
299
272
  * @example
300
273
  * import { Effect } from 'vivth';
301
274
  * import { myDoubleWorker } from './myDoubleWorker.mjs';
@@ -316,7 +289,7 @@ export class WorkerMainThread {
316
289
  /**
317
290
  * @description
318
291
  * - callback to send message to the worker thread;
319
- * @type {(event: WT["Receive"])=>void}
292
+ * @type {(event: WT["RECEIVE"])=>void}
320
293
  * @example
321
294
  * import { myDoubleWorker } from './myDoubleWorker.mjs';
322
295
  *
@@ -0,0 +1,216 @@
1
+ // @ts-check
2
+
3
+ import { FSInline } from '../bundler/FSInline.mjs';
4
+ import { Base64URL } from '../common/Base64URL.mjs';
5
+ import { closeWorkerThreadEventObject } from '../common/eventObjects.mjs';
6
+ import { GetRuntime } from '../function/GetRuntime.mjs';
7
+ import { Try } from '../function/Try.mjs';
8
+ import { Console } from './Console.mjs';
9
+ import { Derived } from './Derived.mjs';
10
+ import { Effect } from './Effect.mjs';
11
+ import { Paths } from './Paths.mjs';
12
+ import { SafeExit } from './SafeExit.mjs';
13
+ import { Signal } from './Signal.mjs';
14
+
15
+ /**
16
+ * @template POST
17
+ * @typedef {import('./WorkerResult.mjs').WorkerResult<POST>} WorkerResult
18
+ */
19
+ /**
20
+ * @typedef {import('./WorkerThread.mjs').WorkerThread} WorkerThread
21
+ * @typedef {import('../common/lazie.mjs').unwrapLazy} unwrapLazy
22
+ */
23
+
24
+ /**
25
+ * @template {WorkerThread} WT
26
+ */
27
+ export class WorkerMainThread {
28
+ /**
29
+ * @type {boolean}
30
+ */
31
+ static #isRegistered = false;
32
+ /**
33
+ * @param {Object} param0
34
+ * @param {typeof WorkerMainThread["workerClass"]} param0.workerClass
35
+ * @param {typeof WorkerMainThread["pathValidator"]} param0.pathValidator
36
+ * @param {typeof WorkerMainThread["basePath"]} [param0.basePath]
37
+ */
38
+ static setup = ({ workerClass, pathValidator, basePath = '' }) => {
39
+ if (!Paths.root) {
40
+ return;
41
+ }
42
+ if (WorkerMainThread.#isRegistered) {
43
+ Console.warn({ message: 'WorkerMainThread.setup, can only be called once' });
44
+ return;
45
+ }
46
+ WorkerMainThread.#isRegistered = true;
47
+ WorkerMainThread.workerClass = workerClass;
48
+ WorkerMainThread.pathValidator = pathValidator;
49
+ WorkerMainThread.basePath = basePath;
50
+ };
51
+ /**
52
+ * @type {typeof Worker|typeof import('worker_threads').Worker}
53
+ */
54
+ static workerClass;
55
+ /**
56
+ * @type {string}
57
+ */
58
+ static basePath;
59
+ /**
60
+ * @type {(paths:{worker: string, root:string, base: string})=>Promise<string>}
61
+ */
62
+ static pathValidator;
63
+ static #options = /** @type {import('worker_threads').WorkerOptions & { type?: 'module' }} */ ({
64
+ type: 'module',
65
+ });
66
+ /**
67
+ * @template {WorkerThread} WT
68
+ * @param {string} handler
69
+ * @param {Omit<WorkerOptions|import('worker_threads').WorkerOptions, 'eval'|'type'>} [options]
70
+ * @returns {WorkerMainThread<WT>}
71
+ */
72
+ static newVivthWorker = (handler, options = {}) => {
73
+ return new WorkerMainThread(handler, options);
74
+ };
75
+ /**
76
+ * @param {Parameters<typeof WorkerMainThread<WT>["newVivthWorker"]>[0]} handler
77
+ * @param {Parameters<typeof WorkerMainThread<WT>["newVivthWorker"]>[1]} [options]
78
+ */
79
+ constructor(handler, options = {}) {
80
+ /**
81
+ * @param {WT["RECEIVE"]} ev
82
+ * @returns {void}
83
+ */
84
+ const listener = (ev) => {
85
+ this.#proxyReceiver.value = ev;
86
+ };
87
+ WorkerMainThread.#workerFilehandler(handler, options, this, listener);
88
+ }
89
+ /**
90
+ * @type {import('./Signal.mjs').Signal<import('./WorkerResult.mjs').WorkerResult<WT["Post"]>|MessageEvent<import('./WorkerResult.mjs').WorkerResult<WT["Post"]>>>}
91
+ */
92
+ #proxyReceiver = new Signal(undefined);
93
+ /**
94
+ * @param {string} handler
95
+ * @param { WorkerOptions
96
+ * | import('worker_threads').WorkerOptions} options
97
+ * @param {WorkerMainThread} worker
98
+ * @param {(any:any)=>void} listener
99
+ * @returns {Promise<void>}
100
+ */
101
+ static #workerFilehandler = async (handler, options, worker, listener) => {
102
+ let resolvedPath;
103
+ WorkerMainThread.#options.eval = true;
104
+ resolvedPath = (await FSInline.vivthFSInlineFile(handler)).toString('utf-8');
105
+ const runtime = GetRuntime();
106
+ const workerClass = WorkerMainThread.workerClass;
107
+ if (!workerClass) {
108
+ Console.error('invalid `Worker` inputed to `WorkerMainThread`;');
109
+ return;
110
+ }
111
+ const [, errorCreatingWorker] = await Try({
112
+ browser: async () => {
113
+ if (runtime !== 'browser') {
114
+ throw new Error('not a browser');
115
+ }
116
+ let worker_;
117
+ const inlineURL = Base64URL(handler, 'application/javascript', btoa);
118
+ worker_ = worker.#worker.value = new workerClass(inlineURL, {
119
+ ...options,
120
+ ...WorkerMainThread.#options,
121
+ });
122
+ if (!('onmessage' in worker_)) {
123
+ throw new Error('not a browser');
124
+ }
125
+ worker_.onmessage = listener;
126
+ if (SafeExit.instance) {
127
+ SafeExit.instance.addCallback(async () => {
128
+ worker_.onmessage = null;
129
+ });
130
+ }
131
+ },
132
+ nonBrowser: async () => {
133
+ const worker_ = (worker.#worker.value = new workerClass(resolvedPath, {
134
+ ...options,
135
+ ...WorkerMainThread.#options,
136
+ }));
137
+ if ('addEventListener' in worker_) {
138
+ worker_.addEventListener('message', listener);
139
+ if (SafeExit.instance) {
140
+ SafeExit.instance.addCallback(async () => {
141
+ worker_.removeEventListener('message', listener);
142
+ });
143
+ }
144
+ } else if ('addListener' in worker_) {
145
+ worker_.addListener('message', listener);
146
+ if (SafeExit.instance) {
147
+ SafeExit.instance.addCallback(async () => {
148
+ worker_.removeListener('message', listener);
149
+ });
150
+ }
151
+ } else {
152
+ throw new Error('not a standard non browser');
153
+ }
154
+ },
155
+ });
156
+ if (errorCreatingWorker) {
157
+ Console.error(errorCreatingWorker);
158
+ return;
159
+ }
160
+ if (SafeExit.instance) {
161
+ SafeExit.instance.addCallback(async () => {
162
+ if (worker.#worker.value) {
163
+ worker.#worker.value.postMessage(closeWorkerThreadEventObject);
164
+ }
165
+ worker.terminate();
166
+ });
167
+ }
168
+ };
169
+ /**
170
+ * lazyly generated because node version need to await
171
+ * @type {Signal<Worker | import('worker_threads').Worker>}
172
+ */
173
+ #worker = new Signal(undefined);
174
+ /**
175
+ * @type {Signal<WT["RECEIVE"]>}
176
+ */
177
+ #proxyPost = new Signal(undefined);
178
+ #handler = new Effect(async ({ subscribe }) => {
179
+ const postData = subscribe(this.#proxyPost).value;
180
+ const worker = subscribe(this.#worker).value;
181
+ if (!worker || postData === undefined) {
182
+ return;
183
+ }
184
+ worker.postMessage(postData);
185
+ });
186
+ /**
187
+ * @type {()=>void}
188
+ */
189
+ terminate = () => {
190
+ /**
191
+ * this is more for browser, as most of this are automatically cleaned with `SafeExit`;
192
+ */
193
+ this.#worker.value?.terminate();
194
+ this.#worker.remove.ref();
195
+ this.#handler.options.removeEffect();
196
+ this.#proxyPost.remove.ref();
197
+ this.#proxyReceiver.remove.ref();
198
+ this.receiverSignal.remove.ref();
199
+ };
200
+ /**
201
+ * @type {Derived<WorkerResult<WT["POST"]>>}
202
+ */
203
+ receiverSignal = new Derived(async ({ subscribe }) => {
204
+ const val = subscribe(this.#proxyReceiver).value;
205
+ if (val instanceof MessageEvent) {
206
+ return val.data;
207
+ }
208
+ return val;
209
+ });
210
+ /**
211
+ * @type {(event: WT["RECEIVE"])=>void}
212
+ */
213
+ postMessage = (data) => {
214
+ this.#proxyPost.value = data;
215
+ };
216
+ }