0.2.0 - Mid migration

This commit is contained in:
Daniel Mason 2022-04-25 14:47:15 +12:00
parent 139e6a915e
commit 7e38fdbd7d
42393 changed files with 5358157 additions and 62 deletions

20
web/node_modules/rollup-plugin-terser/LICENSE generated vendored Normal file
View file

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright 2018 Bogdan Chadkin <trysound@yandex.ru>
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

139
web/node_modules/rollup-plugin-terser/README.md generated vendored Normal file
View file

@ -0,0 +1,139 @@
# rollup-plugin-terser [![Travis Build Status][travis-img]][travis]
[travis-img]: https://travis-ci.org/TrySound/rollup-plugin-terser.svg
[travis]: https://travis-ci.org/TrySound/rollup-plugin-terser
[Rollup](https://github.com/rollup/rollup) plugin to minify generated es bundle. Uses [terser](https://github.com/fabiosantoscode/terser) under the hood.
## Install
```sh
yarn add rollup-plugin-terser --dev
```
_Note: this package requires rollup@0.66 and higher (including rollup@1.0.0)_
## Usage
```js
import { rollup } from "rollup";
import { terser } from "rollup-plugin-terser";
rollup({
input: "main.js",
plugins: [terser()]
});
```
## Why named export?
1. Module is a namespace. Default export often leads to function/component per file dogma and makes code less maintainable.
2. Interop with commonjs is broken in many cases or hard to maintain.
3. Show me any good language with default exports. It's historical javascriptism.
## Options
> ⚠️ **Caveat:** any function used in options object cannot rely on its surrounding scope, since it is executed in an isolated context.
```js
terser(options);
```
`options` - [terser API options](https://github.com/fabiosantoscode/terser#minify-options)
Note: some terser options are set by the plugin automatically:
- `module: true` is set when `format` is `esm` or `es`
- `toplevel: true` is set when `format` is `cjs`
`options.sourcemap: boolean`
Generates source maps and passes them to rollup. Defaults to `true`.
`options.numWorkers: number`
Amount of workers to spawn. Defaults to the number of CPUs minus 1.
`options.include: Array<string | RegExp> | string | RegExp`
`options.exclude: Array<string | RegExp> | string | RegExp`
Specifically include/exclude chunk files names (minimatch pattern, or array of minimatch patterns), By default all chunk files will be minify.
## Examples
### Using as output plugin
```js
// rollup.config.js
import { terser } from "rollup-plugin-terser";
export default {
input: "index.js",
output: [
{ file: "lib.js", format: "cjs" },
{ file: "lib.min.js", format: "cjs", plugins: [terser()] },
{ file: "lib.esm.js", format: "esm" }
]
};
```
### include/exclude
If you'd like that only some of the files will be minify, then you can filter by `include` and `exclude` to do this like so:
```js
// rollup.config.js
import { terser } from "rollup-plugin-terser";
export default {
input: "index.js",
output: [
{ file: "lib.js", format: "cjs" },
{ file: "lib.min.js", format: "cjs" },
{ file: "lib.esm.js", format: "esm" },
{ dir: ".", entryFileNames: "lib-[format].js", format: "iife" }
],
plugins: [
terser({
include: [/^.+\.min\.js$/, "*esm*"],
exclude: ["some*"]
})
]
};
```
### Comments
If you'd like to preserve comments (for licensing for example), then you can specify a function to do this like so:
```js
terser({
output: {
comments: function(node, comment) {
var text = comment.value;
var type = comment.type;
if (type == "comment2") {
// multiline comment
return /@preserve|@license|@cc_on/i.test(text);
}
}
}
});
```
Alternatively, you can also choose to keep all comments (e.g. if a licensing header has already been prepended by a previous rollup plugin):
```js
terser({
output: {
comments: "all"
}
});
```
See [Terser documentation](https://github.com/fabiosantoscode/terser#terser) for further reference.
# License
MIT © [Bogdan Chadkin](mailto:trysound@yandex.ru)

26
web/node_modules/rollup-plugin-terser/index.d.ts generated vendored Normal file
View file

@ -0,0 +1,26 @@
import { Plugin } from 'rollup';
import { MinifyOptions } from 'terser';
export interface Options extends Omit<MinifyOptions, "sourceMap"> {
/**
* Specifically include/exclude chunk files names (minimatch pattern, or array of minimatch patterns), By default all chunk files will be minify.
*/
include?: Array<string | RegExp> | string | RegExp | null;
exclude?: Array<string | RegExp> | string | RegExp | null;
/**
* Amount of workers to spawn. Defaults to the number of CPUs minus 1.
*/
numWorkers?: number;
/**
* Generates source maps and passes them to rollup.
*
* @default true
*/
sourcemap?: boolean;
}
export declare function terser(options?: Options): Plugin;

109
web/node_modules/rollup-plugin-terser/index.js generated vendored Normal file
View file

@ -0,0 +1,109 @@
const { codeFrameColumns } = require("@babel/code-frame");
const Worker = require("jest-worker").default;
const serialize = require("serialize-javascript");
const { createFilter } = require("rollup-pluginutils");
function terser(userOptions = {}) {
if (userOptions.sourceMap != null) {
throw Error("sourceMap option is removed, use sourcemap instead");
}
const filter = createFilter(userOptions.include, userOptions.exclude, {
resolve: false
});
return {
name: "terser",
renderChunk(code, chunk, outputOptions) {
if (!filter(chunk.fileName)) {
return null;
}
if (!this.worker) {
this.worker = new Worker(require.resolve("./transform.js"), {
numWorkers: userOptions.numWorkers
});
this.numOfBundles = 0;
}
this.numOfBundles++;
const defaultOptions = {
sourceMap: userOptions.sourcemap !== false
};
if (outputOptions.format === "es" || outputOptions.format === "esm") {
defaultOptions.module = true;
}
if (outputOptions.format === "cjs") {
defaultOptions.toplevel = true;
}
// TODO rewrite with object spread after dropping node v6
const normalizedOptions = Object.assign({}, defaultOptions, userOptions);
// remove plugin specific options
for (let key of ["include", "exclude", "sourcemap", "numWorkers"]) {
if (normalizedOptions.hasOwnProperty(key)) {
delete normalizedOptions[key];
}
}
const serializedOptions = serialize(normalizedOptions);
const result = this.worker
.transform(code, serializedOptions)
.catch(error => {
const { message, line, col: column } = error;
console.error(
codeFrameColumns(code, { start: { line, column } }, { message })
);
throw error;
});
const handler = () => {
this.numOfBundles--;
if (this.numOfBundles === 0) {
this.worker.end();
this.worker = 0;
}
};
result.then(handler, handler);
return result.then(result => {
if (result.nameCache) {
let { vars, props } = userOptions.nameCache;
// only assign nameCache.vars if it was provided, and if terser produced values:
if (vars) {
const newVars =
result.nameCache.vars && result.nameCache.vars.props;
if (newVars) {
vars.props = vars.props || {};
Object.assign(vars.props, newVars);
}
}
// support populating an empty nameCache object:
if (!props) {
props = userOptions.nameCache.props = {};
}
// merge updated props into original nameCache object:
const newProps =
result.nameCache.props && result.nameCache.props.props;
if (newProps) {
props.props = props.props || {};
Object.assign(props.props, newProps);
}
}
return result.result;
});
}
};
}
exports.terser = terser;

View file

@ -0,0 +1,8 @@
'use strict';
module.exports = (flag, argv) => {
argv = argv || process.argv;
const prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--');
const pos = argv.indexOf(prefix + flag);
const terminatorPos = argv.indexOf('--');
return pos !== -1 && (terminatorPos === -1 ? true : pos < terminatorPos);
};

View file

@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -0,0 +1,44 @@
{
"name": "has-flag",
"version": "3.0.0",
"description": "Check if argv has a specific flag",
"license": "MIT",
"repository": "sindresorhus/has-flag",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"engines": {
"node": ">=4"
},
"scripts": {
"test": "xo && ava"
},
"files": [
"index.js"
],
"keywords": [
"has",
"check",
"detect",
"contains",
"find",
"flag",
"cli",
"command-line",
"argv",
"process",
"arg",
"args",
"argument",
"arguments",
"getopt",
"minimist",
"optimist"
],
"devDependencies": {
"ava": "*",
"xo": "*"
}
}

View file

@ -0,0 +1,70 @@
# has-flag [![Build Status](https://travis-ci.org/sindresorhus/has-flag.svg?branch=master)](https://travis-ci.org/sindresorhus/has-flag)
> Check if [`argv`](https://nodejs.org/docs/latest/api/process.html#process_process_argv) has a specific flag
Correctly stops looking after an `--` argument terminator.
## Install
```
$ npm install has-flag
```
## Usage
```js
// foo.js
const hasFlag = require('has-flag');
hasFlag('unicorn');
//=> true
hasFlag('--unicorn');
//=> true
hasFlag('f');
//=> true
hasFlag('-f');
//=> true
hasFlag('foo=bar');
//=> true
hasFlag('foo');
//=> false
hasFlag('rainbow');
//=> false
```
```
$ node foo.js -f --unicorn --foo=bar -- --rainbow
```
## API
### hasFlag(flag, [argv])
Returns a boolean for whether the flag exists.
#### flag
Type: `string`
CLI flag to look for. The `--` prefix is optional.
#### argv
Type: `string[]`<br>
Default: `process.argv`
CLI arguments.
## License
MIT © [Sindre Sorhus](https://sindresorhus.com)

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) Facebook, Inc. and its affiliates.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,215 @@
# jest-worker
Module for executing heavy tasks under forked processes in parallel, by providing a `Promise` based interface, minimum overhead, and bound workers.
The module works by providing an absolute path of the module to be loaded in all forked processes. Files relative to a node module are also accepted. All methods are exposed on the parent process as promises, so they can be `await`'ed. Child (worker) methods can either be synchronous or asynchronous.
The module also implements support for bound workers. Binding a worker means that, based on certain parameters, the same task will always be executed by the same worker. The way bound workers work is by using the returned string of the `computeWorkerKey` method. If the string was used before for a task, the call will be queued to the related worker that processed the task earlier; if not, it will be executed by the first available worker, then sticked to the worker that executed it; so the next time it will be processed by the same worker. If you have no preference on the worker executing the task, but you have defined a `computeWorkerKey` method because you want _some_ of the tasks to be sticked, you can return `null` from it.
The list of exposed methods can be explicitly provided via the `exposedMethods` option. If it is not provided, it will be obtained by requiring the child module into the main process, and analyzed via reflection. Check the "minimal example" section for a valid one.
## Install
```sh
$ yarn add jest-worker
```
## Example
This example covers the minimal usage:
### File `parent.js`
```javascript
import Worker from 'jest-worker';
async function main() {
const worker = new Worker(require.resolve('./Worker'));
const result = await worker.hello('Alice'); // "Hello, Alice"
}
main();
```
### File `worker.js`
```javascript
export function hello(param) {
return 'Hello, ' + param;
}
```
## Experimental worker
Node 10 shipped with [worker-threads](https://nodejs.org/api/worker_threads.html), a "threading API" that uses SharedArrayBuffers to communicate between the main process and its child threads. This experimental Node feature can significantly improve the communication time between parent and child processes in `jest-worker`.
Since `worker_threads` are considered experimental in Node, you have to opt-in to this behavior by passing `enableWorkerThreads: true` when instantiating the worker. While the feature was unflagged in Node 11.7.0, you'll need to run the Node process with the `--experimental-worker` flag for Node 10.
## API
The only exposed method is a constructor (`Worker`) that is initialized by passing the worker path, plus an options object.
### `workerPath: string` (required)
Node module name or absolute path of the file to be loaded in the child processes. Use `require.resolve` to transform a relative path into an absolute one.
### `options: Object` (optional)
#### `exposedMethods: $ReadOnlyArray<string>` (optional)
List of method names that can be called on the child processes from the parent process. You cannot expose any method named like a public `Worker` method, or starting with `_`. If you use method auto-discovery, then these methods will not be exposed, even if they exist.
#### `numWorkers: number` (optional)
Amount of workers to spawn. Defaults to the number of CPUs minus 1.
#### `maxRetries: number` (optional)
Maximum amount of times that a dead child can be re-spawned, per call. Defaults to `3`, pass `Infinity` to allow endless retries.
#### `forkOptions: Object` (optional)
Allow customizing all options passed to `childProcess.fork`. By default, some values are set (`cwd`, `env` and `execArgv`), but you can override them and customize the rest. For a list of valid values, check [the Node documentation](https://nodejs.org/api/child_process.html#child_process_child_process_fork_modulepath_args_options).
#### `computeWorkerKey: (method: string, ...args: Array<any>) => ?string` (optional)
Every time a method exposed via the API is called, `computeWorkerKey` is also called in order to bound the call to a worker. This is useful for workers that are able to cache the result or part of it. You bound calls to a worker by making `computeWorkerKey` return the same identifier for all different calls. If you do not want to bind the call to any worker, return `null`.
The callback you provide is called with the method name, plus all the rest of the arguments of the call. Thus, you have full control to decide what to return. Check a practical example on bound workers under the "bound worker usage" section.
By default, no process is bound to any worker.
#### `setupArgs: Array<mixed>` (optional)
The arguments that will be passed to the `setup` method during initialization.
#### `workerPool: (workerPath: string, options?: WorkerPoolOptions) => WorkerPoolInterface` (optional)
Provide a custom worker pool to be used for spawning child processes. By default, Jest will use a node thread pool if available and fall back to child process threads.
The arguments that will be passed to the `setup` method during initialization.
#### `enableWorkerThreads: boolean` (optional)
`jest-worker` will automatically detect if `worker_threads` are available, but will not use them unless passed `enableWorkerThreads: true`.
## Worker
The returned `Worker` instance has all the exposed methods, plus some additional ones to interact with the workers itself:
### `getStdout(): Readable`
Returns a `ReadableStream` where the standard output of all workers is piped. Note that the `silent` option of the child workers must be set to `true` to make it work. This is the default set by `jest-worker`, but keep it in mind when overriding options through `forkOptions`.
### `getStderr(): Readable`
Returns a `ReadableStream` where the standard error of all workers is piped. Note that the `silent` option of the child workers must be set to `true` to make it work. This is the default set by `jest-worker`, but keep it in mind when overriding options through `forkOptions`.
### `end()`
Finishes the workers by killing all workers. No further calls can be done to the `Worker` instance.
**Note:** Each worker has a unique id (index that starts with `1`) which is available on `process.env.JEST_WORKER_ID`
## Setting up and tearing down the child process
The child process can define two special methods (both of them can be asynchronous):
- `setup()`: If defined, it's executed before the first call to any method in the child.
- `teardown()`: If defined, it's executed when the farm ends.
# More examples
## Standard usage
This example covers the standard usage:
### File `parent.js`
```javascript
import Worker from 'jest-worker';
async function main() {
const myWorker = new Worker(require.resolve('./Worker'), {
exposedMethods: ['foo', 'bar', 'getWorkerId'],
numWorkers: 4,
});
console.log(await myWorker.foo('Alice')); // "Hello from foo: Alice"
console.log(await myWorker.bar('Bob')); // "Hello from bar: Bob"
console.log(await myWorker.getWorkerId()); // "3" -> this message has sent from the 3rd worker
myWorker.end();
}
main();
```
### File `worker.js`
```javascript
export function foo(param) {
return 'Hello from foo: ' + param;
}
export function bar(param) {
return 'Hello from bar: ' + param;
}
export function getWorkerId() {
return process.env.JEST_WORKER_ID;
}
```
## Bound worker usage:
This example covers the usage with a `computeWorkerKey` method:
### File `parent.js`
```javascript
import Worker from 'jest-worker';
async function main() {
const myWorker = new Worker(require.resolve('./Worker'), {
computeWorkerKey: (method, filename) => filename,
});
// Transform the given file, within the first available worker.
console.log(await myWorker.transform('/tmp/foo.js'));
// Wait a bit.
await sleep(10000);
// Transform the same file again. Will immediately return because the
// transformed file is cached in the worker, and `computeWorkerKey` ensures
// the same worker that processed the file the first time will process it now.
console.log(await myWorker.transform('/tmp/foo.js'));
myWorker.end();
}
main();
```
### File `worker.js`
```javascript
import babel from '@babel/core';
const cache = Object.create(null);
export function transform(filename) {
if (cache[filename]) {
return cache[filename];
}
// jest-worker can handle both immediate results and thenables. If a
// thenable is returned, it will be await'ed until it resolves.
return babel.transformFileAsync(filename).then(result => {
cache[filename] = result;
return result;
});
}
```

View file

@ -0,0 +1,27 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import { FarmOptions } from './types';
export default class Farm {
private _computeWorkerKey;
private _cacheKeys;
private _callback;
private _last;
private _locks;
private _numOfWorkers;
private _offset;
private _queue;
constructor(numOfWorkers: number, callback: Function, computeWorkerKey?: FarmOptions['computeWorkerKey']);
doWork(method: string, ...args: Array<any>): Promise<unknown>;
private _getNextTask;
private _process;
private _enqueue;
private _push;
private _lock;
private _unlock;
private _isLocked;
}
//# sourceMappingURL=Farm.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"Farm.d.ts","sourceRoot":"","sources":["../src/Farm.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAEL,WAAW,EAOZ,MAAM,SAAS,CAAC;AAEjB,MAAM,CAAC,OAAO,OAAO,IAAI;IACvB,OAAO,CAAC,iBAAiB,CAAkC;IAC3D,OAAO,CAAC,UAAU,CAAkC;IACpD,OAAO,CAAC,SAAS,CAAW;IAC5B,OAAO,CAAC,KAAK,CAAmB;IAChC,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAA0B;gBAGtC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,QAAQ,EAClB,gBAAgB,CAAC,EAAE,WAAW,CAAC,kBAAkB,CAAC;IAepD,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IAqC7D,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,QAAQ;IA0BhB,OAAO,CAAC,QAAQ;IAmBhB,OAAO,CAAC,KAAK;IAUb,OAAO,CAAC,KAAK;IAIb,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,SAAS;CAGlB"}

View file

@ -0,0 +1,179 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.default = void 0;
var _types = require('./types');
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
class Farm {
constructor(numOfWorkers, callback, computeWorkerKey) {
_defineProperty(this, '_computeWorkerKey', void 0);
_defineProperty(this, '_cacheKeys', void 0);
_defineProperty(this, '_callback', void 0);
_defineProperty(this, '_last', void 0);
_defineProperty(this, '_locks', void 0);
_defineProperty(this, '_numOfWorkers', void 0);
_defineProperty(this, '_offset', void 0);
_defineProperty(this, '_queue', void 0);
this._cacheKeys = Object.create(null);
this._callback = callback;
this._last = [];
this._locks = [];
this._numOfWorkers = numOfWorkers;
this._offset = 0;
this._queue = [];
if (computeWorkerKey) {
this._computeWorkerKey = computeWorkerKey;
}
}
doWork(method, ...args) {
return new Promise((resolve, reject) => {
const computeWorkerKey = this._computeWorkerKey;
const request = [_types.CHILD_MESSAGE_CALL, false, method, args];
let worker = null;
let hash = null;
if (computeWorkerKey) {
hash = computeWorkerKey.call(this, method, ...args);
worker = hash == null ? null : this._cacheKeys[hash];
}
const onStart = worker => {
if (hash != null) {
this._cacheKeys[hash] = worker;
}
};
const onEnd = (error, result) => {
if (error) {
reject(error);
} else {
resolve(result);
}
};
const task = {
onEnd,
onStart,
request
};
if (worker) {
this._enqueue(task, worker.getWorkerId());
} else {
this._push(task);
}
});
}
_getNextTask(workerId) {
let queueHead = this._queue[workerId];
while (queueHead && queueHead.task.request[1]) {
queueHead = queueHead.next || null;
}
this._queue[workerId] = queueHead;
return queueHead && queueHead.task;
}
_process(workerId) {
if (this._isLocked(workerId)) {
return this;
}
const task = this._getNextTask(workerId);
if (!task) {
return this;
}
const onEnd = (error, result) => {
task.onEnd(error, result);
this._unlock(workerId);
this._process(workerId);
};
task.request[1] = true;
this._lock(workerId);
this._callback(workerId, task.request, task.onStart, onEnd);
return this;
}
_enqueue(task, workerId) {
const item = {
next: null,
task
};
if (task.request[1]) {
return this;
}
if (this._queue[workerId]) {
this._last[workerId].next = item;
} else {
this._queue[workerId] = item;
}
this._last[workerId] = item;
this._process(workerId);
return this;
}
_push(task) {
for (let i = 0; i < this._numOfWorkers; i++) {
this._enqueue(task, (this._offset + i) % this._numOfWorkers);
}
this._offset++;
return this;
}
_lock(workerId) {
this._locks[workerId] = true;
}
_unlock(workerId) {
this._locks[workerId] = false;
}
_isLocked(workerId) {
return this._locks[workerId];
}
}
exports.default = Farm;

View file

@ -0,0 +1,14 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import BaseWorkerPool from './base/BaseWorkerPool';
import { ChildMessage, WorkerOptions, OnStart, OnEnd, WorkerPoolInterface, WorkerInterface } from './types';
declare class WorkerPool extends BaseWorkerPool implements WorkerPoolInterface {
send(workerId: number, request: ChildMessage, onStart: OnStart, onEnd: OnEnd): void;
createWorker(workerOptions: WorkerOptions): WorkerInterface;
}
export default WorkerPool;
//# sourceMappingURL=WorkerPool.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"WorkerPool.d.ts","sourceRoot":"","sources":["../src/WorkerPool.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,cAAc,MAAM,uBAAuB,CAAC;AAEnD,OAAO,EACL,YAAY,EACZ,aAAa,EACb,OAAO,EACP,KAAK,EACL,mBAAmB,EACnB,eAAe,EAChB,MAAM,SAAS,CAAC;AAWjB,cAAM,UAAW,SAAQ,cAAe,YAAW,mBAAmB;IACpE,IAAI,CACF,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,KAAK,GACX,IAAI;IAIP,YAAY,CAAC,aAAa,EAAE,aAAa,GAAG,eAAe;CAU5D;AAED,eAAe,UAAU,CAAC"}

View file

@ -0,0 +1,49 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.default = void 0;
var _BaseWorkerPool = _interopRequireDefault(require('./base/BaseWorkerPool'));
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {default: obj};
}
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const canUseWorkerThreads = () => {
try {
require('worker_threads');
return true;
} catch (_) {
return false;
}
};
class WorkerPool extends _BaseWorkerPool.default {
send(workerId, request, onStart, onEnd) {
this.getWorkerById(workerId).send(request, onStart, onEnd);
}
createWorker(workerOptions) {
let Worker;
if (this._options.enableWorkerThreads && canUseWorkerThreads()) {
Worker = require('./workers/NodeThreadsWorker').default;
} else {
Worker = require('./workers/ChildProcessWorker').default;
}
return new Worker(workerOptions);
}
}
var _default = WorkerPool;
exports.default = _default;

View file

@ -0,0 +1,22 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/// <reference types="node" />
import { WorkerPoolOptions, WorkerOptions, WorkerInterface } from '../types';
export default class BaseWorkerPool {
private readonly _stderr;
private readonly _stdout;
protected readonly _options: WorkerPoolOptions;
private readonly _workers;
constructor(workerPath: string, options: WorkerPoolOptions);
getStderr(): NodeJS.ReadableStream;
getStdout(): NodeJS.ReadableStream;
getWorkers(): Array<WorkerInterface>;
getWorkerById(workerId: number): WorkerInterface;
createWorker(_workerOptions: WorkerOptions): WorkerInterface;
end(): void;
}
//# sourceMappingURL=BaseWorkerPool.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"BaseWorkerPool.d.ts","sourceRoot":"","sources":["../../src/base/BaseWorkerPool.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAKH,OAAO,EAEL,iBAAiB,EACjB,aAAa,EACb,eAAe,EAChB,MAAM,UAAU,CAAC;AAKlB,MAAM,CAAC,OAAO,OAAO,cAAc;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwB;IAChD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwB;IAChD,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IAC/C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAyB;gBAEtC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB;IAyC1D,SAAS,IAAI,MAAM,CAAC,cAAc;IAIlC,SAAS,IAAI,MAAM,CAAC,cAAc;IAIlC,UAAU,IAAI,KAAK,CAAC,eAAe,CAAC;IAIpC,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe;IAIhD,YAAY,CAAC,cAAc,EAAE,aAAa,GAAG,eAAe;IAI5D,GAAG,IAAI,IAAI;CAWZ"}

View file

@ -0,0 +1,134 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.default = void 0;
function _path() {
const data = _interopRequireDefault(require('path'));
_path = function _path() {
return data;
};
return data;
}
function _mergeStream() {
const data = _interopRequireDefault(require('merge-stream'));
_mergeStream = function _mergeStream() {
return data;
};
return data;
}
var _types = require('../types');
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {default: obj};
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
/* istanbul ignore next */
const emptyMethod = () => {};
class BaseWorkerPool {
constructor(workerPath, options) {
_defineProperty(this, '_stderr', void 0);
_defineProperty(this, '_stdout', void 0);
_defineProperty(this, '_options', void 0);
_defineProperty(this, '_workers', void 0);
this._options = options;
this._workers = new Array(options.numWorkers);
if (!_path().default.isAbsolute(workerPath)) {
workerPath = require.resolve(workerPath);
}
const stdout = (0, _mergeStream().default)();
const stderr = (0, _mergeStream().default)();
const forkOptions = options.forkOptions,
maxRetries = options.maxRetries,
setupArgs = options.setupArgs;
for (let i = 0; i < options.numWorkers; i++) {
const workerOptions = {
forkOptions,
maxRetries,
setupArgs,
workerId: i,
workerPath
};
const worker = this.createWorker(workerOptions);
const workerStdout = worker.getStdout();
const workerStderr = worker.getStderr();
if (workerStdout) {
stdout.add(workerStdout);
}
if (workerStderr) {
stderr.add(workerStderr);
}
this._workers[i] = worker;
}
this._stdout = stdout;
this._stderr = stderr;
}
getStderr() {
return this._stderr;
}
getStdout() {
return this._stdout;
}
getWorkers() {
return this._workers;
}
getWorkerById(workerId) {
return this._workers[workerId];
}
createWorker(_workerOptions) {
throw Error('Missing method createWorker in WorkerPool');
}
end() {
// We do not cache the request object here. If so, it would only be only
// processed by one of the workers, and we want them all to close.
for (let i = 0; i < this._workers.length; i++) {
this._workers[i].send(
[_types.CHILD_MESSAGE_END, false],
emptyMethod,
emptyMethod
);
}
}
}
exports.default = BaseWorkerPool;

View file

@ -0,0 +1,46 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/// <reference types="node" />
import { FarmOptions } from './types';
/**
* The Jest farm (publicly called "Worker") is a class that allows you to queue
* methods across multiple child processes, in order to parallelize work. This
* is done by providing an absolute path to a module that will be loaded on each
* of the child processes, and bridged to the main process.
*
* Bridged methods are specified by using the "exposedMethods" property of the
* "options" object. This is an array of strings, where each of them corresponds
* to the exported name in the loaded module.
*
* You can also control the amount of workers by using the "numWorkers" property
* of the "options" object, and the settings passed to fork the process through
* the "forkOptions" property. The amount of workers defaults to the amount of
* CPUS minus one.
*
* Queueing calls can be done in two ways:
* - Standard method: calls will be redirected to the first available worker,
* so they will get executed as soon as they can.
*
* - Sticky method: if a "computeWorkerKey" method is provided within the
* config, the resulting string of this method will be used as a key.
* Every time this key is returned, it is guaranteed that your job will be
* processed by the same worker. This is specially useful if your workers
* are caching results.
*/
export default class JestWorker {
private _ending;
private _farm;
private _options;
private _workerPool;
constructor(workerPath: string, options?: FarmOptions);
private _bindExposedWorkerMethods;
private _callFunctionWithArgs;
getStderr(): NodeJS.ReadableStream;
getStdout(): NodeJS.ReadableStream;
end(): void;
}
//# sourceMappingURL=index.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAKH,OAAO,EAAyC,WAAW,EAAC,MAAM,SAAS,CAAC;AAyB5E;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,OAAO,OAAO,UAAU;IAC7B,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,KAAK,CAAO;IACpB,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,WAAW,CAAsB;gBAE7B,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW;IA+BrD,OAAO,CAAC,yBAAyB;IAkBjC,OAAO,CAAC,qBAAqB;IAW7B,SAAS,IAAI,MAAM,CAAC,cAAc;IAIlC,SAAS,IAAI,MAAM,CAAC,cAAc;IAIlC,GAAG,IAAI,IAAI;CASZ"}

View file

@ -0,0 +1,184 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.default = void 0;
function _os() {
const data = _interopRequireDefault(require('os'));
_os = function _os() {
return data;
};
return data;
}
var _WorkerPool = _interopRequireDefault(require('./WorkerPool'));
var _Farm = _interopRequireDefault(require('./Farm'));
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {default: obj};
}
function _objectSpread(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i] != null ? arguments[i] : {};
var ownKeys = Object.keys(source);
if (typeof Object.getOwnPropertySymbols === 'function') {
ownKeys = ownKeys.concat(
Object.getOwnPropertySymbols(source).filter(function(sym) {
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
})
);
}
ownKeys.forEach(function(key) {
_defineProperty(target, key, source[key]);
});
}
return target;
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function getExposedMethods(workerPath, options) {
let exposedMethods = options.exposedMethods; // If no methods list is given, try getting it by auto-requiring the module.
if (!exposedMethods) {
const module = require(workerPath);
exposedMethods = Object.keys(module).filter(
// @ts-ignore: no index
name => typeof module[name] === 'function'
);
if (typeof module === 'function') {
exposedMethods = [...exposedMethods, 'default'];
}
}
return exposedMethods;
}
/**
* The Jest farm (publicly called "Worker") is a class that allows you to queue
* methods across multiple child processes, in order to parallelize work. This
* is done by providing an absolute path to a module that will be loaded on each
* of the child processes, and bridged to the main process.
*
* Bridged methods are specified by using the "exposedMethods" property of the
* "options" object. This is an array of strings, where each of them corresponds
* to the exported name in the loaded module.
*
* You can also control the amount of workers by using the "numWorkers" property
* of the "options" object, and the settings passed to fork the process through
* the "forkOptions" property. The amount of workers defaults to the amount of
* CPUS minus one.
*
* Queueing calls can be done in two ways:
* - Standard method: calls will be redirected to the first available worker,
* so they will get executed as soon as they can.
*
* - Sticky method: if a "computeWorkerKey" method is provided within the
* config, the resulting string of this method will be used as a key.
* Every time this key is returned, it is guaranteed that your job will be
* processed by the same worker. This is specially useful if your workers
* are caching results.
*/
class JestWorker {
constructor(workerPath, options) {
_defineProperty(this, '_ending', void 0);
_defineProperty(this, '_farm', void 0);
_defineProperty(this, '_options', void 0);
_defineProperty(this, '_workerPool', void 0);
this._options = _objectSpread({}, options);
this._ending = false;
const workerPoolOptions = {
enableWorkerThreads: this._options.enableWorkerThreads || false,
forkOptions: this._options.forkOptions || {},
maxRetries: this._options.maxRetries || 3,
numWorkers:
this._options.numWorkers ||
Math.max(_os().default.cpus().length - 1, 1),
setupArgs: this._options.setupArgs || []
};
if (this._options.WorkerPool) {
// @ts-ignore: constructor target any?
this._workerPool = new this._options.WorkerPool(
workerPath,
workerPoolOptions
);
} else {
this._workerPool = new _WorkerPool.default(workerPath, workerPoolOptions);
}
this._farm = new _Farm.default(
workerPoolOptions.numWorkers,
this._workerPool.send.bind(this._workerPool),
this._options.computeWorkerKey
);
this._bindExposedWorkerMethods(workerPath, this._options);
}
_bindExposedWorkerMethods(workerPath, options) {
getExposedMethods(workerPath, options).forEach(name => {
if (name.startsWith('_')) {
return;
}
if (this.constructor.prototype.hasOwnProperty(name)) {
throw new TypeError('Cannot define a method called ' + name);
} // @ts-ignore: dynamic extension of the class instance is expected.
this[name] = this._callFunctionWithArgs.bind(this, name);
});
}
_callFunctionWithArgs(method, ...args) {
if (this._ending) {
throw new Error('Farm is ended, no more calls can be done to it');
}
return this._farm.doWork(method, ...args);
}
getStderr() {
return this._workerPool.getStderr();
}
getStdout() {
return this._workerPool.getStdout();
}
end() {
if (this._ending) {
throw new Error('Farm is ended, no more calls can be done to it');
}
this._workerPool.end();
this._ending = true;
}
}
exports.default = JestWorker;

View file

@ -0,0 +1,98 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/// <reference types="node" />
import { EventEmitter } from 'events';
import { ForkOptions } from 'child_process';
export declare const CHILD_MESSAGE_INITIALIZE: 0;
export declare const CHILD_MESSAGE_CALL: 1;
export declare const CHILD_MESSAGE_END: 2;
export declare const PARENT_MESSAGE_OK: 0;
export declare const PARENT_MESSAGE_CLIENT_ERROR: 1;
export declare const PARENT_MESSAGE_SETUP_ERROR: 2;
export declare type PARENT_MESSAGE_ERROR = typeof PARENT_MESSAGE_CLIENT_ERROR | typeof PARENT_MESSAGE_SETUP_ERROR;
export { ForkOptions };
export interface WorkerPoolInterface {
getStderr(): NodeJS.ReadableStream;
getStdout(): NodeJS.ReadableStream;
getWorkers(): Array<WorkerInterface>;
createWorker(options: WorkerOptions): WorkerInterface;
send(workerId: number, request: ChildMessage, onStart: OnStart, onEnd: OnEnd): void;
end(): void;
}
export interface WorkerInterface {
send(request: ChildMessage, onProcessStart: OnStart, onProcessEnd: OnEnd): void;
getWorkerId(): number;
getStderr(): NodeJS.ReadableStream | null;
getStdout(): NodeJS.ReadableStream | null;
onExit(exitCode: number): void;
onMessage(message: ParentMessage): void;
}
export declare type FarmOptions = {
computeWorkerKey?: (method: string, ...args: Array<unknown>) => string | null;
exposedMethods?: ReadonlyArray<string>;
forkOptions?: ForkOptions;
setupArgs?: Array<unknown>;
maxRetries?: number;
numWorkers?: number;
WorkerPool?: (workerPath: string, options?: WorkerPoolOptions) => WorkerPoolInterface;
enableWorkerThreads?: boolean;
};
export declare type WorkerPoolOptions = {
setupArgs: Array<unknown>;
forkOptions: ForkOptions;
maxRetries: number;
numWorkers: number;
enableWorkerThreads: boolean;
};
export declare type WorkerOptions = {
forkOptions: ForkOptions;
setupArgs: Array<unknown>;
maxRetries: number;
workerId: number;
workerPath: string;
};
export declare type MessagePort = typeof EventEmitter & {
postMessage(message: unknown): void;
};
export declare type MessageChannel = {
port1: MessagePort;
port2: MessagePort;
};
export declare type ChildMessageInitialize = [typeof CHILD_MESSAGE_INITIALIZE, // type
boolean, // processed
string, // file
// file
Array<unknown> | undefined, // setupArgs
// setupArgs
MessagePort | undefined];
export declare type ChildMessageCall = [typeof CHILD_MESSAGE_CALL, // type
boolean, // processed
string, // method
Array<unknown>];
export declare type ChildMessageEnd = [typeof CHILD_MESSAGE_END, // type
boolean];
export declare type ChildMessage = ChildMessageInitialize | ChildMessageCall | ChildMessageEnd;
export declare type ParentMessageOk = [typeof PARENT_MESSAGE_OK, // type
unknown];
export declare type ParentMessageError = [PARENT_MESSAGE_ERROR, // type
string, // constructor
string, // message
string, // stack
unknown];
export declare type ParentMessage = ParentMessageOk | ParentMessageError;
export declare type OnStart = (worker: WorkerInterface) => void;
export declare type OnEnd = (err: Error | null, result: unknown) => void;
export declare type QueueChildMessage = {
request: ChildMessage;
onStart: OnStart;
onEnd: OnEnd;
};
export declare type QueueItem = {
task: QueueChildMessage;
next: QueueItem | null;
};
//# sourceMappingURL=types.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH,OAAO,EAAC,YAAY,EAAC,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAM1C,eAAO,MAAM,wBAAwB,EAAE,CAAK,CAAC;AAC7C,eAAO,MAAM,kBAAkB,EAAE,CAAK,CAAC;AACvC,eAAO,MAAM,iBAAiB,EAAE,CAAK,CAAC;AAEtC,eAAO,MAAM,iBAAiB,EAAE,CAAK,CAAC;AACtC,eAAO,MAAM,2BAA2B,EAAE,CAAK,CAAC;AAChD,eAAO,MAAM,0BAA0B,EAAE,CAAK,CAAC;AAE/C,oBAAY,oBAAoB,GAC5B,OAAO,2BAA2B,GAClC,OAAO,0BAA0B,CAAC;AAItC,OAAO,EAAC,WAAW,EAAC,CAAC;AAErB,MAAM,WAAW,mBAAmB;IAClC,SAAS,IAAI,MAAM,CAAC,cAAc,CAAC;IACnC,SAAS,IAAI,MAAM,CAAC,cAAc,CAAC;IACnC,UAAU,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;IACrC,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,eAAe,CAAC;IACtD,IAAI,CACF,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,KAAK,GACX,IAAI,CAAC;IACR,GAAG,IAAI,IAAI,CAAC;CACb;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,CACF,OAAO,EAAE,YAAY,EACrB,cAAc,EAAE,OAAO,EACvB,YAAY,EAAE,KAAK,GAClB,IAAI,CAAC;IACR,WAAW,IAAI,MAAM,CAAC;IACtB,SAAS,IAAI,MAAM,CAAC,cAAc,GAAG,IAAI,CAAC;IAC1C,SAAS,IAAI,MAAM,CAAC,cAAc,GAAG,IAAI,CAAC;IAC1C,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAAC;CACzC;AAED,oBAAY,WAAW,GAAG;IACxB,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,MAAM,GAAG,IAAI,CAAC;IAC9E,cAAc,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACvC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,SAAS,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,CACX,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,KACxB,mBAAmB,CAAC;IACzB,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B,CAAC;AAEF,oBAAY,iBAAiB,GAAG;IAC9B,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAC1B,WAAW,EAAE,WAAW,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB,EAAE,OAAO,CAAC;CAC9B,CAAC;AAEF,oBAAY,aAAa,GAAG;IAC1B,WAAW,EAAE,WAAW,CAAC;IACzB,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAIF,oBAAY,WAAW,GAAG,OAAO,YAAY,GAAG;IAC9C,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;CACrC,CAAC;AAEF,oBAAY,cAAc,GAAG;IAC3B,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,EAAE,WAAW,CAAC;CACpB,CAAC;AAEF,oBAAY,sBAAsB,GAAG,CACnC,OAAO,wBAAwB,EAAE,OAAO;AACxC,OAAO,EAAE,YAAY;AACrB,MAAM,EAAE,OAAO;AACf,AADQ,OAAO;AACf,KAAK,CAAC,OAAO,CAAC,GAAG,SAAS,EAAE,YAAY;AACxC,AAD4B,YAAY;AACxC,WAAW,GAAG,SAAS,CACxB,CAAC;AAEF,oBAAY,gBAAgB,GAAG,CAC7B,OAAO,kBAAkB,EAAE,OAAO;AAClC,OAAO,EAAE,YAAY;AACrB,MAAM,EAAE,SAAS;AACjB,KAAK,CAAC,OAAO,CAAC,CACf,CAAC;AAEF,oBAAY,eAAe,GAAG,CAC5B,OAAO,iBAAiB,EAAE,OAAO;AACjC,OAAO,CACR,CAAC;AAEF,oBAAY,YAAY,GACpB,sBAAsB,GACtB,gBAAgB,GAChB,eAAe,CAAC;AAIpB,oBAAY,eAAe,GAAG,CAC5B,OAAO,iBAAiB,EAAE,OAAO;AACjC,OAAO,CACR,CAAC;AAEF,oBAAY,kBAAkB,GAAG,CAC/B,oBAAoB,EAAE,OAAO;AAC7B,MAAM,EAAE,cAAc;AACtB,MAAM,EAAE,UAAU;AAClB,MAAM,EAAE,QAAQ;AAChB,OAAO,CACR,CAAC;AAEF,oBAAY,aAAa,GAAG,eAAe,GAAG,kBAAkB,CAAC;AAIjE,oBAAY,OAAO,GAAG,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;AACxD,oBAAY,KAAK,GAAG,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;AAEjE,oBAAY,iBAAiB,GAAG;IAC9B,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC;CACd,CAAC;AAEF,oBAAY,SAAS,GAAG;IACtB,IAAI,EAAE,iBAAiB,CAAC;IACxB,IAAI,EAAE,SAAS,GAAG,IAAI,CAAC;CACxB,CAAC"}

View file

@ -0,0 +1,43 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
Object.defineProperty(exports, 'ForkOptions', {
enumerable: true,
get: function get() {
return _child_process().ForkOptions;
}
});
exports.PARENT_MESSAGE_SETUP_ERROR = exports.PARENT_MESSAGE_CLIENT_ERROR = exports.PARENT_MESSAGE_OK = exports.CHILD_MESSAGE_END = exports.CHILD_MESSAGE_CALL = exports.CHILD_MESSAGE_INITIALIZE = void 0;
function _child_process() {
const data = require('child_process');
_child_process = function _child_process() {
return data;
};
return data;
}
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
// Because of the dynamic nature of a worker communication process, all messages
// coming from any of the other processes cannot be typed. Thus, many types
const CHILD_MESSAGE_INITIALIZE = 0;
exports.CHILD_MESSAGE_INITIALIZE = CHILD_MESSAGE_INITIALIZE;
const CHILD_MESSAGE_CALL = 1;
exports.CHILD_MESSAGE_CALL = CHILD_MESSAGE_CALL;
const CHILD_MESSAGE_END = 2;
exports.CHILD_MESSAGE_END = CHILD_MESSAGE_END;
const PARENT_MESSAGE_OK = 0;
exports.PARENT_MESSAGE_OK = PARENT_MESSAGE_OK;
const PARENT_MESSAGE_CLIENT_ERROR = 1;
exports.PARENT_MESSAGE_CLIENT_ERROR = PARENT_MESSAGE_CLIENT_ERROR;
const PARENT_MESSAGE_SETUP_ERROR = 2;
exports.PARENT_MESSAGE_SETUP_ERROR = PARENT_MESSAGE_SETUP_ERROR;

View file

@ -0,0 +1,47 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/// <reference types="node" />
import { WorkerInterface, ChildMessage, OnEnd, OnStart, WorkerOptions, ParentMessage } from '../types';
/**
* This class wraps the child process and provides a nice interface to
* communicate with. It takes care of:
*
* - Re-spawning the process if it dies.
* - Queues calls while the worker is busy.
* - Re-sends the requests if the worker blew up.
*
* The reason for queueing them here (since childProcess.send also has an
* internal queue) is because the worker could be doing asynchronous work, and
* this would lead to the child process to read its receiving buffer and start a
* second call. By queueing calls here, we don't send the next call to the
* children until we receive the result of the previous one.
*
* As soon as a request starts to be processed by a worker, its "processed"
* field is changed to "true", so that other workers which might encounter the
* same call skip it.
*/
export default class ChildProcessWorker implements WorkerInterface {
private _child;
private _options;
private _onProcessEnd;
private _fakeStream;
private _request;
private _retries;
private _stderr;
private _stdout;
constructor(options: WorkerOptions);
initialize(): void;
private _shutdown;
onMessage(response: ParentMessage): void;
onExit(exitCode: number): void;
send(request: ChildMessage, onProcessStart: OnStart, onProcessEnd: OnEnd): void;
getWorkerId(): number;
getStdout(): NodeJS.ReadableStream | null;
getStderr(): NodeJS.ReadableStream | null;
private _getFakeStream;
}
//# sourceMappingURL=ChildProcessWorker.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"ChildProcessWorker.d.ts","sourceRoot":"","sources":["../../src/workers/ChildProcessWorker.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAOH,OAAO,EAKL,eAAe,EACf,YAAY,EACZ,KAAK,EACL,OAAO,EACP,aAAa,EACb,aAAa,EACd,MAAM,UAAU,CAAC;AAElB;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,OAAO,OAAO,kBAAmB,YAAW,eAAe;IAChE,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,QAAQ,CAAU;IAC1B,OAAO,CAAC,OAAO,CAAwC;IACvD,OAAO,CAAC,OAAO,CAAwC;gBAE3C,OAAO,EAAE,aAAa;IAUlC,UAAU;IAiEV,OAAO,CAAC,SAAS;IAQjB,SAAS,CAAC,QAAQ,EAAE,aAAa;IA6CjC,MAAM,CAAC,QAAQ,EAAE,MAAM;IAYvB,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK;IAcxE,WAAW;IAIX,SAAS,IAAI,MAAM,CAAC,cAAc,GAAG,IAAI;IAIzC,SAAS,IAAI,MAAM,CAAC,cAAc,GAAG,IAAI;IAIzC,OAAO,CAAC,cAAc;CAMvB"}

View file

@ -0,0 +1,310 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.default = void 0;
function _child_process() {
const data = _interopRequireDefault(require('child_process'));
_child_process = function _child_process() {
return data;
};
return data;
}
function _stream() {
const data = require('stream');
_stream = function _stream() {
return data;
};
return data;
}
function _mergeStream() {
const data = _interopRequireDefault(require('merge-stream'));
_mergeStream = function _mergeStream() {
return data;
};
return data;
}
function _supportsColor() {
const data = _interopRequireDefault(require('supports-color'));
_supportsColor = function _supportsColor() {
return data;
};
return data;
}
var _types = require('../types');
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {default: obj};
}
function _objectSpread(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i] != null ? arguments[i] : {};
var ownKeys = Object.keys(source);
if (typeof Object.getOwnPropertySymbols === 'function') {
ownKeys = ownKeys.concat(
Object.getOwnPropertySymbols(source).filter(function(sym) {
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
})
);
}
ownKeys.forEach(function(key) {
_defineProperty(target, key, source[key]);
});
}
return target;
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
/**
* This class wraps the child process and provides a nice interface to
* communicate with. It takes care of:
*
* - Re-spawning the process if it dies.
* - Queues calls while the worker is busy.
* - Re-sends the requests if the worker blew up.
*
* The reason for queueing them here (since childProcess.send also has an
* internal queue) is because the worker could be doing asynchronous work, and
* this would lead to the child process to read its receiving buffer and start a
* second call. By queueing calls here, we don't send the next call to the
* children until we receive the result of the previous one.
*
* As soon as a request starts to be processed by a worker, its "processed"
* field is changed to "true", so that other workers which might encounter the
* same call skip it.
*/
class ChildProcessWorker {
constructor(options) {
_defineProperty(this, '_child', void 0);
_defineProperty(this, '_options', void 0);
_defineProperty(this, '_onProcessEnd', void 0);
_defineProperty(this, '_fakeStream', void 0);
_defineProperty(this, '_request', void 0);
_defineProperty(this, '_retries', void 0);
_defineProperty(this, '_stderr', void 0);
_defineProperty(this, '_stdout', void 0);
this._options = options;
this._fakeStream = null;
this._request = null;
this._stderr = null;
this._stdout = null;
this.initialize();
}
initialize() {
const forceColor = _supportsColor().default.stdout
? {
FORCE_COLOR: '1'
}
: {};
const child = _child_process().default.fork(
require.resolve('./processChild'),
[],
_objectSpread(
{
cwd: process.cwd(),
env: _objectSpread(
{},
process.env,
{
JEST_WORKER_ID: String(this._options.workerId + 1)
},
forceColor
),
// Suppress --debug / --inspect flags while preserving others (like --harmony).
execArgv: process.execArgv.filter(v => !/^--(debug|inspect)/.test(v)),
silent: true
},
this._options.forkOptions
)
);
if (child.stdout) {
if (!this._stdout) {
// We need to add a permanent stream to the merged stream to prevent it
// from ending when the subprocess stream ends
this._stdout = (0, _mergeStream().default)(this._getFakeStream());
}
this._stdout.add(child.stdout);
}
if (child.stderr) {
if (!this._stderr) {
// We need to add a permanent stream to the merged stream to prevent it
// from ending when the subprocess stream ends
this._stderr = (0, _mergeStream().default)(this._getFakeStream());
}
this._stderr.add(child.stderr);
}
child.on('message', this.onMessage.bind(this));
child.on('exit', this.onExit.bind(this));
child.send([
_types.CHILD_MESSAGE_INITIALIZE,
false,
this._options.workerPath,
this._options.setupArgs
]);
this._child = child;
this._retries++; // If we exceeded the amount of retries, we will emulate an error reply
// coming from the child. This avoids code duplication related with cleaning
// the queue, and scheduling the next call.
if (this._retries > this._options.maxRetries) {
const error = new Error('Call retries were exceeded');
this.onMessage([
_types.PARENT_MESSAGE_CLIENT_ERROR,
error.name,
error.message,
error.stack,
{
type: 'WorkerError'
}
]);
}
}
_shutdown() {
// End the temporary streams so the merged streams end too
if (this._fakeStream) {
this._fakeStream.end();
this._fakeStream = null;
}
}
onMessage(response) {
let error;
switch (response[0]) {
case _types.PARENT_MESSAGE_OK:
this._onProcessEnd(null, response[1]);
break;
case _types.PARENT_MESSAGE_CLIENT_ERROR:
error = response[4];
if (error != null && typeof error === 'object') {
const extra = error; // @ts-ignore: no index
const NativeCtor = global[response[1]];
const Ctor = typeof NativeCtor === 'function' ? NativeCtor : Error;
error = new Ctor(response[2]);
error.type = response[1];
error.stack = response[3];
for (const key in extra) {
// @ts-ignore: adding custom properties to errors.
error[key] = extra[key];
}
}
this._onProcessEnd(error, null);
break;
case _types.PARENT_MESSAGE_SETUP_ERROR:
error = new Error('Error when calling setup: ' + response[2]); // @ts-ignore: adding custom properties to errors.
error.type = response[1];
error.stack = response[3];
this._onProcessEnd(error, null);
break;
default:
throw new TypeError('Unexpected response from worker: ' + response[0]);
}
}
onExit(exitCode) {
if (exitCode !== 0) {
this.initialize();
if (this._request) {
this._child.send(this._request);
}
} else {
this._shutdown();
}
}
send(request, onProcessStart, onProcessEnd) {
onProcessStart(this);
this._onProcessEnd = (...args) => {
// Clean the request to avoid sending past requests to workers that fail
// while waiting for a new request (timers, unhandled rejections...)
this._request = null;
return onProcessEnd(...args);
};
this._request = request;
this._retries = 0;
this._child.send(request);
}
getWorkerId() {
return this._options.workerId;
}
getStdout() {
return this._stdout;
}
getStderr() {
return this._stderr;
}
_getFakeStream() {
if (!this._fakeStream) {
this._fakeStream = new (_stream()).PassThrough();
}
return this._fakeStream;
}
}
exports.default = ChildProcessWorker;

View file

@ -0,0 +1,29 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/// <reference types="node" />
import { ChildMessage, OnEnd, OnStart, WorkerOptions, WorkerInterface, ParentMessage } from '../types';
export default class ExperimentalWorker implements WorkerInterface {
private _worker;
private _options;
private _onProcessEnd;
private _request;
private _retries;
private _stderr;
private _stdout;
private _fakeStream;
constructor(options: WorkerOptions);
initialize(): void;
private _shutdown;
onMessage(response: ParentMessage): void;
onExit(exitCode: number): void;
send(request: ChildMessage, onProcessStart: OnStart, onProcessEnd: OnEnd): void;
getWorkerId(): number;
getStdout(): NodeJS.ReadableStream | null;
getStderr(): NodeJS.ReadableStream | null;
private _getFakeStream;
}
//# sourceMappingURL=NodeThreadsWorker.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"NodeThreadsWorker.d.ts","sourceRoot":"","sources":["../../src/workers/NodeThreadsWorker.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AASH,OAAO,EAKL,YAAY,EACZ,KAAK,EACL,OAAO,EACP,aAAa,EACb,eAAe,EACf,aAAa,EACd,MAAM,UAAU,CAAC;AAElB,MAAM,CAAC,OAAO,OAAO,kBAAmB,YAAW,eAAe;IAChE,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,QAAQ,CAAU;IAC1B,OAAO,CAAC,OAAO,CAAwC;IACvD,OAAO,CAAC,OAAO,CAAwC;IACvD,OAAO,CAAC,WAAW,CAAqB;gBAE5B,OAAO,EAAE,aAAa;IAUlC,UAAU;IAkEV,OAAO,CAAC,SAAS;IAQjB,SAAS,CAAC,QAAQ,EAAE,aAAa;IA2CjC,MAAM,CAAC,QAAQ,EAAE,MAAM;IAYvB,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK;IAexE,WAAW;IAIX,SAAS,IAAI,MAAM,CAAC,cAAc,GAAG,IAAI;IAIzC,SAAS,IAAI,MAAM,CAAC,cAAc,GAAG,IAAI;IAIzC,OAAO,CAAC,cAAc;CAMvB"}

View file

@ -0,0 +1,289 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.default = void 0;
function _path() {
const data = _interopRequireDefault(require('path'));
_path = function _path() {
return data;
};
return data;
}
function _stream() {
const data = require('stream');
_stream = function _stream() {
return data;
};
return data;
}
function _worker_threads() {
const data = require('worker_threads');
_worker_threads = function _worker_threads() {
return data;
};
return data;
}
function _mergeStream() {
const data = _interopRequireDefault(require('merge-stream'));
_mergeStream = function _mergeStream() {
return data;
};
return data;
}
var _types = require('../types');
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {default: obj};
}
function _objectSpread(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i] != null ? arguments[i] : {};
var ownKeys = Object.keys(source);
if (typeof Object.getOwnPropertySymbols === 'function') {
ownKeys = ownKeys.concat(
Object.getOwnPropertySymbols(source).filter(function(sym) {
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
})
);
}
ownKeys.forEach(function(key) {
_defineProperty(target, key, source[key]);
});
}
return target;
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
class ExperimentalWorker {
constructor(options) {
_defineProperty(this, '_worker', void 0);
_defineProperty(this, '_options', void 0);
_defineProperty(this, '_onProcessEnd', void 0);
_defineProperty(this, '_request', void 0);
_defineProperty(this, '_retries', void 0);
_defineProperty(this, '_stderr', void 0);
_defineProperty(this, '_stdout', void 0);
_defineProperty(this, '_fakeStream', void 0);
this._options = options;
this._request = null;
this._stderr = null;
this._stdout = null;
this._fakeStream = null;
this.initialize();
}
initialize() {
this._worker = new (_worker_threads()).Worker(
_path().default.resolve(__dirname, './threadChild.js'),
{
eval: false,
stderr: true,
stdout: true,
workerData: _objectSpread(
{
cwd: process.cwd(),
env: _objectSpread({}, process.env, {
JEST_WORKER_ID: String(this._options.workerId + 1) // 0-indexed workerId, 1-indexed JEST_WORKER_ID
}),
// Suppress --debug / --inspect flags while preserving others (like --harmony).
execArgv: process.execArgv.filter(
v => !/^--(debug|inspect)/.test(v)
),
silent: true
},
this._options.forkOptions
)
}
);
if (this._worker.stdout) {
if (!this._stdout) {
// We need to add a permanent stream to the merged stream to prevent it
// from ending when the subprocess stream ends
this._stdout = (0, _mergeStream().default)(this._getFakeStream());
}
this._stdout.add(this._worker.stdout);
}
if (this._worker.stderr) {
if (!this._stderr) {
// We need to add a permanent stream to the merged stream to prevent it
// from ending when the subprocess stream ends
this._stderr = (0, _mergeStream().default)(this._getFakeStream());
}
this._stderr.add(this._worker.stderr);
}
this._worker.on('message', this.onMessage.bind(this));
this._worker.on('exit', this.onExit.bind(this));
this._worker.postMessage([
_types.CHILD_MESSAGE_INITIALIZE,
false,
this._options.workerPath,
this._options.setupArgs
]);
this._retries++; // If we exceeded the amount of retries, we will emulate an error reply
// coming from the child. This avoids code duplication related with cleaning
// the queue, and scheduling the next call.
if (this._retries > this._options.maxRetries) {
const error = new Error('Call retries were exceeded');
this.onMessage([
_types.PARENT_MESSAGE_CLIENT_ERROR,
error.name,
error.message,
error.stack,
{
type: 'WorkerError'
}
]);
}
}
_shutdown() {
// End the permanent stream so the merged stream end too
if (this._fakeStream) {
this._fakeStream.end();
this._fakeStream = null;
}
}
onMessage(response) {
let error;
switch (response[0]) {
case _types.PARENT_MESSAGE_OK:
this._onProcessEnd(null, response[1]);
break;
case _types.PARENT_MESSAGE_CLIENT_ERROR:
error = response[4];
if (error != null && typeof error === 'object') {
const extra = error; // @ts-ignore: no index
const NativeCtor = global[response[1]];
const Ctor = typeof NativeCtor === 'function' ? NativeCtor : Error;
error = new Ctor(response[2]);
error.type = response[1];
error.stack = response[3];
for (const key in extra) {
// @ts-ignore: no index
error[key] = extra[key];
}
}
this._onProcessEnd(error, null);
break;
case _types.PARENT_MESSAGE_SETUP_ERROR:
error = new Error('Error when calling setup: ' + response[2]); // @ts-ignore: adding custom properties to errors.
error.type = response[1];
error.stack = response[3];
this._onProcessEnd(error, null);
break;
default:
throw new TypeError('Unexpected response from worker: ' + response[0]);
}
}
onExit(exitCode) {
if (exitCode !== 0) {
this.initialize();
if (this._request) {
this._worker.postMessage(this._request);
}
} else {
this._shutdown();
}
}
send(request, onProcessStart, onProcessEnd) {
onProcessStart(this);
this._onProcessEnd = (...args) => {
// Clean the request to avoid sending past requests to workers that fail
// while waiting for a new request (timers, unhandled rejections...)
this._request = null;
return onProcessEnd(...args);
};
this._request = request;
this._retries = 0;
this._worker.postMessage(request);
}
getWorkerId() {
return this._options.workerId;
}
getStdout() {
return this._stdout;
}
getStderr() {
return this._stderr;
}
_getFakeStream() {
if (!this._fakeStream) {
this._fakeStream = new (_stream()).PassThrough();
}
return this._fakeStream;
}
}
exports.default = ExperimentalWorker;

