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

Accept polyfilled abort signals #36

Merged
merged 3 commits into from
Oct 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
## Unreleased

* 👓 Align with [spec version `ae5e0cb`](https://github.com/whatwg/streams/tree/ae5e0cb41e9f72cdd97f3a6d47bc674c1f4049d1/) ([#33](https://github.com/MattiasBuelens/web-streams-polyfill/pull/33))
* 💅 Accept polyfilled `AbortSignal`s. ([#36](https://github.com/MattiasBuelens/web-streams-polyfill/pull/36))

## v2.0.4 (2019-08-01)

Expand Down
10 changes: 10 additions & 0 deletions etc/web-streams-polyfill.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@

```ts

// @public
export interface AbortSignal {
// (undocumented)
readonly aborted: boolean;
// (undocumented)
addEventListener(type: 'abort', listener: () => void): void;
// (undocumented)
removeEventListener(type: 'abort', listener: () => void): void;
}

// @public (undocumented)
export class ByteLengthQueuingStrategy implements QueuingStrategy<ArrayBufferView> {
constructor({ highWaterMark }: {
Expand Down
28 changes: 28 additions & 0 deletions src/lib/abort-signal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* A signal object that allows you to communicate with a request and abort it if required
* via its associated `AbortController` object.
*
* @remarks
* This interface is compatible with the `AbortSignal` interface defined in TypeScript's DOM types.
* It is redefined here, so it can be polyfilled without a DOM, for example with
* {@link https://www.npmjs.com/package/abortcontroller-polyfill | abortcontroller-polyfill} in a Node environment.
*/
export interface AbortSignal {
readonly aborted: boolean;

addEventListener(type: 'abort', listener: () => void): void;

removeEventListener(type: 'abort', listener: () => void): void;
}

export function isAbortSignal(value: unknown): value is AbortSignal {
if (typeof value !== 'object' || value === null) {
return false;
}
try {
return typeof (value as AbortSignal).aborted === 'boolean';
} catch {
// AbortSignal.prototype.aborted throws if its brand check fails
return false;
}
}
18 changes: 1 addition & 17 deletions src/lib/readable-stream.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/// <reference lib="dom" />

import assert from '../stub/assert';
import {
createArrayFromList,
Expand Down Expand Up @@ -59,6 +57,7 @@ import {
UnderlyingSource
} from './readable-stream/underlying-source';
import { noop } from '../utils';
import { AbortSignal, isAbortSignal } from './abort-signal';

export type ReadableByteStream = ReadableStream<Uint8Array>;

Expand Down Expand Up @@ -439,21 +438,6 @@ export {

// Helper functions for the ReadableStream.

export function isAbortSignal(value: any): value is AbortSignal {
if (typeof value !== 'object' || value === null) {
return false;
}

// Use the brand check to distinguish a real AbortSignal from a fake one.
const aborted = Object.getOwnPropertyDescriptor(AbortSignal.prototype, 'aborted')!.get!;
try {
aborted.call(value);
return true;
} catch (e) {
return false;
}
}

function streamBrandCheckException(name: string): TypeError {
return new TypeError(`ReadableStream.prototype.${name} can only be used on a ReadableStream`);
}
9 changes: 2 additions & 7 deletions src/lib/readable-stream/pipe.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
import {
isAbortSignal,
IsReadableStream,
IsReadableStreamLocked,
ReadableStream,
ReadableStreamCancel
} from '../readable-stream';
import { IsReadableStream, IsReadableStreamLocked, ReadableStream, ReadableStreamCancel } from '../readable-stream';
import { AcquireReadableStreamDefaultReader, ReadableStreamDefaultReaderRead } from './default-reader';
import { ReadableStreamReaderGenericRelease } from './generic-reader';
import {
Expand All @@ -29,6 +23,7 @@ import {
uponRejection
} from '../helpers';
import { noop } from '../../utils';
import { AbortSignal, isAbortSignal } from '../abort-signal';

export function ReadableStreamPipeTo<T>(source: ReadableStream<T>,
dest: WritableStream<T>,
Expand Down
5 changes: 4 additions & 1 deletion src/ponyfill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { QueuingStrategy } from './lib/queuing-strategy';
import ByteLengthQueuingStrategy from './lib/byte-length-queuing-strategy';
import CountQueuingStrategy from './lib/count-queuing-strategy';
import { Transformer, TransformStream, TransformStreamDefaultControllerType } from './lib/transform-stream';
import { AbortSignal } from './lib/abort-signal';

export {
ReadableStream,
Expand All @@ -46,5 +47,7 @@ export {

TransformStream,
Transformer,
TransformStreamDefaultControllerType as TransformStreamDefaultController
TransformStreamDefaultControllerType as TransformStreamDefaultController,

AbortSignal
};
2 changes: 2 additions & 0 deletions test/types/readable-stream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ const asyncIteratorReturnResult: Promise<IteratorResult<any>> = asyncIterator.re
}
})();

const abortSignal: polyfill.AbortSignal = new AbortController().signal;

// Compatibility with stream types from DOM
const domUnderlyingSource: UnderlyingSource<string> = underlyingSource;
const domUnderlyingByteSource: UnderlyingByteSource = underlyingByteSource;
Expand Down