@evolu/common 8.0.0-next.2 → 8.0.0-next.3
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/dist/src/Worker.d.ts.map +1 -1
- package/dist/src/Worker.js +55 -12
- package/package.json +1 -1
- package/src/Worker.ts +69 -20
package/dist/src/Worker.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Worker.d.ts","sourceRoot":"","sources":["../../src/Worker.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"Worker.d.ts","sourceRoot":"","sources":["../../src/Worker.ts"],"names":[],"mappings":"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"}
|
package/dist/src/Worker.js
CHANGED
|
@@ -42,18 +42,34 @@ export const createMessageChannel = () => {
|
|
|
42
42
|
handler: null,
|
|
43
43
|
queue: [],
|
|
44
44
|
flushScheduled: false,
|
|
45
|
+
refCount: 0,
|
|
46
|
+
pendingTransferCount: 0,
|
|
47
|
+
closed: false,
|
|
45
48
|
};
|
|
46
49
|
const state2 = {
|
|
47
50
|
handler: null,
|
|
48
51
|
queue: [],
|
|
49
52
|
flushScheduled: false,
|
|
53
|
+
refCount: 0,
|
|
54
|
+
pendingTransferCount: 0,
|
|
55
|
+
closed: false,
|
|
50
56
|
};
|
|
51
57
|
const native1 = createNativeMessagePortToken();
|
|
52
58
|
const native2 = createNativeMessagePortToken();
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
59
|
+
const port1Registration = {
|
|
60
|
+
receive: state1,
|
|
61
|
+
peerReceive: state2,
|
|
62
|
+
native: native1,
|
|
63
|
+
};
|
|
64
|
+
const port2Registration = {
|
|
65
|
+
receive: state2,
|
|
66
|
+
peerReceive: state1,
|
|
67
|
+
native: native2,
|
|
68
|
+
};
|
|
69
|
+
const port1 = createTestPort(port1Registration);
|
|
70
|
+
const port2 = createTestPort(port2Registration);
|
|
71
|
+
nativePortRegistry.set(native1, port1Registration);
|
|
72
|
+
nativePortRegistry.set(native2, port2Registration);
|
|
57
73
|
return {
|
|
58
74
|
port1,
|
|
59
75
|
port2,
|
|
@@ -70,9 +86,9 @@ export const createMessageChannel = () => {
|
|
|
70
86
|
* support. Message delivery through returned ports is asynchronous in-process.
|
|
71
87
|
*/
|
|
72
88
|
export const createMessagePort = (nativePort) => {
|
|
73
|
-
const
|
|
74
|
-
assert(
|
|
75
|
-
return
|
|
89
|
+
const registration = nativePortRegistry.get(nativePort);
|
|
90
|
+
assert(registration, "Unknown native port — did you transfer it?");
|
|
91
|
+
return createTestPort(registration);
|
|
76
92
|
};
|
|
77
93
|
/**
|
|
78
94
|
* Creates a connected {@link TestWorker} for testing.
|
|
@@ -184,14 +200,20 @@ const createMemorySharedWorkerPair = () => {
|
|
|
184
200
|
};
|
|
185
201
|
return { worker, self, connect };
|
|
186
202
|
};
|
|
187
|
-
const createPort = (receive, peerReceive, native) => {
|
|
203
|
+
const createPort = ({ receive, peerReceive, native, }) => {
|
|
204
|
+
if (receive.pendingTransferCount > 0)
|
|
205
|
+
receive.pendingTransferCount -= 1;
|
|
206
|
+
receive.refCount += 1;
|
|
207
|
+
let isDisposed = false;
|
|
188
208
|
const scheduleFlush = (state) => {
|
|
189
|
-
if (state.flushScheduled)
|
|
209
|
+
if (state.flushScheduled || state.closed)
|
|
190
210
|
return;
|
|
191
211
|
state.flushScheduled = true;
|
|
192
212
|
// Native worker messages are task-queued; use macrotask timing.
|
|
193
213
|
setTimeout(() => {
|
|
194
214
|
state.flushScheduled = false;
|
|
215
|
+
if (state.closed)
|
|
216
|
+
return;
|
|
195
217
|
const handler = state.handler;
|
|
196
218
|
if (!handler)
|
|
197
219
|
return;
|
|
@@ -201,26 +223,47 @@ const createPort = (receive, peerReceive, native) => {
|
|
|
201
223
|
}, 0);
|
|
202
224
|
};
|
|
203
225
|
return {
|
|
204
|
-
postMessage: (message) => {
|
|
226
|
+
postMessage: (message, transfer) => {
|
|
227
|
+
for (const transferable of transfer ?? []) {
|
|
228
|
+
if (transferable instanceof globalThis.ArrayBuffer)
|
|
229
|
+
continue;
|
|
230
|
+
const registration = nativePortRegistry.get(transferable);
|
|
231
|
+
if (!registration)
|
|
232
|
+
continue;
|
|
233
|
+
registration.receive.pendingTransferCount += 1;
|
|
234
|
+
registration.receive.closed = false;
|
|
235
|
+
}
|
|
236
|
+
if (peerReceive.closed)
|
|
237
|
+
return;
|
|
205
238
|
peerReceive.queue.push(message);
|
|
206
239
|
scheduleFlush(peerReceive);
|
|
207
240
|
},
|
|
208
241
|
get onMessage() {
|
|
209
|
-
return receive.handler;
|
|
242
|
+
return isDisposed ? null : receive.handler;
|
|
210
243
|
},
|
|
211
244
|
set onMessage(fn) {
|
|
245
|
+
if (isDisposed || receive.closed)
|
|
246
|
+
return;
|
|
212
247
|
receive.handler = fn;
|
|
213
248
|
if (fn)
|
|
214
249
|
scheduleFlush(receive);
|
|
215
250
|
},
|
|
216
251
|
native,
|
|
217
252
|
[Symbol.dispose]: () => {
|
|
253
|
+
if (isDisposed)
|
|
254
|
+
return;
|
|
255
|
+
isDisposed = true;
|
|
256
|
+
receive.refCount -= 1;
|
|
257
|
+
if (receive.refCount > 0 || receive.pendingTransferCount > 0)
|
|
258
|
+
return;
|
|
259
|
+
receive.closed = true;
|
|
218
260
|
receive.handler = null;
|
|
219
261
|
receive.flushScheduled = false;
|
|
262
|
+
receive.queue.length = 0;
|
|
220
263
|
},
|
|
221
264
|
};
|
|
222
265
|
};
|
|
223
|
-
const createTestPort = (
|
|
266
|
+
const createTestPort = (registration) => createPort(registration);
|
|
224
267
|
const createNativeMessagePortToken = () => ({});
|
|
225
268
|
/**
|
|
226
269
|
* Registry mapping native port tokens to their in-memory port counterparts.
|
package/package.json
CHANGED
package/src/Worker.ts
CHANGED
|
@@ -250,21 +250,38 @@ export const createMessageChannel: CreateMessageChannel = <
|
|
|
250
250
|
handler: null,
|
|
251
251
|
queue: [],
|
|
252
252
|
flushScheduled: false,
|
|
253
|
+
refCount: 0,
|
|
254
|
+
pendingTransferCount: 0,
|
|
255
|
+
closed: false,
|
|
253
256
|
};
|
|
254
257
|
const state2: PortState<Input> = {
|
|
255
258
|
handler: null,
|
|
256
259
|
queue: [],
|
|
257
260
|
flushScheduled: false,
|
|
261
|
+
refCount: 0,
|
|
262
|
+
pendingTransferCount: 0,
|
|
263
|
+
closed: false,
|
|
258
264
|
};
|
|
259
265
|
|
|
260
266
|
const native1 = createNativeMessagePortToken<Input, Output>();
|
|
261
267
|
const native2 = createNativeMessagePortToken<Output, Input>();
|
|
262
268
|
|
|
263
|
-
const
|
|
264
|
-
|
|
269
|
+
const port1Registration: PortRegistration<Input, Output> = {
|
|
270
|
+
receive: state1,
|
|
271
|
+
peerReceive: state2,
|
|
272
|
+
native: native1,
|
|
273
|
+
};
|
|
274
|
+
const port2Registration: PortRegistration<Output, Input> = {
|
|
275
|
+
receive: state2,
|
|
276
|
+
peerReceive: state1,
|
|
277
|
+
native: native2,
|
|
278
|
+
};
|
|
265
279
|
|
|
266
|
-
|
|
267
|
-
|
|
280
|
+
const port1 = createTestPort(port1Registration);
|
|
281
|
+
const port2 = createTestPort(port2Registration);
|
|
282
|
+
|
|
283
|
+
nativePortRegistry.set(native1, port1Registration);
|
|
284
|
+
nativePortRegistry.set(native2, port2Registration);
|
|
268
285
|
|
|
269
286
|
return {
|
|
270
287
|
port1,
|
|
@@ -285,9 +302,9 @@ export const createMessageChannel: CreateMessageChannel = <
|
|
|
285
302
|
export const createMessagePort: CreateMessagePort = <Input, Output = never>(
|
|
286
303
|
nativePort: NativeMessagePort<Input, Output>,
|
|
287
304
|
): MessagePort<Input, Output> => {
|
|
288
|
-
const
|
|
289
|
-
assert(
|
|
290
|
-
return
|
|
305
|
+
const registration = nativePortRegistry.get(nativePort);
|
|
306
|
+
assert(registration, "Unknown native port — did you transfer it?");
|
|
307
|
+
return createTestPort(registration as PortRegistration<Input, Output>);
|
|
291
308
|
};
|
|
292
309
|
|
|
293
310
|
/**
|
|
@@ -481,20 +498,34 @@ interface PortState<T> {
|
|
|
481
498
|
handler: ((message: T) => void) | null;
|
|
482
499
|
readonly queue: Array<T>;
|
|
483
500
|
flushScheduled: boolean;
|
|
501
|
+
refCount: number;
|
|
502
|
+
pendingTransferCount: number;
|
|
503
|
+
closed: boolean;
|
|
484
504
|
}
|
|
485
505
|
|
|
486
|
-
|
|
487
|
-
receive: PortState<Output
|
|
488
|
-
peerReceive: PortState<Input
|
|
489
|
-
native: NativeMessagePort<Input, Output
|
|
490
|
-
|
|
506
|
+
interface PortRegistration<Input, Output> {
|
|
507
|
+
readonly receive: PortState<Output>;
|
|
508
|
+
readonly peerReceive: PortState<Input>;
|
|
509
|
+
readonly native: NativeMessagePort<Input, Output>;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
const createPort = <Input, Output>({
|
|
513
|
+
receive,
|
|
514
|
+
peerReceive,
|
|
515
|
+
native,
|
|
516
|
+
}: PortRegistration<Input, Output>): MessagePort<Input, Output> => {
|
|
517
|
+
if (receive.pendingTransferCount > 0) receive.pendingTransferCount -= 1;
|
|
518
|
+
receive.refCount += 1;
|
|
519
|
+
let isDisposed = false;
|
|
520
|
+
|
|
491
521
|
const scheduleFlush = (state: PortState<any>): void => {
|
|
492
|
-
if (state.flushScheduled) return;
|
|
522
|
+
if (state.flushScheduled || state.closed) return;
|
|
493
523
|
state.flushScheduled = true;
|
|
494
524
|
|
|
495
525
|
// Native worker messages are task-queued; use macrotask timing.
|
|
496
526
|
setTimeout(() => {
|
|
497
527
|
state.flushScheduled = false;
|
|
528
|
+
if (state.closed) return;
|
|
498
529
|
|
|
499
530
|
const handler = state.handler;
|
|
500
531
|
if (!handler) return;
|
|
@@ -506,30 +537,48 @@ const createPort = <Input, Output>(
|
|
|
506
537
|
};
|
|
507
538
|
|
|
508
539
|
return {
|
|
509
|
-
postMessage: (message) => {
|
|
540
|
+
postMessage: (message, transfer) => {
|
|
541
|
+
for (const transferable of transfer ?? []) {
|
|
542
|
+
if (transferable instanceof globalThis.ArrayBuffer) continue;
|
|
543
|
+
|
|
544
|
+
const registration = nativePortRegistry.get(transferable);
|
|
545
|
+
if (!registration) continue;
|
|
546
|
+
|
|
547
|
+
registration.receive.pendingTransferCount += 1;
|
|
548
|
+
registration.receive.closed = false;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
if (peerReceive.closed) return;
|
|
510
552
|
peerReceive.queue.push(message);
|
|
511
553
|
scheduleFlush(peerReceive);
|
|
512
554
|
},
|
|
513
555
|
get onMessage() {
|
|
514
|
-
return receive.handler;
|
|
556
|
+
return isDisposed ? null : receive.handler;
|
|
515
557
|
},
|
|
516
558
|
set onMessage(fn) {
|
|
559
|
+
if (isDisposed || receive.closed) return;
|
|
517
560
|
receive.handler = fn;
|
|
518
561
|
if (fn) scheduleFlush(receive);
|
|
519
562
|
},
|
|
520
563
|
native,
|
|
521
564
|
[Symbol.dispose]: () => {
|
|
565
|
+
if (isDisposed) return;
|
|
566
|
+
isDisposed = true;
|
|
567
|
+
|
|
568
|
+
receive.refCount -= 1;
|
|
569
|
+
if (receive.refCount > 0 || receive.pendingTransferCount > 0) return;
|
|
570
|
+
|
|
571
|
+
receive.closed = true;
|
|
522
572
|
receive.handler = null;
|
|
523
573
|
receive.flushScheduled = false;
|
|
574
|
+
receive.queue.length = 0;
|
|
524
575
|
},
|
|
525
576
|
};
|
|
526
577
|
};
|
|
527
578
|
|
|
528
579
|
const createTestPort = <Input, Output>(
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
native: NativeMessagePort<Input, Output>,
|
|
532
|
-
): MessagePort<Input, Output> => createPort(receive, peerReceive, native);
|
|
580
|
+
registration: PortRegistration<Input, Output>,
|
|
581
|
+
): MessagePort<Input, Output> => createPort(registration);
|
|
533
582
|
|
|
534
583
|
const createNativeMessagePortToken = <Input, Output>(): NativeMessagePort<
|
|
535
584
|
Input,
|
|
@@ -548,5 +597,5 @@ const createNativeMessagePortToken = <Input, Output>(): NativeMessagePort<
|
|
|
548
597
|
*/
|
|
549
598
|
const nativePortRegistry = new WeakMap<
|
|
550
599
|
NativeMessagePort<any, any>,
|
|
551
|
-
|
|
600
|
+
PortRegistration<any, any>
|
|
552
601
|
>();
|