Welcome to mirror list, hosted at ThFree Co, Russian Federation.

web_worker_fake.js « __helpers__ « frontend « spec - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: fb37e41a8536275add8a564984ddebbdcfc1a276 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
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);

  // eslint-disable-next-line 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));
  }
}