vivth 1.2.3 → 1.3.1
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 +609 -586
- package/README.src.md +5 -1
- package/bun.lock +6 -0
- package/index.mjs +10 -6
- package/package.json +3 -1
- package/src/bundler/CompileJS.mjs +11 -8
- package/src/bundler/EsBundler.mjs +4 -2
- package/src/bundler/FSInline.mjs +3 -0
- package/src/bundler/FSInlineAnalyzer.mjs +31 -7
- package/src/bundler/FSInlineBundled.mjs +5 -1
- package/src/bundler/adds/ToBundledJSPlugin.mjs +3 -4
- package/src/class/Console.mjs +12 -4
- package/src/class/Derived.mjs +5 -1
- package/src/class/Effect.mjs +6 -6
- package/src/class/EnvSignal.mjs +1 -8
- package/src/class/EventSignal.mjs +8 -7
- package/src/class/FileSafe.mjs +1 -1
- package/src/class/ListSignal.mjs +18 -10
- package/src/class/LitExp.mjs +241 -204
- package/src/class/Paths.mjs +10 -8
- package/src/class/QChannel.mjs +14 -7
- package/src/class/SafeExit.mjs +16 -7
- package/src/class/Signal.mjs +8 -7
- package/src/class/WorkerMainThread.mjs +45 -24
- package/src/class/WorkerMainThreadBundled.mjs +42 -24
- package/src/class/WorkerThread.mjs +21 -7
- package/src/common/Base64URL.mjs +2 -2
- package/src/common/Base64URLFromFile.mjs +1 -1
- package/src/doc/JSautoDOC.mjs +101 -62
- package/src/doc/correctBeforeParse.mjs +139 -0
- package/src/doc/parsedFile.mjs +127 -76
- package/src/function/CreateImmutable.mjs +12 -7
- package/src/function/GetRuntime.mjs +8 -3
- package/src/function/LazyFactory.mjs +10 -4
- package/src/function/Try.mjs +4 -1
- package/src/function/TryAsync.mjs +2 -1
- package/src/function/TrySync.mjs +3 -1
- package/src/function/TsToMjs.mjs +7 -4
- package/src/types/AnyButUndefined.mjs +1 -0
- package/src/types/LitExpResultType.mjs +7 -0
- package/src/types/Runtime.mjs +1 -1
- package/tsconfig.json +27 -5
- package/types/dev/workerThreadClass.d.mts +1 -1
- package/types/index.d.mts +7 -6
- package/types/src/bundler/CompileJS.d.mts +14 -9
- package/types/src/bundler/EsBundler.d.mts +1 -1
- package/types/src/class/Derived.d.mts +4 -64
- package/types/src/class/Effect.d.mts +8 -8
- package/types/src/class/EnvSignal.d.mts +0 -1
- package/types/src/class/EventSignal.d.mts +5 -5
- package/types/src/class/FileSafe.d.mts +2 -2
- package/types/src/class/ListSignal.d.mts +1 -1
- package/types/src/class/LitExp.d.mts +49 -53
- package/types/src/class/Paths.d.mts +4 -4
- package/types/src/class/QChannel.d.mts +1 -1
- package/types/src/class/SafeExit.d.mts +3 -3
- package/types/src/class/Signal.d.mts +3 -3
- package/types/src/class/WorkerMainThread.d.mts +13 -8
- package/types/src/class/WorkerMainThreadBundled.d.mts +13 -8
- package/types/src/class/WorkerThread.d.mts +4 -4
- package/types/src/common/Base64URL.d.mts +2 -2
- package/types/src/common/Base64URLFromFile.d.mts +2 -2
- package/types/src/doc/JSautoDOC.d.mts +34 -12
- package/types/src/doc/correctBeforeParse.d.mts +2 -0
- package/types/src/doc/parsedFile.d.mts +7 -10
- package/types/src/function/CreateImmutable.d.mts +2 -2
- package/types/src/function/Try.d.mts +2 -2
- package/types/src/function/TryAsync.d.mts +2 -2
- package/types/src/function/TrySync.d.mts +3 -2
- package/types/src/function/TsToMjs.d.mts +2 -2
- package/types/src/types/LitExpResultType.d.mts +7 -0
package/src/class/SafeExit.mjs
CHANGED
|
@@ -22,9 +22,9 @@ export class SafeExit {
|
|
|
22
22
|
/**
|
|
23
23
|
* @description
|
|
24
24
|
* - only accessible after instantiation;
|
|
25
|
-
* @type {SafeExit}
|
|
25
|
+
* @type {SafeExit|undefined}
|
|
26
26
|
*/
|
|
27
|
-
static instance
|
|
27
|
+
static instance;
|
|
28
28
|
/**
|
|
29
29
|
* @description
|
|
30
30
|
* @param {Object} options
|
|
@@ -84,7 +84,7 @@ export class SafeExit {
|
|
|
84
84
|
* });
|
|
85
85
|
*/
|
|
86
86
|
constructor({ eventNames, terminator, listener = undefined }) {
|
|
87
|
-
if (SafeExit.instance) {
|
|
87
|
+
if (SafeExit.instance instanceof SafeExit) {
|
|
88
88
|
return SafeExit.instance;
|
|
89
89
|
}
|
|
90
90
|
SafeExit.instance = this;
|
|
@@ -117,8 +117,14 @@ export class SafeExit {
|
|
|
117
117
|
* @type {(eventName:string)=>void}
|
|
118
118
|
*/
|
|
119
119
|
#listener = (eventName) => {
|
|
120
|
+
if (SafeExit.instance === undefined) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
120
123
|
SafeExit.instance.exiting.env.value;
|
|
121
124
|
process.once(eventName, function () {
|
|
125
|
+
if (SafeExit.instance === undefined) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
122
128
|
Console.log(`safe exit via "${eventName}"`);
|
|
123
129
|
SafeExit.instance.exiting.correction(true);
|
|
124
130
|
});
|
|
@@ -141,9 +147,12 @@ export class SafeExit {
|
|
|
141
147
|
/**
|
|
142
148
|
* @type {()=>void}
|
|
143
149
|
*/
|
|
144
|
-
#exit;
|
|
150
|
+
#exit = () => {};
|
|
145
151
|
#autoCleanUp = new Effect(async ({ subscribe }) => {
|
|
146
|
-
if (
|
|
152
|
+
if (
|
|
153
|
+
//
|
|
154
|
+
!subscribe(this.exiting.env).value
|
|
155
|
+
) {
|
|
147
156
|
return;
|
|
148
157
|
}
|
|
149
158
|
setOFSignals.forEach((signal) => {
|
|
@@ -156,13 +165,13 @@ export class SafeExit {
|
|
|
156
165
|
const [, error] = await TryAsync(async () => {
|
|
157
166
|
await cleanup();
|
|
158
167
|
});
|
|
159
|
-
if (
|
|
168
|
+
if (error === undefined) {
|
|
160
169
|
continue;
|
|
161
170
|
}
|
|
162
171
|
Console.warn(error);
|
|
163
172
|
}
|
|
164
173
|
const [, errorExitting] = TrySync(this.#exit);
|
|
165
|
-
if (
|
|
174
|
+
if (errorExitting === undefined) {
|
|
166
175
|
return;
|
|
167
176
|
}
|
|
168
177
|
Console.error(errorExitting);
|
package/src/class/Signal.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import { Console } from './Console.mjs';
|
|
|
7
7
|
import { Effect, setOfEffects } from './Effect.mjs';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* @type {Set<Signal
|
|
10
|
+
* @type {Set<Signal<any>>}
|
|
11
11
|
*/
|
|
12
12
|
export const setOFSignals = new Set();
|
|
13
13
|
|
|
@@ -64,7 +64,7 @@ export class Signal {
|
|
|
64
64
|
* });
|
|
65
65
|
*/
|
|
66
66
|
notify: (callback = undefined) => {
|
|
67
|
-
if (
|
|
67
|
+
if (callback === undefined) {
|
|
68
68
|
Signal.#notify(this.subscribers.setOf);
|
|
69
69
|
return;
|
|
70
70
|
}
|
|
@@ -86,7 +86,7 @@ export class Signal {
|
|
|
86
86
|
const [, error] = TrySync(() => {
|
|
87
87
|
const effects = setOfSubscribers;
|
|
88
88
|
effects.forEach((effect) => {
|
|
89
|
-
if (
|
|
89
|
+
if (setOfEffects.has(effect) === false) {
|
|
90
90
|
effects.delete(effect);
|
|
91
91
|
return;
|
|
92
92
|
}
|
|
@@ -96,7 +96,7 @@ export class Signal {
|
|
|
96
96
|
effect.run();
|
|
97
97
|
});
|
|
98
98
|
});
|
|
99
|
-
if (
|
|
99
|
+
if (error === undefined) {
|
|
100
100
|
return;
|
|
101
101
|
}
|
|
102
102
|
Console.error(error);
|
|
@@ -135,19 +135,20 @@ export class Signal {
|
|
|
135
135
|
*/
|
|
136
136
|
ref: () => {
|
|
137
137
|
this.remove.allSubscribers();
|
|
138
|
+
// @ts-expect-error
|
|
138
139
|
this.#value = null;
|
|
139
140
|
setOFSignals.delete(this);
|
|
140
141
|
},
|
|
141
142
|
}));
|
|
142
143
|
|
|
143
144
|
/**
|
|
144
|
-
* @type {VALUE}
|
|
145
|
+
* @type {VALUE|undefined}
|
|
145
146
|
*/
|
|
146
|
-
#prev
|
|
147
|
+
#prev;
|
|
147
148
|
/**
|
|
148
149
|
* @description
|
|
149
150
|
* - value before change;
|
|
150
|
-
* @returns {VALUE}
|
|
151
|
+
* @returns {VALUE|undefined}
|
|
151
152
|
*/
|
|
152
153
|
get prev() {
|
|
153
154
|
return this.#prev;
|
|
@@ -16,7 +16,11 @@ import { Signal } from './Signal.mjs';
|
|
|
16
16
|
* @typedef {import('./WorkerResult.mjs').WorkerResult<POST>} WorkerResult
|
|
17
17
|
*/
|
|
18
18
|
/**
|
|
19
|
-
* @
|
|
19
|
+
* @template RECEIVE
|
|
20
|
+
* @template POST
|
|
21
|
+
* @typedef {import('./WorkerThread.mjs').WorkerThread<RECEIVE, POST>} WorkerThread
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
20
24
|
* @typedef {import('../common/lazie.mjs').unwrapLazy} unwrapLazy
|
|
21
25
|
*/
|
|
22
26
|
|
|
@@ -24,7 +28,7 @@ import { Signal } from './Signal.mjs';
|
|
|
24
28
|
* @description
|
|
25
29
|
* - class helper to create `Worker` instance;
|
|
26
30
|
* - before any `Worker` functionaily to be used, you need to setup it with `WorkerThread.setup` and `WorkerMainThread.setup` before runing anytyhing;
|
|
27
|
-
* @template {WorkerThread} WT
|
|
31
|
+
* @template {WorkerThread<any, any>} WT
|
|
28
32
|
*/
|
|
29
33
|
export class WorkerMainThread {
|
|
30
34
|
/**
|
|
@@ -69,7 +73,7 @@ export class WorkerMainThread {
|
|
|
69
73
|
* });
|
|
70
74
|
*/
|
|
71
75
|
static setup = ({ workerClass, pathValidator }) => {
|
|
72
|
-
if (
|
|
76
|
+
if (Paths.root === undefined) {
|
|
73
77
|
return;
|
|
74
78
|
}
|
|
75
79
|
if (WorkerMainThread.#isRegistered) {
|
|
@@ -98,7 +102,7 @@ export class WorkerMainThread {
|
|
|
98
102
|
type: 'module',
|
|
99
103
|
});
|
|
100
104
|
/**
|
|
101
|
-
* @template {WorkerThread} WT
|
|
105
|
+
* @template {WorkerThread<any, any>} WT
|
|
102
106
|
* @description
|
|
103
107
|
* - create Worker_instance;
|
|
104
108
|
* @param {string} handler
|
|
@@ -109,9 +113,9 @@ export class WorkerMainThread {
|
|
|
109
113
|
*
|
|
110
114
|
* export const myDoubleWorker = WorkerMainThread.newVivthWorker('./doubleWorkerThread.mjs');
|
|
111
115
|
*/
|
|
112
|
-
static newVivthWorker
|
|
116
|
+
static newVivthWorker(handler, options = {}) {
|
|
113
117
|
return new WorkerMainThread(handler, options);
|
|
114
|
-
}
|
|
118
|
+
}
|
|
115
119
|
/**
|
|
116
120
|
* @private
|
|
117
121
|
* @param {Parameters<typeof WorkerMainThread<WT>["newVivthWorker"]>[0]} handler
|
|
@@ -123,7 +127,7 @@ export class WorkerMainThread {
|
|
|
123
127
|
*/
|
|
124
128
|
constructor(handler, options = {}) {
|
|
125
129
|
/**
|
|
126
|
-
* @param {
|
|
130
|
+
* @param {any} ev
|
|
127
131
|
* @returns {void}
|
|
128
132
|
*/
|
|
129
133
|
const listener = (ev) => {
|
|
@@ -132,21 +136,26 @@ export class WorkerMainThread {
|
|
|
132
136
|
WorkerMainThread.#workerFilehandler(handler, options, this, listener);
|
|
133
137
|
}
|
|
134
138
|
/**
|
|
135
|
-
* @type {import('./Signal.mjs').Signal<import('./WorkerResult.mjs').WorkerResult<WT["
|
|
139
|
+
* @type {import('./Signal.mjs').Signal<import('./WorkerResult.mjs').WorkerResult<WT["POST"]>|MessageEvent<import('./WorkerResult.mjs').WorkerResult<WT["POST"]>>>}
|
|
136
140
|
*/
|
|
141
|
+
// @ts-expect-error
|
|
137
142
|
#proxyReceiver = new Signal(undefined);
|
|
138
143
|
/**
|
|
144
|
+
* @template {WorkerThread<any, any>} WT
|
|
139
145
|
* @param {string} handler
|
|
140
146
|
* @param { WorkerOptions
|
|
141
147
|
* | import('worker_threads').WorkerOptions} options
|
|
142
|
-
* @param {WorkerMainThread} worker
|
|
148
|
+
* @param {WorkerMainThread<WT>} worker
|
|
143
149
|
* @param {(any:any)=>void} listener
|
|
144
150
|
* @returns {Promise<void>}
|
|
145
151
|
*/
|
|
146
|
-
static #workerFilehandler
|
|
152
|
+
static async #workerFilehandler(handler, options, worker, listener) {
|
|
147
153
|
let resolvedPath;
|
|
148
154
|
const pathValidator = WorkerMainThread.pathValidator;
|
|
149
155
|
const [resolvedPath_, error] = await TryAsync(async () => {
|
|
156
|
+
if (Paths.root === undefined) {
|
|
157
|
+
throw new Error('path root undefined');
|
|
158
|
+
}
|
|
150
159
|
return await pathValidator({
|
|
151
160
|
worker: handler,
|
|
152
161
|
root: Paths.root,
|
|
@@ -163,7 +172,10 @@ export class WorkerMainThread {
|
|
|
163
172
|
resolvedPath = resolvedPath_;
|
|
164
173
|
const runtime = GetRuntime();
|
|
165
174
|
const workerClass = WorkerMainThread.workerClass;
|
|
166
|
-
if (
|
|
175
|
+
if (
|
|
176
|
+
//
|
|
177
|
+
!workerClass
|
|
178
|
+
) {
|
|
167
179
|
Console.error('invalid `Worker` inputed to `WorkerMainThread`;');
|
|
168
180
|
return;
|
|
169
181
|
}
|
|
@@ -173,11 +185,15 @@ export class WorkerMainThread {
|
|
|
173
185
|
throw new Error('not a browser');
|
|
174
186
|
}
|
|
175
187
|
let worker_;
|
|
176
|
-
worker_ = worker.#worker.value = new workerClass(
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
188
|
+
worker_ = worker.#worker.value = new workerClass(
|
|
189
|
+
resolvedPath,
|
|
190
|
+
// @ts-expect-error
|
|
191
|
+
{
|
|
192
|
+
...options,
|
|
193
|
+
...WorkerMainThread.#options,
|
|
194
|
+
}
|
|
195
|
+
);
|
|
196
|
+
if ('onmessage' in worker_ === false) {
|
|
181
197
|
throw new Error('not a browser');
|
|
182
198
|
}
|
|
183
199
|
worker_.onmessage = listener;
|
|
@@ -188,10 +204,14 @@ export class WorkerMainThread {
|
|
|
188
204
|
}
|
|
189
205
|
},
|
|
190
206
|
nonBrowser: async () => {
|
|
191
|
-
const worker_ = (worker.#worker.value = new workerClass(
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
207
|
+
const worker_ = (worker.#worker.value = new workerClass(
|
|
208
|
+
resolvedPath,
|
|
209
|
+
// @ts-expect-error
|
|
210
|
+
{
|
|
211
|
+
...options,
|
|
212
|
+
...WorkerMainThread.#options,
|
|
213
|
+
}
|
|
214
|
+
));
|
|
195
215
|
if ('addEventListener' in worker_) {
|
|
196
216
|
worker_.addEventListener('message', listener);
|
|
197
217
|
if (SafeExit.instance) {
|
|
@@ -218,16 +238,17 @@ export class WorkerMainThread {
|
|
|
218
238
|
if (SafeExit.instance) {
|
|
219
239
|
SafeExit.instance.addCallback(async () => {
|
|
220
240
|
if (worker.#worker.value) {
|
|
221
|
-
worker.#worker.value.postMessage(closeWorkerThreadEventObject);
|
|
241
|
+
worker.#worker.value.postMessage(closeWorkerThreadEventObject, []);
|
|
222
242
|
}
|
|
223
243
|
worker.terminate();
|
|
224
244
|
});
|
|
225
245
|
}
|
|
226
|
-
}
|
|
246
|
+
}
|
|
227
247
|
/**
|
|
228
248
|
* lazyly generated because node version need to await
|
|
229
249
|
* @type {Signal<Worker | import('worker_threads').Worker>}
|
|
230
250
|
*/
|
|
251
|
+
// @ts-expect-error
|
|
231
252
|
#worker = new Signal(undefined);
|
|
232
253
|
/**
|
|
233
254
|
* @type {Signal<WT["RECEIVE"]>}
|
|
@@ -236,10 +257,10 @@ export class WorkerMainThread {
|
|
|
236
257
|
#handler = new Effect(async ({ subscribe }) => {
|
|
237
258
|
const postData = subscribe(this.#proxyPost).value;
|
|
238
259
|
const worker = subscribe(this.#worker).value;
|
|
239
|
-
if (
|
|
260
|
+
if (worker === undefined || postData === undefined) {
|
|
240
261
|
return;
|
|
241
262
|
}
|
|
242
|
-
worker.postMessage(postData);
|
|
263
|
+
worker.postMessage(postData, []);
|
|
243
264
|
});
|
|
244
265
|
/**
|
|
245
266
|
* @description
|
|
@@ -17,12 +17,16 @@ import { Signal } from './Signal.mjs';
|
|
|
17
17
|
* @typedef {import('./WorkerResult.mjs').WorkerResult<POST>} WorkerResult
|
|
18
18
|
*/
|
|
19
19
|
/**
|
|
20
|
-
* @
|
|
20
|
+
* @template RECEIVE
|
|
21
|
+
* @template POST
|
|
22
|
+
* @typedef {import('./WorkerThread.mjs').WorkerThread<RECEIVE, POST>} WorkerThread
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
21
25
|
* @typedef {import('../common/lazie.mjs').unwrapLazy} unwrapLazy
|
|
22
26
|
*/
|
|
23
27
|
|
|
24
28
|
/**
|
|
25
|
-
* @template {WorkerThread} WT
|
|
29
|
+
* @template {WorkerThread<any, any>} WT
|
|
26
30
|
*/
|
|
27
31
|
export class WorkerMainThread {
|
|
28
32
|
/**
|
|
@@ -35,7 +39,7 @@ export class WorkerMainThread {
|
|
|
35
39
|
* @param {typeof WorkerMainThread["pathValidator"]} param0.pathValidator
|
|
36
40
|
*/
|
|
37
41
|
static setup = ({ workerClass, pathValidator }) => {
|
|
38
|
-
if (
|
|
42
|
+
if (Paths.root === undefined) {
|
|
39
43
|
return;
|
|
40
44
|
}
|
|
41
45
|
if (WorkerMainThread.#isRegistered) {
|
|
@@ -58,21 +62,21 @@ export class WorkerMainThread {
|
|
|
58
62
|
type: 'module',
|
|
59
63
|
});
|
|
60
64
|
/**
|
|
61
|
-
* @template {WorkerThread} WT
|
|
65
|
+
* @template {WorkerThread<any, any>} WT
|
|
62
66
|
* @param {string} handler
|
|
63
67
|
* @param {Omit<WorkerOptions|import('worker_threads').WorkerOptions, 'eval'|'type'>} [options]
|
|
64
68
|
* @returns {WorkerMainThread<WT>}
|
|
65
69
|
*/
|
|
66
|
-
static newVivthWorker
|
|
70
|
+
static newVivthWorker(handler, options = {}) {
|
|
67
71
|
return new WorkerMainThread(handler, options);
|
|
68
|
-
}
|
|
72
|
+
}
|
|
69
73
|
/**
|
|
70
74
|
* @param {Parameters<typeof WorkerMainThread<WT>["newVivthWorker"]>[0]} handler
|
|
71
75
|
* @param {Parameters<typeof WorkerMainThread<WT>["newVivthWorker"]>[1]} [options]
|
|
72
76
|
*/
|
|
73
77
|
constructor(handler, options = {}) {
|
|
74
78
|
/**
|
|
75
|
-
* @param {
|
|
79
|
+
* @param {any} ev
|
|
76
80
|
* @returns {void}
|
|
77
81
|
*/
|
|
78
82
|
const listener = (ev) => {
|
|
@@ -81,24 +85,29 @@ export class WorkerMainThread {
|
|
|
81
85
|
WorkerMainThread.#workerFilehandler(handler, options, this, listener);
|
|
82
86
|
}
|
|
83
87
|
/**
|
|
84
|
-
* @type {import('./Signal.mjs').Signal<import('./WorkerResult.mjs').WorkerResult<WT["
|
|
88
|
+
* @type {import('./Signal.mjs').Signal<import('./WorkerResult.mjs').WorkerResult<WT["POST"]>|MessageEvent<import('./WorkerResult.mjs').WorkerResult<WT["POST"]>>>}
|
|
85
89
|
*/
|
|
90
|
+
// @ts-expect-error
|
|
86
91
|
#proxyReceiver = new Signal(undefined);
|
|
87
92
|
/**
|
|
93
|
+
* @template {WorkerThread<any, any>} WT
|
|
88
94
|
* @param {string} handler
|
|
89
95
|
* @param { WorkerOptions
|
|
90
96
|
* | import('worker_threads').WorkerOptions} options
|
|
91
|
-
* @param {WorkerMainThread} worker
|
|
97
|
+
* @param {WorkerMainThread<WT>} worker
|
|
92
98
|
* @param {(any:any)=>void} listener
|
|
93
99
|
* @returns {Promise<void>}
|
|
94
100
|
*/
|
|
95
|
-
static #workerFilehandler
|
|
101
|
+
static async #workerFilehandler(handler, options, worker, listener) {
|
|
96
102
|
let resolvedPath;
|
|
97
103
|
WorkerMainThread.#options.eval = true;
|
|
98
104
|
resolvedPath = (await FSInline.vivthFSInlineFile(handler)).toString('utf-8');
|
|
99
105
|
const runtime = GetRuntime();
|
|
100
106
|
const workerClass = WorkerMainThread.workerClass;
|
|
101
|
-
if (
|
|
107
|
+
if (
|
|
108
|
+
//
|
|
109
|
+
!workerClass
|
|
110
|
+
) {
|
|
102
111
|
Console.error('invalid `Worker` inputed to `WorkerMainThread`;');
|
|
103
112
|
return;
|
|
104
113
|
}
|
|
@@ -109,11 +118,15 @@ export class WorkerMainThread {
|
|
|
109
118
|
}
|
|
110
119
|
let worker_;
|
|
111
120
|
const inlineURL = Base64URL(handler, 'application/javascript', btoa);
|
|
112
|
-
worker_ = worker.#worker.value = new workerClass(
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
121
|
+
worker_ = worker.#worker.value = new workerClass(
|
|
122
|
+
inlineURL,
|
|
123
|
+
// @ts-expect-error
|
|
124
|
+
{
|
|
125
|
+
...options,
|
|
126
|
+
...WorkerMainThread.#options,
|
|
127
|
+
}
|
|
128
|
+
);
|
|
129
|
+
if ('onmessage' in worker_ === false) {
|
|
117
130
|
throw new Error('not a browser');
|
|
118
131
|
}
|
|
119
132
|
worker_.onmessage = listener;
|
|
@@ -124,10 +137,14 @@ export class WorkerMainThread {
|
|
|
124
137
|
}
|
|
125
138
|
},
|
|
126
139
|
nonBrowser: async () => {
|
|
127
|
-
const worker_ = (worker.#worker.value = new workerClass(
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
140
|
+
const worker_ = (worker.#worker.value = new workerClass(
|
|
141
|
+
resolvedPath,
|
|
142
|
+
// @ts-expect-error
|
|
143
|
+
{
|
|
144
|
+
...options,
|
|
145
|
+
...WorkerMainThread.#options,
|
|
146
|
+
}
|
|
147
|
+
));
|
|
131
148
|
if ('addEventListener' in worker_) {
|
|
132
149
|
worker_.addEventListener('message', listener);
|
|
133
150
|
if (SafeExit.instance) {
|
|
@@ -154,16 +171,17 @@ export class WorkerMainThread {
|
|
|
154
171
|
if (SafeExit.instance) {
|
|
155
172
|
SafeExit.instance.addCallback(async () => {
|
|
156
173
|
if (worker.#worker.value) {
|
|
157
|
-
worker.#worker.value.postMessage(closeWorkerThreadEventObject);
|
|
174
|
+
worker.#worker.value.postMessage(closeWorkerThreadEventObject, []);
|
|
158
175
|
}
|
|
159
176
|
worker.terminate();
|
|
160
177
|
});
|
|
161
178
|
}
|
|
162
|
-
}
|
|
179
|
+
}
|
|
163
180
|
/**
|
|
164
181
|
* lazyly generated because node version need to await
|
|
165
182
|
* @type {Signal<Worker | import('worker_threads').Worker>}
|
|
166
183
|
*/
|
|
184
|
+
// @ts-expect-error
|
|
167
185
|
#worker = new Signal(undefined);
|
|
168
186
|
/**
|
|
169
187
|
* @type {Signal<WT["RECEIVE"]>}
|
|
@@ -172,10 +190,10 @@ export class WorkerMainThread {
|
|
|
172
190
|
#handler = new Effect(async ({ subscribe }) => {
|
|
173
191
|
const postData = subscribe(this.#proxyPost).value;
|
|
174
192
|
const worker = subscribe(this.#worker).value;
|
|
175
|
-
if (
|
|
193
|
+
if (worker === undefined || postData === undefined) {
|
|
176
194
|
return;
|
|
177
195
|
}
|
|
178
|
-
worker.postMessage(postData);
|
|
196
|
+
worker.postMessage(postData, []);
|
|
179
197
|
});
|
|
180
198
|
/**
|
|
181
199
|
* @type {()=>void}
|
|
@@ -20,9 +20,9 @@ export class WorkerThread {
|
|
|
20
20
|
* @typedef {import('../types/QCBReturn.mjs').QCBReturn} QCBReturn
|
|
21
21
|
*/
|
|
22
22
|
/**
|
|
23
|
-
* @type {Parameters<typeof WorkerThread["setup"]>[0]}
|
|
23
|
+
* @type {Parameters<typeof WorkerThread["setup"]>[0]|undefined}
|
|
24
24
|
*/
|
|
25
|
-
static #refs
|
|
25
|
+
static #refs;
|
|
26
26
|
/**
|
|
27
27
|
* @description
|
|
28
28
|
* - need to be called and exported as new `WorkerThread` class reference;
|
|
@@ -57,7 +57,7 @@ export class WorkerThread {
|
|
|
57
57
|
/**
|
|
58
58
|
* @description
|
|
59
59
|
* - instantiate via created class from `setup` static method;
|
|
60
|
-
* @param {WorkerThread["handler"]} handler
|
|
60
|
+
* @param {WorkerThread<RECEIVE, POST>["handler"]} handler
|
|
61
61
|
* @example
|
|
62
62
|
* import { MyWorkerThread } from './MyWorkerThread.mjs';
|
|
63
63
|
*
|
|
@@ -81,30 +81,41 @@ export class WorkerThread {
|
|
|
81
81
|
* @param {MessageEvent<RECEIVE>|RECEIVE} ev
|
|
82
82
|
* @returns {Promise<void>}
|
|
83
83
|
*/
|
|
84
|
+
// @ts-expect-error
|
|
84
85
|
self.onmessage = async function (ev) {
|
|
85
86
|
const [, error] = await TryAsync(async () => {
|
|
86
87
|
ev = ev instanceof MessageEvent ? ev.data : ev;
|
|
87
88
|
if (WorkerThread.#isCloseWorkerEvent(ev)) {
|
|
88
89
|
this_.#qChannel.close();
|
|
90
|
+
// @ts-expect-error
|
|
89
91
|
self.onmessage = null;
|
|
90
92
|
return;
|
|
91
93
|
}
|
|
92
94
|
const [data, error] = await this_.#qChannel.callback(this, async ({ isLastOnQ }) => {
|
|
95
|
+
// @ts-expect-error
|
|
93
96
|
return await handler(ev, isLastOnQ);
|
|
94
97
|
});
|
|
95
98
|
if (error) {
|
|
96
99
|
throw error;
|
|
97
100
|
}
|
|
101
|
+
// @ts-expect-error
|
|
98
102
|
self.postMessage(new WorkerResult(data, undefined));
|
|
99
103
|
});
|
|
100
|
-
if (
|
|
104
|
+
if (error === undefined) {
|
|
101
105
|
return;
|
|
102
106
|
}
|
|
107
|
+
// @ts-expect-error
|
|
103
108
|
self.postMessage(new WorkerResult(undefined, error?.message ?? 'Unknown error'));
|
|
104
109
|
};
|
|
105
110
|
},
|
|
106
111
|
parentPost: async () => {
|
|
112
|
+
if (WorkerThread.#refs === undefined) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
107
115
|
const { parentPort } = WorkerThread.#refs;
|
|
116
|
+
if (parentPort === null) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
108
119
|
/**
|
|
109
120
|
* @param {MessageEvent<RECEIVE>|RECEIVE} ev
|
|
110
121
|
* @returns {Promise<void>}
|
|
@@ -117,7 +128,8 @@ export class WorkerThread {
|
|
|
117
128
|
parentPort.off('message', listener);
|
|
118
129
|
return;
|
|
119
130
|
}
|
|
120
|
-
const [data, error] = await this_.#qChannel.callback(
|
|
131
|
+
const [data, error] = await this_.#qChannel.callback(this_, async ({ isLastOnQ }) => {
|
|
132
|
+
// @ts-expect-error
|
|
121
133
|
return await handler(ev, isLastOnQ);
|
|
122
134
|
});
|
|
123
135
|
if (error) {
|
|
@@ -125,7 +137,7 @@ export class WorkerThread {
|
|
|
125
137
|
}
|
|
126
138
|
parentPort.postMessage(new WorkerResult(data, undefined));
|
|
127
139
|
});
|
|
128
|
-
if (
|
|
140
|
+
if (error === undefined) {
|
|
129
141
|
return;
|
|
130
142
|
}
|
|
131
143
|
parentPort.postMessage(new WorkerResult(undefined, error?.message ?? 'Unknown error'));
|
|
@@ -133,7 +145,7 @@ export class WorkerThread {
|
|
|
133
145
|
parentPort.on('message', listener);
|
|
134
146
|
},
|
|
135
147
|
}).then(([, error]) => {
|
|
136
|
-
if (
|
|
148
|
+
if (error === undefined) {
|
|
137
149
|
return;
|
|
138
150
|
}
|
|
139
151
|
Console.error(error);
|
|
@@ -150,11 +162,13 @@ export class WorkerThread {
|
|
|
150
162
|
* - helper type, hold no actual value;
|
|
151
163
|
* @type {RECEIVE}
|
|
152
164
|
*/
|
|
165
|
+
// @ts-expect-error
|
|
153
166
|
RECEIVE;
|
|
154
167
|
/**
|
|
155
168
|
* @description
|
|
156
169
|
* - helper type, hold no actual value;
|
|
157
170
|
* @type {POST}
|
|
158
171
|
*/
|
|
172
|
+
// @ts-expect-error
|
|
159
173
|
POST;
|
|
160
174
|
}
|
package/src/common/Base64URL.mjs
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* (str, prevBufferEncoding) =>
|
|
15
15
|
* Buffer.from(str, prevBufferEncoding).toString('base64')
|
|
16
16
|
* ```
|
|
17
|
-
* @returns {
|
|
17
|
+
* @returns {string}
|
|
18
18
|
* @example
|
|
19
19
|
* import { Base64URL } from 'vivth'
|
|
20
20
|
* import fileString from './fileString.mjs';
|
|
@@ -28,4 +28,4 @@ export function Base64URL(fileString, mimeType, btoaFunction) {
|
|
|
28
28
|
binary += String.fromCharCode(byte);
|
|
29
29
|
}
|
|
30
30
|
return `data:${mimeType.toString()};base64,${btoaFunction(binary)}`;
|
|
31
|
-
}
|
|
31
|
+
};
|
|
@@ -11,7 +11,7 @@ import { lookup } from 'mime-types';
|
|
|
11
11
|
* >- can be extremely usefull to display file on desktop app webview, without exposing http server;
|
|
12
12
|
* >- when using `FSInline`, use [Base64URL](#base64url) instead;
|
|
13
13
|
* @param {string} filePath
|
|
14
|
-
* @returns {Promise<
|
|
14
|
+
* @returns {Promise<string>}
|
|
15
15
|
* @example
|
|
16
16
|
* import { join } from 'node:path'
|
|
17
17
|
*
|