View file

@ -0,0 +1,8 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
export {};
//# sourceMappingURL=processChild.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"processChild.d.ts","sourceRoot":"","sources":["../../src/workers/processChild.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}

View file

@ -0,0 +1,166 @@
'use strict';
var _types = require('../types');
function _objectSpread(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i] != null ? arguments[i] : {};
var ownKeys = Object.keys(source);
if (typeof Object.getOwnPropertySymbols === 'function') {
ownKeys = ownKeys.concat(
Object.getOwnPropertySymbols(source).filter(function(sym) {
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
})
);
}
ownKeys.forEach(function(key) {
_defineProperty(target, key, source[key]);
});
}
return target;
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
let file = null;
let setupArgs = [];
let initialized = false;
/**
* This file is a small bootstrapper for workers. It sets up the communication
* between the worker and the parent process, interpreting parent messages and
* sending results back.
*
* The file loaded will be lazily initialized the first time any of the workers
* is called. This is done for optimal performance: if the farm is initialized,
* but no call is made to it, child Node processes will be consuming the least
* possible amount of memory.
*
* If an invalid message is detected, the child will exit (by throwing) with a
* non-zero exit code.
*/
process.on('message', request => {
switch (request[0]) {
case _types.CHILD_MESSAGE_INITIALIZE:
const init = request;
file = init[2];
setupArgs = request[3];
break;
case _types.CHILD_MESSAGE_CALL:
const call = request;
execMethod(call[2], call[3]);
break;
case _types.CHILD_MESSAGE_END:
end();
break;
default:
throw new TypeError(
'Unexpected request from parent process: ' + request[0]
);
}
});
function reportSuccess(result) {
if (!process || !process.send) {
throw new Error('Child can only be used on a forked process');
}
process.send([_types.PARENT_MESSAGE_OK, result]);
}
function reportClientError(error) {
return reportError(error, _types.PARENT_MESSAGE_CLIENT_ERROR);
}
function reportInitializeError(error) {
return reportError(error, _types.PARENT_MESSAGE_SETUP_ERROR);
}
function reportError(error, type) {
if (!process || !process.send) {
throw new Error('Child can only be used on a forked process');
}
if (error == null) {
error = new Error('"null" or "undefined" thrown');
}
process.send([
type,
error.constructor && error.constructor.name,
error.message,
error.stack,
typeof error === 'object' ? _objectSpread({}, error) : error
]);
}
function end() {
const main = require(file);
if (!main.teardown) {
exitProcess();
return;
}
execFunction(main.teardown, main, [], exitProcess, exitProcess);
}
function exitProcess() {
process.exit(0);
}
function execMethod(method, args) {
const main = require(file);
let fn;
if (method === 'default') {
fn = main.__esModule ? main['default'] : main;
} else {
fn = main[method];
}
function execHelper() {
execFunction(fn, main, args, reportSuccess, reportClientError);
}
if (initialized || !main.setup) {
execHelper();
return;
}
initialized = true;
execFunction(main.setup, main, setupArgs, execHelper, reportInitializeError);
}
function execFunction(fn, ctx, args, onResult, onError) {
let result;
try {
result = fn.apply(ctx, args);
} catch (err) {
onError(err);
return;
}
if (result && typeof result.then === 'function') {
result.then(onResult, onError);
} else {
onResult(result);
}
}

