Skip to content

Commit ffed948

Browse files
De-register all shared workers
Co-authored-by: Mark Wubben <mark@novemberborn.net>
1 parent 639b905 commit ffed948

File tree

5 files changed

+88
-20
lines changed

5 files changed

+88
-20
lines changed

lib/plugin-support/shared-workers.js

+32-20
Original file line numberDiff line numberDiff line change
@@ -49,49 +49,61 @@ function launchWorker(filename, initialData) {
4949
}
5050

5151
export async function observeWorkerProcess(fork, runStatus) {
52-
let registrationCount = 0;
53-
let signalDeregistered;
54-
let launched;
55-
const deregistered = new Promise(resolve => {
56-
signalDeregistered = () => {
57-
// Only unref the worker once all test workers have been deregistered, otherwise the worker may exit before test workers are deregistered
58-
launched?.worker.unref();
52+
let signalDone;
53+
54+
const done = new Promise(resolve => {
55+
signalDone = () => {
5956
resolve();
6057
};
6158
});
6259

63-
fork.promise.finally(() => {
64-
if (registrationCount === 0) {
65-
signalDeregistered();
60+
const activeInstances = new Set();
61+
62+
const removeInstance = instance => {
63+
instance.worker.unref();
64+
activeInstances.delete(instance);
65+
66+
if (activeInstances.size === 0) {
67+
signalDone();
68+
}
69+
};
70+
71+
const removeAllInstances = () => {
72+
if (activeInstances.size === 0) {
73+
signalDone();
74+
return;
6675
}
76+
77+
for (const instance of activeInstances) {
78+
removeInstance(instance);
79+
}
80+
};
81+
82+
fork.promise.finally(() => {
83+
removeAllInstances();
6784
});
6885

6986
fork.onConnectSharedWorker(async ({filename, initialData, port, signalError}) => {
70-
launched = launchWorker(filename, initialData);
87+
const launched = launchWorker(filename, initialData);
88+
activeInstances.add(launched);
7189

7290
const handleWorkerMessage = async message => {
7391
if (message.type === 'deregistered-test-worker' && message.id === fork.threadId) {
7492
launched.worker.off('message', handleWorkerMessage);
75-
76-
registrationCount--;
77-
if (registrationCount === 0) {
78-
signalDeregistered();
79-
}
93+
removeInstance(launched);
8094
}
8195
};
8296

8397
launched.statePromises.error.then(error => {
84-
signalDeregistered();
8598
launched.worker.off('message', handleWorkerMessage);
99+
removeAllInstances();
86100
runStatus.emitStateChange({type: 'shared-worker-error', err: serializeError('Shared worker error', true, error)});
87101
signalError();
88102
});
89103

90104
try {
91105
await launched.statePromises.available;
92106

93-
registrationCount++;
94-
95107
port.postMessage({type: 'ready'});
96108

97109
launched.worker.postMessage({
@@ -112,5 +124,5 @@ export async function observeWorkerProcess(fork, runStatus) {
112124
} catch {}
113125
});
114126

115-
return deregistered;
127+
return done;
116128
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"type": "module",
3+
"ava": {
4+
"files": [
5+
"*.js"
6+
]
7+
}
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import test from 'ava';
2+
import {registerSharedWorker} from 'ava/plugin';
3+
4+
const worker1 = registerSharedWorker({
5+
filename: new URL('worker.mjs#1', import.meta.url),
6+
supportedProtocols: ['ava-4'],
7+
initialData: {
8+
id: '1',
9+
},
10+
});
11+
12+
const worker2 = registerSharedWorker({
13+
filename: new URL('worker.mjs#2', import.meta.url),
14+
supportedProtocols: ['ava-4'],
15+
initialData: {
16+
id: '2',
17+
},
18+
});
19+
20+
const messageFromWorker1 = worker1.subscribe().next();
21+
const messageFromWorker2 = worker2.subscribe().next();
22+
23+
test('can load multiple workers', async t => {
24+
const {value: {data: dataFromWorker1}} = await messageFromWorker1;
25+
const {value: {data: dataFromWorker2}} = await messageFromWorker2;
26+
27+
t.deepEqual(dataFromWorker1, {id: '1'});
28+
t.deepEqual(dataFromWorker2, {id: '2'});
29+
t.pass();
30+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export default async ({negotiateProtocol}) => {
2+
const protocol = negotiateProtocol(['ava-4']);
3+
4+
await protocol.ready();
5+
6+
for await (const testWorker of protocol.testWorkers()) {
7+
testWorker.publish(protocol.initialData);
8+
}
9+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import test from '@ava/test';
2+
3+
import {fixture} from '../../helpers/exec.js';
4+
5+
test('can load multiple workers', async t => {
6+
await fixture();
7+
8+
t.pass();
9+
});

0 commit comments

Comments
 (0)