Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: migrate jest-worker to TypeScript #7853

Merged
merged 2 commits into from Feb 10, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -24,6 +24,7 @@
- `[jest-util]`: Migrate to TypeScript ([#7844](https://github.com/facebook/jest/pull/7844))
- `[jest-watcher]`: Migrate to TypeScript ([#7843](https://github.com/facebook/jest/pull/7843))
- `[jest-mock]`: Migrate to TypeScript ([#7847](https://github.com/facebook/jest/pull/7847), [#7850](https://github.com/facebook/jest/pull/7850))
- `[jest-worker]`: Migrate to TypeScript ([#7853](https://github.com/facebook/jest/pull/7853))

### Performance

Expand Down
1 change: 0 additions & 1 deletion packages/jest-cli/src/reporters/coverage_reporter.js
Expand Up @@ -159,7 +159,6 @@ export default class CoverageReporter extends BaseReporter {
if (this._globalConfig.maxWorkers <= 1) {
worker = require('./coverage_worker');
} else {
// $FlowFixMe: assignment of a worker with custom properties.
worker = new Worker(require.resolve('./coverage_worker'), {
exposedMethods: ['worker'],
maxRetries: 2,
Expand Down
1 change: 0 additions & 1 deletion packages/jest-haste-map/src/index.js
Expand Up @@ -670,7 +670,6 @@ class HasteMap extends EventEmitter {
if ((options && options.forceInBand) || this._options.maxWorkers <= 1) {
this._worker = {getSha1, worker};
} else {
// $FlowFixMe: assignment of a worker with custom properties.
this._worker = (new Worker(require.resolve('./worker'), {
exposedMethods: ['getSha1', 'worker'],
maxRetries: 3,
Expand Down
1 change: 0 additions & 1 deletion packages/jest-runner/src/index.js
Expand Up @@ -98,7 +98,6 @@ class TestRunner {
onResult: OnTestSuccess,
onFailure: OnTestFailure,
) {
// $FlowFixMe: class object is augmented with worker when instantiating.
const worker: WorkerInterface = new Worker(TEST_WORKER_PATH, {
exposedMethods: ['worker'],
forkOptions: {stdio: 'pipe'},
Expand Down
2 changes: 2 additions & 0 deletions packages/jest-worker/package.json
Expand Up @@ -8,7 +8,9 @@
},
"license": "MIT",
"main": "build/index.js",
"types": "build/index.d.ts",
"dependencies": {
"@types/node": "*",
"merge-stream": "^1.0.1",
"supports-color": "^6.1.0"
},
Expand Down
Expand Up @@ -3,35 +3,32 @@
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

'use strict';

import type {
import {
ChildMessage,
FarmOptions,
QueueChildMessage,
WorkerInterface,
OnStart,
OnEnd,
CHILD_MESSAGE_CALL,
} from './types';
import {CHILD_MESSAGE_CALL} from './types';

export default class Farm {
_computeWorkerKey: (string, ...Array<any>) => ?string;
_cacheKeys: {[string]: WorkerInterface, __proto__: null};
_computeWorkerKey: FarmOptions['computeWorkerKey'];
_cacheKeys: {[key: string]: WorkerInterface};
_callback: Function;
_last: Array<QueueChildMessage>;
_locks: Array<boolean>;
_numOfWorkers: number;
_offset: number;
_queue: Array<?QueueChildMessage>;
_queue: Array<QueueChildMessage | null>;

constructor(
numOfWorkers: number,
callback: Function,
computeWorkerKey?: (string, ...Array<any>) => ?string,
computeWorkerKey?: FarmOptions['computeWorkerKey'],
) {
this._callback = callback;
this._numOfWorkers = numOfWorkers;
Expand All @@ -45,16 +42,16 @@ export default class Farm {
}
}

doWork(method: string, ...args: Array<any>): Promise<mixed> {
doWork(method: string, ...args: Array<any>): Promise<unknown> {
return new Promise((resolve, reject) => {
const computeWorkerKey = this._computeWorkerKey;
const request: ChildMessage = [CHILD_MESSAGE_CALL, false, method, args];

let worker: ?WorkerInterface = null;
let hash: ?string = null;
let worker: WorkerInterface | null = null;
let hash: string | null = null;

if (computeWorkerKey) {
hash = computeWorkerKey.apply(this, [method].concat(args));
hash = computeWorkerKey.call(this, method, ...args);
worker = hash == null ? null : this._cacheKeys[hash];
}

Expand All @@ -64,7 +61,7 @@ export default class Farm {
}
};

const onEnd: OnEnd = (error: ?Error, result: ?mixed) => {
const onEnd: OnEnd = (error: Error | null, result: unknown) => {
if (error) {
reject(error);
} else {
Expand All @@ -81,11 +78,11 @@ export default class Farm {
});
}

_getNextJob(workerId: number): ?QueueChildMessage {
_getNextJob(workerId: number): QueueChildMessage | null {
let queueHead = this._queue[workerId];

while (queueHead && queueHead.request[1]) {
queueHead = queueHead.next;
queueHead = queueHead.next || null;
}

this._queue[workerId] = queueHead;
Expand All @@ -104,7 +101,7 @@ export default class Farm {
return this;
}

const onEnd = (error: ?Error, result: mixed) => {
const onEnd = (error: Error | null, result: unknown) => {
job.onEnd(error, result);
this.unlock(workerId);
this._process(workerId);
Expand Down
Expand Up @@ -3,15 +3,11 @@
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

'use strict';

import BaseWorkerPool from './base/BaseWorkerPool';

import type {
import {
ChildMessage,
WorkerOptions,
OnStart,
Expand Down
Expand Up @@ -3,26 +3,24 @@
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

'use strict';

import mergeStream from 'merge-stream';
import path from 'path';
import mergeStream from 'merge-stream';

import {CHILD_MESSAGE_END} from '../types';

import type {Readable} from 'stream';
import type {WorkerPoolOptions, WorkerOptions, WorkerInterface} from '../types';
import {
CHILD_MESSAGE_END,
WorkerPoolOptions,
WorkerOptions,
WorkerInterface,
} from '../types';

/* istanbul ignore next */
const emptyMethod = () => {};

export default class BaseWorkerPool {
_stderr: Readable;
_stdout: Readable;
_stderr: NodeJS.ReadableStream;
_stdout: NodeJS.ReadableStream;
_options: WorkerPoolOptions;
_workers: Array<WorkerInterface>;

Expand Down Expand Up @@ -67,11 +65,11 @@ export default class BaseWorkerPool {
this._stderr = stderr;
}

getStderr(): Readable {
getStderr(): NodeJS.ReadableStream {
return this._stderr;
}

getStdout(): Readable {
getStdout(): NodeJS.ReadableStream {
return this._stdout;
}

Expand All @@ -83,7 +81,7 @@ export default class BaseWorkerPool {
return this._workers[workerId];
}

createWorker(workerOptions: WorkerOptions): WorkerInterface {
createWorker(_workerOptions: WorkerOptions): WorkerInterface {
throw Error('Missing method createWorker in WorkerPool');
}

Expand Down
Expand Up @@ -3,39 +3,30 @@
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

'use strict';

import os from 'os';
import WorkerPool from './WorkerPool';
import Farm from './Farm';
import type {
WorkerPoolInterface,
WorkerPoolOptions,
FarmOptions,
} from './types';
import type {Readable} from 'stream';
import {WorkerPoolInterface, WorkerPoolOptions, FarmOptions} from './types';

function getExposedMethods(
workerPath: string,
options: FarmOptions,
): $ReadOnlyArray<string> {
): ReadonlyArray<string> {
let exposedMethods = options.exposedMethods;

// If no methods list is given, try getting it by auto-requiring the module.
if (!exposedMethods) {
// $FlowFixMe: This has to be a dynamic require.
const module: Function | Object = require(workerPath);

exposedMethods = Object.keys(module).filter(
// @ts-ignore: no index
name => typeof module[name] === 'function',
);

if (typeof module === 'function') {
exposedMethods.push('default');
exposedMethods = [...exposedMethods, 'default'];
}
}

Expand Down Expand Up @@ -75,6 +66,7 @@ export default class JestWorker {

constructor(workerPath: string, options?: FarmOptions) {
this._options = {...options};
this._ending = false;

const workerPoolOptions: WorkerPoolOptions = {
enableWorkerThreads: this._options.enableWorkerThreads || false,
Expand All @@ -84,9 +76,15 @@ export default class JestWorker {
setupArgs: this._options.setupArgs || [],
};

this._workerPool = this._options.WorkerPool
? new this._options.WorkerPool(workerPath, workerPoolOptions)
: new WorkerPool(workerPath, workerPoolOptions);
if (this._options.WorkerPool) {
// @ts-ignore: constructor target any?
this._workerPool = new this._options.WorkerPool(
workerPath,
workerPoolOptions,
);
} else {
this._workerPool = new WorkerPool(workerPath, workerPoolOptions);
}

this._farm = new Farm(
workerPoolOptions.numWorkers,
Expand All @@ -107,7 +105,7 @@ export default class JestWorker {
throw new TypeError('Cannot define a method called ' + name);
}

// $FlowFixMe: dynamic extension of the class instance is expected.
// @ts-ignore: dynamic extension of the class instance is expected.
this[name] = this._callFunctionWithArgs.bind(this, name);
});
}
Expand All @@ -120,11 +118,11 @@ export default class JestWorker {
return this._farm.doWork(method, ...args);
}

getStderr(): Readable {
getStderr(): NodeJS.ReadableStream {
return this._workerPool.getStderr();
}

getStdout(): Readable {
getStdout(): NodeJS.ReadableStream {
return this._workerPool.getStdout();
}

Expand Down