troika-worker-utils
Advanced tools
Comparing version 0.25.0 to 0.26.0
@@ -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' |
82614
17
2148