gitlab-org--gitlab-foss/spec/frontend/__helpers__/web_worker_fake.js

72 lines
2.3 KiB
JavaScript

import path from 'path';
const isRelative = (pathArg) => pathArg.startsWith('.');
const transformRequirePath = (base, pathArg) => {
if (!isRelative(pathArg)) {
return pathArg;
}
return path.resolve(base, pathArg);
};
const createRelativeRequire = (filename) => {
const rel = path.relative(__dirname, path.dirname(filename));
const base = path.resolve(__dirname, rel);
// reason: Dynamic require should be fine here since the code is dynamically evaluated anyways.
// eslint-disable-next-line import/no-dynamic-require, global-require
return (pathArg) => require(transformRequirePath(base, pathArg));
};
/**
* Simulates a WebWorker module similar to the kind created by Webpack's [`worker-loader`][1]
*
* [1]: https://webpack.js.org/loaders/worker-loader/
*/
export class FakeWebWorker {
/**
* Constructs a new FakeWebWorker instance
*
* @param {String} filename is the full path of the code, which is used to resolve relative imports.
* @param {String} code is the raw code of the web worker, which is dynamically evaluated on construction.
*/
constructor(filename, code) {
let isAlive = true;
const clientTarget = new EventTarget();
const workerTarget = new EventTarget();
this.addEventListener = (...args) => clientTarget.addEventListener(...args);
this.removeEventListener = (...args) => clientTarget.removeEventListener(...args);
this.postMessage = (message) => {
if (!isAlive) {
return;
}
workerTarget.dispatchEvent(new MessageEvent('message', { data: message }));
};
this.terminate = () => {
isAlive = false;
};
const workerScope = {
addEventListener: (...args) => workerTarget.addEventListener(...args),
removeEventListener: (...args) => workerTarget.removeEventListener(...args),
postMessage: (message) => {
if (!isAlive) {
return;
}
clientTarget.dispatchEvent(new MessageEvent('message', { data: message }));
},
};
// reason: `no-new-func` is like `eval` except it only executed on global scope and it's easy
// to pass in local references. `eval` is very unsafe in production, but in our test environment
// we shold be fine.
// eslint-disable-next-line no-new-func
Function('self', 'require', code)(workerScope, createRelativeRequire(filename));
}
}