View file

@ -0,0 +1,8 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
export {};
//# sourceMappingURL=threadChild.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"threadChild.d.ts","sourceRoot":"","sources":["../../src/workers/threadChild.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}

View file

@ -0,0 +1,176 @@
'use strict';
function _worker_threads() {
const data = require('worker_threads');
_worker_threads = function _worker_threads() {
return data;
};
return data;
}
var _types = require('../types');
function _objectSpread(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i] != null ? arguments[i] : {};
var ownKeys = Object.keys(source);
if (typeof Object.getOwnPropertySymbols === 'function') {
ownKeys = ownKeys.concat(
Object.getOwnPropertySymbols(source).filter(function(sym) {
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
})
);
}
ownKeys.forEach(function(key) {
_defineProperty(target, key, source[key]);
});
}
return target;
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
let file = null;
let setupArgs = [];
let initialized = false;
/**
* This file is a small bootstrapper for workers. It sets up the communication
* between the worker and the parent process, interpreting parent messages and
* sending results back.
*
* The file loaded will be lazily initialized the first time any of the workers
* is called. This is done for optimal performance: if the farm is initialized,
* but no call is made to it, child Node processes will be consuming the least
* possible amount of memory.
*
* If an invalid message is detected, the child will exit (by throwing) with a
* non-zero exit code.
*/
_worker_threads().parentPort.on('message', request => {
switch (request[0]) {
case _types.CHILD_MESSAGE_INITIALIZE:
const init = request;
file = init[2];
setupArgs = request[3];
break;
case _types.CHILD_MESSAGE_CALL:
const call = request;
execMethod(call[2], call[3]);
break;
case _types.CHILD_MESSAGE_END:
end();
break;
default:
throw new TypeError(
'Unexpected request from parent process: ' + request[0]
);
}
});
function reportSuccess(result) {
if (_worker_threads().isMainThread) {
throw new Error('Child can only be used on a forked process');
}
_worker_threads().parentPort.postMessage([_types.PARENT_MESSAGE_OK, result]);
}
function reportClientError(error) {
return reportError(error, _types.PARENT_MESSAGE_CLIENT_ERROR);
}
function reportInitializeError(error) {
return reportError(error, _types.PARENT_MESSAGE_SETUP_ERROR);
}
function reportError(error, type) {
if (_worker_threads().isMainThread) {
throw new Error('Child can only be used on a forked process');
}
if (error == null) {
error = new Error('"null" or "undefined" thrown');
}
_worker_threads().parentPort.postMessage([
type,
error.constructor && error.constructor.name,
error.message,
error.stack,
typeof error === 'object' ? _objectSpread({}, error) : error
]);
}
function end() {
const main = require(file);
if (!main.teardown) {
exitProcess();
return;
}
execFunction(main.teardown, main, [], exitProcess, exitProcess);
}
function exitProcess() {
process.exit(0);
}
function execMethod(method, args) {
const main = require(file);
let fn;
if (method === 'default') {
fn = main.__esModule ? main['default'] : main;
} else {
fn = main[method];
}
function execHelper() {
execFunction(fn, main, args, reportSuccess, reportClientError);
}
if (initialized || !main.setup) {
execHelper();
return;
}
initialized = true;
execFunction(main.setup, main, setupArgs, execHelper, reportInitializeError);
}
function execFunction(fn, ctx, args, onResult, onError) {
let result;
try {
result = fn.apply(ctx, args);
} catch (err) {
onError(err);
return;
}
if (result && typeof result.then === 'function') {
result.then(onResult, onError);
} else {
onResult(result);
}
}

