UNPKG

safe-run

Version:

Run unsafe JavaScript using WebWorkers

124 lines (117 loc) 9.33 kB
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define([], factory); else if(typeof exports === 'object') exports["safe-run"] = factory(); else root["safe-run"] = factory(); })(window, function() { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); /******/ } /******/ }; /******/ /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ /******/ // create a fake namespace object /******/ // mode & 1: value is a module id, require it /******/ // mode & 2: merge all properties of value into the ns /******/ // mode & 4: return value when already ns object /******/ // mode & 8|1: behave like require /******/ __webpack_require__.t = function(value, mode) { /******/ if(mode & 1) value = __webpack_require__(value); /******/ if(mode & 8) return value; /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; /******/ var ns = Object.create(null); /******/ __webpack_require__.r(ns); /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); /******/ return ns; /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = "dist"; /******/ /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = "./src/main.js"); /******/ }) /************************************************************************/ /******/ ({ /***/ "./src/main.js": /*!*********************!*\ !*** ./src/main.js ***! \*********************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return Commander; });\n/* harmony import */ var _soldier__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./soldier */ \"./src/soldier.js\");\n\nclass Commander {\n constructor(timeOut = 200) {\n this.timeOut = timeOut;\n this.soldiers = [];\n this.soldierStatuses = [];\n this.tasks = [];\n this.taskIdCount = 0;\n this.resolves = {};\n this.rejects = {};\n\n for (var count = 0; count < navigator.hardwareConcurrency; count++) {\n this.spawnSoldier(count);\n }\n }\n\n run(dependencies, body, params, args) {\n let taskId = this.taskIdCount++;\n this.tasks.push({\n id: taskId,\n dependencies: dependencies,\n body: body,\n params: params,\n args: args\n });\n let that = this;\n let promise = new Promise(function (resolve, reject) {\n that.resolves[`T${taskId}`] = resolve;\n that.rejects[`T${taskId}`] = reject;\n });\n this.delegateNextTask();\n return promise;\n }\n\n delegateNextTask() {\n if (this.soldierStatuses.indexOf(\"ready\") > -1 && this.tasks.length > 0) {\n let soldierNum = this.soldierStatuses.indexOf(\"ready\");\n let soldier = this.soldiers[soldierNum];\n let task = this.tasks[0];\n let taskId = task.id;\n this.tasks.shift();\n this.soldierStatuses[soldierNum] = \"running\"; //Start timer to kill and respawn soldier if task takes too long\n\n var that = this;\n setTimeout(function () {\n that.abortTask(soldierNum, taskId);\n }, this.timeOut);\n soldier.postMessage({\n type: \"run\",\n soldierNum: soldierNum,\n taskId: taskId,\n dependencies: task.dependencies,\n remoteFunction: task.body,\n params: task.params,\n args: task.args\n });\n }\n }\n\n abortTask(soldierNum, taskId) {\n if (this.soldierStatuses[soldierNum] == \"running\") {\n this.killSoldier(soldierNum);\n this.rejects[`T${taskId}`](new Error(`Task aborted after ${this.timeOut}ms.`));\n this.spawnSoldier(soldierNum);\n this.delegateNextTask();\n }\n }\n\n killSoldier(soldierNum) {\n let soldier = this.soldiers[soldierNum];\n soldier.terminate();\n }\n\n spawnSoldier(soldierNum) {\n this.soldiers[soldierNum] = new Worker(URL.createObjectURL(new Blob([`(${_soldier__WEBPACK_IMPORTED_MODULE_0__[\"default\"]})()`])), {\n type: 'module'\n });\n this.soldierStatuses[soldierNum] = \"ready\";\n\n this.soldiers[soldierNum].onmessage = message => {\n if (message.data.success) {\n this.resolves[`T${message.data.taskId}`](message.data.value);\n this.soldierStatuses[message.data.soldierNum] = \"ready\";\n\n if (this.tasks.length > 0) {\n run(this.tasks[0]);\n }\n } else if (!message.data.success) {\n this.rejects[`T${message.data.taskId}`](message.data.value);\n this.soldierStatuses[message.data.soldierNum] = \"ready\";\n\n if (this.tasks.length > 0) {\n run(this.tasks[0]);\n }\n } else {\n console.log(`Message from soldier: ${message.data.value}`);\n }\n };\n }\n\n}\n\n//# sourceURL=webpack://safe-run/./src/main.js?"); /***/ }), /***/ "./src/soldier.js": /*!************************!*\ !*** ./src/soldier.js ***! \************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\nvar Soldier = () => {\n var importedScripts = [];\n var soldierNum = null;\n\n onmessage = function (message) {\n if (typeof importScripts === \"function\") {\n if (message.data.type == \"initialize\") {\n soldierNum = message.data.soldierNum;\n } else if (message.data.type == \"run\") {\n try {\n if (Array.isArray(message.data.dependencies)) {\n message.data.dependencies.forEach(dep => {\n if (importedScripts.indexOf(dep) == -1) {\n importScripts(dep);\n importedScripts.push(dep);\n }\n });\n }\n\n var remoteFunction = new Function(...(Array.isArray(message.data.params) ? message.data.params : []), message.data.remoteFunction);\n result = remoteFunction(...(Array.isArray(message.data.args) ? message.data.args : []));\n postMessage({\n soldierNum: message.data.soldierNum,\n success: true,\n taskId: message.data.taskId,\n value: result\n });\n } catch (err) {\n postMessage({\n soldierNum: message.data.soldierNum,\n success: false,\n taskId: message.data.taskId,\n value: err.message\n });\n }\n }\n }\n };\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (Soldier);\n\n//# sourceURL=webpack://safe-run/./src/soldier.js?"); /***/ }) /******/ }); });