Socket
Socket
Sign inDemoInstall

comlink

Package Overview
Dependencies
Maintainers
2
Versions
36
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

comlink - npm Package Compare versions

Comparing version 4.0.2 to 4.0.3

1

dist/esm/comlink.d.ts

@@ -17,2 +17,3 @@ /**

export declare const createEndpoint: unique symbol;
export declare const releaseProxy: unique symbol;
declare type Promisify<T> = T extends {

@@ -19,0 +20,0 @@ [proxyMarker]: boolean;

10

dist/esm/protocol.d.ts

@@ -48,3 +48,4 @@ /**

CONSTRUCT = 3,
ENDPOINT = 4
ENDPOINT = 4,
RELEASE = 5
}

@@ -78,2 +79,7 @@ export interface GetMessage {

}
export declare type Message = GetMessage | SetMessage | ApplyMessage | ConstructMessage | EndpointMessage;
export interface ReleaseMessage {
id?: MessageID;
type: MessageType.RELEASE;
path: string[];
}
export declare type Message = GetMessage | SetMessage | ApplyMessage | ConstructMessage | EndpointMessage | ReleaseMessage;

@@ -17,2 +17,3 @@ /**

export declare const createEndpoint: unique symbol;
export declare const releaseProxy: unique symbol;
declare type Promisify<T> = T extends {

@@ -19,0 +20,0 @@ [proxyMarker]: boolean;

@@ -21,2 +21,3 @@ (function (global, factory) {

const createEndpoint = Symbol("Comlink.endpoint");
const releaseProxy = Symbol("Comlink.releaseProxy");
const throwSet = new WeakSet();

@@ -65,3 +66,3 @@ const transferHandlers = new Map([

function expose(obj, ep = self) {
ep.addEventListener("message", (async (ev) => {
ep.addEventListener("message", async function callback(ev) {
if (!ev || !ev.data) {

@@ -109,4 +110,7 @@ return;

break;
default:
console.warn("Unrecognized message", ev.data);
case 5 /* RELEASE */:
{
returnValue = undefined;
}
break;
}

@@ -120,3 +124,8 @@ }

