vivth 1.1.2 → 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 +1215 -433
  3. package/README.src.md +5 -2
  4. package/bun.lock +228 -0
  5. package/index.mjs +17 -4
  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 +27 -1
  26. package/src/class/QChannel.mjs +79 -28
  27. package/src/class/SafeExit.mjs +31 -11
  28. package/src/class/Setup.mjs +5 -2
  29. package/src/class/Signal.mjs +26 -24
  30. package/src/class/WorkerMainThread.mjs +100 -133
  31. package/src/class/WorkerMainThreadBundled.mjs +216 -0
  32. package/src/class/WorkerThread.mjs +38 -32
  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 +13 -4
  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 +18 -1
  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 +6 -5
  80. package/types/src/class/Signal.d.mts +73 -17
  81. package/types/src/class/WorkerMainThread.d.mts +39 -37
  82. package/types/src/class/WorkerMainThreadBundled.d.mts +85 -0
  83. package/types/src/class/WorkerThread.d.mts +32 -27
  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,19 +12,24 @@ 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
@@ -33,13 +38,14 @@ export class WorkerMainThread {
33
38
  * @param {typeof WorkerMainThread["workerClass"]} param0.workerClass
34
39
  * - example:
35
40
  * ```js
36
- * async () => await (import('worker_threads')).Worker
41
+ * import { Worker } from 'node:worker_threads';
37
42
  * ```
38
43
  * @param {typeof WorkerMainThread["pathValidator"]} param0.pathValidator
39
44
  * - example:
40
45
  * ```js
41
46
  * async (workerPath, root, base) => {
42
- * const res = await fetch(`${root}/${base}/${workerPath}`);
47
+ * const truePathCheck = `${root}/${base}/${workerPath}`;
48
+ * const res = await fetch(truePathCheck);
43
49
  * // might also check wheter it need base or not
44
50
  * return await res.ok;
45
51
  * }
@@ -48,10 +54,11 @@ export class WorkerMainThread {
48
54
  * - additonal realtivePath from rootPath;
49
55
  * - default: '';
50
56
  * @example
57
+ * import { Worker } from 'node:worker_threads';
51
58
  * import { WorkerMainThread } from 'vivth';
52
59
  *
53
60
  * WorkerMainThread.setup({
54
- * workerClass: async () => await (import('worker_threads')).Worker,
61
+ * workerClass: Worker,
55
62
  * basePath: 'public/assets/js/workers',
56
63
  * pathValidator: async (workerPath, root, base) => {
57
64
  * const res = await fetch(`${root}/${base}/${workerPath}`);
@@ -77,7 +84,7 @@ export class WorkerMainThread {
77
84
  * @description
78
85
  * - reference for `Worker` class;
79
86
  * - edit via `setup`;
80
- * @type {()=>Promise<typeof Worker|typeof import('worker_threads').Worker>}
87
+ * @type {typeof Worker|typeof import('worker_threads').Worker}
81
88
  */
82
89
  static workerClass;
83
90
  /**
@@ -98,31 +105,38 @@ export class WorkerMainThread {
98
105
  type: 'module',
99
106
  });
100
107
  /**
108
+ * @template {WorkerThread} WT
101
109
  * @description
102
110
  * - create Worker_instance;
103
111
  * @param {string} handler
104
- * - if `isInline` === `false`, `handler` should be:
105
- * >- pointing to worker thread file; WHICH
106
- * >- the path must be relative to `projectRoot`;
107
- * - if `isInline` === `true`, `handler` should be
108
- * >- string literal of prebundled worker thread script; OR
109
- * >- manually made string literal of worker thread script;
110
112
  * @param {Omit<WorkerOptions|import('worker_threads').WorkerOptions, 'eval'|'type'>} [options]
111
- * @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]
112
126
  * @example
113
127
  * import { WorkerMainThread } from 'vivth';
114
128
  *
115
- * export const myDoubleWorker = new WorkerMainThread('./doubleWorkerThread.mjs');
129
+ * export const myDoubleWorker = WorkerMainThread.newVivthWorker('./doubleWorkerThread.mjs');
116
130
  */
117
- constructor(handler, options = {}, isInline = false) {
131
+ constructor(handler, options = {}) {
118
132
  /**
119
- * @param {WT["Receive"]} ev
133
+ * @param {WT["RECEIVE"]} ev
120
134
  * @returns {void}
121
135
  */
122
136
  const listener = (ev) => {
123
137
  this.#proxyReceiver.value = ev;
124
138
  };
125
- WorkerMainThread.#workerFilehandler(handler, options, this, listener, isInline);
139
+ WorkerMainThread.#workerFilehandler(handler, options, this, listener);
126
140
  }
127
141
  /**
128
142
  * @type {import('./Signal.mjs').Signal<import('./WorkerResult.mjs').WorkerResult<WT["Post"]>|MessageEvent<import('./WorkerResult.mjs').WorkerResult<WT["Post"]>>>}
@@ -134,144 +148,97 @@ export class WorkerMainThread {
134
148
  * | import('worker_threads').WorkerOptions} options
135
149
  * @param {WorkerMainThread} worker
136
150
  * @param {(any:any)=>void} listener
137
- * @param {boolean} isInline
138
151
  * @returns {Promise<void>}
139
152
  */
140
- static #workerFilehandler = async (handler, options, worker, listener, isInline) => {
153
+ static #workerFilehandler = async (handler, options, worker, listener) => {
141
154
  let resolvedPath;
142
- if (!isInline) {
143
- const pathValidator = WorkerMainThread.pathValidator;
144
- const [resolvedPath_, error] = await TryAsync(async () => {
145
- return await pathValidator({
146
- worker: handler,
147
- root: Paths.root,
148
- base: WorkerMainThread.basePath,
149
- });
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,
150
161
  });
151
- if (error) {
152
- Console.error({
153
- error,
154
- pathValidator,
155
- message: 'invalid pathValidator inputed to `WorkerMainThread`;',
156
- });
157
- return;
158
- }
159
- resolvedPath = resolvedPath_;
160
- } else {
161
- WorkerMainThread.#options.eval = true;
162
- 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;
163
177
  }
164
- const [_1, error1] = await Try({
165
- universal: async () => {
166
- const WorkerClass = await WorkerMainThread.workerClass();
167
- if (!WorkerClass) {
168
- 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');
169
182
  }
170
- const [_2, error2] = await Try({
171
- browser: async () => {
172
- if (!WorkerMainThread.isBrowser) {
173
- throw new Error('not a browser');
174
- }
175
- let worker_;
176
- if (!isInline) {
177
- worker_ = worker.#worker.value = new WorkerClass(resolvedPath, {
178
- ...options,
179
- ...WorkerMainThread.#options,
180
- });
181
- } else {
182
- const inlineURL = Base64URL(handler, 'application/javascript', btoa);
183
- worker_ = worker.#worker.value = new WorkerClass(inlineURL, {
184
- ...options,
185
- ...WorkerMainThread.#options,
186
- });
187
- }
188
- if (!('onmessage' in worker_)) {
189
- throw new Error();
190
- }
191
- worker_.onmessage = listener;
192
- if (SafeExit.instance) {
193
- SafeExit.instance.addCallback(async () => {
194
- worker_.onmessage = null;
195
- });
196
- }
197
- },
198
- nonBrowser: async () => {
199
- const worker_ = (worker.#worker.value = new WorkerClass(resolvedPath, {
200
- ...options,
201
- ...WorkerMainThread.#options,
202
- }));
203
- if (!('addEventListener' in worker_)) {
204
- throw new Error();
205
- }
206
- worker_.addEventListener('message', listener);
207
- if (SafeExit.instance) {
208
- SafeExit.instance.addCallback(async () => {
209
- worker_.removeEventListener('message', listener);
210
- });
211
- }
212
- },
183
+ let worker_;
184
+ worker_ = worker.#worker.value = new workerClass(resolvedPath, {
185
+ ...options,
186
+ ...WorkerMainThread.#options,
213
187
  });
214
- if (error2) {
215
- throw new Error();
188
+ if (!('onmessage' in worker_)) {
189
+ throw new Error('not a browser');
216
190
  }
191
+ worker_.onmessage = listener;
217
192
  if (SafeExit.instance) {
218
193
  SafeExit.instance.addCallback(async () => {
219
- worker.#worker.value.postMessage(closeWorkerThreadEventObject);
220
- worker.terminate();
194
+ worker_.onmessage = null;
221
195
  });
222
196
  }
223
197
  },
224
- nodeOrBun: async () => {
225
- if (!worker.#worker.value) {
226
- const { Worker } = await import('node:worker_threads');
227
- worker.#worker.value = new Worker(resolvedPath, {
228
- ...options,
229
- ...WorkerMainThread.#options,
230
- });
231
- }
232
- const worker_ = worker.#worker.value;
233
- // @ts-expect-error
234
- worker_.addListener('message', listener);
235
- if (SafeExit.instance) {
236
- SafeExit.instance.addCallback(async () => {
237
- // @ts-expect-error
238
- worker_.removeListener('message', listener);
239
- worker_.postMessage(closeWorkerThreadEventObject);
240
- worker.terminate();
241
- });
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');
242
219
  }
243
220
  },
244
221
  });
245
- if (error1) {
246
- Console.error(error1);
222
+ if (errorCreatingWorker) {
223
+ Console.error(errorCreatingWorker);
247
224
  return;
248
225
  }
249
- };
250
- /**
251
- * @type {boolean}
252
- */
253
- static #isBrowser = undefined;
254
- /**
255
- * @description
256
- * - check whether js run in browser
257
- * @type {boolean}
258
- */
259
- static get isBrowser() {
260
- if (WorkerMainThread.#isBrowser === undefined) {
261
- WorkerMainThread.#isBrowser =
262
- typeof window !== 'undefined' &&
263
- typeof location === 'object' &&
264
- 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
+ });
265
233
  }
266
- return WorkerMainThread.#isBrowser;
267
- }
234
+ };
268
235
  /**
269
236
  * lazyly generated because node version need to await
270
237
  * @type {Signal<Worker | import('worker_threads').Worker>}
271
238
  */
272
239
  #worker = new Signal(undefined);
273
240
  /**
274
- * @type {Signal<WT["Receive"]>}
241
+ * @type {Signal<WT["RECEIVE"]>}
275
242
  */
276
243
  #proxyPost = new Signal(undefined);
277
244
  #handler = new Effect(async ({ subscribe }) => {
@@ -301,7 +268,7 @@ export class WorkerMainThread {
301
268
  /**
302
269
  * @description
303
270
  * - result signal of the processed message;
304
- * @type {Derived<WorkerResult<WT["Post"]>>}
271
+ * @type {Derived<WorkerResult<WT["POST"]>>}
305
272
  * @example
306
273
  * import { Effect } from 'vivth';
307
274
  * import { myDoubleWorker } from './myDoubleWorker.mjs';
@@ -322,7 +289,7 @@ export class WorkerMainThread {
322
289
  /**
323
290
  * @description
324
291
  * - callback to send message to the worker thread;
325
- * @type {(event: WT["Receive"])=>void}
292
+ * @type {(event: WT["RECEIVE"])=>void}
326
293
  * @example
327
294
  * import { myDoubleWorker } from './myDoubleWorker.mjs';
328
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
+ }