import { Component, ComponentContainer, Deferred, LogLevel, Logger, Provider, SDK_VERSION, Sha1, _getProvider, _isFirebaseServerApp, _registerComponent, assert, assertionError, base64, base64Encode, contains, createMockUserToken, deepCopy, deepEqual, errorPrefix, getApp, getDefaultEmulatorHostnameAndPort, getModularInstance, isAdmin, isCloudWorkstation, isEmpty, isMobileCordova, isNodeSdk, isReactNative, isValidFormat, jsonEval, map, pingServer, querystring, registerVersion, safeGet, stringLength, stringToByteArray, stringify, updateEmulatorBanner } from "./chunk-XW5JQOG4.js"; import "./chunk-DC5AMYBS.js"; // node_modules/@firebase/database/dist/index.esm2017.js var name = "@firebase/database"; var version = "1.0.20"; var SDK_VERSION2 = ""; function setSDKVersion(version2) { SDK_VERSION2 = version2; } var DOMStorageWrapper = class { /** * @param domStorage_ - The underlying storage object (e.g. localStorage or sessionStorage) */ constructor(domStorage_) { this.domStorage_ = domStorage_; this.prefix_ = "firebase:"; } /** * @param key - The key to save the value under * @param value - The value being stored, or null to remove the key. */ set(key, value) { if (value == null) { this.domStorage_.removeItem(this.prefixedName_(key)); } else { this.domStorage_.setItem(this.prefixedName_(key), stringify(value)); } } /** * @returns The value that was stored under this key, or null */ get(key) { const storedVal = this.domStorage_.getItem(this.prefixedName_(key)); if (storedVal == null) { return null; } else { return jsonEval(storedVal); } } remove(key) { this.domStorage_.removeItem(this.prefixedName_(key)); } prefixedName_(name2) { return this.prefix_ + name2; } toString() { return this.domStorage_.toString(); } }; var MemoryStorage = class { constructor() { this.cache_ = {}; this.isInMemoryStorage = true; } set(key, value) { if (value == null) { delete this.cache_[key]; } else { this.cache_[key] = value; } } get(key) { if (contains(this.cache_, key)) { return this.cache_[key]; } return null; } remove(key) { delete this.cache_[key]; } }; var createStoragefor = function(domStorageName) { try { if (typeof window !== "undefined" && typeof window[domStorageName] !== "undefined") { const domStorage = window[domStorageName]; domStorage.setItem("firebase:sentinel", "cache"); domStorage.removeItem("firebase:sentinel"); return new DOMStorageWrapper(domStorage); } } catch (e) { } return new MemoryStorage(); }; var PersistentStorage = createStoragefor("localStorage"); var SessionStorage = createStoragefor("sessionStorage"); var logClient = new Logger("@firebase/database"); var LUIDGenerator = /* @__PURE__ */ (function() { let id = 1; return function() { return id++; }; })(); var sha1 = function(str) { const utf8Bytes = stringToByteArray(str); const sha12 = new Sha1(); sha12.update(utf8Bytes); const sha1Bytes = sha12.digest(); return base64.encodeByteArray(sha1Bytes); }; var buildLogMessage_ = function(...varArgs) { let message = ""; for (let i = 0; i < varArgs.length; i++) { const arg = varArgs[i]; if (Array.isArray(arg) || arg && typeof arg === "object" && // eslint-disable-next-line @typescript-eslint/no-explicit-any typeof arg.length === "number") { message += buildLogMessage_.apply(null, arg); } else if (typeof arg === "object") { message += stringify(arg); } else { message += arg; } message += " "; } return message; }; var logger = null; var firstLog_ = true; var enableLogging$1 = function(logger_, persistent) { assert(!persistent || logger_ === true || logger_ === false, "Can't turn on custom loggers persistently."); if (logger_ === true) { logClient.logLevel = LogLevel.VERBOSE; logger = logClient.log.bind(logClient); if (persistent) { SessionStorage.set("logging_enabled", true); } } else if (typeof logger_ === "function") { logger = logger_; } else { logger = null; SessionStorage.remove("logging_enabled"); } }; var log = function(...varArgs) { if (firstLog_ === true) { firstLog_ = false; if (logger === null && SessionStorage.get("logging_enabled") === true) { enableLogging$1(true); } } if (logger) { const message = buildLogMessage_.apply(null, varArgs); logger(message); } }; var logWrapper = function(prefix) { return function(...varArgs) { log(prefix, ...varArgs); }; }; var error = function(...varArgs) { const message = "FIREBASE INTERNAL ERROR: " + buildLogMessage_(...varArgs); logClient.error(message); }; var fatal = function(...varArgs) { const message = `FIREBASE FATAL ERROR: ${buildLogMessage_(...varArgs)}`; logClient.error(message); throw new Error(message); }; var warn = function(...varArgs) { const message = "FIREBASE WARNING: " + buildLogMessage_(...varArgs); logClient.warn(message); }; var warnIfPageIsSecure = function() { if (typeof window !== "undefined" && window.location && window.location.protocol && window.location.protocol.indexOf("https:") !== -1) { warn("Insecure Firebase access from a secure page. Please use https in calls to new Firebase()."); } }; var isInvalidJSONNumber = function(data) { return typeof data === "number" && (data !== data || // NaN data === Number.POSITIVE_INFINITY || data === Number.NEGATIVE_INFINITY); }; var executeWhenDOMReady = function(fn) { if (isNodeSdk() || document.readyState === "complete") { fn(); } else { let called = false; const wrappedFn = function() { if (!document.body) { setTimeout(wrappedFn, Math.floor(10)); return; } if (!called) { called = true; fn(); } }; if (document.addEventListener) { document.addEventListener("DOMContentLoaded", wrappedFn, false); window.addEventListener("load", wrappedFn, false); } else if (document.attachEvent) { document.attachEvent("onreadystatechange", () => { if (document.readyState === "complete") { wrappedFn(); } }); window.attachEvent("onload", wrappedFn); } } }; var MIN_NAME = "[MIN_NAME]"; var MAX_NAME = "[MAX_NAME]"; var nameCompare = function(a, b) { if (a === b) { return 0; } else if (a === MIN_NAME || b === MAX_NAME) { return -1; } else if (b === MIN_NAME || a === MAX_NAME) { return 1; } else { const aAsInt = tryParseInt(a), bAsInt = tryParseInt(b); if (aAsInt !== null) { if (bAsInt !== null) { return aAsInt - bAsInt === 0 ? a.length - b.length : aAsInt - bAsInt; } else { return -1; } } else if (bAsInt !== null) { return 1; } else { return a < b ? -1 : 1; } } }; var stringCompare = function(a, b) { if (a === b) { return 0; } else if (a < b) { return -1; } else { return 1; } }; var requireKey = function(key, obj) { if (obj && key in obj) { return obj[key]; } else { throw new Error("Missing required key (" + key + ") in object: " + stringify(obj)); } }; var ObjectToUniqueKey = function(obj) { if (typeof obj !== "object" || obj === null) { return stringify(obj); } const keys = []; for (const k in obj) { keys.push(k); } keys.sort(); let key = "{"; for (let i = 0; i < keys.length; i++) { if (i !== 0) { key += ","; } key += stringify(keys[i]); key += ":"; key += ObjectToUniqueKey(obj[keys[i]]); } key += "}"; return key; }; var splitStringBySize = function(str, segsize) { const len = str.length; if (len <= segsize) { return [str]; } const dataSegs = []; for (let c = 0; c < len; c += segsize) { if (c + segsize > len) { dataSegs.push(str.substring(c, len)); } else { dataSegs.push(str.substring(c, c + segsize)); } } return dataSegs; }; function each(obj, fn) { for (const key in obj) { if (obj.hasOwnProperty(key)) { fn(key, obj[key]); } } } var doubleToIEEE754String = function(v) { assert(!isInvalidJSONNumber(v), "Invalid JSON number"); const ebits = 11, fbits = 52; const bias = (1 << ebits - 1) - 1; let s, e, f, ln, i; if (v === 0) { e = 0; f = 0; s = 1 / v === -Infinity ? 1 : 0; } else { s = v < 0; v = Math.abs(v); if (v >= Math.pow(2, 1 - bias)) { ln = Math.min(Math.floor(Math.log(v) / Math.LN2), bias); e = ln + bias; f = Math.round(v * Math.pow(2, fbits - ln) - Math.pow(2, fbits)); } else { e = 0; f = Math.round(v / Math.pow(2, 1 - bias - fbits)); } } const bits = []; for (i = fbits; i; i -= 1) { bits.push(f % 2 ? 1 : 0); f = Math.floor(f / 2); } for (i = ebits; i; i -= 1) { bits.push(e % 2 ? 1 : 0); e = Math.floor(e / 2); } bits.push(s ? 1 : 0); bits.reverse(); const str = bits.join(""); let hexByteString = ""; for (i = 0; i < 64; i += 8) { let hexByte = parseInt(str.substr(i, 8), 2).toString(16); if (hexByte.length === 1) { hexByte = "0" + hexByte; } hexByteString = hexByteString + hexByte; } return hexByteString.toLowerCase(); }; var isChromeExtensionContentScript = function() { return !!(typeof window === "object" && window["chrome"] && window["chrome"]["extension"] && !/^chrome/.test(window.location.href)); }; var isWindowsStoreApp = function() { return typeof Windows === "object" && typeof Windows.UI === "object"; }; function errorForServerCode(code, query2) { let reason = "Unknown Error"; if (code === "too_big") { reason = "The data requested exceeds the maximum size that can be accessed with a single request."; } else if (code === "permission_denied") { reason = "Client doesn't have permission to access the desired data."; } else if (code === "unavailable") { reason = "The service is unavailable"; } const error2 = new Error(code + " at " + query2._path.toString() + ": " + reason); error2.code = code.toUpperCase(); return error2; } var INTEGER_REGEXP_ = new RegExp("^-?(0*)\\d{1,10}$"); var INTEGER_32_MIN = -2147483648; var INTEGER_32_MAX = 2147483647; var tryParseInt = function(str) { if (INTEGER_REGEXP_.test(str)) { const intVal = Number(str); if (intVal >= INTEGER_32_MIN && intVal <= INTEGER_32_MAX) { return intVal; } } return null; }; var exceptionGuard = function(fn) { try { fn(); } catch (e) { setTimeout(() => { const stack = e.stack || ""; warn("Exception was thrown by user callback.", stack); throw e; }, Math.floor(0)); } }; var beingCrawled = function() { const userAgent = typeof window === "object" && window["navigator"] && window["navigator"]["userAgent"] || ""; return userAgent.search(/googlebot|google webmaster tools|bingbot|yahoo! slurp|baiduspider|yandexbot|duckduckbot/i) >= 0; }; var setTimeoutNonBlocking = function(fn, time) { const timeout = setTimeout(fn, time); if (typeof timeout === "number" && // @ts-ignore Is only defined in Deno environments. typeof Deno !== "undefined" && // @ts-ignore Deno and unrefTimer are only defined in Deno environments. Deno["unrefTimer"]) { Deno.unrefTimer(timeout); } else if (typeof timeout === "object" && timeout["unref"]) { timeout["unref"](); } return timeout; }; var AppCheckTokenProvider = class { constructor(app, appCheckProvider) { this.appCheckProvider = appCheckProvider; this.appName = app.name; if (_isFirebaseServerApp(app) && app.settings.appCheckToken) { this.serverAppAppCheckToken = app.settings.appCheckToken; } this.appCheck = appCheckProvider === null || appCheckProvider === void 0 ? void 0 : appCheckProvider.getImmediate({ optional: true }); if (!this.appCheck) { appCheckProvider === null || appCheckProvider === void 0 ? void 0 : appCheckProvider.get().then((appCheck) => this.appCheck = appCheck); } } getToken(forceRefresh) { if (this.serverAppAppCheckToken) { if (forceRefresh) { throw new Error("Attempted reuse of `FirebaseServerApp.appCheckToken` after previous usage failed."); } return Promise.resolve({ token: this.serverAppAppCheckToken }); } if (!this.appCheck) { return new Promise((resolve, reject) => { setTimeout(() => { if (this.appCheck) { this.getToken(forceRefresh).then(resolve, reject); } else { resolve(null); } }, 0); }); } return this.appCheck.getToken(forceRefresh); } addTokenChangeListener(listener) { var _a; (_a = this.appCheckProvider) === null || _a === void 0 ? void 0 : _a.get().then((appCheck) => appCheck.addTokenListener(listener)); } notifyForInvalidToken() { warn(`Provided AppCheck credentials for the app named "${this.appName}" are invalid. This usually indicates your app was not initialized correctly.`); } }; var FirebaseAuthTokenProvider = class { constructor(appName_, firebaseOptions_, authProvider_) { this.appName_ = appName_; this.firebaseOptions_ = firebaseOptions_; this.authProvider_ = authProvider_; this.auth_ = null; this.auth_ = authProvider_.getImmediate({ optional: true }); if (!this.auth_) { authProvider_.onInit((auth) => this.auth_ = auth); } } getToken(forceRefresh) { if (!this.auth_) { return new Promise((resolve, reject) => { setTimeout(() => { if (this.auth_) { this.getToken(forceRefresh).then(resolve, reject); } else { resolve(null); } }, 0); }); } return this.auth_.getToken(forceRefresh).catch((error2) => { if (error2 && error2.code === "auth/token-not-initialized") { log("Got auth/token-not-initialized error. Treating as null token."); return null; } else { return Promise.reject(error2); } }); } addTokenChangeListener(listener) { if (this.auth_) { this.auth_.addAuthTokenListener(listener); } else { this.authProvider_.get().then((auth) => auth.addAuthTokenListener(listener)); } } removeTokenChangeListener(listener) { this.authProvider_.get().then((auth) => auth.removeAuthTokenListener(listener)); } notifyForInvalidToken() { let errorMessage = 'Provided authentication credentials for the app named "' + this.appName_ + '" are invalid. This usually indicates your app was not initialized correctly. '; if ("credential" in this.firebaseOptions_) { errorMessage += 'Make sure the "credential" property provided to initializeApp() is authorized to access the specified "databaseURL" and is from the correct project.'; } else if ("serviceAccount" in this.firebaseOptions_) { errorMessage += 'Make sure the "serviceAccount" property provided to initializeApp() is authorized to access the specified "databaseURL" and is from the correct project.'; } else { errorMessage += 'Make sure the "apiKey" and "databaseURL" properties provided to initializeApp() match the values provided for your app at https://console.firebase.google.com/.'; } warn(errorMessage); } }; var EmulatorTokenProvider = class { constructor(accessToken) { this.accessToken = accessToken; } getToken(forceRefresh) { return Promise.resolve({ accessToken: this.accessToken }); } addTokenChangeListener(listener) { listener(this.accessToken); } removeTokenChangeListener(listener) { } notifyForInvalidToken() { } }; EmulatorTokenProvider.OWNER = "owner"; var PROTOCOL_VERSION = "5"; var VERSION_PARAM = "v"; var TRANSPORT_SESSION_PARAM = "s"; var REFERER_PARAM = "r"; var FORGE_REF = "f"; var FORGE_DOMAIN_RE = /(console\.firebase|firebase-console-\w+\.corp|firebase\.corp)\.google\.com/; var LAST_SESSION_PARAM = "ls"; var APPLICATION_ID_PARAM = "p"; var APP_CHECK_TOKEN_PARAM = "ac"; var WEBSOCKET = "websocket"; var LONG_POLLING = "long_polling"; var RepoInfo = class { /** * @param host - Hostname portion of the url for the repo * @param secure - Whether or not this repo is accessed over ssl * @param namespace - The namespace represented by the repo * @param webSocketOnly - Whether to prefer websockets over all other transports (used by Nest). * @param nodeAdmin - Whether this instance uses Admin SDK credentials * @param persistenceKey - Override the default session persistence storage key */ constructor(host, secure, namespace, webSocketOnly, nodeAdmin = false, persistenceKey = "", includeNamespaceInQueryParams = false, isUsingEmulator = false, emulatorOptions = null) { this.secure = secure; this.namespace = namespace; this.webSocketOnly = webSocketOnly; this.nodeAdmin = nodeAdmin; this.persistenceKey = persistenceKey; this.includeNamespaceInQueryParams = includeNamespaceInQueryParams; this.isUsingEmulator = isUsingEmulator; this.emulatorOptions = emulatorOptions; this._host = host.toLowerCase(); this._domain = this._host.substr(this._host.indexOf(".") + 1); this.internalHost = PersistentStorage.get("host:" + host) || this._host; } isCacheableHost() { return this.internalHost.substr(0, 2) === "s-"; } isCustomHost() { return this._domain !== "firebaseio.com" && this._domain !== "firebaseio-demo.com"; } get host() { return this._host; } set host(newHost) { if (newHost !== this.internalHost) { this.internalHost = newHost; if (this.isCacheableHost()) { PersistentStorage.set("host:" + this._host, this.internalHost); } } } toString() { let str = this.toURLString(); if (this.persistenceKey) { str += "<" + this.persistenceKey + ">"; } return str; } toURLString() { const protocol = this.secure ? "https://" : "http://"; const query2 = this.includeNamespaceInQueryParams ? `?ns=${this.namespace}` : ""; return `${protocol}${this.host}/${query2}`; } }; function repoInfoNeedsQueryParam(repoInfo) { return repoInfo.host !== repoInfo.internalHost || repoInfo.isCustomHost() || repoInfo.includeNamespaceInQueryParams; } function repoInfoConnectionURL(repoInfo, type, params) { assert(typeof type === "string", "typeof type must == string"); assert(typeof params === "object", "typeof params must == object"); let connURL; if (type === WEBSOCKET) { connURL = (repoInfo.secure ? "wss://" : "ws://") + repoInfo.internalHost + "/.ws?"; } else if (type === LONG_POLLING) { connURL = (repoInfo.secure ? "https://" : "http://") + repoInfo.internalHost + "/.lp?"; } else { throw new Error("Unknown connection type: " + type); } if (repoInfoNeedsQueryParam(repoInfo)) { params["ns"] = repoInfo.namespace; } const pairs = []; each(params, (key, value) => { pairs.push(key + "=" + value); }); return connURL + pairs.join("&"); } var StatsCollection = class { constructor() { this.counters_ = {}; } incrementCounter(name2, amount = 1) { if (!contains(this.counters_, name2)) { this.counters_[name2] = 0; } this.counters_[name2] += amount; } get() { return deepCopy(this.counters_); } }; var collections = {}; var reporters = {}; function statsManagerGetCollection(repoInfo) { const hashString = repoInfo.toString(); if (!collections[hashString]) { collections[hashString] = new StatsCollection(); } return collections[hashString]; } function statsManagerGetOrCreateReporter(repoInfo, creatorFunction) { const hashString = repoInfo.toString(); if (!reporters[hashString]) { reporters[hashString] = creatorFunction(); } return reporters[hashString]; } var PacketReceiver = class { /** * @param onMessage_ */ constructor(onMessage_) { this.onMessage_ = onMessage_; this.pendingResponses = []; this.currentResponseNum = 0; this.closeAfterResponse = -1; this.onClose = null; } closeAfter(responseNum, callback) { this.closeAfterResponse = responseNum; this.onClose = callback; if (this.closeAfterResponse < this.currentResponseNum) { this.onClose(); this.onClose = null; } } /** * Each message from the server comes with a response number, and an array of data. The responseNumber * allows us to ensure that we process them in the right order, since we can't be guaranteed that all * browsers will respond in the same order as the requests we sent */ handleResponse(requestNum, data) { this.pendingResponses[requestNum] = data; while (this.pendingResponses[this.currentResponseNum]) { const toProcess = this.pendingResponses[this.currentResponseNum]; delete this.pendingResponses[this.currentResponseNum]; for (let i = 0; i < toProcess.length; ++i) { if (toProcess[i]) { exceptionGuard(() => { this.onMessage_(toProcess[i]); }); } } if (this.currentResponseNum === this.closeAfterResponse) { if (this.onClose) { this.onClose(); this.onClose = null; } break; } this.currentResponseNum++; } } }; var FIREBASE_LONGPOLL_START_PARAM = "start"; var FIREBASE_LONGPOLL_CLOSE_COMMAND = "close"; var FIREBASE_LONGPOLL_COMMAND_CB_NAME = "pLPCommand"; var FIREBASE_LONGPOLL_DATA_CB_NAME = "pRTLPCB"; var FIREBASE_LONGPOLL_ID_PARAM = "id"; var FIREBASE_LONGPOLL_PW_PARAM = "pw"; var FIREBASE_LONGPOLL_SERIAL_PARAM = "ser"; var FIREBASE_LONGPOLL_CALLBACK_ID_PARAM = "cb"; var FIREBASE_LONGPOLL_SEGMENT_NUM_PARAM = "seg"; var FIREBASE_LONGPOLL_SEGMENTS_IN_PACKET = "ts"; var FIREBASE_LONGPOLL_DATA_PARAM = "d"; var FIREBASE_LONGPOLL_DISCONN_FRAME_REQUEST_PARAM = "dframe"; var MAX_URL_DATA_SIZE = 1870; var SEG_HEADER_SIZE = 30; var MAX_PAYLOAD_SIZE = MAX_URL_DATA_SIZE - SEG_HEADER_SIZE; var KEEPALIVE_REQUEST_INTERVAL = 25e3; var LP_CONNECT_TIMEOUT = 3e4; var BrowserPollConnection = class _BrowserPollConnection { /** * @param connId An identifier for this connection, used for logging * @param repoInfo The info for the endpoint to send data to. * @param applicationId The Firebase App ID for this project. * @param appCheckToken The AppCheck token for this client. * @param authToken The AuthToken to use for this connection. * @param transportSessionId Optional transportSessionid if we are * reconnecting for an existing transport session * @param lastSessionId Optional lastSessionId if the PersistentConnection has * already created a connection previously */ constructor(connId, repoInfo, applicationId, appCheckToken, authToken, transportSessionId, lastSessionId) { this.connId = connId; this.repoInfo = repoInfo; this.applicationId = applicationId; this.appCheckToken = appCheckToken; this.authToken = authToken; this.transportSessionId = transportSessionId; this.lastSessionId = lastSessionId; this.bytesSent = 0; this.bytesReceived = 0; this.everConnected_ = false; this.log_ = logWrapper(connId); this.stats_ = statsManagerGetCollection(repoInfo); this.urlFn = (params) => { if (this.appCheckToken) { params[APP_CHECK_TOKEN_PARAM] = this.appCheckToken; } return repoInfoConnectionURL(repoInfo, LONG_POLLING, params); }; } /** * @param onMessage - Callback when messages arrive * @param onDisconnect - Callback with connection lost. */ open(onMessage, onDisconnect2) { this.curSegmentNum = 0; this.onDisconnect_ = onDisconnect2; this.myPacketOrderer = new PacketReceiver(onMessage); this.isClosed_ = false; this.connectTimeoutTimer_ = setTimeout(() => { this.log_("Timed out trying to connect."); this.onClosed_(); this.connectTimeoutTimer_ = null; }, Math.floor(LP_CONNECT_TIMEOUT)); executeWhenDOMReady(() => { if (this.isClosed_) { return; } this.scriptTagHolder = new FirebaseIFrameScriptHolder((...args) => { const [command, arg1, arg2, arg3, arg4] = args; this.incrementIncomingBytes_(args); if (!this.scriptTagHolder) { return; } if (this.connectTimeoutTimer_) { clearTimeout(this.connectTimeoutTimer_); this.connectTimeoutTimer_ = null; } this.everConnected_ = true; if (command === FIREBASE_LONGPOLL_START_PARAM) { this.id = arg1; this.password = arg2; } else if (command === FIREBASE_LONGPOLL_CLOSE_COMMAND) { if (arg1) { this.scriptTagHolder.sendNewPolls = false; this.myPacketOrderer.closeAfter(arg1, () => { this.onClosed_(); }); } else { this.onClosed_(); } } else { throw new Error("Unrecognized command received: " + command); } }, (...args) => { const [pN, data] = args; this.incrementIncomingBytes_(args); this.myPacketOrderer.handleResponse(pN, data); }, () => { this.onClosed_(); }, this.urlFn); const urlParams = {}; urlParams[FIREBASE_LONGPOLL_START_PARAM] = "t"; urlParams[FIREBASE_LONGPOLL_SERIAL_PARAM] = Math.floor(Math.random() * 1e8); if (this.scriptTagHolder.uniqueCallbackIdentifier) { urlParams[FIREBASE_LONGPOLL_CALLBACK_ID_PARAM] = this.scriptTagHolder.uniqueCallbackIdentifier; } urlParams[VERSION_PARAM] = PROTOCOL_VERSION; if (this.transportSessionId) { urlParams[TRANSPORT_SESSION_PARAM] = this.transportSessionId; } if (this.lastSessionId) { urlParams[LAST_SESSION_PARAM] = this.lastSessionId; } if (this.applicationId) { urlParams[APPLICATION_ID_PARAM] = this.applicationId; } if (this.appCheckToken) { urlParams[APP_CHECK_TOKEN_PARAM] = this.appCheckToken; } if (typeof location !== "undefined" && location.hostname && FORGE_DOMAIN_RE.test(location.hostname)) { urlParams[REFERER_PARAM] = FORGE_REF; } const connectURL = this.urlFn(urlParams); this.log_("Connecting via long-poll to " + connectURL); this.scriptTagHolder.addTag(connectURL, () => { }); }); } /** * Call this when a handshake has completed successfully and we want to consider the connection established */ start() { this.scriptTagHolder.startLongPoll(this.id, this.password); this.addDisconnectPingFrame(this.id, this.password); } /** * Forces long polling to be considered as a potential transport */ static forceAllow() { _BrowserPollConnection.forceAllow_ = true; } /** * Forces longpolling to not be considered as a potential transport */ static forceDisallow() { _BrowserPollConnection.forceDisallow_ = true; } // Static method, use string literal so it can be accessed in a generic way static isAvailable() { if (isNodeSdk()) { return false; } else if (_BrowserPollConnection.forceAllow_) { return true; } else { return !_BrowserPollConnection.forceDisallow_ && typeof document !== "undefined" && document.createElement != null && !isChromeExtensionContentScript() && !isWindowsStoreApp(); } } /** * No-op for polling */ markConnectionHealthy() { } /** * Stops polling and cleans up the iframe */ shutdown_() { this.isClosed_ = true; if (this.scriptTagHolder) { this.scriptTagHolder.close(); this.scriptTagHolder = null; } if (this.myDisconnFrame) { document.body.removeChild(this.myDisconnFrame); this.myDisconnFrame = null; } if (this.connectTimeoutTimer_) { clearTimeout(this.connectTimeoutTimer_); this.connectTimeoutTimer_ = null; } } /** * Triggered when this transport is closed */ onClosed_() { if (!this.isClosed_) { this.log_("Longpoll is closing itself"); this.shutdown_(); if (this.onDisconnect_) { this.onDisconnect_(this.everConnected_); this.onDisconnect_ = null; } } } /** * External-facing close handler. RealTime has requested we shut down. Kill our connection and tell the server * that we've left. */ close() { if (!this.isClosed_) { this.log_("Longpoll is being closed."); this.shutdown_(); } } /** * Send the JSON object down to the server. It will need to be stringified, base64 encoded, and then * broken into chunks (since URLs have a small maximum length). * @param data - The JSON data to transmit. */ send(data) { const dataStr = stringify(data); this.bytesSent += dataStr.length; this.stats_.incrementCounter("bytes_sent", dataStr.length); const base64data = base64Encode(dataStr); const dataSegs = splitStringBySize(base64data, MAX_PAYLOAD_SIZE); for (let i = 0; i < dataSegs.length; i++) { this.scriptTagHolder.enqueueSegment(this.curSegmentNum, dataSegs.length, dataSegs[i]); this.curSegmentNum++; } } /** * This is how we notify the server that we're leaving. * We aren't able to send requests with DHTML on a window close event, but we can * trigger XHR requests in some browsers (everything but Opera basically). */ addDisconnectPingFrame(id, pw) { if (isNodeSdk()) { return; } this.myDisconnFrame = document.createElement("iframe"); const urlParams = {}; urlParams[FIREBASE_LONGPOLL_DISCONN_FRAME_REQUEST_PARAM] = "t"; urlParams[FIREBASE_LONGPOLL_ID_PARAM] = id; urlParams[FIREBASE_LONGPOLL_PW_PARAM] = pw; this.myDisconnFrame.src = this.urlFn(urlParams); this.myDisconnFrame.style.display = "none"; document.body.appendChild(this.myDisconnFrame); } /** * Used to track the bytes received by this client */ incrementIncomingBytes_(args) { const bytesReceived = stringify(args).length; this.bytesReceived += bytesReceived; this.stats_.incrementCounter("bytes_received", bytesReceived); } }; var FirebaseIFrameScriptHolder = class _FirebaseIFrameScriptHolder { /** * @param commandCB - The callback to be called when control commands are received from the server. * @param onMessageCB - The callback to be triggered when responses arrive from the server. * @param onDisconnect - The callback to be triggered when this tag holder is closed * @param urlFn - A function that provides the URL of the endpoint to send data to. */ constructor(commandCB, onMessageCB, onDisconnect2, urlFn) { this.onDisconnect = onDisconnect2; this.urlFn = urlFn; this.outstandingRequests = /* @__PURE__ */ new Set(); this.pendingSegs = []; this.currentSerial = Math.floor(Math.random() * 1e8); this.sendNewPolls = true; if (!isNodeSdk()) { this.uniqueCallbackIdentifier = LUIDGenerator(); window[FIREBASE_LONGPOLL_COMMAND_CB_NAME + this.uniqueCallbackIdentifier] = commandCB; window[FIREBASE_LONGPOLL_DATA_CB_NAME + this.uniqueCallbackIdentifier] = onMessageCB; this.myIFrame = _FirebaseIFrameScriptHolder.createIFrame_(); let script = ""; if (this.myIFrame.src && this.myIFrame.src.substr(0, "javascript:".length) === "javascript:") { const currentDomain = document.domain; script = '