View file

@ -0,0 +1,29 @@
{
"name": "jest-worker",
"version": "24.9.0",
"repository": {
"type": "git",
"url": "https://github.com/facebook/jest.git",
"directory": "packages/jest-worker"
},
"license": "MIT",
"main": "build/index.js",
"types": "build/index.d.ts",
"dependencies": {
"merge-stream": "^2.0.0",
"supports-color": "^6.1.0"
},
"devDependencies": {
"@types/merge-stream": "^1.1.2",
"@types/supports-color": "^5.3.0",
"get-stream": "^4.1.0",
"worker-farm": "^1.6.0"
},
"engines": {
"node": ">= 6"
},
"publishConfig": {
"access": "public"
},
"gitHead": "9ad0f4bc6b8bdd94989804226c28c9960d9da7d1"
}

View file

@ -0,0 +1,11 @@
{
"spellright.language": [
"en"
],
"spellright.documentTypes": [
"markdown",
"latex",
"plaintext",
"javascript"
]
}

View file

@ -0,0 +1,27 @@
Copyright 2014 Yahoo! Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Yahoo! Inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL YAHOO! INC. BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,144 @@
Serialize JavaScript
====================
Serialize JavaScript to a _superset_ of JSON that includes regular expressions, dates and functions.
[![npm Version][npm-badge]][npm]
[![Dependency Status][david-badge]][david]
[![Build Status][travis-badge]][travis]
## Overview
The code in this package began its life as an internal module to [express-state][]. To expand its usefulness, it now lives as `serialize-javascript` — an independent package on npm.
You're probably wondering: **What about `JSON.stringify()`!?** We've found that sometimes we need to serialize JavaScript **functions**, **regexps**, **dates**, **sets** or **maps**. A great example is a web app that uses client-side URL routing where the route definitions are regexps that need to be shared from the server to the client. But this module is also great for communicating between node processes.
The string returned from this package's single export function is literal JavaScript which can be saved to a `.js` file, or be embedded into an HTML document by making the content of a `<script>` element.
> **HTML characters and JavaScript line terminators are escaped automatically.**
Please note that serialization for ES6 Sets & Maps requires support for `Array.from` (not available in IE or Node < 0.12), or an `Array.from` polyfill.
## Installation
Install using npm:
```shell
$ npm install serialize-javascript
```
## Usage
```js
var serialize = require('serialize-javascript');
serialize({
str : 'string',
num : 0,
obj : {foo: 'foo'},
arr : [1, 2, 3],
bool : true,
nil : null,
undef: undefined,
inf : Infinity,
date : new Date("Thu, 28 Apr 2016 22:02:17 GMT"),
map : new Map([['hello', 'world']]),
set : new Set([123, 456]),
fn : function echo(arg) { return arg; },
re : /([^\s]+)/g,
big : BigInt(10),
});
```
The above will produce the following string output:
```js
'{"str":"string","num":0,"obj":{"foo":"foo"},"arr":[1,2,3],"bool":true,"nil":null,"undef":undefined,"inf":Infinity,"date":new Date("2016-04-28T22:02:17.000Z"),"map":new Map([["hello","world"]]),"set":new Set([123,456]),"fn":function echo(arg) { return arg; },"re":new RegExp("([^\\\\s]+)", "g"),"big":BigInt("10")}'
```
Note: to produced a beautified string, you can pass an optional second argument to `serialize()` to define the number of spaces to be used for the indentation.
### Automatic Escaping of HTML Characters
A primary feature of this package is to serialize code to a string of literal JavaScript which can be embedded in an HTML document by adding it as the contents of the `<script>` element. In order to make this safe, HTML characters and JavaScript line terminators are escaped automatically.
```js
serialize({
haxorXSS: '</script>'
});
```
The above will produce the following string, HTML-escaped output which is safe to put into an HTML document as it will not cause the inline script element to terminate:
```js
'{"haxorXSS":"\\u003C\\u002Fscript\\u003E"}'
```
> You can pass an optional `unsafe` argument to `serialize()` for straight serialization.
### Options
The `serialize()` function accepts an `options` object as its second argument. All options are being defaulted to `undefined`:
#### `options.space`
This option is the same as the `space` argument that can be passed to [`JSON.stringify`][JSON.stringify]. It can be used to add whitespace and indentation to the serialized output to make it more readable.
```js
serialize(obj, {space: 2});
```
#### `options.isJSON`
This option is a signal to `serialize()` that the object being serialized does not contain any function or regexps values. This enables a hot-path that allows serialization to be over 3x faster. If you're serializing a lot of data, and know its pure JSON, then you can enable this option for a speed-up.
**Note:** That when using this option, the output will still be escaped to protect against XSS.
```js
serialize(obj, {isJSON: true});
```
#### `options.unsafe`
This option is to signal `serialize()` that we want to do a straight conversion, without the XSS protection. This options needs to be explicitly set to `true`. HTML characters and JavaScript line terminators will not be escaped. You will have to roll your own.
```js
serialize(obj, {unsafe: true});
```
#### `options.ignoreFunction`
This option is to signal `serialize()` that we do not want serialize JavaScript function.
Just treat function like `JSON.stringify` do, but other features will work as expected.
```js
serialize(obj, {ignoreFunction: true});
```
## Deserializing
For some use cases you might also need to deserialize the string. This is explicitly not part of this module. However, you can easily write it yourself:
```js
function deserialize(serializedJavascript){
return eval('(' + serializedJavascript + ')');
}
```
**Note:** Don't forget the parentheses around the serialized javascript, as the opening bracket `{` will be considered to be the start of a body.
## License
This software is free to use under the Yahoo! Inc. BSD license.
See the [LICENSE file][LICENSE] for license text and copyright information.
[npm]: https://www.npmjs.org/package/serialize-javascript
[npm-badge]: https://img.shields.io/npm/v/serialize-javascript.svg?style=flat-square
[david]: https://david-dm.org/yahoo/serialize-javascript
[david-badge]: https://img.shields.io/david/yahoo/serialize-javascript.svg?style=flat-square
[travis]: https://travis-ci.org/yahoo/serialize-javascript
[travis-badge]: https://img.shields.io/travis/yahoo/serialize-javascript.svg?style=flat-square
[express-state]: https://github.com/yahoo/express-state
[JSON.stringify]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
[LICENSE]: https://github.com/yahoo/serialize-javascript/blob/master/LICENSE