ep.postMessage({ ...wireValue, id }, transferables);
}));
if (type === 5 /* RELEASE */) {
// detach and deactive after sending release response above.
ep.removeEventListener("message", callback);
closeEndPoint(ep);
}
});
if (ep.start) {

@@ -126,8 +135,33 @@ ep.start();

}
function isMessagePort(endpoint) {
return endpoint.constructor.name === "MessagePort";
}
function closeEndPoint(endpoint) {
if (isMessagePort(endpoint))
endpoint.close();
}
function wrap(ep) {
return createProxy(ep);
}
function throwIfProxyReleased(isReleased) {
if (isReleased) {
throw new Error("Proxy has been released and is not useable");
}
}
function createProxy(ep, path = []) {
let isProxyReleased = false;
const proxy = new Proxy(function () { }, {
get(_target, prop) {
throwIfProxyReleased(isProxyReleased);
if (prop === releaseProxy) {
return () => {
return requestResponseMessage(ep, {
type: 5 /* RELEASE */,
path: path.map(p => p.toString())
}).then(() => {
closeEndPoint(ep);
isProxyReleased = true;
});
};
}
if (prop === "then") {

@@ -146,2 +180,3 @@ if (path.length === 0) {

set(_target, prop, rawValue) {
throwIfProxyReleased(isProxyReleased);
// FIXME: ES6 Proxy Handler `set` methods are supposed to return a

@@ -157,2 +192,3 @@ // boolean. To show good will, we return true asynchronously ¯\_(ツ)_/¯

apply(_target, _thisArg, rawArgumentList) {
throwIfProxyReleased(isProxyReleased);
const last = path[path.length - 1];

@@ -176,2 +212,3 @@ if (last === createEndpoint) {

construct(_target, rawArgumentList) {
throwIfProxyReleased(isProxyReleased);
const [argumentList, transferables] = processArguments(rawArgumentList);

@@ -266,2 +303,3 @@ return requestResponseMessage(ep, {

exports.proxyMarker = proxyMarker;
exports.releaseProxy = releaseProxy;
exports.transfer = transfer;

@@ -268,0 +306,0 @@ exports.transferHandlers = transferHandlers;

@@ -1,2 +0,2 @@

!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e=e||self).Comlink={})}(this,function(e){"use strict";const t=Symbol("Comlink.proxy"),n=Symbol("Comlink.endpoint"),r=new WeakSet,a=new Map([["proxy",{canHandle:e=>e&&e[t],serialize(e){const{port1:t,port2:n}=new MessageChannel;return s(e,t),[n,[n]]},deserialize:e=>(e.start(),o(e))}],["throw",{canHandle:e=>r.has(e),serialize(e){const t=e instanceof Error;let n=e;return t&&(n={isError:t,message:e.message,stack:e.stack}),[n,[]]},deserialize(e){if(e.isError)throw Object.assign(new Error,e);throw e}}]]);function s(e,t=self){t.addEventListener("message",async n=>{if(!n||!n.data)return;const{id:a,type:o,path:i}={path:[],...n.data},c=(n.data.argumentList||[]).map(l);let f;try{const t=i.slice(0,-1).reduce((e,t)=>e[t],e),a=i.reduce((e,t)=>e[t],e);switch(o){case 0:f=await a;break;case 1:t[i.slice(-1)[0]]=l(n.data.value),f=!0;break;case 2:f=await a.apply(t,c);break;case 3:f=u(await new a(...c));break;case 4:{const{port1:t,port2:n}=new MessageChannel;s(e,n),f=p(t,[t])}break;default:console.warn("Unrecognized message",n.data)}}catch(e){f=e,r.add(e)}const[m,g]=d(f);t.postMessage({...m,id:a},g)}),t.start&&t.start()}function o(e){return function e(t,r=[]){const a=new Proxy(function(){},{get(n,s){if("then"===s){if(0===r.length)return{then:()=>a};const e=f(t,{type:0,path:r.map(e=>e.toString())}).then(l);return e.then.bind(e)}return e(t,[...r,s])},set(e,n,a){const[s,o]=d(a);return f(t,{type:1,path:[...r,n].map(e=>e.toString()),value:s},o).then(l)},apply(a,s,o){const c=r[r.length-1];if(c===n)return f(t,{type:4}).then(l);if("bind"===c)return e(t,r.slice(0,-1));const[p,u]=i(o);return f(t,{type:2,path:r.map(e=>e.toString()),argumentList:p},u).then(l)},construct(e,n){const[a,s]=i(n);return f(t,{type:3,path:r.map(e=>e.toString()),argumentList:a},s).then(l)}});return a}(e)}function i(e){const t=e.map(d);return[t.map(e=>e[0]),(n=t.map(e=>e[1]),Array.prototype.concat.apply([],n))];var n}const c=new WeakMap;function p(e,t){return c.set(e,t),e}function u(e){return Object.assign(e,{[t]:!0})}function d(e){for(const[t,n]of a)if(n.canHandle(e)){const[r,a]=n.serialize(e);return[{type:3,name:t,value:r},a]}return[{type:0,value:e},c.get(e)||[]]}function l(e){switch(e.type){case 3:return a.get(e.name).deserialize(e.value);case 0:return e.value}}function f(e,t,n){return new Promise(r=>{const a=new Array(4).fill(0).map(()=>Math.floor(Math.random()*Number.MAX_SAFE_INTEGER).toString(16)).join("-");e.addEventListener("message",function t(n){n.data&&n.data.id&&n.data.id===a&&(e.removeEventListener("message",t),r(n.data))}),e.start&&e.start(),e.postMessage({id:a,...t},n)})}e.createEndpoint=n,e.expose=s,e.proxy=u,e.proxyMarker=t,e.transfer=p,e.transferHandlers=a,e.windowEndpoint=function(e,t=self){return{postMessage:(t,n)=>e.postMessage(t,"*",n),addEventListener:t.addEventListener.bind(t),removeEventListener:t.removeEventListener.bind(t)}},e.wrap=o,Object.defineProperty(e,"__esModule",{value:!0})});
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e=e||self).Comlink={})}(this,(function(e){"use strict";const t=Symbol("Comlink.proxy"),n=Symbol("Comlink.endpoint"),r=Symbol("Comlink.releaseProxy"),a=new WeakSet,s=new Map([["proxy",{canHandle:e=>e&&e[t],serialize(e){const{port1:t,port2:n}=new MessageChannel;return o(e,t),[n,[n]]},deserialize:e=>(e.start(),c(e))}],["throw",{canHandle:e=>a.has(e),serialize(e){const t=e instanceof Error;let n=e;return t&&(n={isError:t,message:e.message,stack:e.stack}),[n,[]]},deserialize(e){if(e.isError)throw Object.assign(new Error,e);throw e}}]]);function o(e,t=self){t.addEventListener("message",(async function n(r){if(!r||!r.data)return;const{id:s,type:c,path:u}={path:[],...r.data},p=(r.data.argumentList||[]).map(y);let d;try{const t=u.slice(0,-1).reduce((e,t)=>e[t],e),n=u.reduce((e,t)=>e[t],e);switch(c){case 0:d=await n;break;case 1:t[u.slice(-1)[0]]=y(r.data.value),d=!0;break;case 2:d=await n.apply(t,p);break;case 3:d=f(await new n(...p));break;case 4:{const{port1:t,port2:n}=new MessageChannel;o(e,n),d=l(t,[t])}break;case 5:d=void 0}}catch(e){d=e,a.add(e)}const[h,g]=m(d);t.postMessage({...h,id:s},g),5===c&&(t.removeEventListener("message",n),i(t))})),t.start&&t.start()}function i(e){(function(e){return"MessagePort"===e.constructor.name})(e)&&e.close()}function c(e){return function e(t,a=[]){let s=!1;const o=new Proxy((function(){}),{get(n,c){if(u(s),c===r)return()=>h(t,{type:5,path:a.map(e=>e.toString())}).then(()=>{i(t),s=!0});if("then"===c){if(0===a.length)return{then:()=>o};const e=h(t,{type:0,path:a.map(e=>e.toString())}).then(y);return e.then.bind(e)}return e(t,[...a,c])},set(e,n,r){u(s);const[o,i]=m(r);return h(t,{type:1,path:[...a,n].map(e=>e.toString()),value:o},i).then(y)},apply(r,o,i){u(s);const c=a[a.length-1];if(c===n)return h(t,{type:4}).then(y);if("bind"===c)return e(t,a.slice(0,-1));const[d,l]=p(i);return h(t,{type:2,path:a.map(e=>e.toString()),argumentList:d},l).then(y)},construct(e,n){u(s);const[r,o]=p(n);return h(t,{type:3,path:a.map(e=>e.toString()),argumentList:r},o).then(y)}});return o}(e)}function u(e){if(e)throw new Error("Proxy has been released and is not useable")}function p(e){const t=e.map(m);return[t.map(e=>e[0]),(n=t.map(e=>e[1]),Array.prototype.concat.apply([],n))];var n}const d=new WeakMap;function l(e,t){return d.set(e,t),e}function f(e){return Object.assign(e,{[t]:!0})}function m(e){for(const[t,n]of s)if(n.canHandle(e)){const[r,a]=n.serialize(e);return[{type:3,name:t,value:r},a]}return[{type:0,value:e},d.get(e)||[]]}function y(e){switch(e.type){case 3:return s.get(e.name).deserialize(e.value);case 0:return e.value}}function h(e,t,n){return new Promise(r=>{const a=new Array(4).fill(0).map(()=>Math.floor(Math.random()*Number.MAX_SAFE_INTEGER).toString(16)).join("-");e.addEventListener("message",(function t(n){n.data&&n.data.id&&n.data.id===a&&(e.removeEventListener("message",t),r(n.data))})),e.start&&e.start(),e.postMessage({id:a,...t},n)})}e.createEndpoint=n,e.expose=o,e.proxy=f,e.proxyMarker=t,e.releaseProxy=r,e.transfer=l,e.transferHandlers=s,e.windowEndpoint=function(e,t=self){return{postMessage:(t,n)=>e.postMessage(t,"*",n),addEventListener:t.addEventListener.bind(t),removeEventListener:t.removeEventListener.bind(t)}},e.wrap=c,Object.defineProperty(e,"__esModule",{value:!0})}));
//# sourceMappingURL=comlink.min.js.map

@@ -1,2 +0,2 @@

!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).Comlink=t()}(this,function(){"use strict";return function(e){const t=new WeakMap;return{postMessage:e.postMessage.bind(e),addEventListener:(n,s)=>{const o=e=>{"handleEvent"in s?s.handleEvent({data:e}):s({data:e})};e.on("message",o),t.set(s,o)},removeEventListener:(n,s)=>{const o=t.get(s);o&&(e.off("message",o),t.delete(s))},start:e.start&&e.start.bind(e)}}});
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).Comlink=t()}(this,(function(){"use strict";return function(e){const t=new WeakMap;return{postMessage:e.postMessage.bind(e),addEventListener:(n,s)=>{const o=e=>{"handleEvent"in s?s.handleEvent({data:e}):s({data:e})};e.on("message",o),t.set(s,o)},removeEventListener:(n,s)=>{const o=t.get(s);o&&(e.off("message",o),t.delete(s))},start:e.start&&e.start.bind(e)}}}));
//# sourceMappingURL=node-adapter.min.js.map

@@ -48,3 +48,4 @@ /**

CONSTRUCT = 3,
ENDPOINT = 4
ENDPOINT = 4,
RELEASE = 5
}

@@ -78,2 +79,7 @@ export interface GetMessage {

}
export declare type Message = GetMessage | SetMessage | ApplyMessage | ConstructMessage | EndpointMessage;
export interface ReleaseMessage {
id?: MessageID;
type: MessageType.RELEASE;
path: string[];
}
export declare type Message = GetMessage | SetMessage | ApplyMessage | ConstructMessage | EndpointMessage | ReleaseMessage;
{
"name": "comlink",
"version": "4.0.2",
"version": "4.0.3",
"description": "Comlink makes WebWorkers enjoyable",

@@ -34,20 +34,20 @@ "main": "dist/umd/comlink.js",

"conditional-type-checks": "1.0.1",
"husky": "3.0.1",
"karma": "4.2.0",
"husky": "3.0.7",
"karma": "4.3.0",
"karma-chai": "0.1.0",
"karma-chrome-launcher": "3.0.0",
"karma-chrome-launcher": "3.1.0",
"karma-detect-browsers": "2.3.3",
"karma-firefox-launcher": "1.1.0",
"karma-firefox-launcher": "1.2.0",
"karma-mocha": "1.3.0",
"karma-safari-launcher": "1.0.0",
"karma-safaritechpreview-launcher": "2.0.2",
"mocha": "6.2.0",
"mocha": "6.2.1",
"prettier": "1.18.2",
"rimraf": "2.6.3",
"rollup": "1.17.0",
"rollup-plugin-terser": "5.1.1",
"rollup-plugin-typescript2": "0.22.0",
"typescript": "3.5.3"
"rimraf": "3.0.0",
"rollup": "1.22.0",
"rollup-plugin-terser": "5.1.2",
"rollup-plugin-typescript2": "0.24.3",
"typescript": "3.6.3"
},
"dependencies": {}
}

@@ -32,2 +32,69 @@ # Comlink

## Examples
### [Running a simple function](https://github.com/GoogleChromeLabs/comlink/tree/master/docs/examples/01-simple-example)
**main.js**
```javascript
import * as Comlink from "https://unpkg.com/comlink@alpha/dist/esm/comlink.mjs";
async function init() {
const worker = new Worker("worker.js");
// WebWorkers use `postMessage` and therefore work with Comlink.
const obj = Comlink.wrap(worker);
alert(`Counter: ${await obj.counter}`);
await obj.inc();
alert(`Counter: ${await obj.counter}`);
}
init();
```
**worker.js**
```javascript
importScripts("https://unpkg.com/comlink@alpha/dist/umd/comlink.js");
// importScripts("../../../dist/umd/comlink.js");
const obj = {
counter: 0,
inc() {
this.counter++;
}
};
Comlink.expose(obj);
```
### [Callbacks](https://github.com/torch2424/comlink/tree/master/docs/examples/02-callback-example)
**main.js**
```javascript
import * as Comlink from "https://unpkg.com/comlink@alpha/dist/esm/comlink.mjs";
// import * as Comlink from "../../../dist/esm/comlink.mjs";
function callback(value) {
alert(`Result: ${value}`);
}
async function init() {
const remoteFunction = Comlink.wrap(new Worker("worker.js"));
await remoteFunction(Comlink.proxy(callback));
}
init();
```
**worker.js**
```javascript
importScripts("https://unpkg.com/comlink@alpha/dist/umd/comlink.js");
// importScripts("../../../dist/umd/comlink.js");
async function remoteFunction(cb) {
await cb("A string from a worker");
}
Comlink.expose(remoteFunction);
```
**For additional examples, please see the [docs/examples](./docs/examples) directory in the project.**
## API

@@ -39,3 +106,3 @@

`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 inherintly 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.
`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.

@@ -90,2 +157,13 @@ ### `Comlink.transfer(value, transferables)` and `Comlink.proxy(value)`

### `Comlink.releaseProxy`
Every proxy created by Comlink has the `[releaseProxy]` method.
Calling it will detach the proxy and the exposed object from the message channel, allowing both ends to be garbage collected.
```js
const proxy = Comlink.wrap(port);
// ... use the proxy ...
proxy[Comlink.releaseProxy]();
```
### `Comlink.createEndpoint`

@@ -120,4 +198,8 @@

## Additional Resources
- [Simplify Web Worker code with Comlink](https://davidea.st/articles/comlink-simple-web-worker)
---
License Apache-2.0

@@ -27,2 +27,3 @@ /**

export const createEndpoint = Symbol("Comlink.endpoint");
export const releaseProxy = Symbol("Comlink.releaseProxy");
const throwSet = new WeakSet();

@@ -100,3 +101,3 @@

export function expose(obj: any, ep: Endpoint = self as any) {
ep.addEventListener("message", (async (ev: MessageEvent) => {
ep.addEventListener("message", async function callback(ev: MessageEvent) {
if (!ev || !ev.data) {

@@ -144,4 +145,7 @@ return;

break;
default:
console.warn("Unrecognized message", ev.data);
case MessageType.RELEASE:
{
returnValue = undefined;
}
break;
}

@@ -154,3 +158,8 @@ } catch (e) {

ep.postMessage({ ...wireValue, id }, transferables);
}) as any);
if (type === MessageType.RELEASE) {
// detach and deactive after sending release response above.
ep.removeEventListener("message", callback as any);
closeEndPoint(ep);
}
} as any);
if (ep.start) {

@@ -161,2 +170,10 @@ ep.start();

function isMessagePort(endpoint: Endpoint): endpoint is MessagePort {
return endpoint.constructor.name === "MessagePort";
}
function closeEndPoint(endpoint: Endpoint) {
if (isMessagePort(endpoint)) endpoint.close();
}
export function wrap<T>(ep: Endpoint): Remote<T> {

@@ -166,2 +183,8 @@ return createProxy<T>(ep) as any;

function throwIfProxyReleased(isReleased: boolean) {
if (isReleased) {
throw new Error("Proxy has been released and is not useable");
}
}
function createProxy<T>(

@@ -171,4 +194,17 @@ ep: Endpoint,

): Remote<T> {
const proxy: Function = new Proxy(function() {}, {
let isProxyReleased = false;
const proxy = new Proxy(function() {}, {
get(_target, prop) {
throwIfProxyReleased(isProxyReleased);
if (prop === releaseProxy) {
return () => {
return requestResponseMessage(ep, {
type: MessageType.RELEASE,
path: path.map(p => p.toString())
}).then(() => {
closeEndPoint(ep);
isProxyReleased = true;
});
};
}
if (prop === "then") {

@@ -187,2 +223,3 @@ if (path.length === 0) {

set(_target, prop, rawValue) {
throwIfProxyReleased(isProxyReleased);
// FIXME: ES6 Proxy Handler `set` methods are supposed to return a

@@ -202,2 +239,3 @@ // boolean. To show good will, we return true asynchronously ¯\_(ツ)_/¯

apply(_target, _thisArg, rawArgumentList) {
throwIfProxyReleased(isProxyReleased);
const last = path[path.length - 1];

@@ -225,2 +263,3 @@ if ((last as any) === createEndpoint) {

construct(_target, rawArgumentList) {
throwIfProxyReleased(isProxyReleased);
const [argumentList, transferables] = processArguments(rawArgumentList);

@@ -227,0 +266,0 @@ return requestResponseMessage(

@@ -69,3 +69,4 @@ /**

CONSTRUCT,
ENDPOINT
ENDPOINT,
RELEASE
}

@@ -105,2 +106,8 @@

export interface ReleaseMessage {
id?: MessageID;
type: MessageType.RELEASE;
path: string[];
}
export type Message =

@@ -111,2 +118,3 @@ | GetMessage

| ConstructMessage
| EndpointMessage;
| EndpointMessage
| ReleaseMessage;

@@ -499,2 +499,10 @@ /**

});
it("released proxy should no longer be useable and throw an exception", async function() {
const thing = Comlink.wrap(this.port1);
Comlink.expose(SampleClass, this.port2);
const instance = await new thing();
await instance[Comlink.releaseProxy]();
expect(() => instance.method()).to.throw();
});
});

@@ -501,0 +509,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc