Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

troika-worker-utils

Package Overview
Dependencies
Maintainers
1
Versions
48
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

troika-worker-utils - npm Package Compare versions

Comparing version 0.22.0 to 0.23.0

__tests__/_jsdom-worker.js

6

__tests__/ThenableWorkerModule.test.js
import {defineWorkerModule} from '../src/WorkerModules.js'
import ThenableWorkerModule from '../src/ThenableWorkerModule.js'
require('./_jsdom-worker.js')
// Sometimes URL.$$objects hangs around between suites which prevents jsdom-worker
// from attaching its custom `fetch` override that knows how to read fake blob URLs
delete global.URL.$$objects
require('jsdom-worker')
beforeEach(() => {

@@ -11,0 +7,0 @@ // Functions that are run in the worker can place breadcrumbs in this object that

import {defineWorkerModule} from '../src/WorkerModules.js'
require('./_jsdom-worker.js')
// Sometimes URL.$$objects hangs around between suites which prevents jsdom-worker
// from attaching its custom `fetch` override that knows how to read fake blob URLs
delete global.URL.$$objects
require('jsdom-worker')
beforeEach(() => {

@@ -10,0 +5,0 @@ // Functions that are run in the worker can place breadcrumbs in this object that

@@ -6,2 +6,13 @@ # Change Log

# [0.23.0](https://github.com/protectwise/troika/compare/v0.22.0...v0.23.0) (2020-04-16)
### Features
* **troika-worker-modules:** improve rehydration of functions in worker ([8f63090](https://github.com/protectwise/troika/commit/8f63090a5ad4fa3569faeade8e5c532ebfb065c5)), closes [#31](https://github.com/protectwise/troika/issues/31)
# [0.22.0](https://github.com/protectwise/troika/compare/v0.21.0...v0.22.0) (2020-04-02)

@@ -8,0 +19,0 @@

@@ -179,3 +179,3 @@ /**

// Handle messages for registering a module
function registerModule({id, dependencies=[], init=function(){}, getTransferables=null}, callback) {
function registerModule({id, name, dependencies=[], init=function(){}, getTransferables=null}, callback) {
// Only register once

@@ -197,9 +197,14 @@ if (modules[id]) return

// Rehydrate functions
init = new Function(`return (${init})`)();
init = rehydrate(`<${name}>.init`, init);
if (getTransferables) {
getTransferables = new Function(`return (${getTransferables})`)();
getTransferables = rehydrate(`<${name}>.getTransferables`, getTransferables);
}
// Initialize the module and store its value
const value = init(...dependencies);
let value = null;
if (typeof init === 'function') {
value = init(...dependencies);
} else {
console.error('worker module init function failed to rehydrate');
}
modules[id] = {

@@ -248,2 +253,21 @@ id,

function rehydrate(name, str) {
let result = void 0;
self.troikaDefine = r => result = r;
let url = URL.createObjectURL(
new Blob(
[`/** ${name.replace(/\*/g, '')} **/\n\ntroikaDefine(\n${str}\n)`],
{type: 'application/javascript'}
)
);
try {
importScripts(url);
} catch(err) {
console.error(err);
}
URL.revokeObjectURL(url);
delete self.troikaDefine;
return result
}
// Handler for all messages within the worker

@@ -301,2 +325,3 @@ self.addEventListener('message', e => {

let _messageId = 0;
let _allowInitAsString = false;
const workers = Object.create(null);

@@ -330,2 +355,4 @@ const openRequests = Object.create(null);

* in the response that can/should be transfered rather than cloned.
* @param {string} [options.name] - A descriptive name for this module; this can be useful for
* debugging but is not currently used for anything else.
* @param {string} [options.workerId] - By default all modules will run in the same dedicated worker,

@@ -339,3 +366,3 @@ * but if you want to use multiple workers you can pass a `workerId` to indicate a specific

function defineWorkerModule(options) {
if (!options || typeof options.init !== 'function') {
if ((!options || typeof options.init !== 'function') && !_allowInitAsString) {
throw new Error('requires `options.init` function')

@@ -348,2 +375,3 @@ }

const id = `workerModule${++_workerModuleId}`;
const name = options.name || id;
let registrationThenable = null;

@@ -354,6 +382,9 @@

if (typeof dep === 'function' && !dep.workerModuleData) {
_allowInitAsString = true;
dep = defineWorkerModule({
workerId,
init: new Function(`return function(){return (${stringifyFunction(dep)})}`)()
name: `<${name}> function dependency: ${dep.name}`,
init: `function(){return (\n${stringifyFunction(dep)}\n)}`
});
_allowInitAsString = false;
}

@@ -385,2 +416,3 @@ // Grab postable data for worker modules

id,
name,
dependencies,

@@ -416,3 +448,6 @@ init: stringifyFunction(init),

URL.createObjectURL(
new Blob([`;(${bootstrap})()`], {type: 'application/javascript'})
new Blob(
[`/** Worker Module Bootstrap: ${workerId.replace(/\*/g, '')} **/\n\n;(${bootstrap})()`],
{type: 'application/javascript'}
)
)

@@ -466,2 +501,3 @@ );

var ThenableWorkerModule = defineWorkerModule({
name: 'Thenable',
dependencies: [Thenable],

@@ -468,0 +504,0 @@ init: function(Thenable) {

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

var id = ref.id;
var name = ref.name;
var dependencies = ref.dependencies; if ( dependencies === void 0 ) dependencies = [];

@@ -211,9 +212,14 @@ var init = ref.init; if ( init === void 0 ) init = function(){};

// Rehydrate functions
init = new Function(("return (" + init + ")"))();
init = rehydrate(("<" + name + ">.init"), init);
if (getTransferables) {
getTransferables = new Function(("return (" + getTransferables + ")"))();
getTransferables = rehydrate(("<" + name + ">.getTransferables"), getTransferables);
}
// Initialize the module and store its value
var value = init.apply(void 0, dependencies);
var value = null;
if (typeof init === 'function') {
value = init.apply(void 0, dependencies);
} else {
console.error('worker module init function failed to rehydrate');
}
modules[id] = {

@@ -266,2 +272,21 @@ id: id,

function rehydrate(name, str) {
var result = void 0;
self.troikaDefine = function (r) { return result = r; };
var url = URL.createObjectURL(
new Blob(
[("/** " + (name.replace(/\*/g, '')) + " **/\n\ntroikaDefine(\n" + str + "\n)")],
{type: 'application/javascript'}
)
);
try {
importScripts(url);
} catch(err) {
console.error(err);
}
URL.revokeObjectURL(url);
delete self.troikaDefine;
return result
}
// Handler for all messages within the worker

@@ -322,2 +347,3 @@ self.addEventListener('message', function (e) {

var _messageId = 0;
var _allowInitAsString = false;
var workers = Object.create(null);

@@ -351,2 +377,4 @@ var openRequests = Object.create(null);

* in the response that can/should be transfered rather than cloned.
* @param {string} [options.name] - A descriptive name for this module; this can be useful for
* debugging but is not currently used for anything else.
* @param {string} [options.workerId] - By default all modules will run in the same dedicated worker,

@@ -360,3 +388,3 @@ * but if you want to use multiple workers you can pass a `workerId` to indicate a specific

function defineWorkerModule(options) {
if (!options || typeof options.init !== 'function') {
if ((!options || typeof options.init !== 'function') && !_allowInitAsString) {
throw new Error('requires `options.init` function')

@@ -372,2 +400,3 @@ }

var id = "workerModule" + (++_workerModuleId);
var name = options.name || id;
var registrationThenable = null;

@@ -378,6 +407,9 @@

if (typeof dep === 'function' && !dep.workerModuleData) {
_allowInitAsString = true;
dep = defineWorkerModule({
workerId: workerId,
init: new Function(("return function(){return (" + (stringifyFunction(dep)) + ")}"))()
name: ("<" + name + "> function dependency: " + (dep.name)),
init: ("function(){return (\n" + (stringifyFunction(dep)) + "\n)}")
});
_allowInitAsString = false;
}

@@ -414,2 +446,3 @@ // Grab postable data for worker modules

id: id,
name: name,
dependencies: dependencies,

@@ -445,3 +478,6 @@ init: stringifyFunction(init),

URL.createObjectURL(
new Blob([(";(" + bootstrap + ")()")], {type: 'application/javascript'})
new Blob(
[("/** Worker Module Bootstrap: " + (workerId.replace(/\*/g, '')) + " **/\n\n;(" + bootstrap + ")()")],
{type: 'application/javascript'}
)
)

@@ -495,2 +531,3 @@ );

var ThenableWorkerModule = defineWorkerModule({
name: 'Thenable',
dependencies: [Thenable],

@@ -497,0 +534,0 @@ init: function(Thenable) {

@@ -1,9 +0,10 @@

'use strict';(function(l,q){"object"===typeof exports&&"undefined"!==typeof module?q(exports):"function"===typeof define&&define.amd?define(["exports"],q):(l=l||self,q(l.troika_worker_utils={}))})(this,function(l){function q(){function c(b,e){u++;var t=0;try{e===r&&h();var l=0<b&&a(e);l?l.call(e,f(function(a){t++;c(1,a)}),f(function(a){t++;c(-1,a)})):(k=b,p=e,g||(setTimeout(d,0),g=1))}catch(z){k||t||c(-1,z)}}function d(){var a=e;g=0;e=[];a.forEach(b)}function b(a){a()}function a(a){a=a&&(m(a)||"object"===
typeof a)&&a.then;return m(a)&&a}function f(a){var c=0;return function(){for(var f=[],g=arguments.length;g--;)f[g]=arguments[g];c++||a.apply(this,f)}}function h(){throw new TypeError("Chaining cycle detected");}var k=0,e=[],p,g=0,u=0,l=f(function(a){u||c(1,a)}),n=f(function(a){u||c(-1,a)}),m=function(a){return"function"===typeof a},r={then:function(c,f){var b=q();e.push(function(){var g=0<k?c:f;if(m(g))try{var e=g(p);e===b&&h();var d=a(e);d?d.call(e,b.resolve,b.reject):b.resolve(e)}catch(A){b.reject(A)}else b[0<
k?"resolve":"reject"](p)});k&&!g&&(setTimeout(d,0),g=1);return b},resolve:l,reject:n};return r}function B(){var c,d,b=new Promise(function(a,b){c=a;d=b});return{then:b.then.bind(b),resolve:c,reject:d}}function C(){function c(a,f){var h=a.id,k=a.dependencies;void 0===k&&(k=[]);var e=a.init;void 0===e&&(e=function(){});a=a.getTransferables;void 0===a&&(a=null);if(!b[h])try{k=k.map(function(a){a&&a.isWorkerModule&&(c(a,function(a){if(a instanceof Error)throw a;}),a=b[a.id].value);return a});e=(new Function("return ("+
e+")"))();a&&(a=(new Function("return ("+a+")"))());var d=e.apply(void 0,k);b[h]={id:h,value:d,getTransferables:a};f(d)}catch(g){g&&g.noLog||console.error(g),f(g)}}function d(a,c){function f(a){try{var f=b[e].getTransferables&&b[e].getTransferables(a);f&&Array.isArray(f)&&f.length||(f=void 0);c(a,f)}catch(w){console.error(w),c(w)}}var d,e=a.id;a=a.args;b[e]&&"function"===typeof b[e].value||c(Error("Worker module "+e+": not found or its 'init' did not return a function"));try{var p=(d=b[e]).value.apply(d,
a);p&&"function"===typeof p.then?p.then(f,function(a){return c(a instanceof Error?a:Error(""+a))}):f(p)}catch(g){c(g)}}var b=Object.create(null);self.addEventListener("message",function(a){var b=a.data,h=b.messageId;a=b.action;b=b.data;try{"registerModule"===a&&c(b,function(a){a instanceof Error?postMessage({messageId:h,success:!1,error:a.message}):postMessage({messageId:h,success:!0,result:{isCallable:"function"===typeof a}})}),"callModule"===a&&d(b,function(a,b){a instanceof Error?postMessage({messageId:h,
success:!1,error:a.message}):postMessage({messageId:h,success:!0,result:a},b||void 0)})}catch(k){postMessage({messageId:h,success:!1,error:k.stack})}})}function r(c){function d(){for(var a=[],b=arguments.length;b--;)a[b]=arguments[b];e||(e=x(h,"registerModule",d.workerModuleData));return e.then(function(b){if(b.isCallable)return x(h,"callModule",{id:k,args:a});throw Error("Worker module function was called but `init` did not return a callable function");})}if(!c||"function"!==typeof c.init)throw Error("requires `options.init` function");
var b=c.dependencies,a=c.init,f=c.getTransferables,h=c.workerId;null==h&&(h="#default");var k="workerModule"+ ++D,e=null;b=b&&b.map(function(a){"function"!==typeof a||a.workerModuleData||(a=r({workerId:h,init:(new Function("return function(){return ("+m(a)+")}"))()}));a&&a.workerModuleData&&(a=a.workerModuleData);return a});d.workerModuleData={isWorkerModule:!0,id:k,dependencies:b,init:m(a),getTransferables:f&&m(f)};return d}function m(c){c=c.toString();!/^function/.test(c)&&/^\w+\s*\(/.test(c)&&
(c="function "+c);return c}function E(c){var d=y[c];d||(d=m(C),d=y[c]=new Worker(URL.createObjectURL(new Blob([";("+d+")()"],{type:"application/javascript"}))),d.onmessage=function(b){b=b.data;var a=b.messageId,c=n[a];if(!c)throw Error("WorkerModule response with empty or unknown messageId");delete n[a];n.count--;c(b)});return d}function x(c,d,b){var a=v(),f=++F;n[f]=function(b){b.success?a.resolve(b.result):a.reject(Error("Error in worker "+d+" call: "+b.error))};n._count++;1E3<n.count&&console.warn("Large number of open WorkerModule requests, some may not be returning");
E(c).postMessage({messageId:f,action:d,data:b});return a}var v="function"===typeof Promise?B:q,D=0,F=0,y=Object.create(null),n=Object.create(null);n._count=0;var G=r({dependencies:[v],init:function(c){return c}});l.Thenable=v;l.ThenableWorkerModule=G;l.defineWorkerModule=r;l.stringifyFunction=m;Object.defineProperty(l,"__esModule",{value:!0})})
'use strict';(function(n,r){"object"===typeof exports&&"undefined"!==typeof module?r(exports):"function"===typeof define&&define.amd?define(["exports"],r):(n=n||self,r(n.troika_worker_utils={}))})(this,function(n){function r(){function b(e,c){h++;var u=0;try{c===q&&k();var t=0<e&&f(c);t?t.call(c,a(function(a){u++;b(1,a)}),a(function(a){u++;b(-1,a)})):(l=e,m=c,d||(setTimeout(g,0),d=1))}catch(B){l||u||b(-1,B)}}function g(){var a=e;d=0;e=[];a.forEach(c)}function c(a){a()}function f(a){a=a&&(p(a)||"object"===
typeof a)&&a.then;return p(a)&&a}function a(a){var b=0;return function(){for(var e=[],d=arguments.length;d--;)e[d]=arguments[d];b++||a.apply(this,e)}}function k(){throw new TypeError("Chaining cycle detected");}var l=0,e=[],m,d=0,h=0,t=a(function(a){h||b(1,a)}),n=a(function(a){h||b(-1,a)}),p=function(a){return"function"===typeof a},q={then:function(a,b){var h=r();e.push(function(){var e=0<l?a:b;if(p(e))try{var d=e(m);d===h&&k();var c=f(d);c?c.call(d,h.resolve,h.reject):h.resolve(d)}catch(C){h.reject(C)}else h[0<
l?"resolve":"reject"](m)});l&&!d&&(setTimeout(g,0),d=1);return h},resolve:t,reject:n};return q}function D(){var b,g,c=new Promise(function(c,a){b=c;g=a});return{then:c.then.bind(c),resolve:b,reject:g}}function E(){function b(a,k){var l=a.id,e=a.name,m=a.dependencies;void 0===m&&(m=[]);var d=a.init;void 0===d&&(d=function(){});a=a.getTransferables;void 0===a&&(a=null);if(!f[l])try{m=m.map(function(a){a&&a.isWorkerModule&&(b(a,function(a){if(a instanceof Error)throw a;}),a=f[a.id].value);return a}),
d=c("<"+e+">.init",d),a&&(a=c("<"+e+">.getTransferables",a)),e=null,"function"===typeof d?e=d.apply(void 0,m):console.error("worker module init function failed to rehydrate"),f[l]={id:l,value:e,getTransferables:a},k(e)}catch(h){h&&h.noLog||console.error(h),k(h)}}function g(a,b){function c(a){try{var d=f[k].getTransferables&&f[k].getTransferables(a);d&&Array.isArray(d)&&d.length||(d=void 0);b(a,d)}catch(y){console.error(y),b(y)}}var e,k=a.id;a=a.args;f[k]&&"function"===typeof f[k].value||b(Error("Worker module "+
k+": not found or its 'init' did not return a function"));try{var d=(e=f[k]).value.apply(e,a);d&&"function"===typeof d.then?d.then(c,function(a){return b(a instanceof Error?a:Error(""+a))}):c(d)}catch(h){b(h)}}function c(a,b){var c=void 0;self.troikaDefine=function(a){return c=a};a=URL.createObjectURL(new Blob(["/** "+a.replace(/\*/g,"")+" **/\n\ntroikaDefine(\n"+b+"\n)"],{type:"application/javascript"}));try{importScripts(a)}catch(e){console.error(e)}URL.revokeObjectURL(a);delete self.troikaDefine;
return c}var f=Object.create(null);self.addEventListener("message",function(a){var c=a.data,f=c.messageId;a=c.action;c=c.data;try{"registerModule"===a&&b(c,function(a){a instanceof Error?postMessage({messageId:f,success:!1,error:a.message}):postMessage({messageId:f,success:!0,result:{isCallable:"function"===typeof a}})}),"callModule"===a&&g(c,function(a,b){a instanceof Error?postMessage({messageId:f,success:!1,error:a.message}):postMessage({messageId:f,success:!0,result:a},b||void 0)})}catch(e){postMessage({messageId:f,
success:!1,error:e.stack})}})}function v(b){function g(){for(var a=[],b=arguments.length;b--;)a[b]=arguments[b];m||(m=z(k,"registerModule",g.workerModuleData));return m.then(function(b){if(b.isCallable)return z(k,"callModule",{id:l,args:a});throw Error("Worker module function was called but `init` did not return a callable function");})}if(!(b&&"function"===typeof b.init||w))throw Error("requires `options.init` function");var c=b.dependencies,f=b.init,a=b.getTransferables,k=b.workerId;null==k&&(k=
"#default");var l="workerModule"+ ++F,e=b.name||l,m=null;c=c&&c.map(function(a){"function"!==typeof a||a.workerModuleData||(w=!0,a=v({workerId:k,name:"<"+e+"> function dependency: "+a.name,init:"function(){return (\n"+q(a)+"\n)}"}),w=!1);a&&a.workerModuleData&&(a=a.workerModuleData);return a});g.workerModuleData={isWorkerModule:!0,id:l,name:e,dependencies:c,init:q(f),getTransferables:a&&q(a)};return g}function q(b){b=b.toString();!/^function/.test(b)&&/^\w+\s*\(/.test(b)&&(b="function "+b);return b}
function G(b){var g=A[b];g||(g=q(E),g=A[b]=new Worker(URL.createObjectURL(new Blob(["/** Worker Module Bootstrap: "+b.replace(/\*/g,"")+" **/\n\n;("+g+")()"],{type:"application/javascript"}))),g.onmessage=function(b){b=b.data;var c=b.messageId,a=p[c];if(!a)throw Error("WorkerModule response with empty or unknown messageId");delete p[c];p.count--;a(b)});return g}function z(b,g,c){var f=x(),a=++H;p[a]=function(a){a.success?f.resolve(a.result):f.reject(Error("Error in worker "+g+" call: "+a.error))};
p._count++;1E3<p.count&&console.warn("Large number of open WorkerModule requests, some may not be returning");G(b).postMessage({messageId:a,action:g,data:c});return f}var x="function"===typeof Promise?D:r,F=0,H=0,w=!1,A=Object.create(null),p=Object.create(null);p._count=0;var I=v({name:"Thenable",dependencies:[x],init:function(b){return b}});n.Thenable=x;n.ThenableWorkerModule=I;n.defineWorkerModule=v;n.stringifyFunction=q;Object.defineProperty(n,"__esModule",{value:!0})})
{
"name": "troika-worker-utils",
"version": "0.22.0",
"version": "0.23.0",
"description": "Utilities for executing code in Web Workers",

@@ -17,3 +17,3 @@ "author": "Jason Johnston <jason.johnston@protectwise.com>",

"module:src": "src/index.js",
"gitHead": "c3ff4002b468f00bc7c4775578e0ad9d950ff52d"
"gitHead": "c58983745861fe3fc4a5ec15a24addce603061c9"
}

@@ -10,2 +10,3 @@ import Thenable from './Thenable.js'

export default defineWorkerModule({
name: 'Thenable',
dependencies: [Thenable],

@@ -12,0 +13,0 @@ init: function(Thenable) {

@@ -9,3 +9,3 @@ /**

// Handle messages for registering a module
function registerModule({id, dependencies=[], init=function(){}, getTransferables=null}, callback) {
function registerModule({id, name, dependencies=[], init=function(){}, getTransferables=null}, callback) {
// Only register once

@@ -27,9 +27,14 @@ if (modules[id]) return

// Rehydrate functions
init = new Function(`return (${init})`)()
init = rehydrate(`<${name}>.init`, init)
if (getTransferables) {
getTransferables = new Function(`return (${getTransferables})`)()
getTransferables = rehydrate(`<${name}>.getTransferables`, getTransferables)
}
// Initialize the module and store its value
const value = init(...dependencies)
let value = null
if (typeof init === 'function') {
value = init(...dependencies)
} else {
console.error('worker module init function failed to rehydrate')
}
modules[id] = {

@@ -78,2 +83,21 @@ id,

function rehydrate(name, str) {
let result = void 0
self.troikaDefine = r => result = r
let url = URL.createObjectURL(
new Blob(
[`/** ${name.replace(/\*/g, '')} **/\n\ntroikaDefine(\n${str}\n)`],
{type: 'application/javascript'}
)
)
try {
importScripts(url)
} catch(err) {
console.error(err)
}
URL.revokeObjectURL(url)
delete self.troikaDefine
return result
}
// Handler for all messages within the worker

@@ -80,0 +104,0 @@ self.addEventListener('message', e => {

@@ -6,2 +6,3 @@ import Thenable from './Thenable.js'

let _messageId = 0
let _allowInitAsString = false
const workers = Object.create(null)

@@ -35,2 +36,4 @@ const openRequests = Object.create(null)

* in the response that can/should be transfered rather than cloned.
* @param {string} [options.name] - A descriptive name for this module; this can be useful for
* debugging but is not currently used for anything else.
* @param {string} [options.workerId] - By default all modules will run in the same dedicated worker,

@@ -44,3 +47,3 @@ * but if you want to use multiple workers you can pass a `workerId` to indicate a specific

export function defineWorkerModule(options) {
if (!options || typeof options.init !== 'function') {
if ((!options || typeof options.init !== 'function') && !_allowInitAsString) {
throw new Error('requires `options.init` function')

@@ -53,2 +56,3 @@ }

const id = `workerModule${++_workerModuleId}`
const name = options.name || id
let registrationThenable = null

@@ -59,6 +63,9 @@

if (typeof dep === 'function' && !dep.workerModuleData) {
_allowInitAsString = true
dep = defineWorkerModule({
workerId,
init: new Function(`return function(){return (${stringifyFunction(dep)})}`)()
name: `<${name}> function dependency: ${dep.name}`,
init: `function(){return (\n${stringifyFunction(dep)}\n)}`
})
_allowInitAsString = false
}

@@ -90,2 +97,3 @@ // Grab postable data for worker modules

id,
name,
dependencies,

@@ -121,3 +129,6 @@ init: stringifyFunction(init),

URL.createObjectURL(
new Blob([`;(${bootstrap})()`], {type: 'application/javascript'})
new Blob(
[`/** Worker Module Bootstrap: ${workerId.replace(/\*/g, '')} **/\n\n;(${bootstrap})()`],
{type: 'application/javascript'}
)
)

@@ -124,0 +135,0 @@ )

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