{"_id":"@atc-group/comlink","_rev":"4-e82c3139cb789bb7f15bc94cc80fa03d","name":"@atc-group/comlink","dist-tags":{"latest":"5.0.0"},"versions":{"4.4.3":{"name":"@atc-group/comlink","version":"4.4.3","author":{"name":"Surma","email":"surma@google.com"},"license":"Apache-2.0","_id":"@atc-group/comlink@4.4.3","maintainers":[{"name":"atcgroupdev","email":"atcgroupdev@gmail.com"},{"name":"toanzzz","email":"me@toan.io"}],"homepage":"https://github.com/GoogleChromeLabs/comlink#readme","bugs":{"url":"https://github.com/GoogleChromeLabs/comlink/issues"},"dist":{"shasum":"b60bab88b5ff89d13907e3bc983a1741bf00a0dc","tarball":"https://registry.npmjs.org/@atc-group/comlink/-/comlink-4.4.3.tgz","fileCount":91,"integrity":"sha512-9C8B1A8/R0fW4JJrC93IQWu9Z+Kzdry91QYR+SLZNcEmNDFU4tOBbQA2qV2jVXSSxfx3m+Ae+79SFm48DQ2jTw==","signatures":[{"sig":"MEQCICKgVqxvSQw9gHA6KwKfGFYQ2IYlGBvbs5XJVtccK9eyAiA7YsGGsbmmjB5Yv0E9j0FvAsAYJR5ClL99jzYq7yuFeA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":456703},"main":"dist/umd/comlink.js","types":"dist/umd/src/comlink.d.ts","module":"dist/esm/comlink.mjs","gitHead":"431aed4aabcacfeb78a58a7146e3016117f9e3f2","scripts":{"fmt":"prettier --write './*.{mjs,js,ts,md,json,html}' './{src,docs,tests}/{,**/}*.{mjs,js,ts,md,json,html}'","test":"npm run fmt_test && npm run build && npm run test:types && npm run test:unit && npm run test:node","build":"rollup -c","fmt_test":"test $(prettier -l './*.{mjs,js,ts,md,json,html}' './{src,docs,tests}/{**/,}*.{mjs,js,ts,md,json,html}' | wc -l) -eq 0","test:node":"mocha ./tests/node/main.mjs","test:unit":"karma start","watchtest":"CHROME_ONLY=1 karma start --no-single-run","test:types":"tsc -p ./tests/tsconfig.json","test:types:watch":"npm run test:types -- --watch"},"_npmUser":{"name":"atcgroupdev","email":"atcgroupdev@gmail.com"},"repository":{"url":"git+https://github.com/GoogleChromeLabs/comlink.git","type":"git"},"_npmVersion":"10.2.4","description":"Comlink makes WebWorkers enjoyable","directories":{},"sideEffects":false,"_nodeVersion":"20.11.0","_hasShrinkwrap":false,"devDependencies":{"chai":"^4.3.7","husky":"8.0.3","karma":"6.4.1","mocha":"10.2.0","tslib":"2.4.1","rimraf":"4.1.2","rollup":"3.10.1","prettier":"2.8.3","karma-chai":"0.1.0","typescript":"4.9.4","karma-mocha":"2.0.1","@rollup/plugin-terser":"0.4.0","karma-chrome-launcher":"3.1.1","karma-detect-browsers":"2.3.3","karma-safari-launcher":"1.0.0","karma-firefox-launcher":"2.1.2","conditional-type-checks":"1.0.6","@rollup/plugin-typescript":"11.0.0","karma-safaritechpreview-launcher":"2.0.2"},"_npmOperationalInternal":{"tmp":"tmp/comlink_4.4.3_1746149218211_0.49859361259099044","host":"s3://npm-registry-packages-npm-production"}},"4.4.4":{"name":"@atc-group/comlink","version":"4.4.4","author":{"name":"Surma","email":"surma@google.com"},"license":"Apache-2.0","_id":"@atc-group/comlink@4.4.4","maintainers":[{"name":"atcgroupdev","email":"atcgroupdev@gmail.com"},{"name":"toanzzz","email":"me@toan.io"}],"homepage":"https://github.com/GoogleChromeLabs/comlink#readme","bugs":{"url":"https://github.com/GoogleChromeLabs/comlink/issues"},"dist":{"shasum":"75f9b387e842cd82c2ee49a977d267a6aa7df4a0","tarball":"https://registry.npmjs.org/@atc-group/comlink/-/comlink-4.4.4.tgz","fileCount":91,"integrity":"sha512-mwNR3ARCxj9LMgLwjFlWeiYYw7bjTQZBWFoIp3qF2ktzB9551OQwiSaiXFmd+F3gf0strXnnV6yNt/Tfow07Fw==","signatures":[{"sig":"MEUCIEeKAIy61QS4PMYeVx6Go68eNrcnXJUEZb1jhact43v8AiEAioMR3UTQEffCSE/DihPqnWPPRW5k8gDLHkugqWgMPxg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":456703},"main":"dist/umd/comlink.js","types":"dist/umd/src/comlink.d.ts","module":"dist/esm/comlink.mjs","gitHead":"431aed4aabcacfeb78a58a7146e3016117f9e3f2","scripts":{"fmt":"prettier --write './*.{mjs,js,ts,md,json,html}' './{src,docs,tests}/{,**/}*.{mjs,js,ts,md,json,html}'","test":"npm run fmt_test && npm run build && npm run test:types && npm run test:unit && npm run test:node","build":"rollup -c","fmt_test":"test $(prettier -l './*.{mjs,js,ts,md,json,html}' './{src,docs,tests}/{**/,}*.{mjs,js,ts,md,json,html}' | wc -l) -eq 0","test:node":"mocha ./tests/node/main.mjs","test:unit":"karma start","watchtest":"CHROME_ONLY=1 karma start --no-single-run","test:types":"tsc -p ./tests/tsconfig.json","test:types:watch":"npm run test:types -- --watch"},"_npmUser":{"name":"atcgroupdev","email":"atcgroupdev@gmail.com"},"repository":{"url":"git+https://github.com/GoogleChromeLabs/comlink.git","type":"git"},"_npmVersion":"10.2.4","description":"Comlink makes WebWorkers enjoyable","directories":{},"sideEffects":false,"_nodeVersion":"20.11.0","_hasShrinkwrap":false,"devDependencies":{"chai":"^4.3.7","husky":"8.0.3","karma":"6.4.1","mocha":"10.2.0","tslib":"2.4.1","rimraf":"4.1.2","rollup":"3.10.1","prettier":"2.8.3","karma-chai":"0.1.0","typescript":"4.9.4","karma-mocha":"2.0.1","@rollup/plugin-terser":"0.4.0","karma-chrome-launcher":"3.1.1","karma-detect-browsers":"2.3.3","karma-safari-launcher":"1.0.0","karma-firefox-launcher":"2.1.2","conditional-type-checks":"1.0.6","@rollup/plugin-typescript":"11.0.0","karma-safaritechpreview-launcher":"2.0.2"},"_npmOperationalInternal":{"tmp":"tmp/comlink_4.4.4_1767521373606_0.6984687450401477","host":"s3://npm-registry-packages-npm-production"}},"4.4.5":{"name":"@atc-group/comlink","version":"4.4.5","author":{"name":"Surma","email":"surma@google.com"},"license":"Apache-2.0","_id":"@atc-group/comlink@4.4.5","maintainers":[{"name":"atcgroupdev","email":"atcgroupdev@gmail.com"},{"name":"toanzzz","email":"me@toan.io"}],"homepage":"https://github.com/GoogleChromeLabs/comlink#readme","bugs":{"url":"https://github.com/GoogleChromeLabs/comlink/issues"},"dist":{"shasum":"8d4ce89b08fbd9b07ffba93ff144043645315aa5","tarball":"https://registry.npmjs.org/@atc-group/comlink/-/comlink-4.4.5.tgz","fileCount":30,"integrity":"sha512-4y9O4AaEWPvu+s5P6PaB3JZINTSoH8kWgmXeAexE0AOhp38MEcQC1cttJD36Kkos/MqMYu1iNblLQx3HQmo4cA==","signatures":[{"sig":"MEUCIQCqPU3A8z/+8xwdtbdGL2kGYJ6cXfRGS0xER/qWKswInAIgF/snMiFiyd7cIfVIph01FLVB+u9ruC5Vdwzv2AHfW9U=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":424088},"main":"dist/umd/comlink.js","types":"dist/umd/comlink.d.ts","module":"dist/esm/comlink.mjs","gitHead":"114a4a6448a855a613f1cb9a7c89290606c003cf","scripts":{"fmt":"prettier --write './*.{mjs,js,ts,md,json,html}' './{src,docs,tests}/{,**/}*.{mjs,js,ts,md,json,html}'","test":"npm run fmt_test && npm run build && npm run test:types && npm run test:unit && npm run test:node && npm run test:regressions","build":"rollup -c","fmt_test":"test $(prettier -l './*.{mjs,js,ts,md,json,html}' './{src,docs,tests}/{**/,}*.{mjs,js,ts,md,json,html}' | wc -l) -eq 0","test:node":"node ./tests/node/run.mjs","test:unit":"karma start","watchtest":"CHROME_ONLY=1 karma start --no-single-run","test:types":"tsc -p ./tests/tsconfig.json","test:regressions":"node --expose-gc ./tests/node/regressions.mjs","test:types:watch":"npm run test:types -- --watch"},"_npmUser":{"name":"atcgroupdev","email":"atcgroupdev@gmail.com"},"repository":{"url":"git+https://github.com/GoogleChromeLabs/comlink.git","type":"git"},"_npmVersion":"11.12.1","description":"Comlink makes WebWorkers enjoyable","directories":{},"sideEffects":false,"_nodeVersion":"26.0.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"chai":"^4.3.7","husky":"8.0.3","karma":"6.4.1","mocha":"10.2.0","tslib":"2.4.1","rimraf":"4.1.2","rollup":"3.10.1","prettier":"2.8.3","karma-chai":"0.1.0","typescript":"4.9.4","karma-mocha":"2.0.1","@rollup/plugin-terser":"0.4.0","karma-chrome-launcher":"3.1.1","karma-detect-browsers":"2.3.3","karma-safari-launcher":"1.0.0","karma-firefox-launcher":"2.1.2","conditional-type-checks":"1.0.6","@rollup/plugin-typescript":"11.0.0","karma-safaritechpreview-launcher":"2.0.2"},"_npmOperationalInternal":{"tmp":"tmp/comlink_4.4.5_1784872974902_0.032700956879891274","host":"s3://npm-registry-packages-npm-production"}},"5.0.0":{"name":"@atc-group/comlink","version":"5.0.0","description":"Comlink makes WebWorkers enjoyable, and talks to a Rust peer over a socket or stdio","main":"dist/umd/comlink.js","module":"dist/esm/comlink.mjs","types":"dist/umd/comlink.d.ts","exports":{".":{"types":"./dist/umd/comlink.d.ts","import":"./dist/esm/comlink.mjs","require":"./dist/umd/comlink.js","default":"./dist/umd/comlink.js"},"./interop":{"types":"./dist/umd/interop.d.ts","import":"./dist/esm/interop.mjs","require":"./dist/umd/interop.js","default":"./dist/umd/interop.js"},"./node-adapter":{"types":"./dist/umd/node-adapter.d.ts","import":"./dist/esm/node-adapter.mjs","require":"./dist/umd/node-adapter.js","default":"./dist/umd/node-adapter.js"},"./dist/*":"./dist/*","./package.json":"./package.json"},"sideEffects":false,"publishConfig":{"access":"public"},"scripts":{"build":"rollup -c","test:unit":"karma start","test:node":"node ./tests/node/run.mjs","test:regressions":"node --expose-gc ./tests/node/regressions.mjs","test:protocol":"node ./tests/protocol/vectors.mjs && node ./tests/protocol/codec.mjs && node ./tests/protocol/transport.mjs","build:rust":"cargo build --manifest-path ./rust/Cargo.toml --examples","test:rust":"cargo test --manifest-path ./rust/Cargo.toml","test:interop":"npm run build:rust && node ./tests/interop/js-client-rust-server.mjs && npm run test:rust","test:types":"tsc -p ./tests/tsconfig.json","test:types:watch":"npm run test:types -- --watch","test":"npm run fmt_test && npm run build && npm run test:types && npm run test:unit && npm run test:node && npm run test:regressions && npm run test:protocol","test:all":"npm run test && npm run test:interop","fmt":"prettier --write './*.{mjs,js,ts,md,json,html}' './{src,docs,tests,schema,protocol-vectors}/{,**/}*.{mjs,js,ts,md,json,html}'","fmt_test":"test $(prettier -l './*.{mjs,js,ts,md,json,html}' './{src,docs,tests,schema,protocol-vectors}/{**/,}*.{mjs,js,ts,md,json,html}' | wc -l) -eq 0","watchtest":"CHROME_ONLY=1 karma start --no-single-run"},"author":{"name":"Surma","email":"surma@google.com"},"repository":{"type":"git","url":"git+https://github.com/gigasource/comlink.git"},"license":"Apache-2.0","devDependencies":{"@rollup/plugin-terser":"0.4.0","@rollup/plugin-typescript":"11.0.0","chai":"^4.3.7","conditional-type-checks":"1.0.6","husky":"8.0.3","karma":"6.4.1","karma-chai":"0.1.0","karma-chrome-launcher":"3.1.1","karma-detect-browsers":"2.3.3","karma-firefox-launcher":"2.1.2","karma-mocha":"2.0.1","karma-safari-launcher":"1.0.0","karma-safaritechpreview-launcher":"2.0.2","mocha":"10.2.0","prettier":"2.8.3","rimraf":"4.1.2","rollup":"3.10.1","tslib":"2.4.1","typescript":"4.9.4"},"gitHead":"162e991b5fe60b28853fc6abc727d13a3738965a","_id":"@atc-group/comlink@5.0.0","bugs":{"url":"https://github.com/gigasource/comlink/issues"},"homepage":"https://github.com/gigasource/comlink#readme","_nodeVersion":"26.0.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-gga/vXdh8Zn4su3JghdKCkCmQGNsFsa4IUEfFMczS281bYOjSABPQD5IYCbJeifJRXCpEqk9f5H6eIz9CHgAMA==","shasum":"9923cde54cb0c80623a9c460346571dda0608125","tarball":"https://registry.npmjs.org/@atc-group/comlink/-/comlink-5.0.0.tgz","fileCount":42,"unpackedSize":568558,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCPp/F5QdbPxy9ZdsT0bVgQWBHZ88/OdDy7nPZ792t+qgIgS4svlsGuDkRf3IZKYR7K96YHPC6UtJjJKTD/gOb4HO4="}]},"_npmUser":{"name":"atcgroupdev","email":"atcgroupdev@gmail.com"},"directories":{},"maintainers":[{"name":"atcgroupdev","email":"atcgroupdev@gmail.com"},{"name":"toanzzz","email":"me@toan.io"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/comlink_5.0.0_1784933967859_0.7068823226427747"},"_hasShrinkwrap":false}},"time":{"created":"2025-05-02T01:26:58.130Z","modified":"2026-07-24T22:59:28.219Z","4.4.3":"2025-05-02T01:26:58.491Z","4.4.4":"2026-01-04T10:09:33.758Z","4.4.5":"2026-07-24T06:02:55.088Z","5.0.0":"2026-07-24T22:59:28.007Z"},"bugs":{"url":"https://github.com/gigasource/comlink/issues"},"author":{"name":"Surma","email":"surma@google.com"},"license":"Apache-2.0","homepage":"https://github.com/gigasource/comlink#readme","repository":{"type":"git","url":"git+https://github.com/gigasource/comlink.git"},"description":"Comlink makes WebWorkers enjoyable, and talks to a Rust peer over a socket or stdio","maintainers":[{"name":"atcgroupdev","email":"atcgroupdev@gmail.com"},{"name":"toanzzz","email":"me@toan.io"}],"readme":"# Comlink\n\nComlink makes [WebWorkers][webworker] enjoyable. Comlink is a **tiny library (3.9kB compressed)**, that removes the mental barrier of thinking about `postMessage` and hides the fact that you are working with workers.\n\nAt a more abstract level it is an RPC implementation for `postMessage` and [ES6 Proxies][es6 proxy].\n\n```\n$ npm install --save comlink\n```\n\n![Comlink in action](https://user-images.githubusercontent.com/234957/54164510-cdab2d80-4454-11e9-92d0-7356aa6c5746.png)\n\n## Browsers support & bundle size\n\n![Chrome 56+](https://img.shields.io/badge/Chrome-56+-green.svg?style=flat-square)\n![Edge 15+](https://img.shields.io/badge/Edge-15+-green.svg?style=flat-square)\n![Firefox 52+](https://img.shields.io/badge/Firefox-52+-green.svg?style=flat-square)\n![Opera 43+](https://img.shields.io/badge/Opera-43+-green.svg?style=flat-square)\n![Safari 10.1+](https://img.shields.io/badge/Safari-10.1+-green.svg?style=flat-square)\n![Samsung Internet 6.0+](https://img.shields.io/badge/Samsung_Internet-6.0+-green.svg?style=flat-square)\n\nBrowsers without [ES6 Proxy] support can use the [proxy-polyfill].\n\n**Size**: ~2.5k, ~1.2k gzip’d, ~1.1k brotli’d\n\n## Introduction\n\nOn mobile phones, and especially on low-end mobile phones, it is important to keep the main thread as idle as possible so it can respond to user interactions quickly and provide a jank-free experience. **The UI thread ought to be for UI work only**. WebWorkers are a web API that allow you to run code in a separate thread. To communicate with another thread, WebWorkers offer the `postMessage` API. You can send JavaScript objects as messages using `myWorker.postMessage(someObject)`, triggering a `message` event inside the worker.\n\nComlink turns this messaged-based API into a something more developer-friendly by providing an RPC implementation: Values from one thread can be used within the other thread (and vice versa) just like local values.\n\n## Examples\n\n### [Running a simple function](./docs/examples/01-simple-example)\n\n**main.js**\n\n```javascript\nimport * as Comlink from \"https://unpkg.com/comlink/dist/esm/comlink.mjs\";\nasync function init() {\n  const worker = new Worker(\"worker.js\");\n  // WebWorkers use `postMessage` and therefore work with Comlink.\n  const obj = Comlink.wrap(worker);\n  alert(`Counter: ${await obj.counter}`);\n  await obj.inc();\n  alert(`Counter: ${await obj.counter}`);\n}\ninit();\n```\n\n**worker.js**\n\n```javascript\nimportScripts(\"https://unpkg.com/comlink/dist/umd/comlink.js\");\n// importScripts(\"../../../dist/umd/comlink.js\");\n\nconst obj = {\n  counter: 0,\n  inc() {\n    this.counter++;\n  },\n};\n\nComlink.expose(obj);\n```\n\n### [Callbacks](./docs/examples/02-callback-example)\n\n**main.js**\n\n```javascript\nimport * as Comlink from \"https://unpkg.com/comlink/dist/esm/comlink.mjs\";\n// import * as Comlink from \"../../../dist/esm/comlink.mjs\";\nfunction callback(value) {\n  alert(`Result: ${value}`);\n}\nasync function init() {\n  const remoteFunction = Comlink.wrap(new Worker(\"worker.js\"));\n  await remoteFunction(callback);\n}\ninit();\n```\n\n**worker.js**\n\n```javascript\nimportScripts(\"https://unpkg.com/comlink/dist/umd/comlink.js\");\n// importScripts(\"../../../dist/umd/comlink.js\");\n\nasync function remoteFunction(cb) {\n  await cb(\"A string from a worker\");\n}\n\nComlink.expose(remoteFunction);\n```\n\n### Chainable remote calls\n\nCalls can be extended synchronously with more property accesses and calls. Comlink sends the whole chain as one pipeline, so intermediate values remain on the remote side and the chain takes one round-trip:\n\n```js\nconst total = await api.getCart().applyDiscount(\"SUMMER\").getTotal();\n```\n\nA chain must be completed in the same microtask in which it is created. Comlink automatically dispatches an un-awaited leaf call to preserve fire-and-forget behavior. Extending it later throws an error; await the result first and then call the next method on that result. To dispatch immediately without awaiting, call `chain[Comlink.dispatch]()`.\n\nConstructing a value from a call chain is not supported. Await the chain and construct from its result instead.\n\n### [Talking to a Rust peer](./docs/rust-interop.md)\n\nThe other side of a Comlink connection does not have to be JavaScript. `expose` and `wrap` are unchanged; the endpoint carries a JSON codec and NDJSON or WebSocket framing instead of `postMessage`:\n\n```js\nimport { streamEndpoint } from \"@atc-group/comlink/interop\";\n\nconst api = Comlink.wrap(streamEndpoint(child.stdout, child.stdin));\nconst total = await api.getCart().applyDiscount(\"SUMMER\").getTotal();\n```\n\nChains stay one round-trip and callbacks work in both directions, because neither feature needs a `MessagePort` — both are addressed by id on the connection. The wire format is specified in [PROTOCOL.md](./docs/PROTOCOL.md) and pinned by the golden vectors in [protocol-vectors](./protocol-vectors), which both implementations run. The Rust half lives in [`rust/`](./rust).\n\n### [`SharedWorker`](./docs/examples/07-sharedworker-example)\n\nWhen using Comlink with a [`SharedWorker`](https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker) you have to:\n\n1. Use the [`port`](https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker/port) property, of the `SharedWorker` instance, when calling `Comlink.wrap`.\n2. Call `Comlink.expose` within the [`onconnect`](https://developer.mozilla.org/en-US/docs/Web/API/SharedWorkerGlobalScope/onconnect) callback of the shared worker.\n\n**Pro tip:** You can access DevTools for any shared worker currently running in Chrome by going to: **chrome://inspect/#workers**\n\n**main.js**\n\n```javascript\nimport * as Comlink from \"https://unpkg.com/comlink/dist/esm/comlink.mjs\";\nasync function init() {\n  const worker = new SharedWorker(\"worker.js\");\n  /**\n   * SharedWorkers communicate via the `postMessage` function in their `port` property.\n   * Therefore you must use the SharedWorker's `port` property when calling `Comlink.wrap`.\n   */\n  const obj = Comlink.wrap(worker.port);\n  alert(`Counter: ${await obj.counter}`);\n  await obj.inc();\n  alert(`Counter: ${await obj.counter}`);\n}\ninit();\n```\n\n**worker.js**\n\n```javascript\nimportScripts(\"https://unpkg.com/comlink/dist/umd/comlink.js\");\n// importScripts(\"../../../dist/umd/comlink.js\");\n\nconst obj = {\n  counter: 0,\n  inc() {\n    this.counter++;\n  },\n};\n\n/**\n * When a connection is made into this shared worker, expose `obj`\n * via the connection `port`.\n */\nonconnect = function (event) {\n  const port = event.ports[0];\n\n  Comlink.expose(obj, port);\n};\n\n// Single line alternative:\n// onconnect = (e) => Comlink.expose(obj, e.ports[0]);\n```\n\n**For additional examples, please see the [docs/examples](./docs/examples) directory in the project.**\n\n## API\n\n### `Comlink.wrap(endpoint)` and `Comlink.expose(value, endpoint?, allowedOrigins?)`\n\nComlink’s goal is to make _exposed_ values from one thread available in the other. `expose` exposes `value` on `endpoint`, where `endpoint` is a [`postMessage`-like interface][endpoint] and `allowedOrigins` is an array of\nRegExp or strings defining which origins should be allowed access (defaults to special case of `['*']` for all origins).\n\n`wrap` wraps the _other_ end of the message channel and returns a proxy. The proxy will have all properties and functions of the exposed value, but access and invocations are inherently asynchronous. This means that a function that returns a number will now return _a promise_ for a number. **As a rule of thumb: If you are using the proxy, put `await` in front of it.** Exceptions will be caught and re-thrown on the other side.\n\n### `Comlink.transfer(value, transferables)` and `Comlink.proxy(value)`\n\nBy default, every function parameter, return value and object property value is copied, in the sense of [structured cloning]. Structured cloning can be thought of as deep copying, but has some limitations. See [this table][structured clone table] for details.\n\nIf you want a value to be transferred rather than copied — provided the value is or contains a [`Transferable`][transferable] — you can wrap the value in a `transfer()` call and provide a list of transferable values:\n\n```js\nconst data = new Uint8Array([1, 2, 3, 4, 5]);\nawait myProxy.someFunction(Comlink.transfer(data, [data.buffer]));\n```\n\nBare function arguments are automatically registered as callbacks. Reusing the same function with the same endpoint preserves its remote identity, so registration APIs such as `on(event, callback)` and `off(event, callback)` work as expected:\n\n```js\nconst handler = (data) => console.log(data);\nawait myProxy.on(\"ready\", handler);\nawait myProxy.off(\"ready\", handler);\n```\n\nCall `Comlink.releaseCallback(handler)` to release a callback deterministically. Comlink also releases callback registrations automatically when the remote callback stub is garbage collected on runtimes with `WeakRef` and `FinalizationRegistry` support.\n\n`Comlink.proxy(value)` remains available and unchanged for objects or functions that should use a dedicated proxied `MessageChannel` rather than the automatic callback registry.\n\n### Transfer handlers and event listeners\n\nIt is common that you want to use Comlink to add an event listener, where the event source is on another thread:\n\n```js\nbutton.addEventListener(\"click\", myProxy.onClick.bind(myProxy));\n```\n\nWhile this won’t throw immediately, `onClick` will never actually be called. This is because [`Event`][event] is neither structured cloneable nor transferable. As a workaround, Comlink offers transfer handlers.\n\nEach function parameter and return value is given to _all_ registered transfer handlers. If one of the event handler signals that it can process the value by returning `true` from `canHandle()`, it is now responsible for serializing the value to structured cloneable data and for deserializing the value. A transfer handler has be set up on _both sides_ of the message channel. Here’s an example transfer handler for events:\n\n```js\nComlink.transferHandlers.set(\"EVENT\", {\n  canHandle: (obj) => obj instanceof Event,\n  serialize: (ev) => {\n    return [\n      {\n        target: {\n          id: ev.target.id,\n          classList: [...ev.target.classList],\n        },\n      },\n      [],\n    ];\n  },\n  deserialize: (obj) => obj,\n});\n```\n\nNote that this particular transfer handler won’t create an actual `Event`, but just an object that has the `event.target.id` and `event.target.classList` property. Often, this is enough. If not, the transfer handler can be easily augmented to provide all necessary data.\n\n### `Comlink.releaseProxy`\n\nEvery proxy created by Comlink has the `[releaseProxy]()` method.\nCalling it will detach the proxy and the exposed object from the message channel, allowing both ends to be garbage collected.\n\n```js\nconst proxy = Comlink.wrap(port);\n// ... use the proxy ...\nproxy[Comlink.releaseProxy]();\n```\n\nIf the browser supports the [WeakRef proposal], `[releaseProxy]()` will be called automatically when the proxy created by `wrap()` gets garbage collected.\n\n### `Comlink.dispatch` and `Comlink.releaseCallback`\n\n`chain[Comlink.dispatch]()` dispatches a chain immediately and returns the same result promise that a later `await chain` observes. This is useful for explicit fire-and-forget dispatch.\n\n`Comlink.releaseCallback(callback)` removes a bare function from every endpoint where it was automatically registered and tells the corresponding remote endpoints to release their cached stubs.\n\n### `Comlink.finalizer`\n\nIf an exposed object has a property `[Comlink.finalizer]`, the property will be invoked as a function when the proxy is being released. This can happen either through a manual invocation of `[releaseProxy]()` or automatically during garbage collection if the runtime supports the [WeakRef proposal] (see `Comlink.releaseProxy` above). Note that when the finalizer function is invoked, the endpoint is closed and no more communication can happen.\n\n### `Comlink.createEndpoint`\n\nEvery proxy created by Comlink has the `[createEndpoint]()` method.\nCalling it will return a new `MessagePort`, that has been hooked up to the same object as the proxy that `[createEndpoint]()` has been called on.\n\n```js\nconst port = myProxy[Comlink.createEndpoint]();\nconst newProxy = Comlink.wrap(port);\n```\n\n### `Comlink.windowEndpoint(window, context = self, targetOrigin = \"*\")`\n\nWindows and Web Workers have a slightly different variants of `postMessage`. If you want to use Comlink to communicate with an iframe or another window, you need to wrap it with `windowEndpoint()`.\n\n`window` is the window that should be communicate with. `context` is the `EventTarget` on which messages _from_ the `window` can be received (often `self`). `targetOrigin` is passed through to `postMessage` and allows to filter messages by origin. For details, see the documentation for [`Window.postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage).\n\nFor a usage example, take a look at the non-worker examples in the `docs` folder.\n\n## TypeScript\n\nComlink does provide TypeScript types. When you `expose()` something of type `T`, the corresponding `wrap()` call will return something of type `Comlink.Remote<T>`. 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 <type>`.\n\n## Node\n\nComlink works with Node’s [`worker_threads`][worker_threads] module. Take a look at the example in the `docs` folder.\n\n[webworker]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API\n[umd]: https://github.com/umdjs/umd\n[transferable]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Transferable_objects\n[messageport]: https://developer.mozilla.org/en-US/docs/Web/API/MessagePort\n[examples]: https://github.com/GoogleChromeLabs/comlink/tree/master/docs/examples\n[dist]: https://github.com/GoogleChromeLabs/comlink/tree/master/dist\n[delivrjs]: https://cdn.jsdelivr.net/\n[es6 proxy]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy\n[proxy-polyfill]: https://github.com/GoogleChrome/proxy-polyfill\n[endpoint]: src/protocol.ts\n[structured cloning]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm\n[structured clone table]: structured-clone-table.md\n[event]: https://developer.mozilla.org/en-US/docs/Web/API/Event\n[worker_threads]: https://nodejs.org/api/worker_threads.html\n[weakref proposal]: https://github.com/tc39/proposal-weakrefs\n\n## Additional Resources\n\n- [Simplify Web Worker code with Comlink](https://davidea.st/articles/comlink-simple-web-worker)\n\n---\n\nLicense Apache-2.0\n","readmeFilename":"README.md"}