Skip to content

Commit

Permalink
Convert PCancelable to typescript (#10215)
Browse files Browse the repository at this point in the history
  • Loading branch information
G-Rath committed Jul 4, 2020
1 parent 10375b3 commit e8b7f57
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 95 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Expand Up @@ -13,6 +13,9 @@

### Chore & Maintenance

- `[jest-jasmine2]` Convert `PCancelable` to TypeScript ([#10215](https://github.com/facebook/jest/pull/10215))
- `[jest-jasmine2]` Refine typings of `queueRunner` ([#10215](https://github.com/facebook/jest/pull/10215))

### Performance

## 26.1.0
Expand Down
84 changes: 0 additions & 84 deletions packages/jest-jasmine2/src/PCancelable.js

This file was deleted.

88 changes: 88 additions & 0 deletions packages/jest-jasmine2/src/PCancelable.ts
@@ -0,0 +1,88 @@
/**
* 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.
*/

class CancelError extends Error {
constructor() {
super('Promise was canceled');
this.name = 'CancelError';
}
}

export default class PCancelable<T> extends Promise<T> {
private _pending = true;
private _canceled = false;
private _promise: Promise<T>;
private _cancel?: () => void;
private _reject: (reason?: unknown) => void = () => {};

constructor(
executor: (
onCancel: (cancelHandler: () => void) => void,
resolve: (value?: T | PromiseLike<T>) => void,
reject: (reason?: unknown) => void,
) => void,
) {
super(resolve => resolve());

this._promise = new Promise((resolve, reject) => {
this._reject = reject;

return executor(
fn => {
this._cancel = fn;
},
val => {
this._pending = false;
resolve(val);
},
err => {
this._pending = false;
reject(err);
},
);
});
}

then<TResult1 = T, TResult2 = never>(
onFulfilled?:
| ((value: T) => TResult1 | PromiseLike<TResult1>)
| undefined
| null,
onRejected?:
| ((reason: any) => TResult2 | PromiseLike<TResult2>)
| undefined
| null,
): Promise<TResult1 | TResult2> {
return this._promise.then(onFulfilled, onRejected);
}

catch<TResult>(
onRejected?:
| ((reason: any) => TResult | PromiseLike<TResult>)
| undefined
| null,
): Promise<T | TResult> {
return this._promise.catch(onRejected);
}

cancel(): void {
if (!this._pending || this._canceled) {
return;
}

if (typeof this._cancel === 'function') {
try {
this._cancel();
} catch (err) {
this._reject(err);
}
}

this._canceled = true;
this._reject(new CancelError());
}
}
2 changes: 1 addition & 1 deletion packages/jest-jasmine2/src/__tests__/pTimeout.test.ts
Expand Up @@ -39,7 +39,7 @@ describe('pTimeout', () => {
it('calls `onTimeout` on timeout.', async () => {
const onTimeout = jest.fn();
// A Promise that never resolves or rejects.
const promise = new Promise(() => {});
const promise = new Promise<void>(() => {});
const timeoutPromise = pTimeout(
promise,
1000,
Expand Down
6 changes: 3 additions & 3 deletions packages/jest-jasmine2/src/pTimeout.ts
Expand Up @@ -8,12 +8,12 @@
// A specialized version of `p-timeout` that does not touch globals.
// It does not throw on timeout.
export default function pTimeout(
promise: Promise<any>,
promise: Promise<void>,
ms: number,
clearTimeout: NodeJS.Global['clearTimeout'],
setTimeout: NodeJS.Global['setTimeout'],
onTimeout: () => any,
): Promise<any> {
onTimeout: () => void,
): Promise<void> {
return new Promise((resolve, reject) => {
const timer = setTimeout(() => resolve(onTimeout()), ms);
promise.then(
Expand Down
18 changes: 11 additions & 7 deletions packages/jest-jasmine2/src/queueRunner.ts
Expand Up @@ -6,7 +6,6 @@
*/

import {formatTime} from 'jest-util';
// @ts-expect-error ignore vendor file
import PCancelable from './PCancelable';
import pTimeout from './pTimeout';

Expand All @@ -27,15 +26,20 @@ export type QueueableFn = {
initError?: Error;
};

// har to type :(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export default function queueRunner(options: Options) {
const token = new PCancelable((onCancel: Function, resolve: Function) => {
type PromiseCallback = (() => void | PromiseLike<void>) | undefined | null;

export default function queueRunner(
options: Options,
): PromiseLike<void> & {
cancel: () => void;
catch: (onRejected?: PromiseCallback) => Promise<void>;
} {
const token = new PCancelable<void>((onCancel, resolve) => {
onCancel(resolve);
});

const mapper = ({fn, timeout, initError = new Error()}: QueueableFn) => {
let promise = new Promise(resolve => {
let promise = new Promise<void>(resolve => {
const next = function (...args: [Error]) {
const err = args[0];
if (err) {
Expand All @@ -56,7 +60,7 @@ export default function queueRunner(options: Options) {
}
});

promise = Promise.race([promise, token]);
promise = Promise.race<void>([promise, token]);

if (!timeout) {
return promise;
Expand Down

0 comments on commit e8b7f57

Please sign in to comment.