diff --git a/packages/firestore/exp/register.ts b/packages/firestore/exp/register.ts index 20f54426322..420d11b5bf2 100644 --- a/packages/firestore/exp/register.ts +++ b/packages/firestore/exp/register.ts @@ -25,7 +25,7 @@ import { Component, ComponentType } from '@firebase/component'; import { name, version } from '../package.json'; import { setSDKVersion } from '../src/core/version'; import { FirebaseFirestore } from '../src/exp/database'; -import { Settings } from '../src/exp/settings'; +import { PrivateSettings } from '../src/lite/settings'; declare module '@firebase/component' { interface NameServiceMapping { @@ -38,15 +38,14 @@ export function registerFirestore(variant?: string): void { _registerComponent( new Component( 'firestore-exp', - (container, { options: settings }: { options?: Settings }) => { + (container, { options: settings }: { options?: PrivateSettings }) => { const app = container.getProvider('app-exp').getImmediate()!; const firestoreInstance = new FirebaseFirestore( app, container.getProvider('auth-internal') ); - if (settings) { - firestoreInstance._setSettings(settings); - } + settings = { useFetchStreams: true, ...settings }; + firestoreInstance._setSettings(settings); return firestoreInstance; }, ComponentType.PUBLIC diff --git a/packages/firestore/src/core/database_info.ts b/packages/firestore/src/core/database_info.ts index a61b019b8bd..218e0626d80 100644 --- a/packages/firestore/src/core/database_info.ts +++ b/packages/firestore/src/core/database_info.ts @@ -30,6 +30,8 @@ export class DatabaseInfo { * when using WebChannel as the network transport. * @param autoDetectLongPolling - Whether to use the detectBufferingProxy * option when using WebChannel as the network transport. + * @param useFetchStreams Whether to use the Fetch API instead of + * XMLHTTPRequest */ constructor( readonly databaseId: DatabaseId, @@ -38,7 +40,8 @@ export class DatabaseInfo { readonly host: string, readonly ssl: boolean, readonly forceLongPolling: boolean, - readonly autoDetectLongPolling: boolean + readonly autoDetectLongPolling: boolean, + readonly useFetchStreams: boolean ) {} } diff --git a/packages/firestore/src/lite/components.ts b/packages/firestore/src/lite/components.ts index 3d896fa5fc0..8486ec6d51e 100644 --- a/packages/firestore/src/lite/components.ts +++ b/packages/firestore/src/lite/components.ts @@ -113,6 +113,7 @@ export function makeDatabaseInfo( settings.host, settings.ssl, settings.experimentalForceLongPolling, - settings.experimentalAutoDetectLongPolling + settings.experimentalAutoDetectLongPolling, + settings.useFetchStreams ); } diff --git a/packages/firestore/src/lite/settings.ts b/packages/firestore/src/lite/settings.ts index a69fde68af5..998e9a18423 100644 --- a/packages/firestore/src/lite/settings.ts +++ b/packages/firestore/src/lite/settings.ts @@ -58,6 +58,8 @@ export interface PrivateSettings extends Settings { experimentalForceLongPolling?: boolean; // Used in firestore@exp experimentalAutoDetectLongPolling?: boolean; + // Used in firestore@exp + useFetchStreams?: boolean; } /** @@ -80,6 +82,8 @@ export class FirestoreSettings { readonly ignoreUndefinedProperties: boolean; + readonly useFetchStreams: boolean; + // Can be a google-auth-library or gapi client. // eslint-disable-next-line @typescript-eslint/no-explicit-any credentials?: any; @@ -120,6 +124,7 @@ export class FirestoreSettings { this.experimentalForceLongPolling = !!settings.experimentalForceLongPolling; this.experimentalAutoDetectLongPolling = !!settings.experimentalAutoDetectLongPolling; + this.useFetchStreams = !!settings.useFetchStreams; validateIsNotUsedTogether( 'experimentalForceLongPolling', @@ -139,7 +144,8 @@ export class FirestoreSettings { other.experimentalForceLongPolling && this.experimentalAutoDetectLongPolling === other.experimentalAutoDetectLongPolling && - this.ignoreUndefinedProperties === other.ignoreUndefinedProperties + this.ignoreUndefinedProperties === other.ignoreUndefinedProperties && + this.useFetchStreams === other.useFetchStreams ); } } diff --git a/packages/firestore/src/platform/browser/webchannel_connection.ts b/packages/firestore/src/platform/browser/webchannel_connection.ts index b956a44827f..239ba6a44de 100644 --- a/packages/firestore/src/platform/browser/webchannel_connection.ts +++ b/packages/firestore/src/platform/browser/webchannel_connection.ts @@ -30,6 +30,7 @@ import { WebChannel, WebChannelError, WebChannelOptions, + FetchXmlHttpFactory, XhrIo, getStatEventTarget, EventTarget, @@ -62,11 +63,13 @@ const XHR_TIMEOUT_SECS = 15; export class WebChannelConnection extends RestConnection { private readonly forceLongPolling: boolean; private readonly autoDetectLongPolling: boolean; + private readonly useFetchStreams: boolean; constructor(info: DatabaseInfo) { super(info); this.forceLongPolling = info.forceLongPolling; this.autoDetectLongPolling = info.autoDetectLongPolling; + this.useFetchStreams = info.useFetchStreams; } protected performRPCRequest( @@ -194,6 +197,10 @@ export class WebChannelConnection extends RestConnection { detectBufferingProxy: this.autoDetectLongPolling }; + if (this.useFetchStreams) { + request.xmlHttpFactory = new FetchXmlHttpFactory({}); + } + this.modifyHeadersForRequest(request.initMessageHeaders!, token); // Sending the custom headers we just added to request.initMessageHeaders diff --git a/packages/webchannel-wrapper/externs/overrides.js b/packages/webchannel-wrapper/externs/overrides.js index 0a44510527b..60f98a6382c 100644 --- a/packages/webchannel-wrapper/externs/overrides.js +++ b/packages/webchannel-wrapper/externs/overrides.js @@ -68,6 +68,9 @@ goog.net.WebChannel.Options.forceLongPolling; /** @type {boolean|undefined} */ goog.net.WebChannel.Options.detectBufferingProxy; +/** @type {unknown} */ +goog.net.WebChannel.Options.xmlHttpFactory; + goog.labs.net.webChannel.requestStats.Event = {}; goog.labs.net.webChannel.requestStats.Event.STAT_EVENT; diff --git a/packages/webchannel-wrapper/src/index.d.ts b/packages/webchannel-wrapper/src/index.d.ts index c271534d6d6..cf99793c013 100644 --- a/packages/webchannel-wrapper/src/index.d.ts +++ b/packages/webchannel-wrapper/src/index.d.ts @@ -130,3 +130,7 @@ export interface WebChannelTransport { export function createWebChannelTransport(): WebChannelTransport; export function getStatEventTarget(): EventTarget; + +export class FetchXmlHttpFactory { + constructor(options: {}); +} diff --git a/packages/webchannel-wrapper/src/index.js b/packages/webchannel-wrapper/src/index.js index 86c1075a730..1cf3d2537d1 100644 --- a/packages/webchannel-wrapper/src/index.js +++ b/packages/webchannel-wrapper/src/index.js @@ -23,6 +23,7 @@ goog.provide('firebase.webchannel.wrapper'); // goog.net.WebChannelTransport goog.require('goog.net.createWebChannelTransport'); +goog.require('goog.net.FetchXmlHttpFactory'); goog.require('goog.labs.net.webChannel.requestStats'); goog.require('goog.labs.net.webChannel.WebChannelBaseTransport'); @@ -83,5 +84,6 @@ module['exports']['ErrorCode'] = goog.net.ErrorCode; module['exports']['EventType'] = goog.net.EventType; module['exports']['Event'] = goog.labs.net.webChannel.requestStats.Event; module['exports']['Stat'] = goog.labs.net.webChannel.requestStats.Stat; +module['exports']['FetchXmlHttpFactory'] = goog.net.FetchXmlHttpFactory; module['exports']['WebChannel'] = goog.net.WebChannel; module['exports']['XhrIo'] = goog.net.XhrIo;