From 676c775f6dcf5d4261a096cce5fd9dfba49d4861 Mon Sep 17 00:00:00 2001 From: Ivan Goncharov Date: Tue, 4 May 2021 14:50:10 +0300 Subject: [PATCH] Fix Flow issues with Symbol.asyncIterator (#3043) --- flow-typed/core.js | 4 ++-- .../__tests__/mapAsyncIterator-test.js | 6 +++--- src/subscription/__tests__/simplePubSub-test.js | 2 +- src/subscription/__tests__/simplePubSub.js | 14 ++++++-------- src/subscription/__tests__/subscribe-test.js | 9 +++++---- src/subscription/mapAsyncIterator.js | 13 +++++-------- 6 files changed, 22 insertions(+), 26 deletions(-) diff --git a/flow-typed/core.js b/flow-typed/core.js index 38e3f8f679..67f9680f09 100644 --- a/flow-typed/core.js +++ b/flow-typed/core.js @@ -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. @@ -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. diff --git a/src/subscription/__tests__/mapAsyncIterator-test.js b/src/subscription/__tests__/mapAsyncIterator-test.js index e2d1b632c9..a0540ab3dd 100644 --- a/src/subscription/__tests__/mapAsyncIterator-test.js +++ b/src/subscription/__tests__/mapAsyncIterator-test.js @@ -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; }, @@ -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; }, @@ -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; }, diff --git a/src/subscription/__tests__/simplePubSub-test.js b/src/subscription/__tests__/simplePubSub-test.js index 18f596b898..e919d770e3 100644 --- a/src/subscription/__tests__/simplePubSub-test.js +++ b/src/subscription/__tests__/simplePubSub-test.js @@ -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); diff --git a/src/subscription/__tests__/simplePubSub.js b/src/subscription/__tests__/simplePubSub.js index c7f9639419..6eb64ad5ea 100644 --- a/src/subscription/__tests__/simplePubSub.js +++ b/src/subscription/__tests__/simplePubSub.js @@ -16,8 +16,8 @@ export class SimplePubSub { return this._subscribers.size > 0; } - getSubscriber(transform?: (T) => R): AsyncGenerator { - const pullQueue = []; + getSubscriber(transform: (T) => R): AsyncGenerator { + const pullQueue: Array<(result: IteratorResult) => void> = []; const pushQueue = []; let listening = true; this._subscribers.add(pushValue); @@ -32,9 +32,7 @@ export class SimplePubSub { 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 }); @@ -45,7 +43,7 @@ export class SimplePubSub { } return new Promise((resolve) => pullQueue.push(resolve)); }, - return() { + return(): Promise> { emptyQueue(); return Promise.resolve({ value: undefined, done: true }); }, @@ -56,10 +54,10 @@ export class SimplePubSub { [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 { diff --git a/src/subscription/__tests__/subscribe-test.js b/src/subscription/__tests__/subscribe-test.js index 54aa6714e0..5924a2371c 100644 --- a/src/subscription/__tests__/subscribe-test.js +++ b/src/subscription/__tests__/subscribe-test.js @@ -187,7 +187,7 @@ describe('Subscription Initialization Phase', () => { fields: { importantEmail: { type: GraphQLString, - subscribe: () => pubsub.getSubscriber(), + subscribe: () => pubsub.getSubscriber((x) => x), }, }, }), @@ -219,7 +219,7 @@ describe('Subscription Initialization Phase', () => { type: GraphQLString, subscribe: async () => { await resolveOnNextTick(); - return pubsub.getSubscriber(); + return pubsub.getSubscriber((x) => x); }, }, }, @@ -253,7 +253,8 @@ describe('Subscription Initialization Phase', () => { type: EmailEventType, subscribe() { didResolveImportantEmail = true; - return new SimplePubSub().getSubscriber(); + // istanbul ignore next (FIXME) + return new SimplePubSub().getSubscriber((x) => x); }, }, nonImportantEmail: { @@ -261,7 +262,7 @@ describe('Subscription Initialization Phase', () => { // istanbul ignore next (Shouldn't be called) subscribe() { didResolveNonImportantEmail = true; - return new SimplePubSub().getSubscriber(); + return new SimplePubSub().getSubscriber((x) => x); }, }, }, diff --git a/src/subscription/mapAsyncIterator.js b/src/subscription/mapAsyncIterator.js index 75e3495148..65eeffad5a 100644 --- a/src/subscription/mapAsyncIterator.js +++ b/src/subscription/mapAsyncIterator.js @@ -8,9 +8,8 @@ export function mapAsyncIterator( iterable: AsyncIterable | AsyncGenerator, callback: (T) => PromiseOrValue, ): AsyncGenerator { - // $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') { @@ -37,13 +36,11 @@ export function mapAsyncIterator( } } - /* TODO: Flow doesn't support symbols as keys: - https://github.com/facebook/flow/issues/3258 */ - return ({ + return { next(): Promise> { return mapResult(iterator.next()); }, - return() { + return(): Promise> { return typeof iterator.return === 'function' ? mapResult(iterator.return()) : Promise.resolve({ value: undefined, done: true }); @@ -57,5 +54,5 @@ export function mapAsyncIterator( [Symbol.asyncIterator]() { return this; }, - }: $FlowFixMe); + }; }