webworkify-webpack2
Version:
launch a web worker that can require() in the browser with webpack, compatible with webworkify
121 lines (103 loc) • 5.35 kB
JavaScript
var __webpack_require__ = arguments[2];
var sources = __webpack_require__.m;
var ENTRY_MODULE = __webpack_require__.s || "0";
// In webpack 2 the moduleId property is called `i` instead of `id`.
var webworkifyWebpackModuleId = arguments[0].id || arguments[0].i;
var webpackBootstrapFunc = function(modules) {
var installedModules = {};
function __webpack_require__(moduleId) {
if(installedModules[moduleId])
return installedModules[moduleId].exports;
var module = installedModules[moduleId] = {
exports: {},
id: moduleId,
loaded: false
};
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
module.loaded = true;
return module.exports;
}
__webpack_require__.m = modules;
__webpack_require__.c = installedModules;
__webpack_require__.oe = function(err) { throw err; };
__webpack_require__.p = "";
var f = __webpack_require__(__webpack_require__.s = entryModule);
return f.default || f; // try to call default if defined to also support babel esmodule exports
}
// http://stackoverflow.com/a/2593661/130442
function quoteRegExp(str) {
return (str+'').replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&");
}
module.exports = function (fn, options) {
var moduleWrapperStrings = [];
var potentialFnModuleIds = [ENTRY_MODULE];
var sourcesKeys = Object.keys(sources); // when using the CommonChunks plugin, webpacl sometimes storing sources in object instead of array
// first, find the modules that required webworkify-webpack, and note their requires so that we can limit the number of potential duplicate matches
// while we're at it, save the string version for use later
var key;
for (var i = 0, l = sourcesKeys.length; i < l; i++) {
var k = sourcesKeys[i];
if (!sources[k]) {
continue;
}
var wrapperFuncString = sources[k].toString();
moduleWrapperStrings[k] = wrapperFuncString;
// __webpack_require__ is the third argument passed to the wrapper function, but it may have been renamed by minification
var wrapperSignature = wrapperFuncString.match(/^function\s?\(\w+,\s*\w+,\s*(\w+)\)/);
if (!wrapperSignature) {
// no matches means the module doesn't use __webpack_require__, and we can skip it entirely
continue;
}
var webpackRequireName = wrapperSignature[1];
var isWebworkifyWebpackRequired = wrapperFuncString.match(
new RegExp(quoteRegExp(webpackRequireName) + '\\((/\\*.*?\\*/)?\\s*' + quoteRegExp(webworkifyWebpackModuleId) + '\\s*\\)', 'g')
);
if (isWebworkifyWebpackRequired) {
// find all calls that look like __webpack_require__(\d+), and aren't webworkify-webpack
var re = new RegExp(quoteRegExp(webpackRequireName) + '\\((/\\*.*?\\*/)?\\s*(\\d+)\\s*\\)', 'g');
var match;
while (match = re.exec(wrapperFuncString)) {
if (match[2] != ('' + webworkifyWebpackModuleId)) {
potentialFnModuleIds.push(match[2]);
}
}
}
}
var fnString = fn.toString()
// FF adds a "use strict"; to the function body
.replace(/"use strict";\n\n/, '');
var fnStringNoSpace = fnString
.replace(/^function\s?\((.*)\)(\s?)\{(\n"use strict";\n)?/, 'function($1)$2{');
var fnStringWithSpace = fnString
.replace(/^function\s?\((.*)\)(\s?)\{(\n"use strict";\n)?/, 'function ($1)$2{');
// find the first moduleId from the above list that contains fnString
var key = potentialFnModuleIds.find(function (moduleId) {
var wrapperFuncString = sources[moduleId].toString();
if (wrapperFuncString.indexOf(fnStringNoSpace) > -1 || wrapperFuncString.indexOf(fnStringWithSpace) > -1) {
var exp = __webpack_require__(moduleId);
// Using babel as a transpiler to use esmodule, the export will always
// be an object with the default export as a property of it. To ensure
// the existing api and babel esmodule exports are both supported we
// check for both
if (!(exp && (exp === fn || exp.default === fn))) {
moduleWrapperStrings[moduleId] = wrapperFuncString.substring(0, wrapperFuncString.length - 1) + '\n' + fnString.match(/function\s?(.+?)\s?\(.*/)[1] + '();\n}';
}
return true;
}
return false;
});
if (typeof key === 'undefined') {
throw new Error('webworkify-webpack: Could not locate module containing worker function! Make sure you aren\'t using eval sourcemaps and that you pass named functions to webworkify-webpack!');
}
var src = 'var fn = (' + webpackBootstrapFunc.toString().replace('entryModule', key) + ')(['
+ moduleWrapperStrings.join(',')
+ ']);\n'
+ '(typeof fn === "function") && fn(self);'; // not a function when calling a function from the current scope
var blob = new Blob([src], { type: 'text/javascript' })
if (options && options.bare) { return blob; }
var URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
var workerUrl = URL.createObjectURL(blob);
var worker = new Worker(workerUrl);
worker.objectURL = workerUrl;
return worker;
};