View file

@ -0,0 +1,247 @@
/*
Copyright (c) 2014, Yahoo! Inc. All rights reserved.
Copyrights licensed under the New BSD License.
See the accompanying LICENSE file for terms.
*/
'use strict';
var randomBytes = require('randombytes');
// Generate an internal UID to make the regexp pattern harder to guess.
var UID_LENGTH = 16;
var UID = generateUID();
var PLACE_HOLDER_REGEXP = new RegExp('(\\\\)?"@__(F|R|D|M|S|U|I|B)-' + UID + '-(\\d+)__@"', 'g');
var IS_NATIVE_CODE_REGEXP = /\{\s*\[native code\]\s*\}/g;
var IS_PURE_FUNCTION = /function.*?\(/;
var IS_ARROW_FUNCTION = /.*?=>.*?/;
var UNSAFE_CHARS_REGEXP = /[<>\/\u2028\u2029]/g;
var RESERVED_SYMBOLS = ['*', 'async'];
// Mapping of unsafe HTML and invalid JavaScript line terminator chars to their
// Unicode char counterparts which are safe to use in JavaScript strings.
var ESCAPED_CHARS = {
'<' : '\\u003C',
'>' : '\\u003E',
'/' : '\\u002F',
'\u2028': '\\u2028',
'\u2029': '\\u2029'
};
function escapeUnsafeChars(unsafeChar) {
return ESCAPED_CHARS[unsafeChar];
}
function generateUID() {
var bytes = randomBytes(UID_LENGTH);
var result = '';
for(var i=0; i<UID_LENGTH; ++i) {
result += bytes[i].toString(16);
}
return result;
}
function deleteFunctions(obj){
var functionKeys = [];
for (var key in obj) {
if (typeof obj[key] === "function") {
functionKeys.push(key);
}
}
for (var i = 0; i < functionKeys.length; i++) {
delete obj[functionKeys[i]];
}
}
module.exports = function serialize(obj, options) {
options || (options = {});
// Backwards-compatibility for `space` as the second argument.
if (typeof options === 'number' || typeof options === 'string') {
options = {space: options};
}
var functions = [];
var regexps = [];
var dates = [];
var maps = [];
var sets = [];
var undefs = [];
var infinities= [];
var bigInts = [];
// Returns placeholders for functions and regexps (identified by index)
// which are later replaced by their string representation.
function replacer(key, value) {
// For nested function
if(options.ignoreFunction){
deleteFunctions(value);
}
if (!value && value !== undefined) {
return value;
}
// If the value is an object w/ a toJSON method, toJSON is called before
// the replacer runs, so we use this[key] to get the non-toJSONed value.
var origValue = this[key];
var type = typeof origValue;
if (type === 'object') {
if(origValue instanceof RegExp) {
return '@__R-' + UID + '-' + (regexps.push(origValue) - 1) + '__@';
}
if(origValue instanceof Date) {
return '@__D-' + UID + '-' + (dates.push(origValue) - 1) + '__@';
}
if(origValue instanceof Map) {
return '@__M-' + UID + '-' + (maps.push(origValue) - 1) + '__@';
}
if(origValue instanceof Set) {
return '@__S-' + UID + '-' + (sets.push(origValue) - 1) + '__@';
}
}
if (type === 'function') {
return '@__F-' + UID + '-' + (functions.push(origValue) - 1) + '__@';
}
if (type === 'undefined') {
return '@__U-' + UID + '-' + (undefs.push(origValue) - 1) + '__@';
}
if (type === 'number' && !isNaN(origValue) && !isFinite(origValue)) {
return '@__I-' + UID + '-' + (infinities.push(origValue) - 1) + '__@';
}
if (type === 'bigint') {
return '@__B-' + UID + '-' + (bigInts.push(origValue) - 1) + '__@';
}
return value;
}
function serializeFunc(fn) {
var serializedFn = fn.toString();
if (IS_NATIVE_CODE_REGEXP.test(serializedFn)) {
throw new TypeError('Serializing native function: ' + fn.name);
}
// pure functions, example: {key: function() {}}
if(IS_PURE_FUNCTION.test(serializedFn)) {
return serializedFn;
}
// arrow functions, example: arg1 => arg1+5
if(IS_ARROW_FUNCTION.test(serializedFn)) {
return serializedFn;
}
var argsStartsAt = serializedFn.indexOf('(');
var def = serializedFn.substr(0, argsStartsAt)
.trim()
.split(' ')
.filter(function(val) { return val.length > 0 });
var nonReservedSymbols = def.filter(function(val) {
return RESERVED_SYMBOLS.indexOf(val) === -1
});
// enhanced literal objects, example: {key() {}}
if(nonReservedSymbols.length > 0) {
return (def.indexOf('async') > -1 ? 'async ' : '') + 'function'
+ (def.join('').indexOf('*') > -1 ? '*' : '')
+ serializedFn.substr(argsStartsAt);
}
// arrow functions
return serializedFn;
}
// Check if the parameter is function
if (options.ignoreFunction && typeof obj === "function") {
obj = undefined;
}
// Protects against `JSON.stringify()` returning `undefined`, by serializing
// to the literal string: "undefined".
if (obj === undefined) {
return String(obj);
}
var str;
// Creates a JSON string representation of the value.
// NOTE: Node 0.12 goes into slow mode with extra JSON.stringify() args.
if (options.isJSON && !options.space) {
str = JSON.stringify(obj);
} else {
str = JSON.stringify(obj, options.isJSON ? null : replacer, options.space);
}
// Protects against `JSON.stringify()` returning `undefined`, by serializing
// to the literal string: "undefined".
if (typeof str !== 'string') {
return String(str);
}
// Replace unsafe HTML and invalid JavaScript line terminator chars with
// their safe Unicode char counterpart. This _must_ happen before the
// regexps and functions are serialized and added back to the string.
if (options.unsafe !== true) {
str = str.replace(UNSAFE_CHARS_REGEXP, escapeUnsafeChars);
}
if (functions.length === 0 && regexps.length === 0 && dates.length === 0 && maps.length === 0 && sets.length === 0 && undefs.length === 0 && infinities.length === 0 && bigInts.length === 0) {
return str;
}
// Replaces all occurrences of function, regexp, date, map and set placeholders in the
// JSON string with their string representations. If the original value can
// not be found, then `undefined` is used.
return str.replace(PLACE_HOLDER_REGEXP, function (match, backSlash, type, valueIndex) {
// The placeholder may not be preceded by a backslash. This is to prevent
// replacing things like `"a\"@__R-<UID>-0__@"` and thus outputting
// invalid JS.
if (backSlash) {
return match;
}
if (type === 'D') {
return "new Date(\"" + dates[valueIndex].toISOString() + "\")";
}
if (type === 'R') {
return "new RegExp(" + serialize(regexps[valueIndex].source) + ", \"" + regexps[valueIndex].flags + "\")";
}
if (type === 'M') {
return "new Map(" + serialize(Array.from(maps[valueIndex].entries()), options) + ")";
}
if (type === 'S') {
return "new Set(" + serialize(Array.from(sets[valueIndex].values()), options) + ")";
}
if (type === 'U') {
return 'undefined'
}
if (type === 'I') {
return infinities[valueIndex];
}
if (type === 'B') {
return "BigInt(\"" + bigInts[valueIndex] + "\")";
}
var fn = functions[valueIndex];
return serializeFunc(fn);
});
}

View file

@ -0,0 +1,36 @@
{
"name": "serialize-javascript",
"version": "4.0.0",
"description": "Serialize JavaScript to a superset of JSON that includes regular expressions and functions.",
"main": "index.js",
"scripts": {
"benchmark": "node -v && node test/benchmark/serialize.js",
"test": "nyc --reporter=lcov mocha test/unit"
},
"repository": {
"type": "git",
"url": "git+https://github.com/yahoo/serialize-javascript.git"
},
"keywords": [
"serialize",
"serialization",
"javascript",
"js",
"json"
],
"author": "Eric Ferraiuolo <edf@ericf.me>",
"license": "BSD-3-Clause",
"bugs": {
"url": "https://github.com/yahoo/serialize-javascript/issues"
},
"homepage": "https://github.com/yahoo/serialize-javascript",
"devDependencies": {
"benchmark": "^2.1.4",
"chai": "^4.1.0",
"mocha": "^7.0.0",
"nyc": "^15.0.0"
},
"dependencies": {
"randombytes": "^2.1.0"
}
}

View file

@ -0,0 +1,5 @@
'use strict';
module.exports = {
stdout: false,
stderr: false
};

View file

@ -0,0 +1,138 @@
'use strict';
const os = require('os');
const hasFlag = require('has-flag');
const {env} = process;
let forceColor;
if (hasFlag('no-color') ||
hasFlag('no-colors') ||
hasFlag('color=false') ||
hasFlag('color=never')) {
forceColor = 0;
} else if (hasFlag('color') ||
hasFlag('colors') ||
hasFlag('color=true') ||
hasFlag('color=always')) {
forceColor = 1;
}
if ('FORCE_COLOR' in env) {
if (env.FORCE_COLOR === true || env.FORCE_COLOR === 'true') {
forceColor = 1;
} else if (env.FORCE_COLOR === false || env.FORCE_COLOR === 'false') {
forceColor = 0;
} else {
forceColor = env.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env.FORCE_COLOR, 10), 3);
}
}
function translateLevel(level) {
if (level === 0) {
return false;
}
return {
level,
hasBasic: true,
has256: level >= 2,
has16m: level >= 3
};
}
function supportsColor(stream) {
if (forceColor === 0) {
return 0;
}
if (hasFlag('color=16m') ||
hasFlag('color=full') ||
hasFlag('color=truecolor')) {
return 3;
}
if (hasFlag('color=256')) {
return 2;
}
if (stream && !stream.isTTY && forceColor === undefined) {
return 0;
}
const min = forceColor || 0;
if (env.TERM === 'dumb') {
return min;
}
if (process.platform === 'win32') {
// Node.js 7.5.0 is the first version of Node.js to include a patch to
// libuv that enables 256 color output on Windows. Anything earlier and it
// won't work. However, here we target Node.js 8 at minimum as it is an LTS
// release, and Node.js 7 is not. Windows 10 build 10586 is the first Windows
// release that supports 256 colors. Windows 10 build 14931 is the first release
// that supports 16m/TrueColor.
const osRelease = os.release().split('.');
if (
Number(process.versions.node.split('.')[0]) >= 8 &&
Number(osRelease[0]) >= 10 &&
Number(osRelease[2]) >= 10586
) {
return Number(osRelease[2]) >= 14931 ? 3 : 2;
}
return 1;
}
if ('CI' in env) {
if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(sign => sign in env) || env.CI_NAME === 'codeship') {
return 1;
}
return min;
}
if ('TEAMCITY_VERSION' in env) {
return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
}
if (env.COLORTERM === 'truecolor') {
return 3;
}
if ('TERM_PROGRAM' in env) {
const version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10);
switch (env.TERM_PROGRAM) {
case 'iTerm.app':
return version >= 3 ? 3 : 2;
case 'Apple_Terminal':
return 2;
// No default
}
}
if (/-256(color)?$/i.test(env.TERM)) {
return 2;
}
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
return 1;
}
if ('COLORTERM' in env) {
return 1;
}
return min;
}
function getSupportLevel(stream) {
const level = supportsColor(stream);
return translateLevel(level);
}
module.exports = {
supportsColor: getSupportLevel,
stdout: getSupportLevel(process.stdout),
stderr: getSupportLevel(process.stderr)
};

