diff --git a/README.md b/README.md index dda9e10f..7e3df9cd 100644 --- a/README.md +++ b/README.md @@ -184,6 +184,19 @@ Windows and Web Workers have a slightly different variants of `postMessage`. If For a usage example, take a look at the non-worker examples in the `docs` folder. +### `.terminate()` + +Web Workers must be terminated to release resources and threads. When using comlink with [`comlink-loader`](https://github.com/GoogleChromeLabs/comlink-loader) call the terminate method on the proxy returned by `comlink-loader` as comlink-loader doesn't give access to the underlying Worker object. + +```ts +import MyWorker from "comlink-loader!./worker"; +const workerProxy = new MyWorker() as any; +const result = await workerProxy.doSomething(); +workerProxy.terminate(); +``` + +Note: `workerProxy[Comlink.releaseProxy]();` wouldn't work in this case as it only releases the endpoint created for the proxy. + ## TypeScript Comlink does provide TypeScript types. When you `expose()` something of type `T`, the corresponding `wrap()` call will return something of type `Comlink.Remote`. While this type has been battle-tested over some time now, it is implemented on a best-effort basis. There are some nuances that are incredibly hard if not impossible to encode correctly in TypeScript’s type system. It _may_ sometimes be necessary to force a certain type using `as unknown as `. diff --git a/src/comlink.ts b/src/comlink.ts index fbecf655..05f9811c 100644 --- a/src/comlink.ts +++ b/src/comlink.ts @@ -421,6 +421,12 @@ function createProxy( apply(_target, _thisArg, rawArgumentList) { throwIfProxyReleased(isProxyReleased); const last = path[path.length - 1]; + // Users would expect terminate to kill the Worker not call a terminate method inside the worker + if (last === "terminate" && ep instanceof Worker) { + isProxyReleased = true; + ep.terminate(); + return Promise.resolve(); + } if ((last as any) === createEndpoint) { return requestResponseMessage(ep, { type: MessageType.ENDPOINT, diff --git a/tests/worker.comlink.test.js b/tests/worker.comlink.test.js index 3d87ef98..349995bf 100644 --- a/tests/worker.comlink.test.js +++ b/tests/worker.comlink.test.js @@ -33,4 +33,21 @@ describe("Comlink across workers", function () { const otherProxy = Comlink.wrap(otherEp); expect(await otherProxy(20, 1)).to.equal(21); }); + + it("honors terminate on the proxy", function () { + const originalTerminate = this.worker.terminate; + + let terminateCalled = false; + // poorman's mock + this.worker.terminate = function () { + terminateCalled = true; + }; + + const proxy = Comlink.wrap(this.worker); + expect(terminateCalled).to.be.false; + proxy.terminate(); + expect(terminateCalled).to.be.true; + + this.worker.terminate = originalTerminate; + }); });