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

Fix Flow issues with Symbol.asyncIterator #3043

Merged
merged 1 commit into from May 4, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions flow-typed/core.js
Expand Up @@ -260,7 +260,7 @@ declare opaque type $SymbolToStringTag: symbol;
declare opaque type $SymbolUnscopables: symbol;

declare class Symbol {
static asyncIterator: string; // graphql-js HACK
static asyncIterator: '@@asyncIterator'; // graphql-js HACK

/**
* Returns a new unique Symbol value.
Expand All @@ -287,7 +287,7 @@ declare class Symbol {
* by Array.prototype.concat.
*/
static isConcatSpreadable: $SymboIsConcatSpreadable;
static iterator: string; // polyfill '@@iterator'
static iterator: '@@iterator';
/**
* Returns a key from the global symbol registry matching the given Symbol if found.
* Otherwise, returns a undefined.
Expand Down
6 changes: 3 additions & 3 deletions src/subscription/__tests__/mapAsyncIterator-test.js
Expand Up @@ -25,7 +25,7 @@ describe('mapAsyncIterator', () => {
it('maps over async iterable', async () => {
const items = [1, 2, 3];

const iterable: $FlowFixMe = {
const iterable = {
[Symbol.asyncIterator]() {
return this;
},
Expand Down Expand Up @@ -122,7 +122,7 @@ describe('mapAsyncIterator', () => {
it('allows returning early from mapped async iterable', async () => {
const items = [1, 2, 3];

const iterable: any = {
const iterable = {
[Symbol.asyncIterator]() {
return this;
},
Expand Down Expand Up @@ -185,7 +185,7 @@ describe('mapAsyncIterator', () => {
it('allows throwing errors through async iterable', async () => {
const items = [1, 2, 3];

const iterable: any = {
const iterable = {
[Symbol.asyncIterator]() {
return this;
},
Expand Down
2 changes: 1 addition & 1 deletion src/subscription/__tests__/simplePubSub-test.js
Expand Up @@ -6,7 +6,7 @@ import { SimplePubSub } from './simplePubSub';
describe('SimplePubSub', () => {
it('subscribe async-iterator mock', async () => {
const pubsub = new SimplePubSub();
const iterator = pubsub.getSubscriber();
const iterator = pubsub.getSubscriber((x) => x);

// Queue up publishes
expect(pubsub.emit('Apple')).to.equal(true);
Expand Down
14 changes: 6 additions & 8 deletions src/subscription/__tests__/simplePubSub.js
Expand Up @@ -16,8 +16,8 @@ export class SimplePubSub<T> {
return this._subscribers.size > 0;
}

getSubscriber<R>(transform?: (T) => R): AsyncGenerator<R, void, void> {
const pullQueue = [];
getSubscriber<R>(transform: (T) => R): AsyncGenerator<R, void, void> {
const pullQueue: Array<(result: IteratorResult<R, void>) => void> = [];
const pushQueue = [];
let listening = true;
this._subscribers.add(pushValue);
Expand All @@ -32,9 +32,7 @@ export class SimplePubSub<T> {
pushQueue.length = 0;
};

/* TODO: Flow doesn't support symbols as keys:
https://github.com/facebook/flow/issues/3258 */
return ({
return {
next() {
if (!listening) {
return Promise.resolve({ value: undefined, done: true });
Expand All @@ -45,7 +43,7 @@ export class SimplePubSub<T> {
}
return new Promise((resolve) => pullQueue.push(resolve));
},
return() {
return(): Promise<IteratorResult<R, void>> {
emptyQueue();
return Promise.resolve({ value: undefined, done: true });
},
Expand All @@ -56,10 +54,10 @@ export class SimplePubSub<T> {
[Symbol.asyncIterator]() {
return this;
},
}: any);
};

function pushValue(event: T): void {
const value = transform != null ? transform(event) : event;
const value: R = transform(event);
if (pullQueue.length > 0) {
pullQueue.shift()({ value, done: false });
} else {
Expand Down
9 changes: 5 additions & 4 deletions src/subscription/__tests__/subscribe-test.js
Expand Up @@ -187,7 +187,7 @@ describe('Subscription Initialization Phase', () => {
fields: {
importantEmail: {
type: GraphQLString,
subscribe: () => pubsub.getSubscriber(),
subscribe: () => pubsub.getSubscriber((x) => x),
},
},
}),
Expand Down Expand Up @@ -219,7 +219,7 @@ describe('Subscription Initialization Phase', () => {
type: GraphQLString,
subscribe: async () => {
await resolveOnNextTick();
return pubsub.getSubscriber();
return pubsub.getSubscriber((x) => x);
},
},
},
Expand Down Expand Up @@ -253,15 +253,16 @@ describe('Subscription Initialization Phase', () => {
type: EmailEventType,
subscribe() {
didResolveImportantEmail = true;
return new SimplePubSub().getSubscriber();
// istanbul ignore next (FIXME)
return new SimplePubSub().getSubscriber((x) => x);
},
},
nonImportantEmail: {
type: EmailEventType,
// istanbul ignore next (Shouldn't be called)
subscribe() {
didResolveNonImportantEmail = true;
return new SimplePubSub().getSubscriber();
return new SimplePubSub().getSubscriber((x) => x);
},
},
},
Expand Down
13 changes: 5 additions & 8 deletions src/subscription/mapAsyncIterator.js
Expand Up @@ -8,9 +8,8 @@ export function mapAsyncIterator<T, U>(
iterable: AsyncIterable<T> | AsyncGenerator<T, void, void>,
callback: (T) => PromiseOrValue<U>,
): AsyncGenerator<U, void, void> {
// $FlowFixMe[prop-missing]
const iteratorMethod = iterable[Symbol.asyncIterator];
const iterator: any = iteratorMethod.call(iterable);
// $FlowIssue[incompatible-use]
const iterator = iterable[Symbol.asyncIterator]();

async function abruptClose(error: mixed) {
if (typeof iterator.return === 'function') {
Expand All @@ -37,13 +36,11 @@ export function mapAsyncIterator<T, U>(
}
}

/* TODO: Flow doesn't support symbols as keys:
https://github.com/facebook/flow/issues/3258 */
return ({
return {
next(): Promise<IteratorResult<U, void>> {
return mapResult(iterator.next());
},
return() {
return(): Promise<IteratorResult<U, void>> {
return typeof iterator.return === 'function'
? mapResult(iterator.return())
: Promise.resolve({ value: undefined, done: true });
Expand All @@ -57,5 +54,5 @@ export function mapAsyncIterator<T, U>(
[Symbol.asyncIterator]() {
return this;
},
}: $FlowFixMe);
};
}