View file

@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -0,0 +1,53 @@
{
"name": "supports-color",
"version": "6.1.0",
"description": "Detect whether a terminal supports color",
"license": "MIT",
"repository": "chalk/supports-color",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"engines": {
"node": ">=6"
},
"scripts": {
"test": "xo && ava"
},
"files": [
"index.js",
"browser.js"
],
"keywords": [
"color",
"colour",
"colors",
"terminal",
"console",
"cli",
"ansi",
"styles",
"tty",
"rgb",
"256",
"shell",
"xterm",
"command-line",
"support",
"supports",
"capability",
"detect",
"truecolor",
"16m"
],
"dependencies": {
"has-flag": "^3.0.0"
},
"devDependencies": {
"ava": "^0.25.0",
"import-fresh": "^2.0.0",
"xo": "^0.23.0"
},
"browser": "browser.js"
}

View file

@ -0,0 +1,85 @@
# supports-color [![Build Status](https://travis-ci.org/chalk/supports-color.svg?branch=master)](https://travis-ci.org/chalk/supports-color)
> Detect whether a terminal supports color
---
<div align="center">
<b>
<a href="https://tidelift.com/subscription/pkg/npm-supports-color?utm_source=npm-supports-color&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a>
</b>
<br>
<sub>
Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
</sub>
</div>
---
## Install
```
$ npm install supports-color
```
## Usage
```js
const supportsColor = require('supports-color');
if (supportsColor.stdout) {
console.log('Terminal stdout supports color');
}
if (supportsColor.stdout.has256) {
console.log('Terminal stdout supports 256 colors');
}
if (supportsColor.stderr.has16m) {
console.log('Terminal stderr supports 16 million colors (truecolor)');
}
```
## API
Returns an `Object` with a `stdout` and `stderr` property for testing either streams. Each property is an `Object`, or `false` if color is not supported.
The `stdout`/`stderr` objects specifies a level of support for color through a `.level` property and a corresponding flag:
- `.level = 1` and `.hasBasic = true`: Basic color support (16 colors)
- `.level = 2` and `.has256 = true`: 256 color support
- `.level = 3` and `.has16m = true`: Truecolor support (16 million colors)
## Info
It obeys the `--color` and `--no-color` CLI flags.
For situations where using `--color` is not possible, use the environment variable `FORCE_COLOR=1` (level 1), `FORCE_COLOR=2` (level 2), or `FORCE_COLOR=3` (level 3) to forcefully enable color, or `FORCE_COLOR=0` to forcefully disable. The use of `FORCE_COLOR` overrides all other color support checks.
Explicit 256/Truecolor mode can be enabled using the `--color=256` and `--color=16m` flags, respectively.
## Security
To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure.
## Related
- [supports-color-cli](https://github.com/chalk/supports-color-cli) - CLI for this module
- [chalk](https://github.com/chalk/chalk) - Terminal string styling done right
## Maintainers
- [Sindre Sorhus](https://github.com/sindresorhus)
- [Josh Junon](https://github.com/qix-)
## License
MIT

51
web/node_modules/rollup-plugin-terser/package.json generated vendored Normal file
View file

@ -0,0 +1,51 @@
{
"name": "rollup-plugin-terser",
"version": "5.3.1",
"description": "Rollup plugin to minify generated es bundle",
"main": "index.js",
"types": "index.d.ts",
"files": [
"index.js",
"index.d.ts",
"transform.js"
],
"scripts": {
"test": "jest",
"prepublish": "yarn test"
},
"babel": {
"plugins": [
"@babel/transform-async-to-generator"
]
},
"repository": {
"type": "git",
"url": "git+https://github.com/TrySound/rollup-plugin-terser.git"
},
"keywords": [
"rollup",
"rollup-plugin",
"terser",
"minify"
],
"author": "Bogdan Chadkin <trysound@yandex.ru>",
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.5.5",
"jest-worker": "^24.9.0",
"rollup-pluginutils": "^2.8.2",
"serialize-javascript": "^4.0.0",
"terser": "^4.6.2"
},
"peerDependencies": {
"rollup": ">=0.66.0 <3"
},
"devDependencies": {
"@babel/core": "^7.7.7",
"@babel/plugin-transform-async-to-generator": "^7.7.4",
"babel-jest": "^24.9.0",
"jest": "^24.9.0",
"prettier": "^1.19.1",
"rollup": "^2.0.0"
}
}

13
web/node_modules/rollup-plugin-terser/transform.js generated vendored Normal file
View file

@ -0,0 +1,13 @@
const { minify } = require("terser");
const transform = (code, optionsString) => {
const options = eval(`(${optionsString})`);
const result = minify(code, options);
if (result.error) {
throw result.error;
} else {
return { result, nameCache: options.nameCache };
}
};
exports.transform = transform;