Comparing version 2.1.0 to 2.2.0
@@ -63,8 +63,12 @@ /** | ||
const irequest = event.data; | ||
let that = await irequest.callPath.slice(0, -1).reduce((obj, propName) => obj[propName], rootObj); | ||
let obj = await irequest.callPath.reduce((obj, propName) => obj[propName], rootObj); | ||
if (irequest.type === 'APPLY' || irequest.type === 'CONSTRUCT') { | ||
const isAsyncGenerator = obj.constructor.name === 'AsyncGeneratorFunction'; | ||
let iresult = obj; | ||
// If there is an arguments list, proxy-fy parameters as necessary | ||
if ('argumentsList' in irequest) { | ||
irequest.argumentsList = | ||
irequest.argumentsList.map(arg => { | ||
if (arg[transferMarker] === 'PROXY') | ||
return Comlink.proxy(arg.endpoint); | ||
return proxy(arg.endpoint); | ||
else | ||
@@ -74,29 +78,11 @@ return arg; | ||
} | ||
switch (irequest.type) { | ||
case 'APPLY': { | ||
irequest.callPath.pop(); | ||
const that = await irequest.callPath.reduce((obj, propName) => obj[propName], rootObj); | ||
const isAsyncGenerator = obj.constructor.name === 'AsyncGeneratorFunction'; | ||
obj = await obj.apply(that, irequest.argumentsList); | ||
// If the function being called is an async generator, proxy the | ||
// result. | ||
if (isAsyncGenerator) | ||
obj = proxyValue(obj); | ||
} // fallthrough! | ||
case 'GET': { | ||
const iresult = makeInvocationResult(obj); | ||
iresult.id = irequest.id; | ||
return endpoint.postMessage(iresult, transferableProperties([iresult])); | ||
} | ||
case 'CONSTRUCT': { | ||
const instance = new obj(...(irequest.argumentsList || [])); // eslint-disable-line new-cap | ||
const { port1, port2 } = new MessageChannel(); | ||
expose(instance, port1); | ||
return endpoint.postMessage({ | ||
id: irequest.id, | ||
type: 'PROXY', | ||
endpoint: port2, | ||
}, [port2]); | ||
} | ||
} | ||
if (irequest.type === 'APPLY') | ||
iresult = await obj.apply(that, irequest.argumentsList); | ||
if (isAsyncGenerator) | ||
iresult = proxyValue(iresult); | ||
if (irequest.type === 'CONSTRUCT') | ||
iresult = proxyValue(new obj(...(irequest.argumentsList || []))); // eslint-disable-line new-cap | ||
iresult = makeInvocationResult(iresult); | ||
iresult.id = irequest.id; | ||
return endpoint.postMessage(iresult, transferableProperties([iresult])); | ||
}); | ||
@@ -103,0 +89,0 @@ } |
@@ -1,1 +0,1 @@ | ||
export const Comlink=function(){function a(b){if(j(b)&&(b=d(b)),!e(b))throw Error('endpoint does not have all of addEventListener, removeEventListener and postMessage defined');return f(b),m(async(d)=>{let e=[];('APPLY'===d.type||'CONSTRUCT'===d.type)&&(e=d.argumentsList=d.argumentsList.map((a)=>{if(!q(a))return a;const{port1:b,port2:d}=new MessageChannel;return c(a,b),{[w]:'PROXY',endpoint:d}}));const f=await k(b,d,p(e)),g=f.data;return'PROXY'===g.type?a(g.endpoint):g.obj})}function b(a){return a[v]=!0,a}function c(a,h){if(j(h)&&(h=d(h)),!e(h))throw Error('endpoint does not have all of addEventListener, removeEventListener and postMessage defined');f(h),g(h,async function(d){if(!d.data.id)return;const e=d.data;let f=await e.callPath.reduce((a,b)=>a[b],a);switch(('APPLY'===e.type||'CONSTRUCT'===e.type)&&(e.argumentsList=e.argumentsList.map((a)=>{return'PROXY'===a[w]?Comlink.proxy(a.endpoint):a})),e.type){case'APPLY':{e.callPath.pop();const c=await e.callPath.reduce((a,b)=>a[b],a),d='AsyncGeneratorFunction'===f.constructor.name;f=await f.apply(c,e.argumentsList),d&&(f=b(f))}case'GET':{const a=r(f);return a.id=e.id,h.postMessage(a,p([a]))}case'CONSTRUCT':{const a=new f(...(e.argumentsList||[])),{port1:b,port2:d}=new MessageChannel;return c(a,b),h.postMessage({id:e.id,type:'PROXY',endpoint:d},[d])}}})}function d(a){if('Window'!==self.constructor.name)throw Error('self is not a window');return{addEventListener:self.addEventListener.bind(self),removeEventListener:self.removeEventListener.bind(self),postMessage:(b,c)=>a.postMessage(b,'*',c)}}function e(a){return'addEventListener'in a&&'removeEventListener'in a&&'postMessage'in a}function f(a){i(a)&&a.start()}function g(a,b){a.addEventListener('message',b)}function h(a,b){a.removeEventListener('message',b)}function i(a){return'MessagePort'===a.constructor.name}function j(a){return['window','length','location','parent','opener'].every((b)=>b in a)}function k(a,b,c){const d=`${s}-${t++}`;return new Promise((e)=>{g(a,function b(c){c.data.id!==d||(h(a,b),e(c))}),b=Object.assign({},b,{id:d}),a.postMessage(b,c)})}function l(){return'asyncIterator'in Symbol}function m(a){let b=[];return new Proxy(function(){},{construct(c,d){const e=a({type:'CONSTRUCT',callPath:b,argumentsList:d});return b=[],e},apply(c,d,e){if('bind'===b[b.length-1]){const c=b.slice();return b=[],(...b)=>a({type:'APPLY',callPath:c.slice(0,-1),argumentsList:b})}const f=a({type:'APPLY',callPath:b,argumentsList:e});return b=[],f},get(c,d,e){if('then'===d&&0===b.length)return{then:()=>e};if(l()&&d===Symbol.asyncIterator)return()=>e;if('then'===d){const c=a({type:'GET',callPath:b});return b=[],Promise.resolve(c).then.bind(c)}return b.push(d),e}})}function n(a){return u.some((b)=>a instanceof b)}function*o(a){if(!a)return;if('string'==typeof a)return;yield a;let b=Object.values(a);Array.isArray(a)&&(b=a);for(const c of b)yield*o(c)}function p(a){const b=[];for(const c of o(a))n(c)&&b.push(c);return b}function q(a){return a&&a[v]}function r(a){if(q(a)){const{port1:b,port2:d}=new MessageChannel;return c(a,b),{type:'PROXY',endpoint:d}}return{type:'OBJECT',obj:a}}const s=Math.floor(Math.random()*Number.MAX_SAFE_INTEGER);let t=0;const u=[ArrayBuffer,MessagePort],v=Symbol('proxyValue'),w='__omg_so_secret';return{proxy:a,proxyValue:b,expose:c}}(); | ||
export const Comlink=function(){function a(b){if(j(b)&&(b=d(b)),!e(b))throw Error('endpoint does not have all of addEventListener, removeEventListener and postMessage defined');return f(b),m(async(d)=>{let e=[];('APPLY'===d.type||'CONSTRUCT'===d.type)&&(e=d.argumentsList=d.argumentsList.map((a)=>{if(!q(a))return a;const{port1:b,port2:d}=new MessageChannel;return c(a,b),{[w]:'PROXY',endpoint:d}}));const f=await k(b,d,p(e)),g=f.data;return'PROXY'===g.type?a(g.endpoint):g.obj})}function b(a){return a[v]=!0,a}function c(c,h){if(j(h)&&(h=d(h)),!e(h))throw Error('endpoint does not have all of addEventListener, removeEventListener and postMessage defined');f(h),g(h,async function(d){if(!d.data.id)return;const e=d.data;let f=await e.callPath.slice(0,-1).reduce((a,b)=>a[b],c),g=await e.callPath.reduce((a,b)=>a[b],c);const i='AsyncGeneratorFunction'===g.constructor.name;let j=g;return'argumentsList'in e&&(e.argumentsList=e.argumentsList.map((b)=>{return'PROXY'===b[w]?a(b.endpoint):b})),'APPLY'===e.type&&(j=await g.apply(f,e.argumentsList)),i&&(j=b(j)),'CONSTRUCT'===e.type&&(j=b(new g(...(e.argumentsList||[])))),j=r(j),j.id=e.id,h.postMessage(j,p([j]))})}function d(a){if('Window'!==self.constructor.name)throw Error('self is not a window');return{addEventListener:self.addEventListener.bind(self),removeEventListener:self.removeEventListener.bind(self),postMessage:(b,c)=>a.postMessage(b,'*',c)}}function e(a){return'addEventListener'in a&&'removeEventListener'in a&&'postMessage'in a}function f(a){i(a)&&a.start()}function g(a,b){a.addEventListener('message',b)}function h(a,b){a.removeEventListener('message',b)}function i(a){return'MessagePort'===a.constructor.name}function j(a){return['window','length','location','parent','opener'].every((b)=>b in a)}function k(a,b,c){const d=`${s}-${t++}`;return new Promise((e)=>{g(a,function b(c){c.data.id!==d||(h(a,b),e(c))}),b=Object.assign({},b,{id:d}),a.postMessage(b,c)})}function l(){return'asyncIterator'in Symbol}function m(a){let b=[];return new Proxy(function(){},{construct(c,d){const e=a({type:'CONSTRUCT',callPath:b,argumentsList:d});return b=[],e},apply(c,d,e){if('bind'===b[b.length-1]){const c=b.slice();return b=[],(...b)=>a({type:'APPLY',callPath:c.slice(0,-1),argumentsList:b})}const f=a({type:'APPLY',callPath:b,argumentsList:e});return b=[],f},get(c,d,e){if('then'===d&&0===b.length)return{then:()=>e};if(l()&&d===Symbol.asyncIterator)return()=>e;if('then'===d){const c=a({type:'GET',callPath:b});return b=[],Promise.resolve(c).then.bind(c)}return b.push(d),e}})}function n(a){return u.some((b)=>a instanceof b)}function*o(a){if(!a)return;if('string'==typeof a)return;yield a;let b=Object.values(a);Array.isArray(a)&&(b=a);for(const c of b)yield*o(c)}function p(a){const b=[];for(const c of o(a))n(c)&&b.push(c);return b}function q(a){return a&&a[v]}function r(a){if(q(a)){const{port1:b,port2:d}=new MessageChannel;return c(a,b),{type:'PROXY',endpoint:d}}return{type:'OBJECT',obj:a}}const s=Math.floor(Math.random()*Number.MAX_SAFE_INTEGER);let t=0;const u=[ArrayBuffer,MessagePort],v=Symbol('proxyValue'),w='__omg_so_secret';return{proxy:a,proxyValue:b,expose:c}}(); |
@@ -65,8 +65,12 @@ "use strict"; | ||
const irequest = event.data; | ||
let that = await irequest.callPath.slice(0, -1).reduce((obj, propName) => obj[propName], rootObj); | ||
let obj = await irequest.callPath.reduce((obj, propName) => obj[propName], rootObj); | ||
if (irequest.type === 'APPLY' || irequest.type === 'CONSTRUCT') { | ||
const isAsyncGenerator = obj.constructor.name === 'AsyncGeneratorFunction'; | ||
let iresult = obj; | ||
// If there is an arguments list, proxy-fy parameters as necessary | ||
if ('argumentsList' in irequest) { | ||
irequest.argumentsList = | ||
irequest.argumentsList.map(arg => { | ||
if (arg[transferMarker] === 'PROXY') | ||
return self.Comlink.proxy(arg.endpoint); | ||
return proxy(arg.endpoint); | ||
else | ||
@@ -76,29 +80,11 @@ return arg; | ||
} | ||
switch (irequest.type) { | ||
case 'APPLY': { | ||
irequest.callPath.pop(); | ||
const that = await irequest.callPath.reduce((obj, propName) => obj[propName], rootObj); | ||
const isAsyncGenerator = obj.constructor.name === 'AsyncGeneratorFunction'; | ||
obj = await obj.apply(that, irequest.argumentsList); | ||
// If the function being called is an async generator, proxy the | ||
// result. | ||
if (isAsyncGenerator) | ||
obj = proxyValue(obj); | ||
} // fallthrough! | ||
case 'GET': { | ||
const iresult = makeInvocationResult(obj); | ||
iresult.id = irequest.id; | ||
return endpoint.postMessage(iresult, transferableProperties([iresult])); | ||
} | ||
case 'CONSTRUCT': { | ||
const instance = new obj(...(irequest.argumentsList || [])); // eslint-disable-line new-cap | ||
const { port1, port2 } = new MessageChannel(); | ||
expose(instance, port1); | ||
return endpoint.postMessage({ | ||
id: irequest.id, | ||
type: 'PROXY', | ||
endpoint: port2, | ||
}, [port2]); | ||
} | ||
} | ||
if (irequest.type === 'APPLY') | ||
iresult = await obj.apply(that, irequest.argumentsList); | ||
if (isAsyncGenerator) | ||
iresult = proxyValue(iresult); | ||
if (irequest.type === 'CONSTRUCT') | ||
iresult = proxyValue(new obj(...(irequest.argumentsList || []))); // eslint-disable-line new-cap | ||
iresult = makeInvocationResult(iresult); | ||
iresult.id = irequest.id; | ||
return endpoint.postMessage(iresult, transferableProperties([iresult])); | ||
}); | ||
@@ -105,0 +91,0 @@ } |
@@ -1,1 +0,1 @@ | ||
'use strict';self.Comlink=function(){function a(b){if(j(b)&&(b=d(b)),!e(b))throw Error('endpoint does not have all of addEventListener, removeEventListener and postMessage defined');return f(b),m(async(d)=>{let e=[];('APPLY'===d.type||'CONSTRUCT'===d.type)&&(e=d.argumentsList=d.argumentsList.map((a)=>{if(!q(a))return a;const{port1:b,port2:d}=new MessageChannel;return c(a,b),{[w]:'PROXY',endpoint:d}}));const f=await k(b,d,p(e)),g=f.data;return'PROXY'===g.type?a(g.endpoint):g.obj})}function b(a){return a[v]=!0,a}function c(a,h){if(j(h)&&(h=d(h)),!e(h))throw Error('endpoint does not have all of addEventListener, removeEventListener and postMessage defined');f(h),g(h,async function(d){if(!d.data.id)return;const e=d.data;let f=await e.callPath.reduce((a,b)=>a[b],a);switch(('APPLY'===e.type||'CONSTRUCT'===e.type)&&(e.argumentsList=e.argumentsList.map((a)=>{return'PROXY'===a[w]?self.Comlink.proxy(a.endpoint):a})),e.type){case'APPLY':{e.callPath.pop();const c=await e.callPath.reduce((a,b)=>a[b],a),d='AsyncGeneratorFunction'===f.constructor.name;f=await f.apply(c,e.argumentsList),d&&(f=b(f))}case'GET':{const a=r(f);return a.id=e.id,h.postMessage(a,p([a]))}case'CONSTRUCT':{const a=new f(...(e.argumentsList||[])),{port1:b,port2:d}=new MessageChannel;return c(a,b),h.postMessage({id:e.id,type:'PROXY',endpoint:d},[d])}}})}function d(a){if('Window'!==self.constructor.name)throw Error('self is not a window');return{addEventListener:self.addEventListener.bind(self),removeEventListener:self.removeEventListener.bind(self),postMessage:(b,c)=>a.postMessage(b,'*',c)}}function e(a){return'addEventListener'in a&&'removeEventListener'in a&&'postMessage'in a}function f(a){i(a)&&a.start()}function g(a,b){a.addEventListener('message',b)}function h(a,b){a.removeEventListener('message',b)}function i(a){return'MessagePort'===a.constructor.name}function j(a){return['window','length','location','parent','opener'].every((b)=>b in a)}function k(a,b,c){const d=`${s}-${t++}`;return new Promise((e)=>{g(a,function b(c){c.data.id!==d||(h(a,b),e(c))}),b=Object.assign({},b,{id:d}),a.postMessage(b,c)})}function l(){return'asyncIterator'in Symbol}function m(a){let b=[];return new Proxy(function(){},{construct(c,d){const e=a({type:'CONSTRUCT',callPath:b,argumentsList:d});return b=[],e},apply(c,d,e){if('bind'===b[b.length-1]){const c=b.slice();return b=[],(...b)=>a({type:'APPLY',callPath:c.slice(0,-1),argumentsList:b})}const f=a({type:'APPLY',callPath:b,argumentsList:e});return b=[],f},get(c,d,e){if('then'===d&&0===b.length)return{then:()=>e};if(l()&&d===Symbol.asyncIterator)return()=>e;if('then'===d){const c=a({type:'GET',callPath:b});return b=[],Promise.resolve(c).then.bind(c)}return b.push(d),e}})}function n(a){return u.some((b)=>a instanceof b)}function*o(a){if(!a)return;if('string'==typeof a)return;yield a;let b=Object.values(a);Array.isArray(a)&&(b=a);for(const c of b)yield*o(c)}function p(a){const b=[];for(const c of o(a))n(c)&&b.push(c);return b}function q(a){return a&&a[v]}function r(a){if(q(a)){const{port1:b,port2:d}=new MessageChannel;return c(a,b),{type:'PROXY',endpoint:d}}return{type:'OBJECT',obj:a}}const s=Math.floor(Math.random()*Number.MAX_SAFE_INTEGER);let t=0;const u=[ArrayBuffer,MessagePort],v=Symbol('proxyValue'),w='__omg_so_secret';return{proxy:a,proxyValue:b,expose:c}}(); | ||
'use strict';self.Comlink=function(){function a(b){if(j(b)&&(b=d(b)),!e(b))throw Error('endpoint does not have all of addEventListener, removeEventListener and postMessage defined');return f(b),m(async(d)=>{let e=[];('APPLY'===d.type||'CONSTRUCT'===d.type)&&(e=d.argumentsList=d.argumentsList.map((a)=>{if(!q(a))return a;const{port1:b,port2:d}=new MessageChannel;return c(a,b),{[w]:'PROXY',endpoint:d}}));const f=await k(b,d,p(e)),g=f.data;return'PROXY'===g.type?a(g.endpoint):g.obj})}function b(a){return a[v]=!0,a}function c(c,h){if(j(h)&&(h=d(h)),!e(h))throw Error('endpoint does not have all of addEventListener, removeEventListener and postMessage defined');f(h),g(h,async function(d){if(!d.data.id)return;const e=d.data;let f=await e.callPath.slice(0,-1).reduce((a,b)=>a[b],c),g=await e.callPath.reduce((a,b)=>a[b],c);const i='AsyncGeneratorFunction'===g.constructor.name;let j=g;return'argumentsList'in e&&(e.argumentsList=e.argumentsList.map((b)=>{return'PROXY'===b[w]?a(b.endpoint):b})),'APPLY'===e.type&&(j=await g.apply(f,e.argumentsList)),i&&(j=b(j)),'CONSTRUCT'===e.type&&(j=b(new g(...(e.argumentsList||[])))),j=r(j),j.id=e.id,h.postMessage(j,p([j]))})}function d(a){if('Window'!==self.constructor.name)throw Error('self is not a window');return{addEventListener:self.addEventListener.bind(self),removeEventListener:self.removeEventListener.bind(self),postMessage:(b,c)=>a.postMessage(b,'*',c)}}function e(a){return'addEventListener'in a&&'removeEventListener'in a&&'postMessage'in a}function f(a){i(a)&&a.start()}function g(a,b){a.addEventListener('message',b)}function h(a,b){a.removeEventListener('message',b)}function i(a){return'MessagePort'===a.constructor.name}function j(a){return['window','length','location','parent','opener'].every((b)=>b in a)}function k(a,b,c){const d=`${s}-${t++}`;return new Promise((e)=>{g(a,function b(c){c.data.id!==d||(h(a,b),e(c))}),b=Object.assign({},b,{id:d}),a.postMessage(b,c)})}function l(){return'asyncIterator'in Symbol}function m(a){let b=[];return new Proxy(function(){},{construct(c,d){const e=a({type:'CONSTRUCT',callPath:b,argumentsList:d});return b=[],e},apply(c,d,e){if('bind'===b[b.length-1]){const c=b.slice();return b=[],(...b)=>a({type:'APPLY',callPath:c.slice(0,-1),argumentsList:b})}const f=a({type:'APPLY',callPath:b,argumentsList:e});return b=[],f},get(c,d,e){if('then'===d&&0===b.length)return{then:()=>e};if(l()&&d===Symbol.asyncIterator)return()=>e;if('then'===d){const c=a({type:'GET',callPath:b});return b=[],Promise.resolve(c).then.bind(c)}return b.push(d),e}})}function n(a){return u.some((b)=>a instanceof b)}function*o(a){if(!a)return;if('string'==typeof a)return;yield a;let b=Object.values(a);Array.isArray(a)&&(b=a);for(const c of b)yield*o(c)}function p(a){const b=[];for(const c of o(a))n(c)&&b.push(c);return b}function q(a){return a&&a[v]}function r(a){if(q(a)){const{port1:b,port2:d}=new MessageChannel;return c(a,b),{type:'PROXY',endpoint:d}}return{type:'OBJECT',obj:a}}const s=Math.floor(Math.random()*Number.MAX_SAFE_INTEGER);let t=0;const u=[ArrayBuffer,MessagePort],v=Symbol('proxyValue'),w='__omg_so_secret';return{proxy:a,proxyValue:b,expose:c}}(); |
@@ -74,8 +74,12 @@ /** | ||
const irequest = event.data; | ||
let that = await irequest.callPath.slice(0, -1).reduce((obj, propName) => obj[propName], rootObj); | ||
let obj = await irequest.callPath.reduce((obj, propName) => obj[propName], rootObj); | ||
if (irequest.type === 'APPLY' || irequest.type === 'CONSTRUCT') { | ||
const isAsyncGenerator = obj.constructor.name === 'AsyncGeneratorFunction'; | ||
let iresult = obj; | ||
// If there is an arguments list, proxy-fy parameters as necessary | ||
if ('argumentsList' in irequest) { | ||
irequest.argumentsList = | ||
irequest.argumentsList.map(arg => { | ||
if (arg[transferMarker] === 'PROXY') | ||
return exports.Comlink.proxy(arg.endpoint); | ||
return proxy(arg.endpoint); | ||
else | ||
@@ -85,29 +89,11 @@ return arg; | ||
} | ||
switch (irequest.type) { | ||
case 'APPLY': { | ||
irequest.callPath.pop(); | ||
const that = await irequest.callPath.reduce((obj, propName) => obj[propName], rootObj); | ||
const isAsyncGenerator = obj.constructor.name === 'AsyncGeneratorFunction'; | ||
obj = await obj.apply(that, irequest.argumentsList); | ||
// If the function being called is an async generator, proxy the | ||
// result. | ||
if (isAsyncGenerator) | ||
obj = proxyValue(obj); | ||
} // fallthrough! | ||
case 'GET': { | ||
const iresult = makeInvocationResult(obj); | ||
iresult.id = irequest.id; | ||
return endpoint.postMessage(iresult, transferableProperties([iresult])); | ||
} | ||
case 'CONSTRUCT': { | ||
const instance = new obj(...(irequest.argumentsList || [])); // eslint-disable-line new-cap | ||
const { port1, port2 } = new MessageChannel(); | ||
expose(instance, port1); | ||
return endpoint.postMessage({ | ||
id: irequest.id, | ||
type: 'PROXY', | ||
endpoint: port2, | ||
}, [port2]); | ||
} | ||
} | ||
if (irequest.type === 'APPLY') | ||
iresult = await obj.apply(that, irequest.argumentsList); | ||
if (isAsyncGenerator) | ||
iresult = proxyValue(iresult); | ||
if (irequest.type === 'CONSTRUCT') | ||
iresult = proxyValue(new obj(...(irequest.argumentsList || []))); // eslint-disable-line new-cap | ||
iresult = makeInvocationResult(iresult); | ||
iresult.id = irequest.id; | ||
return endpoint.postMessage(iresult, transferableProperties([iresult])); | ||
}); | ||
@@ -114,0 +100,0 @@ } |
@@ -1,1 +0,1 @@ | ||
(function(a){if("object"==typeof module&&"object"==typeof module.exports){var b=a(require,exports);b!==void 0&&(module.exports=b)}else"function"==typeof define&&define.amd&&define(["require","exports"],a)})(function(a,b){"use strict";Object.defineProperty(b,"__esModule",{value:!0}),b.Comlink=function(){function a(b){if(k(b)&&(b=e(b)),!f(b))throw Error("endpoint does not have all of addEventListener, removeEventListener and postMessage defined");return g(b),n(async(c)=>{let e=[];("APPLY"===c.type||"CONSTRUCT"===c.type)&&(e=c.argumentsList=c.argumentsList.map((a)=>{if(!r(a))return a;const{port1:b,port2:c}=new MessageChannel;return d(a,b),{[x]:"PROXY",endpoint:c}}));const f=await l(b,c,q(e)),g=f.data;return"PROXY"===g.type?a(g.endpoint):g.obj})}function c(a){return a[w]=!0,a}function d(a,i){if(k(i)&&(i=e(i)),!f(i))throw Error("endpoint does not have all of addEventListener, removeEventListener and postMessage defined");g(i),h(i,async function(e){if(!e.data.id)return;const f=e.data;let g=await f.callPath.reduce((a,b)=>a[b],a);switch(("APPLY"===f.type||"CONSTRUCT"===f.type)&&(f.argumentsList=f.argumentsList.map((a)=>{return"PROXY"===a[x]?b.Comlink.proxy(a.endpoint):a})),f.type){case"APPLY":{f.callPath.pop();const b=await f.callPath.reduce((a,b)=>a[b],a),d="AsyncGeneratorFunction"===g.constructor.name;g=await g.apply(b,f.argumentsList),d&&(g=c(g))}case"GET":{const a=s(g);return a.id=f.id,i.postMessage(a,q([a]))}case"CONSTRUCT":{const a=new g(...(f.argumentsList||[])),{port1:b,port2:c}=new MessageChannel;return d(a,b),i.postMessage({id:f.id,type:"PROXY",endpoint:c},[c])}}})}function e(a){if("Window"!==self.constructor.name)throw Error("self is not a window");return{addEventListener:self.addEventListener.bind(self),removeEventListener:self.removeEventListener.bind(self),postMessage:(b,c)=>a.postMessage(b,"*",c)}}function f(a){return"addEventListener"in a&&"removeEventListener"in a&&"postMessage"in a}function g(a){j(a)&&a.start()}function h(a,b){a.addEventListener("message",b)}function i(a,b){a.removeEventListener("message",b)}function j(a){return"MessagePort"===a.constructor.name}function k(a){return["window","length","location","parent","opener"].every((b)=>b in a)}function l(a,b,c){const d=`${t}-${u++}`;return new Promise((e)=>{h(a,function b(c){c.data.id!==d||(i(a,b),e(c))}),b=Object.assign({},b,{id:d}),a.postMessage(b,c)})}function m(){return"asyncIterator"in Symbol}function n(a){let b=[];return new Proxy(function(){},{construct(c,d){const e=a({type:"CONSTRUCT",callPath:b,argumentsList:d});return b=[],e},apply(c,d,e){if("bind"===b[b.length-1]){const c=b.slice();return b=[],(...b)=>a({type:"APPLY",callPath:c.slice(0,-1),argumentsList:b})}const f=a({type:"APPLY",callPath:b,argumentsList:e});return b=[],f},get(c,d,e){if("then"===d&&0===b.length)return{then:()=>e};if(m()&&d===Symbol.asyncIterator)return()=>e;if("then"===d){const c=a({type:"GET",callPath:b});return b=[],Promise.resolve(c).then.bind(c)}return b.push(d),e}})}function o(a){return v.some((b)=>a instanceof b)}function*p(a){if(!a)return;if("string"==typeof a)return;yield a;let b=Object.values(a);Array.isArray(a)&&(b=a);for(const c of b)yield*p(c)}function q(a){const b=[];for(const c of p(a))o(c)&&b.push(c);return b}function r(a){return a&&a[w]}function s(a){if(r(a)){const{port1:b,port2:c}=new MessageChannel;return d(a,b),{type:"PROXY",endpoint:c}}return{type:"OBJECT",obj:a}}const t=Math.floor(Math.random()*Number.MAX_SAFE_INTEGER);let u=0;const v=[ArrayBuffer,MessagePort],w=Symbol("proxyValue"),x="__omg_so_secret";return{proxy:a,proxyValue:c,expose:d}}()}); | ||
(function(a){if("object"==typeof module&&"object"==typeof module.exports){var b=a(require,exports);b!==void 0&&(module.exports=b)}else"function"==typeof define&&define.amd&&define(["require","exports"],a)})(function(a,b){"use strict";Object.defineProperty(b,"__esModule",{value:!0}),b.Comlink=function(){function a(b){if(j(b)&&(b=d(b)),!e(b))throw Error("endpoint does not have all of addEventListener, removeEventListener and postMessage defined");return f(b),m(async(d)=>{let e=[];("APPLY"===d.type||"CONSTRUCT"===d.type)&&(e=d.argumentsList=d.argumentsList.map((a)=>{if(!q(a))return a;const{port1:b,port2:d}=new MessageChannel;return c(a,b),{[w]:"PROXY",endpoint:d}}));const f=await k(b,d,p(e)),g=f.data;return"PROXY"===g.type?a(g.endpoint):g.obj})}function b(a){return a[v]=!0,a}function c(c,h){if(j(h)&&(h=d(h)),!e(h))throw Error("endpoint does not have all of addEventListener, removeEventListener and postMessage defined");f(h),g(h,async function(d){if(!d.data.id)return;const e=d.data;let f=await e.callPath.slice(0,-1).reduce((a,b)=>a[b],c),g=await e.callPath.reduce((a,b)=>a[b],c);const i="AsyncGeneratorFunction"===g.constructor.name;let j=g;return"argumentsList"in e&&(e.argumentsList=e.argumentsList.map((b)=>{return"PROXY"===b[w]?a(b.endpoint):b})),"APPLY"===e.type&&(j=await g.apply(f,e.argumentsList)),i&&(j=b(j)),"CONSTRUCT"===e.type&&(j=b(new g(...(e.argumentsList||[])))),j=r(j),j.id=e.id,h.postMessage(j,p([j]))})}function d(a){if("Window"!==self.constructor.name)throw Error("self is not a window");return{addEventListener:self.addEventListener.bind(self),removeEventListener:self.removeEventListener.bind(self),postMessage:(b,c)=>a.postMessage(b,"*",c)}}function e(a){return"addEventListener"in a&&"removeEventListener"in a&&"postMessage"in a}function f(a){i(a)&&a.start()}function g(a,b){a.addEventListener("message",b)}function h(a,b){a.removeEventListener("message",b)}function i(a){return"MessagePort"===a.constructor.name}function j(a){return["window","length","location","parent","opener"].every((b)=>b in a)}function k(a,b,c){const d=`${s}-${t++}`;return new Promise((e)=>{g(a,function b(c){c.data.id!==d||(h(a,b),e(c))}),b=Object.assign({},b,{id:d}),a.postMessage(b,c)})}function l(){return"asyncIterator"in Symbol}function m(a){let b=[];return new Proxy(function(){},{construct(c,d){const e=a({type:"CONSTRUCT",callPath:b,argumentsList:d});return b=[],e},apply(c,d,e){if("bind"===b[b.length-1]){const c=b.slice();return b=[],(...b)=>a({type:"APPLY",callPath:c.slice(0,-1),argumentsList:b})}const f=a({type:"APPLY",callPath:b,argumentsList:e});return b=[],f},get(c,d,e){if("then"===d&&0===b.length)return{then:()=>e};if(l()&&d===Symbol.asyncIterator)return()=>e;if("then"===d){const c=a({type:"GET",callPath:b});return b=[],Promise.resolve(c).then.bind(c)}return b.push(d),e}})}function n(a){return u.some((b)=>a instanceof b)}function*o(a){if(!a)return;if("string"==typeof a)return;yield a;let b=Object.values(a);Array.isArray(a)&&(b=a);for(const c of b)yield*o(c)}function p(a){const b=[];for(const c of o(a))n(c)&&b.push(c);return b}function q(a){return a&&a[v]}function r(a){if(q(a)){const{port1:b,port2:d}=new MessageChannel;return c(a,b),{type:"PROXY",endpoint:d}}return{type:"OBJECT",obj:a}}const s=Math.floor(Math.random()*Number.MAX_SAFE_INTEGER);let t=0;const u=[ArrayBuffer,MessagePort],v=Symbol("proxyValue"),w="__omg_so_secret";return{proxy:a,proxyValue:b,expose:c}}()}); |
{ | ||
"name": "comlinkjs", | ||
"version": "2.1.0", | ||
"version": "2.2.0", | ||
"description": "", | ||
@@ -11,10 +11,11 @@ "main": "comlink.umd.js", | ||
"unittest": "karma start", | ||
"linter": "eslint comlink.ts", | ||
"linter": "eslint comlink.ts && eslint messagechanneladapter.ts", | ||
"watchtest": "karma start --no-single-run --browsers ChromeHeadless", | ||
"watchtestharmony": "karma start --no-single-run --browsers ChromeCanaryHeadlessHarmony", | ||
"version": "sed -i .bak -E 's!comlinkjs@[0-9.]+!comlinkjs@'${npm_package_version}'!' README.md && git add README.md", | ||
"mypublish": "npm run build && npm run test && cp README.md package.json dist && npm publish dist", | ||
"build": "rm -rf dist && mkdir dist && npm run compile && npm run mangle_global && npm run minify", | ||
"compile": "tsc --outDir dist -m none && mv dist/comlink.{,global.}js && tsc --outDir dist -m es2015 && mv dist/comlink.{,es6.}js && tsc -d --outDir dist -m umd && mv dist/comlink.{,umd.}js", | ||
"mangle_global": "sed -i .bak 's!exports.Comlink!self.Comlink!' dist/comlink.global.js && sed -i .bak 's!^.*\"__esModule\".*$!!' dist/comlink.global.js", | ||
"minify": "babili -o dist/comlink.global.{min.,}js && babili -o dist/comlink.es6.{min.,}js && babili -o dist/comlink.umd.{min.,}js" | ||
"compile": "tsc --outDir dist -m none && mv dist/comlink.{,global.}js && mv dist/messagechanneladapter.{,global.}js && tsc --outDir dist -m es2015 && mv dist/comlink.{,es6.}js && mv dist/messagechanneladapter.{,es6.}js && tsc -d --outDir dist -m umd && mv dist/comlink.{,umd.}js && mv dist/messagechanneladapter.{,umd.}js", | ||
"mangle_global": "sed -i .bak 's!exports.Comlink!self.Comlink!' dist/comlink.global.js && sed -i .bak 's!^.*\"__esModule\".*$!!' dist/comlink.global.js && sed -i .bak 's!exports.MessageChannelAdapter!self.MessageChannelAdapter!' dist/messagechanneladapter.global.js && sed -i .bak 's!^.*\"__esModule\".*$!!' dist/messagechanneladapter.global.js", | ||
"minify": "babili -o dist/comlink.global.{min.,}js && babili -o dist/comlink.es6.{min.,}js && babili -o dist/comlink.umd.{min.,}js && babili -o dist/messagechanneladapter.global.{min.,}js && babili -o dist/messagechanneladapter.es6.{min.,}js && babili -o dist/messagechanneladapter.umd.{min.,}js" | ||
}, | ||
@@ -49,3 +50,3 @@ "keywords": [], | ||
"karma-safari-launcher": "1.0.0", | ||
"karma-typescript": "3.0.6", | ||
"karma-typescript": "3.0.7", | ||
"mocha": "3.5.3", | ||
@@ -52,0 +53,0 @@ "postcss": "6.0.12", |
@@ -5,6 +5,13 @@ # Comlink | ||
**TL;DR: With Comlink you can work on objects from another JavaScript realm | ||
(like a Worker or an iframe) as if it was a local object. Just use `await` | ||
**With Comlink you can work on values from another JavaScript realm | ||
(like a Worker or an iframe) as if it was a local value. Just use `await` | ||
whenever using the remote value.** | ||
Anything that works with `postMessage` can be used as a communication channel. | ||
## Usage | ||
You can download Comlink from the [dist folder][dist]. Alternatively, you can | ||
install it via npm | ||
``` | ||
@@ -14,9 +21,8 @@ $ npm install --save comlinkjs | ||
Comlink allows you to expose an arbitrary JavaScript value (objects, classes, | ||
functions, etc) to the endpoint of an communications channel. Anything that | ||
works with `postMessage` can be used as a communication channel. On the other | ||
end of that channel you can use Comlink to synthesize an ES6 proxy. Every action | ||
performed on that proxy object will be serialized using a simple (and naïve) RPC | ||
protocol and be applied to the exposed value on the other side. | ||
or use a CDN like [delivrjs]: | ||
``` | ||
https://cdn.jsdelivr.net/npm/comlinkjs@2.2.0/comlink.es6.min.js | ||
``` | ||
**Size**: ~3.1k, ~1.3k gzip’d. | ||
@@ -26,2 +32,4 @@ | ||
There’s more examples in the [examples directory][examples]. | ||
```html | ||
@@ -70,2 +78,25 @@ <-- index.html --> | ||
## Module formats | ||
The Comlink module is provided in 3 different formats: | ||
* **“es6”**: This package uses the native ES6 module format. Due to some | ||
necessary hackery, the module exports a `Comlink` object. Import it as | ||
follows: | ||
```js | ||
import {Comlink} from '../dist/comlink.es6.js'; | ||
// ... | ||
``` | ||
* **“global”**: This package adds a `Comlink` namespace on `self`. Useful for | ||
workers or projects without a module loader. | ||
* **“umd”**: This package uses [UMD] so it is compatible with AMD, CommonJS | ||
and requireJS. | ||
These packages can be mixed and matched. A worker using `global` can be | ||
connected to a window using `es6`. For the sake of network conservation, I do | ||
recommend sticking to one format, though. | ||
## API | ||
@@ -82,5 +113,6 @@ | ||
Note that as of now all parameters for function or method invocations will be | ||
structurally cloned or transferred if they are [transferable]. As a result, | ||
callback functions are currently not supported as parameter values. | ||
Note that all parameters for a function or method invocations will be | ||
structurally cloned or transferred if they are [transferable]. If you want to | ||
pass use functions as parameters (e.g. callbacks), make sure to wrap them with | ||
`proxyValue` (see below). | ||
@@ -100,5 +132,5 @@ *) Technically it can be any object with `postMessage`, `addEventListener` and | ||
If structurally cloning a value is undesired (either for a function parameter or | ||
its return value), wrapping the value in a `proxyValue` call proxy that value | ||
instead. This is necessary for callback functions being passed around or for the | ||
Singleton pattern: | ||
a function’s return value), wrapping the value in a `proxyValue` call will proxy | ||
that value instead. This is necessary for callback functions being passed | ||
around: | ||
@@ -121,24 +153,20 @@ ```js | ||
## Module formats | ||
# MessageChannelAdapter | ||
The Comlink module is provided in 3 different formats: | ||
`MessageChannelAdapter` is a small utility function that turns string-based | ||
communication channels – like a [WebSocket], [RTCDataChannel] or | ||
[PresentationConnection] – into a Comlink-compatible `postMessage`-based API | ||
that can transfer `MessagePorts`. | ||
* **“es6”**: This package uses the native ES6 module format. Due to some | ||
necessary hackery, the module exports a `Comlink` object. Import it as | ||
follows: | ||
## Usage | ||
```js | ||
import {Comlink} from '../dist/comlink.es6.js'; | ||
See the [examples], specifically WebRTC and Presentation API. | ||
// ... | ||
``` | ||
## API | ||
* **“global”**: This package adds a `Comlink` namespace on `self`. Useful for | ||
workers or projects without a module loader. | ||
* **“umd”**: This package uses [UMD] so it is compatible with AMD, CommonJS | ||
and requireJS. | ||
### `MessageChannelAdapter.wrap(endpoint)` | ||
These packages can be mixed and matched. A worker using `global` can be | ||
connected to a window using `es6`. For the sake of network conservation, I do | ||
recommend sticking to one format, though. | ||
`wrap` returns a `MessagePort` that serializes messages using `JSON.stringify` | ||
and handles transferred `MessagePort`s automatically. `endpoint` is expected to | ||
have `send` and `addEventListener`. | ||
@@ -148,4 +176,10 @@ [UMD]: https://github.com/umdjs/umd | ||
[MessagePort]: https://developer.mozilla.org/en-US/docs/Web/API/MessagePort | ||
[examples]: https://github.com/GoogleChromeLabs/comlink/tree/master/docs/examples | ||
[dist]: https://github.com/GoogleChromeLabs/comlink/tree/master/dist | ||
[delivrjs]: https://cdn.jsdelivr.net/ | ||
[WebSocket]: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket | ||
[RTCDataChannel]: https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel | ||
[PresentationConnection]: https://developer.mozilla.org/en-US/docs/Web/API/PresentationConnection | ||
--- | ||
License Apache-2.0 |
Sorry, the diff of this file is not supported yet
79977
18
1140
178