safe-run
Version:
Run unsafe JavaScript using WebWorkers
124 lines (117 loc) • 9.33 kB
JavaScript
(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?");
/***/ })
/******/ });
});