New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.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.25.0 to 0.26.0

src/mainThreadFallback.js

3

__tests__/_jsdom-worker.js

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

this.terminate = () => {
throw Error('Not Supported');
// [TROIKA EDIT]: don't throw.
// throw Error('Not Supported');
};

@@ -121,0 +122,0 @@ global.fetch(url)

@@ -1,4 +0,4 @@

import {defineWorkerModule} from '../src/WorkerModules.js'
import ThenableWorkerModule from '../src/ThenableWorkerModule.js'
require('./_jsdom-worker.js')
const {defineWorkerModule} = require('../src/WorkerModules.js')
const {default: ThenableWorkerModule} = require('../src/ThenableWorkerModule.js')

@@ -5,0 +5,0 @@

@@ -1,3 +0,3 @@

import {defineWorkerModule} from '../src/WorkerModules.js'
require('./_jsdom-worker.js')
const {defineWorkerModule} = require('../src/WorkerModules.js')

@@ -4,0 +4,0 @@ beforeEach(() => {

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

# [0.26.0](https://github.com/protectwise/troika/compare/v0.25.0...v0.26.0) (2020-05-24)
### Features
* **troika-worker-utils:** add main thread fallback when web workers are not allowed ([c754d0b](https://github.com/protectwise/troika/commit/c754d0b2e716eadb2e478bb12fb2880d8a4ad63f))
# [0.25.0](https://github.com/protectwise/troika/compare/v0.24.1...v0.25.0) (2020-05-19)

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

@@ -163,9 +163,32 @@ /**

/**
* Promise.all() impl:
*/
BespokeThenable.all = NativePromiseThenable.all = function(items) {
let resultCount = 0;
let results = [];
let out = DefaultThenable();
if (items.length === 0) {
out.resolve([]);
} else {
items.forEach((item, i) => {
let itemThenable = DefaultThenable();
itemThenable.resolve(item);
itemThenable.then(res => {
resultCount++;
results[i] = res;
if (resultCount === items.length) {
out.resolve(results);
}
}, out.reject);
});
}
return out
};
/**
* Choose the best Thenable implementation and export it as the default.
*/
var Thenable = (
typeof Promise === 'function' ? NativePromiseThenable : BespokeThenable
);
const DefaultThenable = typeof Promise === 'function' ? NativePromiseThenable : BespokeThenable;

@@ -321,2 +344,39 @@ /**

/**
* Fallback for `defineWorkerModule` that behaves identically but runs in the main
* thread, for when the execution environment doesn't support web workers or they
* are disallowed due to e.g. CSP security restrictions.
*/
function defineMainThreadModule(options) {
let moduleFunc = function(...args) {
return moduleFunc._getInitResult().then(initResult => {
if (typeof initResult === 'function') {
return initResult(...args)
} else {
throw new Error('Worker module function was called but `init` did not return a callable function')
}
})
};
moduleFunc._getInitResult = function() {
// We can ignore getTransferables in main thread. TODO workerId?
let {dependencies, init} = options;
// Resolve dependencies
dependencies = Array.isArray(dependencies) ? dependencies.map(dep =>
dep && dep._getInitResult ? dep._getInitResult() : dep
) : [];
// Invoke init with the resolved dependencies
let initThenable = DefaultThenable.all(dependencies).then(deps => {
return init.apply(null, deps)
});
// Cache the resolved promise for subsequent calls
moduleFunc._getInitResult = () => initThenable;
return initThenable
};
return moduleFunc
}
let _workerModuleId = 0;

@@ -329,2 +389,20 @@ let _messageId = 0;

let supportsWorkers = () => {
let supported = false;
try {
// TODO additional checks for things like importScripts within the worker?
// Would need to be an async check.
let worker = new Worker(
URL.createObjectURL(
new Blob([''], {type: 'application/javascript'})
)
);
worker.terminate();
supported = true;
} catch(err) {
console.warn(`Troika createWorkerModule: web workers not allowed in current environment; falling back to main thread execution.`, err);
}
supportsWorkers = () => supported;
return supported
};

@@ -368,2 +446,7 @@ /**

let {dependencies, init, getTransferables, workerId} = options;
if (!supportsWorkers()) {
return defineMainThreadModule(options)
}
if (workerId == null) {

@@ -468,3 +551,3 @@ workerId = '#default';

function callWorker(workerId, action, data) {
const thenable = Thenable();
const thenable = DefaultThenable();
const messageId = ++_messageId;

@@ -497,3 +580,3 @@ openRequests[messageId] = response => {

name: 'Thenable',
dependencies: [Thenable],
dependencies: [DefaultThenable],
init: function(Thenable) {

@@ -504,2 +587,2 @@ return Thenable

export { Thenable, ThenableWorkerModule, defineWorkerModule, stringifyFunction };
export { DefaultThenable as Thenable, ThenableWorkerModule, defineWorkerModule, stringifyFunction };

@@ -172,9 +172,32 @@ (function (global, factory) {

/**
* Promise.all() impl:
*/
BespokeThenable.all = NativePromiseThenable.all = function(items) {
var resultCount = 0;
var results = [];
var out = DefaultThenable();
if (items.length === 0) {
out.resolve([]);
} else {
items.forEach(function (item, i) {
var itemThenable = DefaultThenable();
itemThenable.resolve(item);
itemThenable.then(function (res) {
resultCount++;
results[i] = res;
if (resultCount === items.length) {
out.resolve(results);
}
}, out.reject);
});
}
return out
};
/**
* Choose the best Thenable implementation and export it as the default.
*/
var Thenable = (
typeof Promise === 'function' ? NativePromiseThenable : BespokeThenable
);
var DefaultThenable = typeof Promise === 'function' ? NativePromiseThenable : BespokeThenable;

@@ -343,2 +366,42 @@ /**

/**
* Fallback for `defineWorkerModule` that behaves identically but runs in the main
* thread, for when the execution environment doesn't support web workers or they
* are disallowed due to e.g. CSP security restrictions.
*/
function defineMainThreadModule(options) {
var moduleFunc = function() {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
return moduleFunc._getInitResult().then(function (initResult) {
if (typeof initResult === 'function') {
return initResult.apply(void 0, args)
} else {
throw new Error('Worker module function was called but `init` did not return a callable function')
}
})
};
moduleFunc._getInitResult = function() {
// We can ignore getTransferables in main thread. TODO workerId?
var dependencies = options.dependencies;
var init = options.init;
// Resolve dependencies
dependencies = Array.isArray(dependencies) ? dependencies.map(function (dep) { return dep && dep._getInitResult ? dep._getInitResult() : dep; }
) : [];
// Invoke init with the resolved dependencies
var initThenable = DefaultThenable.all(dependencies).then(function (deps) {
return init.apply(null, deps)
});
// Cache the resolved promise for subsequent calls
moduleFunc._getInitResult = function () { return initThenable; };
return initThenable
};
return moduleFunc
}
var _workerModuleId = 0;

@@ -351,2 +414,20 @@ var _messageId = 0;

var supportsWorkers = function () {
var supported = false;
try {
// TODO additional checks for things like importScripts within the worker?
// Would need to be an async check.
var worker = new Worker(
URL.createObjectURL(
new Blob([''], {type: 'application/javascript'})
)
);
worker.terminate();
supported = true;
} catch(err) {
console.warn("Troika createWorkerModule: web workers not allowed in current environment; falling back to main thread execution.", err);
}
supportsWorkers = function () { return supported; };
return supported
};

@@ -393,2 +474,7 @@ /**

var workerId = options.workerId;
if (!supportsWorkers()) {
return defineMainThreadModule(options)
}
if (workerId == null) {

@@ -498,3 +584,3 @@ workerId = '#default';

function callWorker(workerId, action, data) {
var thenable = Thenable();
var thenable = DefaultThenable();
var messageId = ++_messageId;

@@ -527,3 +613,3 @@ openRequests[messageId] = function (response) {

name: 'Thenable',
dependencies: [Thenable],
dependencies: [DefaultThenable],
init: function(Thenable) {

@@ -534,3 +620,3 @@ return Thenable

exports.Thenable = Thenable;
exports.Thenable = DefaultThenable;
exports.ThenableWorkerModule = ThenableWorkerModule;

@@ -537,0 +623,0 @@ exports.defineWorkerModule = defineWorkerModule;

@@ -1,10 +0,12 @@

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

@@ -163,9 +163,33 @@ /**

/**
* Promise.all() impl:
*/
BespokeThenable.all = NativePromiseThenable.all = function(items) {
let resultCount = 0
let results = []
let out = DefaultThenable()
if (items.length === 0) {
out.resolve([])
} else {
items.forEach((item, i) => {
let itemThenable = DefaultThenable()
itemThenable.resolve(item)
itemThenable.then(res => {
resultCount++
results[i] = res
if (resultCount === items.length) {
out.resolve(results)
}
}, out.reject)
})
}
return out
}
/**
* Choose the best Thenable implementation and export it as the default.
*/
export default (
typeof Promise === 'function' ? NativePromiseThenable : BespokeThenable
)
const DefaultThenable = typeof Promise === 'function' ? NativePromiseThenable : BespokeThenable
export default DefaultThenable
import Thenable from './Thenable.js'
import { workerBootstrap } from './workerBootstrap.js'
import { defineMainThreadModule } from './mainThreadFallback.js'

@@ -11,2 +12,20 @@ let _workerModuleId = 0

let supportsWorkers = () => {
let supported = false
try {
// TODO additional checks for things like importScripts within the worker?
// Would need to be an async check.
let worker = new Worker(
URL.createObjectURL(
new Blob([''], {type: 'application/javascript'})
)
)
worker.terminate()
supported = true
} catch(err) {
console.warn(`Troika createWorkerModule: web workers not allowed in current environment; falling back to main thread execution.`, err)
}
supportsWorkers = () => supported
return supported
}

@@ -50,2 +69,7 @@ /**

let {dependencies, init, getTransferables, workerId} = options
if (!supportsWorkers()) {
return defineMainThreadModule(options)
}
if (workerId == null) {

@@ -52,0 +76,0 @@ workerId = '#default'

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