{"version":3,"file":"a198fdd9-58498406d7cbeeb82710.js","mappings":"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","sources":["webpack://gatsby-starter-default/./node_modules/@firebase/database/dist/index.esm2017.js"],"sourcesContent":["import { _getProvider, getApp, SDK_VERSION as SDK_VERSION$1, _registerComponent, registerVersion } from '@firebase/app';\nimport { Component, ComponentContainer, Provider } from '@firebase/component';\nimport { stringify, jsonEval, contains, assert, isNodeSdk, stringToByteArray, Sha1, base64, deepCopy, base64Encode, isMobileCordova, stringLength, Deferred, safeGet, isAdmin, isValidFormat, isEmpty, isReactNative, assertionError, map, querystring, errorPrefix, getModularInstance, getDefaultEmulatorHostnameAndPort, createMockUserToken } from '@firebase/util';\nimport { Logger, LogLevel } from '@firebase/logger';\n\nconst name = \"@firebase/database\";\nconst version = \"1.0.2\";\n\n/**\r\n * @license\r\n * Copyright 2019 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/** The semver (www.semver.org) version of the SDK. */\r\nlet SDK_VERSION = '';\r\n/**\r\n * SDK_VERSION should be set before any database instance is created\r\n * @internal\r\n */\r\nfunction setSDKVersion(version) {\r\n SDK_VERSION = version;\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * Wraps a DOM Storage object and:\r\n * - automatically encode objects as JSON strings before storing them to allow us to store arbitrary types.\r\n * - prefixes names with \"firebase:\" to avoid collisions with app data.\r\n *\r\n * We automatically (see storage.js) create two such wrappers, one for sessionStorage,\r\n * and one for localStorage.\r\n *\r\n */\r\nclass DOMStorageWrapper {\r\n /**\r\n * @param domStorage_ - The underlying storage object (e.g. localStorage or sessionStorage)\r\n */\r\n constructor(domStorage_) {\r\n this.domStorage_ = domStorage_;\r\n // Use a prefix to avoid collisions with other stuff saved by the app.\r\n this.prefix_ = 'firebase:';\r\n }\r\n /**\r\n * @param key - The key to save the value under\r\n * @param value - The value being stored, or null to remove the key.\r\n */\r\n set(key, value) {\r\n if (value == null) {\r\n this.domStorage_.removeItem(this.prefixedName_(key));\r\n }\r\n else {\r\n this.domStorage_.setItem(this.prefixedName_(key), stringify(value));\r\n }\r\n }\r\n /**\r\n * @returns The value that was stored under this key, or null\r\n */\r\n get(key) {\r\n const storedVal = this.domStorage_.getItem(this.prefixedName_(key));\r\n if (storedVal == null) {\r\n return null;\r\n }\r\n else {\r\n return jsonEval(storedVal);\r\n }\r\n }\r\n remove(key) {\r\n this.domStorage_.removeItem(this.prefixedName_(key));\r\n }\r\n prefixedName_(name) {\r\n return this.prefix_ + name;\r\n }\r\n toString() {\r\n return this.domStorage_.toString();\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * An in-memory storage implementation that matches the API of DOMStorageWrapper\r\n * (TODO: create interface for both to implement).\r\n */\r\nclass MemoryStorage {\r\n constructor() {\r\n this.cache_ = {};\r\n this.isInMemoryStorage = true;\r\n }\r\n set(key, value) {\r\n if (value == null) {\r\n delete this.cache_[key];\r\n }\r\n else {\r\n this.cache_[key] = value;\r\n }\r\n }\r\n get(key) {\r\n if (contains(this.cache_, key)) {\r\n return this.cache_[key];\r\n }\r\n return null;\r\n }\r\n remove(key) {\r\n delete this.cache_[key];\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * Helper to create a DOMStorageWrapper or else fall back to MemoryStorage.\r\n * TODO: Once MemoryStorage and DOMStorageWrapper have a shared interface this method annotation should change\r\n * to reflect this type\r\n *\r\n * @param domStorageName - Name of the underlying storage object\r\n * (e.g. 'localStorage' or 'sessionStorage').\r\n * @returns Turning off type information until a common interface is defined.\r\n */\r\nconst createStoragefor = function (domStorageName) {\r\n try {\r\n // NOTE: just accessing \"localStorage\" or \"window['localStorage']\" may throw a security exception,\r\n // so it must be inside the try/catch.\r\n if (typeof window !== 'undefined' &&\r\n typeof window[domStorageName] !== 'undefined') {\r\n // Need to test cache. Just because it's here doesn't mean it works\r\n const domStorage = window[domStorageName];\r\n domStorage.setItem('firebase:sentinel', 'cache');\r\n domStorage.removeItem('firebase:sentinel');\r\n return new DOMStorageWrapper(domStorage);\r\n }\r\n }\r\n catch (e) { }\r\n // Failed to create wrapper. Just return in-memory storage.\r\n // TODO: log?\r\n return new MemoryStorage();\r\n};\r\n/** A storage object that lasts across sessions */\r\nconst PersistentStorage = createStoragefor('localStorage');\r\n/** A storage object that only lasts one session */\r\nconst SessionStorage = createStoragefor('sessionStorage');\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nconst logClient = new Logger('@firebase/database');\r\n/**\r\n * Returns a locally-unique ID (generated by just incrementing up from 0 each time its called).\r\n */\r\nconst LUIDGenerator = (function () {\r\n let id = 1;\r\n return function () {\r\n return id++;\r\n };\r\n})();\r\n/**\r\n * Sha1 hash of the input string\r\n * @param str - The string to hash\r\n * @returns {!string} The resulting hash\r\n */\r\nconst sha1 = function (str) {\r\n const utf8Bytes = stringToByteArray(str);\r\n const sha1 = new Sha1();\r\n sha1.update(utf8Bytes);\r\n const sha1Bytes = sha1.digest();\r\n return base64.encodeByteArray(sha1Bytes);\r\n};\r\nconst buildLogMessage_ = function (...varArgs) {\r\n let message = '';\r\n for (let i = 0; i < varArgs.length; i++) {\r\n const arg = varArgs[i];\r\n if (Array.isArray(arg) ||\r\n (arg &&\r\n typeof arg === 'object' &&\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n typeof arg.length === 'number')) {\r\n message += buildLogMessage_.apply(null, arg);\r\n }\r\n else if (typeof arg === 'object') {\r\n message += stringify(arg);\r\n }\r\n else {\r\n message += arg;\r\n }\r\n message += ' ';\r\n }\r\n return message;\r\n};\r\n/**\r\n * Use this for all debug messages in Firebase.\r\n */\r\nlet logger = null;\r\n/**\r\n * Flag to check for log availability on first log message\r\n */\r\nlet firstLog_ = true;\r\n/**\r\n * The implementation of Firebase.enableLogging (defined here to break dependencies)\r\n * @param logger_ - A flag to turn on logging, or a custom logger\r\n * @param persistent - Whether or not to persist logging settings across refreshes\r\n */\r\nconst enableLogging$1 = function (logger_, persistent) {\r\n assert(!persistent || logger_ === true || logger_ === false, \"Can't turn on custom loggers persistently.\");\r\n if (logger_ === true) {\r\n logClient.logLevel = LogLevel.VERBOSE;\r\n logger = logClient.log.bind(logClient);\r\n if (persistent) {\r\n SessionStorage.set('logging_enabled', true);\r\n }\r\n }\r\n else if (typeof logger_ === 'function') {\r\n logger = logger_;\r\n }\r\n else {\r\n logger = null;\r\n SessionStorage.remove('logging_enabled');\r\n }\r\n};\r\nconst log = function (...varArgs) {\r\n if (firstLog_ === true) {\r\n firstLog_ = false;\r\n if (logger === null && SessionStorage.get('logging_enabled') === true) {\r\n enableLogging$1(true);\r\n }\r\n }\r\n if (logger) {\r\n const message = buildLogMessage_.apply(null, varArgs);\r\n logger(message);\r\n }\r\n};\r\nconst logWrapper = function (prefix) {\r\n return function (...varArgs) {\r\n log(prefix, ...varArgs);\r\n };\r\n};\r\nconst error = function (...varArgs) {\r\n const message = 'FIREBASE INTERNAL ERROR: ' + buildLogMessage_(...varArgs);\r\n logClient.error(message);\r\n};\r\nconst fatal = function (...varArgs) {\r\n const message = `FIREBASE FATAL ERROR: ${buildLogMessage_(...varArgs)}`;\r\n logClient.error(message);\r\n throw new Error(message);\r\n};\r\nconst warn = function (...varArgs) {\r\n const message = 'FIREBASE WARNING: ' + buildLogMessage_(...varArgs);\r\n logClient.warn(message);\r\n};\r\n/**\r\n * Logs a warning if the containing page uses https. Called when a call to new Firebase\r\n * does not use https.\r\n */\r\nconst warnIfPageIsSecure = function () {\r\n // Be very careful accessing browser globals. Who knows what may or may not exist.\r\n if (typeof window !== 'undefined' &&\r\n window.location &&\r\n window.location.protocol &&\r\n window.location.protocol.indexOf('https:') !== -1) {\r\n warn('Insecure Firebase access from a secure page. ' +\r\n 'Please use https in calls to new Firebase().');\r\n }\r\n};\r\n/**\r\n * Returns true if data is NaN, or +/- Infinity.\r\n */\r\nconst isInvalidJSONNumber = function (data) {\r\n return (typeof data === 'number' &&\r\n (data !== data || // NaN\r\n data === Number.POSITIVE_INFINITY ||\r\n data === Number.NEGATIVE_INFINITY));\r\n};\r\nconst executeWhenDOMReady = function (fn) {\r\n if (isNodeSdk() || document.readyState === 'complete') {\r\n fn();\r\n }\r\n else {\r\n // Modeled after jQuery. Try DOMContentLoaded and onreadystatechange (which\r\n // fire before onload), but fall back to onload.\r\n let called = false;\r\n const wrappedFn = function () {\r\n if (!document.body) {\r\n setTimeout(wrappedFn, Math.floor(10));\r\n return;\r\n }\r\n if (!called) {\r\n called = true;\r\n fn();\r\n }\r\n };\r\n if (document.addEventListener) {\r\n document.addEventListener('DOMContentLoaded', wrappedFn, false);\r\n // fallback to onload.\r\n window.addEventListener('load', wrappedFn, false);\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n }\r\n else if (document.attachEvent) {\r\n // IE.\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n document.attachEvent('onreadystatechange', () => {\r\n if (document.readyState === 'complete') {\r\n wrappedFn();\r\n }\r\n });\r\n // fallback to onload.\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n window.attachEvent('onload', wrappedFn);\r\n // jQuery has an extra hack for IE that we could employ (based on\r\n // http://javascript.nwbox.com/IEContentLoaded/) But it looks really old.\r\n // I'm hoping we don't need it.\r\n }\r\n }\r\n};\r\n/**\r\n * Minimum key name. Invalid for actual data, used as a marker to sort before any valid names\r\n */\r\nconst MIN_NAME = '[MIN_NAME]';\r\n/**\r\n * Maximum key name. Invalid for actual data, used as a marker to sort above any valid names\r\n */\r\nconst MAX_NAME = '[MAX_NAME]';\r\n/**\r\n * Compares valid Firebase key names, plus min and max name\r\n */\r\nconst nameCompare = function (a, b) {\r\n if (a === b) {\r\n return 0;\r\n }\r\n else if (a === MIN_NAME || b === MAX_NAME) {\r\n return -1;\r\n }\r\n else if (b === MIN_NAME || a === MAX_NAME) {\r\n return 1;\r\n }\r\n else {\r\n const aAsInt = tryParseInt(a), bAsInt = tryParseInt(b);\r\n if (aAsInt !== null) {\r\n if (bAsInt !== null) {\r\n return aAsInt - bAsInt === 0 ? a.length - b.length : aAsInt - bAsInt;\r\n }\r\n else {\r\n return -1;\r\n }\r\n }\r\n else if (bAsInt !== null) {\r\n return 1;\r\n }\r\n else {\r\n return a < b ? -1 : 1;\r\n }\r\n }\r\n};\r\n/**\r\n * @returns {!number} comparison result.\r\n */\r\nconst stringCompare = function (a, b) {\r\n if (a === b) {\r\n return 0;\r\n }\r\n else if (a < b) {\r\n return -1;\r\n }\r\n else {\r\n return 1;\r\n }\r\n};\r\nconst requireKey = function (key, obj) {\r\n if (obj && key in obj) {\r\n return obj[key];\r\n }\r\n else {\r\n throw new Error('Missing required key (' + key + ') in object: ' + stringify(obj));\r\n }\r\n};\r\nconst ObjectToUniqueKey = function (obj) {\r\n if (typeof obj !== 'object' || obj === null) {\r\n return stringify(obj);\r\n }\r\n const keys = [];\r\n // eslint-disable-next-line guard-for-in\r\n for (const k in obj) {\r\n keys.push(k);\r\n }\r\n // Export as json, but with the keys sorted.\r\n keys.sort();\r\n let key = '{';\r\n for (let i = 0; i < keys.length; i++) {\r\n if (i !== 0) {\r\n key += ',';\r\n }\r\n key += stringify(keys[i]);\r\n key += ':';\r\n key += ObjectToUniqueKey(obj[keys[i]]);\r\n }\r\n key += '}';\r\n return key;\r\n};\r\n/**\r\n * Splits a string into a number of smaller segments of maximum size\r\n * @param str - The string\r\n * @param segsize - The maximum number of chars in the string.\r\n * @returns The string, split into appropriately-sized chunks\r\n */\r\nconst splitStringBySize = function (str, segsize) {\r\n const len = str.length;\r\n if (len <= segsize) {\r\n return [str];\r\n }\r\n const dataSegs = [];\r\n for (let c = 0; c < len; c += segsize) {\r\n if (c + segsize > len) {\r\n dataSegs.push(str.substring(c, len));\r\n }\r\n else {\r\n dataSegs.push(str.substring(c, c + segsize));\r\n }\r\n }\r\n return dataSegs;\r\n};\r\n/**\r\n * Apply a function to each (key, value) pair in an object or\r\n * apply a function to each (index, value) pair in an array\r\n * @param obj - The object or array to iterate over\r\n * @param fn - The function to apply\r\n */\r\nfunction each(obj, fn) {\r\n for (const key in obj) {\r\n if (obj.hasOwnProperty(key)) {\r\n fn(key, obj[key]);\r\n }\r\n }\r\n}\r\n/**\r\n * Borrowed from http://hg.secondlife.com/llsd/src/tip/js/typedarray.js (MIT License)\r\n * I made one modification at the end and removed the NaN / Infinity\r\n * handling (since it seemed broken [caused an overflow] and we don't need it). See MJL comments.\r\n * @param v - A double\r\n *\r\n */\r\nconst doubleToIEEE754String = function (v) {\r\n assert(!isInvalidJSONNumber(v), 'Invalid JSON number'); // MJL\r\n const ebits = 11, fbits = 52;\r\n const bias = (1 << (ebits - 1)) - 1;\r\n let s, e, f, ln, i;\r\n // Compute sign, exponent, fraction\r\n // Skip NaN / Infinity handling --MJL.\r\n if (v === 0) {\r\n e = 0;\r\n f = 0;\r\n s = 1 / v === -Infinity ? 1 : 0;\r\n }\r\n else {\r\n s = v < 0;\r\n v = Math.abs(v);\r\n if (v >= Math.pow(2, 1 - bias)) {\r\n // Normalized\r\n ln = Math.min(Math.floor(Math.log(v) / Math.LN2), bias);\r\n e = ln + bias;\r\n f = Math.round(v * Math.pow(2, fbits - ln) - Math.pow(2, fbits));\r\n }\r\n else {\r\n // Denormalized\r\n e = 0;\r\n f = Math.round(v / Math.pow(2, 1 - bias - fbits));\r\n }\r\n }\r\n // Pack sign, exponent, fraction\r\n const bits = [];\r\n for (i = fbits; i; i -= 1) {\r\n bits.push(f % 2 ? 1 : 0);\r\n f = Math.floor(f / 2);\r\n }\r\n for (i = ebits; i; i -= 1) {\r\n bits.push(e % 2 ? 1 : 0);\r\n e = Math.floor(e / 2);\r\n }\r\n bits.push(s ? 1 : 0);\r\n bits.reverse();\r\n const str = bits.join('');\r\n // Return the data as a hex string. --MJL\r\n let hexByteString = '';\r\n for (i = 0; i < 64; i += 8) {\r\n let hexByte = parseInt(str.substr(i, 8), 2).toString(16);\r\n if (hexByte.length === 1) {\r\n hexByte = '0' + hexByte;\r\n }\r\n hexByteString = hexByteString + hexByte;\r\n }\r\n return hexByteString.toLowerCase();\r\n};\r\n/**\r\n * Used to detect if we're in a Chrome content script (which executes in an\r\n * isolated environment where long-polling doesn't work).\r\n */\r\nconst isChromeExtensionContentScript = function () {\r\n return !!(typeof window === 'object' &&\r\n window['chrome'] &&\r\n window['chrome']['extension'] &&\r\n !/^chrome/.test(window.location.href));\r\n};\r\n/**\r\n * Used to detect if we're in a Windows 8 Store app.\r\n */\r\nconst isWindowsStoreApp = function () {\r\n // Check for the presence of a couple WinRT globals\r\n return typeof Windows === 'object' && typeof Windows.UI === 'object';\r\n};\r\n/**\r\n * Converts a server error code to a Javascript Error\r\n */\r\nfunction errorForServerCode(code, query) {\r\n let reason = 'Unknown Error';\r\n if (code === 'too_big') {\r\n reason =\r\n 'The data requested exceeds the maximum size ' +\r\n 'that can be accessed with a single request.';\r\n }\r\n else if (code === 'permission_denied') {\r\n reason = \"Client doesn't have permission to access the desired data.\";\r\n }\r\n else if (code === 'unavailable') {\r\n reason = 'The service is unavailable';\r\n }\r\n const error = new Error(code + ' at ' + query._path.toString() + ': ' + reason);\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n error.code = code.toUpperCase();\r\n return error;\r\n}\r\n/**\r\n * Used to test for integer-looking strings\r\n */\r\nconst INTEGER_REGEXP_ = new RegExp('^-?(0*)\\\\d{1,10}$');\r\n/**\r\n * For use in keys, the minimum possible 32-bit integer.\r\n */\r\nconst INTEGER_32_MIN = -2147483648;\r\n/**\r\n * For use in kyes, the maximum possible 32-bit integer.\r\n */\r\nconst INTEGER_32_MAX = 2147483647;\r\n/**\r\n * If the string contains a 32-bit integer, return it. Else return null.\r\n */\r\nconst tryParseInt = function (str) {\r\n if (INTEGER_REGEXP_.test(str)) {\r\n const intVal = Number(str);\r\n if (intVal >= INTEGER_32_MIN && intVal <= INTEGER_32_MAX) {\r\n return intVal;\r\n }\r\n }\r\n return null;\r\n};\r\n/**\r\n * Helper to run some code but catch any exceptions and re-throw them later.\r\n * Useful for preventing user callbacks from breaking internal code.\r\n *\r\n * Re-throwing the exception from a setTimeout is a little evil, but it's very\r\n * convenient (we don't have to try to figure out when is a safe point to\r\n * re-throw it), and the behavior seems reasonable:\r\n *\r\n * * If you aren't pausing on exceptions, you get an error in the console with\r\n * the correct stack trace.\r\n * * If you're pausing on all exceptions, the debugger will pause on your\r\n * exception and then again when we rethrow it.\r\n * * If you're only pausing on uncaught exceptions, the debugger will only pause\r\n * on us re-throwing it.\r\n *\r\n * @param fn - The code to guard.\r\n */\r\nconst exceptionGuard = function (fn) {\r\n try {\r\n fn();\r\n }\r\n catch (e) {\r\n // Re-throw exception when it's safe.\r\n setTimeout(() => {\r\n // It used to be that \"throw e\" would result in a good console error with\r\n // relevant context, but as of Chrome 39, you just get the firebase.js\r\n // file/line number where we re-throw it, which is useless. So we log\r\n // e.stack explicitly.\r\n const stack = e.stack || '';\r\n warn('Exception was thrown by user callback.', stack);\r\n throw e;\r\n }, Math.floor(0));\r\n }\r\n};\r\n/**\r\n * @returns {boolean} true if we think we're currently being crawled.\r\n */\r\nconst beingCrawled = function () {\r\n const userAgent = (typeof window === 'object' &&\r\n window['navigator'] &&\r\n window['navigator']['userAgent']) ||\r\n '';\r\n // For now we whitelist the most popular crawlers. We should refine this to be the set of crawlers we\r\n // believe to support JavaScript/AJAX rendering.\r\n // NOTE: Google Webmaster Tools doesn't really belong, but their \"This is how a visitor to your website\r\n // would have seen the page\" is flaky if we don't treat it as a crawler.\r\n return (userAgent.search(/googlebot|google webmaster tools|bingbot|yahoo! slurp|baiduspider|yandexbot|duckduckbot/i) >= 0);\r\n};\r\n/**\r\n * Same as setTimeout() except on Node.JS it will /not/ prevent the process from exiting.\r\n *\r\n * It is removed with clearTimeout() as normal.\r\n *\r\n * @param fn - Function to run.\r\n * @param time - Milliseconds to wait before running.\r\n * @returns The setTimeout() return value.\r\n */\r\nconst setTimeoutNonBlocking = function (fn, time) {\r\n const timeout = setTimeout(fn, time);\r\n // Note: at the time of this comment, unrefTimer is under the unstable set of APIs. Run with --unstable to enable the API.\r\n if (typeof timeout === 'number' &&\r\n // @ts-ignore Is only defined in Deno environments.\r\n typeof Deno !== 'undefined' &&\r\n // @ts-ignore Deno and unrefTimer are only defined in Deno environments.\r\n Deno['unrefTimer']) {\r\n // @ts-ignore Deno and unrefTimer are only defined in Deno environments.\r\n Deno.unrefTimer(timeout);\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n }\r\n else if (typeof timeout === 'object' && timeout['unref']) {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n timeout['unref']();\r\n }\r\n return timeout;\r\n};\n\n/**\r\n * @license\r\n * Copyright 2021 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * Abstraction around AppCheck's token fetching capabilities.\r\n */\r\nclass AppCheckTokenProvider {\r\n constructor(appName_, appCheckProvider) {\r\n this.appName_ = appName_;\r\n this.appCheckProvider = appCheckProvider;\r\n this.appCheck = appCheckProvider === null || appCheckProvider === void 0 ? void 0 : appCheckProvider.getImmediate({ optional: true });\r\n if (!this.appCheck) {\r\n appCheckProvider === null || appCheckProvider === void 0 ? void 0 : appCheckProvider.get().then(appCheck => (this.appCheck = appCheck));\r\n }\r\n }\r\n getToken(forceRefresh) {\r\n if (!this.appCheck) {\r\n return new Promise((resolve, reject) => {\r\n // Support delayed initialization of FirebaseAppCheck. This allows our\r\n // customers to initialize the RTDB SDK before initializing Firebase\r\n // AppCheck and ensures that all requests are authenticated if a token\r\n // becomes available before the timoeout below expires.\r\n setTimeout(() => {\r\n if (this.appCheck) {\r\n this.getToken(forceRefresh).then(resolve, reject);\r\n }\r\n else {\r\n resolve(null);\r\n }\r\n }, 0);\r\n });\r\n }\r\n return this.appCheck.getToken(forceRefresh);\r\n }\r\n addTokenChangeListener(listener) {\r\n var _a;\r\n (_a = this.appCheckProvider) === null || _a === void 0 ? void 0 : _a.get().then(appCheck => appCheck.addTokenListener(listener));\r\n }\r\n notifyForInvalidToken() {\r\n warn(`Provided AppCheck credentials for the app named \"${this.appName_}\" ` +\r\n 'are invalid. This usually indicates your app was not initialized correctly.');\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * Abstraction around FirebaseApp's token fetching capabilities.\r\n */\r\nclass FirebaseAuthTokenProvider {\r\n constructor(appName_, firebaseOptions_, authProvider_) {\r\n this.appName_ = appName_;\r\n this.firebaseOptions_ = firebaseOptions_;\r\n this.authProvider_ = authProvider_;\r\n this.auth_ = null;\r\n this.auth_ = authProvider_.getImmediate({ optional: true });\r\n if (!this.auth_) {\r\n authProvider_.onInit(auth => (this.auth_ = auth));\r\n }\r\n }\r\n getToken(forceRefresh) {\r\n if (!this.auth_) {\r\n return new Promise((resolve, reject) => {\r\n // Support delayed initialization of FirebaseAuth. This allows our\r\n // customers to initialize the RTDB SDK before initializing Firebase\r\n // Auth and ensures that all requests are authenticated if a token\r\n // becomes available before the timoeout below expires.\r\n setTimeout(() => {\r\n if (this.auth_) {\r\n this.getToken(forceRefresh).then(resolve, reject);\r\n }\r\n else {\r\n resolve(null);\r\n }\r\n }, 0);\r\n });\r\n }\r\n return this.auth_.getToken(forceRefresh).catch(error => {\r\n // TODO: Need to figure out all the cases this is raised and whether\r\n // this makes sense.\r\n if (error && error.code === 'auth/token-not-initialized') {\r\n log('Got auth/token-not-initialized error. Treating as null token.');\r\n return null;\r\n }\r\n else {\r\n return Promise.reject(error);\r\n }\r\n });\r\n }\r\n addTokenChangeListener(listener) {\r\n // TODO: We might want to wrap the listener and call it with no args to\r\n // avoid a leaky abstraction, but that makes removing the listener harder.\r\n if (this.auth_) {\r\n this.auth_.addAuthTokenListener(listener);\r\n }\r\n else {\r\n this.authProvider_\r\n .get()\r\n .then(auth => auth.addAuthTokenListener(listener));\r\n }\r\n }\r\n removeTokenChangeListener(listener) {\r\n this.authProvider_\r\n .get()\r\n .then(auth => auth.removeAuthTokenListener(listener));\r\n }\r\n notifyForInvalidToken() {\r\n let errorMessage = 'Provided authentication credentials for the app named \"' +\r\n this.appName_ +\r\n '\" are invalid. This usually indicates your app was not ' +\r\n 'initialized correctly. ';\r\n if ('credential' in this.firebaseOptions_) {\r\n errorMessage +=\r\n 'Make sure the \"credential\" property provided to initializeApp() ' +\r\n 'is authorized to access the specified \"databaseURL\" and is from the correct ' +\r\n 'project.';\r\n }\r\n else if ('serviceAccount' in this.firebaseOptions_) {\r\n errorMessage +=\r\n 'Make sure the \"serviceAccount\" property provided to initializeApp() ' +\r\n 'is authorized to access the specified \"databaseURL\" and is from the correct ' +\r\n 'project.';\r\n }\r\n else {\r\n errorMessage +=\r\n 'Make sure the \"apiKey\" and \"databaseURL\" properties provided to ' +\r\n 'initializeApp() match the values provided for your app at ' +\r\n 'https://console.firebase.google.com/.';\r\n }\r\n warn(errorMessage);\r\n }\r\n}\r\n/* AuthTokenProvider that supplies a constant token. Used by Admin SDK or mockUserToken with emulators. */\r\nclass EmulatorTokenProvider {\r\n constructor(accessToken) {\r\n this.accessToken = accessToken;\r\n }\r\n getToken(forceRefresh) {\r\n return Promise.resolve({\r\n accessToken: this.accessToken\r\n });\r\n }\r\n addTokenChangeListener(listener) {\r\n // Invoke the listener immediately to match the behavior in Firebase Auth\r\n // (see packages/auth/src/auth.js#L1807)\r\n listener(this.accessToken);\r\n }\r\n removeTokenChangeListener(listener) { }\r\n notifyForInvalidToken() { }\r\n}\r\n/** A string that is treated as an admin access token by the RTDB emulator. Used by Admin SDK. */\r\nEmulatorTokenProvider.OWNER = 'owner';\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nconst PROTOCOL_VERSION = '5';\r\nconst VERSION_PARAM = 'v';\r\nconst TRANSPORT_SESSION_PARAM = 's';\r\nconst REFERER_PARAM = 'r';\r\nconst FORGE_REF = 'f';\r\n// Matches console.firebase.google.com, firebase-console-*.corp.google.com and\r\n// firebase.corp.google.com\r\nconst FORGE_DOMAIN_RE = /(console\\.firebase|firebase-console-\\w+\\.corp|firebase\\.corp)\\.google\\.com/;\r\nconst LAST_SESSION_PARAM = 'ls';\r\nconst APPLICATION_ID_PARAM = 'p';\r\nconst APP_CHECK_TOKEN_PARAM = 'ac';\r\nconst WEBSOCKET = 'websocket';\r\nconst LONG_POLLING = 'long_polling';\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * A class that holds metadata about a Repo object\r\n */\r\nclass RepoInfo {\r\n /**\r\n * @param host - Hostname portion of the url for the repo\r\n * @param secure - Whether or not this repo is accessed over ssl\r\n * @param namespace - The namespace represented by the repo\r\n * @param webSocketOnly - Whether to prefer websockets over all other transports (used by Nest).\r\n * @param nodeAdmin - Whether this instance uses Admin SDK credentials\r\n * @param persistenceKey - Override the default session persistence storage key\r\n */\r\n constructor(host, secure, namespace, webSocketOnly, nodeAdmin = false, persistenceKey = '', includeNamespaceInQueryParams = false, isUsingEmulator = false) {\r\n this.secure = secure;\r\n this.namespace = namespace;\r\n this.webSocketOnly = webSocketOnly;\r\n this.nodeAdmin = nodeAdmin;\r\n this.persistenceKey = persistenceKey;\r\n this.includeNamespaceInQueryParams = includeNamespaceInQueryParams;\r\n this.isUsingEmulator = isUsingEmulator;\r\n this._host = host.toLowerCase();\r\n this._domain = this._host.substr(this._host.indexOf('.') + 1);\r\n this.internalHost =\r\n PersistentStorage.get('host:' + host) || this._host;\r\n }\r\n isCacheableHost() {\r\n return this.internalHost.substr(0, 2) === 's-';\r\n }\r\n isCustomHost() {\r\n return (this._domain !== 'firebaseio.com' &&\r\n this._domain !== 'firebaseio-demo.com');\r\n }\r\n get host() {\r\n return this._host;\r\n }\r\n set host(newHost) {\r\n if (newHost !== this.internalHost) {\r\n this.internalHost = newHost;\r\n if (this.isCacheableHost()) {\r\n PersistentStorage.set('host:' + this._host, this.internalHost);\r\n }\r\n }\r\n }\r\n toString() {\r\n let str = this.toURLString();\r\n if (this.persistenceKey) {\r\n str += '<' + this.persistenceKey + '>';\r\n }\r\n return str;\r\n }\r\n toURLString() {\r\n const protocol = this.secure ? 'https://' : 'http://';\r\n const query = this.includeNamespaceInQueryParams\r\n ? `?ns=${this.namespace}`\r\n : '';\r\n return `${protocol}${this.host}/${query}`;\r\n }\r\n}\r\nfunction repoInfoNeedsQueryParam(repoInfo) {\r\n return (repoInfo.host !== repoInfo.internalHost ||\r\n repoInfo.isCustomHost() ||\r\n repoInfo.includeNamespaceInQueryParams);\r\n}\r\n/**\r\n * Returns the websocket URL for this repo\r\n * @param repoInfo - RepoInfo object\r\n * @param type - of connection\r\n * @param params - list\r\n * @returns The URL for this repo\r\n */\r\nfunction repoInfoConnectionURL(repoInfo, type, params) {\r\n assert(typeof type === 'string', 'typeof type must == string');\r\n assert(typeof params === 'object', 'typeof params must == object');\r\n let connURL;\r\n if (type === WEBSOCKET) {\r\n connURL =\r\n (repoInfo.secure ? 'wss://' : 'ws://') + repoInfo.internalHost + '/.ws?';\r\n }\r\n else if (type === LONG_POLLING) {\r\n connURL =\r\n (repoInfo.secure ? 'https://' : 'http://') +\r\n repoInfo.internalHost +\r\n '/.lp?';\r\n }\r\n else {\r\n throw new Error('Unknown connection type: ' + type);\r\n }\r\n if (repoInfoNeedsQueryParam(repoInfo)) {\r\n params['ns'] = repoInfo.namespace;\r\n }\r\n const pairs = [];\r\n each(params, (key, value) => {\r\n pairs.push(key + '=' + value);\r\n });\r\n return connURL + pairs.join('&');\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * Tracks a collection of stats.\r\n */\r\nclass StatsCollection {\r\n constructor() {\r\n this.counters_ = {};\r\n }\r\n incrementCounter(name, amount = 1) {\r\n if (!contains(this.counters_, name)) {\r\n this.counters_[name] = 0;\r\n }\r\n this.counters_[name] += amount;\r\n }\r\n get() {\r\n return deepCopy(this.counters_);\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nconst collections = {};\r\nconst reporters = {};\r\nfunction statsManagerGetCollection(repoInfo) {\r\n const hashString = repoInfo.toString();\r\n if (!collections[hashString]) {\r\n collections[hashString] = new StatsCollection();\r\n }\r\n return collections[hashString];\r\n}\r\nfunction statsManagerGetOrCreateReporter(repoInfo, creatorFunction) {\r\n const hashString = repoInfo.toString();\r\n if (!reporters[hashString]) {\r\n reporters[hashString] = creatorFunction();\r\n }\r\n return reporters[hashString];\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * This class ensures the packets from the server arrive in order\r\n * This class takes data from the server and ensures it gets passed into the callbacks in order.\r\n */\r\nclass PacketReceiver {\r\n /**\r\n * @param onMessage_\r\n */\r\n constructor(onMessage_) {\r\n this.onMessage_ = onMessage_;\r\n this.pendingResponses = [];\r\n this.currentResponseNum = 0;\r\n this.closeAfterResponse = -1;\r\n this.onClose = null;\r\n }\r\n closeAfter(responseNum, callback) {\r\n this.closeAfterResponse = responseNum;\r\n this.onClose = callback;\r\n if (this.closeAfterResponse < this.currentResponseNum) {\r\n this.onClose();\r\n this.onClose = null;\r\n }\r\n }\r\n /**\r\n * Each message from the server comes with a response number, and an array of data. The responseNumber\r\n * allows us to ensure that we process them in the right order, since we can't be guaranteed that all\r\n * browsers will respond in the same order as the requests we sent\r\n */\r\n handleResponse(requestNum, data) {\r\n this.pendingResponses[requestNum] = data;\r\n while (this.pendingResponses[this.currentResponseNum]) {\r\n const toProcess = this.pendingResponses[this.currentResponseNum];\r\n delete this.pendingResponses[this.currentResponseNum];\r\n for (let i = 0; i < toProcess.length; ++i) {\r\n if (toProcess[i]) {\r\n exceptionGuard(() => {\r\n this.onMessage_(toProcess[i]);\r\n });\r\n }\r\n }\r\n if (this.currentResponseNum === this.closeAfterResponse) {\r\n if (this.onClose) {\r\n this.onClose();\r\n this.onClose = null;\r\n }\r\n break;\r\n }\r\n this.currentResponseNum++;\r\n }\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n// URL query parameters associated with longpolling\r\nconst FIREBASE_LONGPOLL_START_PARAM = 'start';\r\nconst FIREBASE_LONGPOLL_CLOSE_COMMAND = 'close';\r\nconst FIREBASE_LONGPOLL_COMMAND_CB_NAME = 'pLPCommand';\r\nconst FIREBASE_LONGPOLL_DATA_CB_NAME = 'pRTLPCB';\r\nconst FIREBASE_LONGPOLL_ID_PARAM = 'id';\r\nconst FIREBASE_LONGPOLL_PW_PARAM = 'pw';\r\nconst FIREBASE_LONGPOLL_SERIAL_PARAM = 'ser';\r\nconst FIREBASE_LONGPOLL_CALLBACK_ID_PARAM = 'cb';\r\nconst FIREBASE_LONGPOLL_SEGMENT_NUM_PARAM = 'seg';\r\nconst FIREBASE_LONGPOLL_SEGMENTS_IN_PACKET = 'ts';\r\nconst FIREBASE_LONGPOLL_DATA_PARAM = 'd';\r\nconst FIREBASE_LONGPOLL_DISCONN_FRAME_REQUEST_PARAM = 'dframe';\r\n//Data size constants.\r\n//TODO: Perf: the maximum length actually differs from browser to browser.\r\n// We should check what browser we're on and set accordingly.\r\nconst MAX_URL_DATA_SIZE = 1870;\r\nconst SEG_HEADER_SIZE = 30; //ie: &seg=8299234&ts=982389123&d=\r\nconst MAX_PAYLOAD_SIZE = MAX_URL_DATA_SIZE - SEG_HEADER_SIZE;\r\n/**\r\n * Keepalive period\r\n * send a fresh request at minimum every 25 seconds. Opera has a maximum request\r\n * length of 30 seconds that we can't exceed.\r\n */\r\nconst KEEPALIVE_REQUEST_INTERVAL = 25000;\r\n/**\r\n * How long to wait before aborting a long-polling connection attempt.\r\n */\r\nconst LP_CONNECT_TIMEOUT = 30000;\r\n/**\r\n * This class manages a single long-polling connection.\r\n */\r\nclass BrowserPollConnection {\r\n /**\r\n * @param connId An identifier for this connection, used for logging\r\n * @param repoInfo The info for the endpoint to send data to.\r\n * @param applicationId The Firebase App ID for this project.\r\n * @param appCheckToken The AppCheck token for this client.\r\n * @param authToken The AuthToken to use for this connection.\r\n * @param transportSessionId Optional transportSessionid if we are\r\n * reconnecting for an existing transport session\r\n * @param lastSessionId Optional lastSessionId if the PersistentConnection has\r\n * already created a connection previously\r\n */\r\n constructor(connId, repoInfo, applicationId, appCheckToken, authToken, transportSessionId, lastSessionId) {\r\n this.connId = connId;\r\n this.repoInfo = repoInfo;\r\n this.applicationId = applicationId;\r\n this.appCheckToken = appCheckToken;\r\n this.authToken = authToken;\r\n this.transportSessionId = transportSessionId;\r\n this.lastSessionId = lastSessionId;\r\n this.bytesSent = 0;\r\n this.bytesReceived = 0;\r\n this.everConnected_ = false;\r\n this.log_ = logWrapper(connId);\r\n this.stats_ = statsManagerGetCollection(repoInfo);\r\n this.urlFn = (params) => {\r\n // Always add the token if we have one.\r\n if (this.appCheckToken) {\r\n params[APP_CHECK_TOKEN_PARAM] = this.appCheckToken;\r\n }\r\n return repoInfoConnectionURL(repoInfo, LONG_POLLING, params);\r\n };\r\n }\r\n /**\r\n * @param onMessage - Callback when messages arrive\r\n * @param onDisconnect - Callback with connection lost.\r\n */\r\n open(onMessage, onDisconnect) {\r\n this.curSegmentNum = 0;\r\n this.onDisconnect_ = onDisconnect;\r\n this.myPacketOrderer = new PacketReceiver(onMessage);\r\n this.isClosed_ = false;\r\n this.connectTimeoutTimer_ = setTimeout(() => {\r\n this.log_('Timed out trying to connect.');\r\n // Make sure we clear the host cache\r\n this.onClosed_();\r\n this.connectTimeoutTimer_ = null;\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n }, Math.floor(LP_CONNECT_TIMEOUT));\r\n // Ensure we delay the creation of the iframe until the DOM is loaded.\r\n executeWhenDOMReady(() => {\r\n if (this.isClosed_) {\r\n return;\r\n }\r\n //Set up a callback that gets triggered once a connection is set up.\r\n this.scriptTagHolder = new FirebaseIFrameScriptHolder((...args) => {\r\n const [command, arg1, arg2, arg3, arg4] = args;\r\n this.incrementIncomingBytes_(args);\r\n if (!this.scriptTagHolder) {\r\n return; // we closed the connection.\r\n }\r\n if (this.connectTimeoutTimer_) {\r\n clearTimeout(this.connectTimeoutTimer_);\r\n this.connectTimeoutTimer_ = null;\r\n }\r\n this.everConnected_ = true;\r\n if (command === FIREBASE_LONGPOLL_START_PARAM) {\r\n this.id = arg1;\r\n this.password = arg2;\r\n }\r\n else if (command === FIREBASE_LONGPOLL_CLOSE_COMMAND) {\r\n // Don't clear the host cache. We got a response from the server, so we know it's reachable\r\n if (arg1) {\r\n // We aren't expecting any more data (other than what the server's already in the process of sending us\r\n // through our already open polls), so don't send any more.\r\n this.scriptTagHolder.sendNewPolls = false;\r\n // arg1 in this case is the last response number sent by the server. We should try to receive\r\n // all of the responses up to this one before closing\r\n this.myPacketOrderer.closeAfter(arg1, () => {\r\n this.onClosed_();\r\n });\r\n }\r\n else {\r\n this.onClosed_();\r\n }\r\n }\r\n else {\r\n throw new Error('Unrecognized command received: ' + command);\r\n }\r\n }, (...args) => {\r\n const [pN, data] = args;\r\n this.incrementIncomingBytes_(args);\r\n this.myPacketOrderer.handleResponse(pN, data);\r\n }, () => {\r\n this.onClosed_();\r\n }, this.urlFn);\r\n //Send the initial request to connect. The serial number is simply to keep the browser from pulling previous results\r\n //from cache.\r\n const urlParams = {};\r\n urlParams[FIREBASE_LONGPOLL_START_PARAM] = 't';\r\n urlParams[FIREBASE_LONGPOLL_SERIAL_PARAM] = Math.floor(Math.random() * 100000000);\r\n if (this.scriptTagHolder.uniqueCallbackIdentifier) {\r\n urlParams[FIREBASE_LONGPOLL_CALLBACK_ID_PARAM] =\r\n this.scriptTagHolder.uniqueCallbackIdentifier;\r\n }\r\n urlParams[VERSION_PARAM] = PROTOCOL_VERSION;\r\n if (this.transportSessionId) {\r\n urlParams[TRANSPORT_SESSION_PARAM] = this.transportSessionId;\r\n }\r\n if (this.lastSessionId) {\r\n urlParams[LAST_SESSION_PARAM] = this.lastSessionId;\r\n }\r\n if (this.applicationId) {\r\n urlParams[APPLICATION_ID_PARAM] = this.applicationId;\r\n }\r\n if (this.appCheckToken) {\r\n urlParams[APP_CHECK_TOKEN_PARAM] = this.appCheckToken;\r\n }\r\n if (typeof location !== 'undefined' &&\r\n location.hostname &&\r\n FORGE_DOMAIN_RE.test(location.hostname)) {\r\n urlParams[REFERER_PARAM] = FORGE_REF;\r\n }\r\n const connectURL = this.urlFn(urlParams);\r\n this.log_('Connecting via long-poll to ' + connectURL);\r\n this.scriptTagHolder.addTag(connectURL, () => {\r\n /* do nothing */\r\n });\r\n });\r\n }\r\n /**\r\n * Call this when a handshake has completed successfully and we want to consider the connection established\r\n */\r\n start() {\r\n this.scriptTagHolder.startLongPoll(this.id, this.password);\r\n this.addDisconnectPingFrame(this.id, this.password);\r\n }\r\n /**\r\n * Forces long polling to be considered as a potential transport\r\n */\r\n static forceAllow() {\r\n BrowserPollConnection.forceAllow_ = true;\r\n }\r\n /**\r\n * Forces longpolling to not be considered as a potential transport\r\n */\r\n static forceDisallow() {\r\n BrowserPollConnection.forceDisallow_ = true;\r\n }\r\n // Static method, use string literal so it can be accessed in a generic way\r\n static isAvailable() {\r\n if (isNodeSdk()) {\r\n return false;\r\n }\r\n else if (BrowserPollConnection.forceAllow_) {\r\n return true;\r\n }\r\n else {\r\n // NOTE: In React-Native there's normally no 'document', but if you debug a React-Native app in\r\n // the Chrome debugger, 'document' is defined, but document.createElement is null (2015/06/08).\r\n return (!BrowserPollConnection.forceDisallow_ &&\r\n typeof document !== 'undefined' &&\r\n document.createElement != null &&\r\n !isChromeExtensionContentScript() &&\r\n !isWindowsStoreApp());\r\n }\r\n }\r\n /**\r\n * No-op for polling\r\n */\r\n markConnectionHealthy() { }\r\n /**\r\n * Stops polling and cleans up the iframe\r\n */\r\n shutdown_() {\r\n this.isClosed_ = true;\r\n if (this.scriptTagHolder) {\r\n this.scriptTagHolder.close();\r\n this.scriptTagHolder = null;\r\n }\r\n //remove the disconnect frame, which will trigger an XHR call to the server to tell it we're leaving.\r\n if (this.myDisconnFrame) {\r\n document.body.removeChild(this.myDisconnFrame);\r\n this.myDisconnFrame = null;\r\n }\r\n if (this.connectTimeoutTimer_) {\r\n clearTimeout(this.connectTimeoutTimer_);\r\n this.connectTimeoutTimer_ = null;\r\n }\r\n }\r\n /**\r\n * Triggered when this transport is closed\r\n */\r\n onClosed_() {\r\n if (!this.isClosed_) {\r\n this.log_('Longpoll is closing itself');\r\n this.shutdown_();\r\n if (this.onDisconnect_) {\r\n this.onDisconnect_(this.everConnected_);\r\n this.onDisconnect_ = null;\r\n }\r\n }\r\n }\r\n /**\r\n * External-facing close handler. RealTime has requested we shut down. Kill our connection and tell the server\r\n * that we've left.\r\n */\r\n close() {\r\n if (!this.isClosed_) {\r\n this.log_('Longpoll is being closed.');\r\n this.shutdown_();\r\n }\r\n }\r\n /**\r\n * Send the JSON object down to the server. It will need to be stringified, base64 encoded, and then\r\n * broken into chunks (since URLs have a small maximum length).\r\n * @param data - The JSON data to transmit.\r\n */\r\n send(data) {\r\n const dataStr = stringify(data);\r\n this.bytesSent += dataStr.length;\r\n this.stats_.incrementCounter('bytes_sent', dataStr.length);\r\n //first, lets get the base64-encoded data\r\n const base64data = base64Encode(dataStr);\r\n //We can only fit a certain amount in each URL, so we need to split this request\r\n //up into multiple pieces if it doesn't fit in one request.\r\n const dataSegs = splitStringBySize(base64data, MAX_PAYLOAD_SIZE);\r\n //Enqueue each segment for transmission. We assign each chunk a sequential ID and a total number\r\n //of segments so that we can reassemble the packet on the server.\r\n for (let i = 0; i < dataSegs.length; i++) {\r\n this.scriptTagHolder.enqueueSegment(this.curSegmentNum, dataSegs.length, dataSegs[i]);\r\n this.curSegmentNum++;\r\n }\r\n }\r\n /**\r\n * This is how we notify the server that we're leaving.\r\n * We aren't able to send requests with DHTML on a window close event, but we can\r\n * trigger XHR requests in some browsers (everything but Opera basically).\r\n */\r\n addDisconnectPingFrame(id, pw) {\r\n if (isNodeSdk()) {\r\n return;\r\n }\r\n this.myDisconnFrame = document.createElement('iframe');\r\n const urlParams = {};\r\n urlParams[FIREBASE_LONGPOLL_DISCONN_FRAME_REQUEST_PARAM] = 't';\r\n urlParams[FIREBASE_LONGPOLL_ID_PARAM] = id;\r\n urlParams[FIREBASE_LONGPOLL_PW_PARAM] = pw;\r\n this.myDisconnFrame.src = this.urlFn(urlParams);\r\n this.myDisconnFrame.style.display = 'none';\r\n document.body.appendChild(this.myDisconnFrame);\r\n }\r\n /**\r\n * Used to track the bytes received by this client\r\n */\r\n incrementIncomingBytes_(args) {\r\n // TODO: This is an annoying perf hit just to track the number of incoming bytes. Maybe it should be opt-in.\r\n const bytesReceived = stringify(args).length;\r\n this.bytesReceived += bytesReceived;\r\n this.stats_.incrementCounter('bytes_received', bytesReceived);\r\n }\r\n}\r\n/*********************************************************************************************\r\n * A wrapper around an iframe that is used as a long-polling script holder.\r\n *********************************************************************************************/\r\nclass FirebaseIFrameScriptHolder {\r\n /**\r\n * @param commandCB - The callback to be called when control commands are recevied from the server.\r\n * @param onMessageCB - The callback to be triggered when responses arrive from the server.\r\n * @param onDisconnect - The callback to be triggered when this tag holder is closed\r\n * @param urlFn - A function that provides the URL of the endpoint to send data to.\r\n */\r\n constructor(commandCB, onMessageCB, onDisconnect, urlFn) {\r\n this.onDisconnect = onDisconnect;\r\n this.urlFn = urlFn;\r\n //We maintain a count of all of the outstanding requests, because if we have too many active at once it can cause\r\n //problems in some browsers.\r\n this.outstandingRequests = new Set();\r\n //A queue of the pending segments waiting for transmission to the server.\r\n this.pendingSegs = [];\r\n //A serial number. We use this for two things:\r\n // 1) A way to ensure the browser doesn't cache responses to polls\r\n // 2) A way to make the server aware when long-polls arrive in a different order than we started them. The\r\n // server needs to release both polls in this case or it will cause problems in Opera since Opera can only execute\r\n // JSONP code in the order it was added to the iframe.\r\n this.currentSerial = Math.floor(Math.random() * 100000000);\r\n // This gets set to false when we're \"closing down\" the connection (e.g. we're switching transports but there's still\r\n // incoming data from the server that we're waiting for).\r\n this.sendNewPolls = true;\r\n if (!isNodeSdk()) {\r\n //Each script holder registers a couple of uniquely named callbacks with the window. These are called from the\r\n //iframes where we put the long-polling script tags. We have two callbacks:\r\n // 1) Command Callback - Triggered for control issues, like starting a connection.\r\n // 2) Message Callback - Triggered when new data arrives.\r\n this.uniqueCallbackIdentifier = LUIDGenerator();\r\n window[FIREBASE_LONGPOLL_COMMAND_CB_NAME + this.uniqueCallbackIdentifier] = commandCB;\r\n window[FIREBASE_LONGPOLL_DATA_CB_NAME + this.uniqueCallbackIdentifier] =\r\n onMessageCB;\r\n //Create an iframe for us to add script tags to.\r\n this.myIFrame = FirebaseIFrameScriptHolder.createIFrame_();\r\n // Set the iframe's contents.\r\n let script = '';\r\n // if we set a javascript url, it's IE and we need to set the document domain. The javascript url is sufficient\r\n // for ie9, but ie8 needs to do it again in the document itself.\r\n if (this.myIFrame.src &&\r\n this.myIFrame.src.substr(0, 'javascript:'.length) === 'javascript:') {\r\n const currentDomain = document.domain;\r\n script = '';\r\n }\r\n const iframeContents = '' + script + '';\r\n try {\r\n this.myIFrame.doc.open();\r\n this.myIFrame.doc.write(iframeContents);\r\n this.myIFrame.doc.close();\r\n }\r\n catch (e) {\r\n log('frame writing exception');\r\n if (e.stack) {\r\n log(e.stack);\r\n }\r\n log(e);\r\n }\r\n }\r\n else {\r\n this.commandCB = commandCB;\r\n this.onMessageCB = onMessageCB;\r\n }\r\n }\r\n /**\r\n * Each browser has its own funny way to handle iframes. Here we mush them all together into one object that I can\r\n * actually use.\r\n */\r\n static createIFrame_() {\r\n const iframe = document.createElement('iframe');\r\n iframe.style.display = 'none';\r\n // This is necessary in order to initialize the document inside the iframe\r\n if (document.body) {\r\n document.body.appendChild(iframe);\r\n try {\r\n // If document.domain has been modified in IE, this will throw an error, and we need to set the\r\n // domain of the iframe's document manually. We can do this via a javascript: url as the src attribute\r\n // Also note that we must do this *after* the iframe has been appended to the page. Otherwise it doesn't work.\r\n const a = iframe.contentWindow.document;\r\n if (!a) {\r\n // Apologies for the log-spam, I need to do something to keep closure from optimizing out the assignment above.\r\n log('No IE domain setting required');\r\n }\r\n }\r\n catch (e) {\r\n const domain = document.domain;\r\n iframe.src =\r\n \"javascript:void((function(){document.open();document.domain='\" +\r\n domain +\r\n \"';document.close();})())\";\r\n }\r\n }\r\n else {\r\n // LongPollConnection attempts to delay initialization until the document is ready, so hopefully this\r\n // never gets hit.\r\n throw 'Document body has not initialized. Wait to initialize Firebase until after the document is ready.';\r\n }\r\n // Get the document of the iframe in a browser-specific way.\r\n if (iframe.contentDocument) {\r\n iframe.doc = iframe.contentDocument; // Firefox, Opera, Safari\r\n }\r\n else if (iframe.contentWindow) {\r\n iframe.doc = iframe.contentWindow.document; // Internet Explorer\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n }\r\n else if (iframe.document) {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n iframe.doc = iframe.document; //others?\r\n }\r\n return iframe;\r\n }\r\n /**\r\n * Cancel all outstanding queries and remove the frame.\r\n */\r\n close() {\r\n //Mark this iframe as dead, so no new requests are sent.\r\n this.alive = false;\r\n if (this.myIFrame) {\r\n //We have to actually remove all of the html inside this iframe before removing it from the\r\n //window, or IE will continue loading and executing the script tags we've already added, which\r\n //can lead to some errors being thrown. Setting textContent seems to be the safest way to do this.\r\n this.myIFrame.doc.body.textContent = '';\r\n setTimeout(() => {\r\n if (this.myIFrame !== null) {\r\n document.body.removeChild(this.myIFrame);\r\n this.myIFrame = null;\r\n }\r\n }, Math.floor(0));\r\n }\r\n // Protect from being called recursively.\r\n const onDisconnect = this.onDisconnect;\r\n if (onDisconnect) {\r\n this.onDisconnect = null;\r\n onDisconnect();\r\n }\r\n }\r\n /**\r\n * Actually start the long-polling session by adding the first script tag(s) to the iframe.\r\n * @param id - The ID of this connection\r\n * @param pw - The password for this connection\r\n */\r\n startLongPoll(id, pw) {\r\n this.myID = id;\r\n this.myPW = pw;\r\n this.alive = true;\r\n //send the initial request. If there are requests queued, make sure that we transmit as many as we are currently able to.\r\n while (this.newRequest_()) { }\r\n }\r\n /**\r\n * This is called any time someone might want a script tag to be added. It adds a script tag when there aren't\r\n * too many outstanding requests and we are still alive.\r\n *\r\n * If there are outstanding packet segments to send, it sends one. If there aren't, it sends a long-poll anyways if\r\n * needed.\r\n */\r\n newRequest_() {\r\n // We keep one outstanding request open all the time to receive data, but if we need to send data\r\n // (pendingSegs.length > 0) then we create a new request to send the data. The server will automatically\r\n // close the old request.\r\n if (this.alive &&\r\n this.sendNewPolls &&\r\n this.outstandingRequests.size < (this.pendingSegs.length > 0 ? 2 : 1)) {\r\n //construct our url\r\n this.currentSerial++;\r\n const urlParams = {};\r\n urlParams[FIREBASE_LONGPOLL_ID_PARAM] = this.myID;\r\n urlParams[FIREBASE_LONGPOLL_PW_PARAM] = this.myPW;\r\n urlParams[FIREBASE_LONGPOLL_SERIAL_PARAM] = this.currentSerial;\r\n let theURL = this.urlFn(urlParams);\r\n //Now add as much data as we can.\r\n let curDataString = '';\r\n let i = 0;\r\n while (this.pendingSegs.length > 0) {\r\n //first, lets see if the next segment will fit.\r\n const nextSeg = this.pendingSegs[0];\r\n if (nextSeg.d.length +\r\n SEG_HEADER_SIZE +\r\n curDataString.length <=\r\n MAX_URL_DATA_SIZE) {\r\n //great, the segment will fit. Lets append it.\r\n const theSeg = this.pendingSegs.shift();\r\n curDataString =\r\n curDataString +\r\n '&' +\r\n FIREBASE_LONGPOLL_SEGMENT_NUM_PARAM +\r\n i +\r\n '=' +\r\n theSeg.seg +\r\n '&' +\r\n FIREBASE_LONGPOLL_SEGMENTS_IN_PACKET +\r\n i +\r\n '=' +\r\n theSeg.ts +\r\n '&' +\r\n FIREBASE_LONGPOLL_DATA_PARAM +\r\n i +\r\n '=' +\r\n theSeg.d;\r\n i++;\r\n }\r\n else {\r\n break;\r\n }\r\n }\r\n theURL = theURL + curDataString;\r\n this.addLongPollTag_(theURL, this.currentSerial);\r\n return true;\r\n }\r\n else {\r\n return false;\r\n }\r\n }\r\n /**\r\n * Queue a packet for transmission to the server.\r\n * @param segnum - A sequential id for this packet segment used for reassembly\r\n * @param totalsegs - The total number of segments in this packet\r\n * @param data - The data for this segment.\r\n */\r\n enqueueSegment(segnum, totalsegs, data) {\r\n //add this to the queue of segments to send.\r\n this.pendingSegs.push({ seg: segnum, ts: totalsegs, d: data });\r\n //send the data immediately if there isn't already data being transmitted, unless\r\n //startLongPoll hasn't been called yet.\r\n if (this.alive) {\r\n this.newRequest_();\r\n }\r\n }\r\n /**\r\n * Add a script tag for a regular long-poll request.\r\n * @param url - The URL of the script tag.\r\n * @param serial - The serial number of the request.\r\n */\r\n addLongPollTag_(url, serial) {\r\n //remember that we sent this request.\r\n this.outstandingRequests.add(serial);\r\n const doNewRequest = () => {\r\n this.outstandingRequests.delete(serial);\r\n this.newRequest_();\r\n };\r\n // If this request doesn't return on its own accord (by the server sending us some data), we'll\r\n // create a new one after the KEEPALIVE interval to make sure we always keep a fresh request open.\r\n const keepaliveTimeout = setTimeout(doNewRequest, Math.floor(KEEPALIVE_REQUEST_INTERVAL));\r\n const readyStateCB = () => {\r\n // Request completed. Cancel the keepalive.\r\n clearTimeout(keepaliveTimeout);\r\n // Trigger a new request so we can continue receiving data.\r\n doNewRequest();\r\n };\r\n this.addTag(url, readyStateCB);\r\n }\r\n /**\r\n * Add an arbitrary script tag to the iframe.\r\n * @param url - The URL for the script tag source.\r\n * @param loadCB - A callback to be triggered once the script has loaded.\r\n */\r\n addTag(url, loadCB) {\r\n if (isNodeSdk()) {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n this.doNodeLongPoll(url, loadCB);\r\n }\r\n else {\r\n setTimeout(() => {\r\n try {\r\n // if we're already closed, don't add this poll\r\n if (!this.sendNewPolls) {\r\n return;\r\n }\r\n const newScript = this.myIFrame.doc.createElement('script');\r\n newScript.type = 'text/javascript';\r\n newScript.async = true;\r\n newScript.src = url;\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n newScript.onload = newScript.onreadystatechange =\r\n function () {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n const rstate = newScript.readyState;\r\n if (!rstate || rstate === 'loaded' || rstate === 'complete') {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n newScript.onload = newScript.onreadystatechange = null;\r\n if (newScript.parentNode) {\r\n newScript.parentNode.removeChild(newScript);\r\n }\r\n loadCB();\r\n }\r\n };\r\n newScript.onerror = () => {\r\n log('Long-poll script failed to load: ' + url);\r\n this.sendNewPolls = false;\r\n this.close();\r\n };\r\n this.myIFrame.doc.body.appendChild(newScript);\r\n }\r\n catch (e) {\r\n // TODO: we should make this error visible somehow\r\n }\r\n }, Math.floor(1));\r\n }\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nconst WEBSOCKET_MAX_FRAME_SIZE = 16384;\r\nconst WEBSOCKET_KEEPALIVE_INTERVAL = 45000;\r\nlet WebSocketImpl = null;\r\nif (typeof MozWebSocket !== 'undefined') {\r\n WebSocketImpl = MozWebSocket;\r\n}\r\nelse if (typeof WebSocket !== 'undefined') {\r\n WebSocketImpl = WebSocket;\r\n}\r\n/**\r\n * Create a new websocket connection with the given callbacks.\r\n */\r\nclass WebSocketConnection {\r\n /**\r\n * @param connId identifier for this transport\r\n * @param repoInfo The info for the websocket endpoint.\r\n * @param applicationId The Firebase App ID for this project.\r\n * @param appCheckToken The App Check Token for this client.\r\n * @param authToken The Auth Token for this client.\r\n * @param transportSessionId Optional transportSessionId if this is connecting\r\n * to an existing transport session\r\n * @param lastSessionId Optional lastSessionId if there was a previous\r\n * connection\r\n */\r\n constructor(connId, repoInfo, applicationId, appCheckToken, authToken, transportSessionId, lastSessionId) {\r\n this.connId = connId;\r\n this.applicationId = applicationId;\r\n this.appCheckToken = appCheckToken;\r\n this.authToken = authToken;\r\n this.keepaliveTimer = null;\r\n this.frames = null;\r\n this.totalFrames = 0;\r\n this.bytesSent = 0;\r\n this.bytesReceived = 0;\r\n this.log_ = logWrapper(this.connId);\r\n this.stats_ = statsManagerGetCollection(repoInfo);\r\n this.connURL = WebSocketConnection.connectionURL_(repoInfo, transportSessionId, lastSessionId, appCheckToken, applicationId);\r\n this.nodeAdmin = repoInfo.nodeAdmin;\r\n }\r\n /**\r\n * @param repoInfo - The info for the websocket endpoint.\r\n * @param transportSessionId - Optional transportSessionId if this is connecting to an existing transport\r\n * session\r\n * @param lastSessionId - Optional lastSessionId if there was a previous connection\r\n * @returns connection url\r\n */\r\n static connectionURL_(repoInfo, transportSessionId, lastSessionId, appCheckToken, applicationId) {\r\n const urlParams = {};\r\n urlParams[VERSION_PARAM] = PROTOCOL_VERSION;\r\n if (!isNodeSdk() &&\r\n typeof location !== 'undefined' &&\r\n location.hostname &&\r\n FORGE_DOMAIN_RE.test(location.hostname)) {\r\n urlParams[REFERER_PARAM] = FORGE_REF;\r\n }\r\n if (transportSessionId) {\r\n urlParams[TRANSPORT_SESSION_PARAM] = transportSessionId;\r\n }\r\n if (lastSessionId) {\r\n urlParams[LAST_SESSION_PARAM] = lastSessionId;\r\n }\r\n if (appCheckToken) {\r\n urlParams[APP_CHECK_TOKEN_PARAM] = appCheckToken;\r\n }\r\n if (applicationId) {\r\n urlParams[APPLICATION_ID_PARAM] = applicationId;\r\n }\r\n return repoInfoConnectionURL(repoInfo, WEBSOCKET, urlParams);\r\n }\r\n /**\r\n * @param onMessage - Callback when messages arrive\r\n * @param onDisconnect - Callback with connection lost.\r\n */\r\n open(onMessage, onDisconnect) {\r\n this.onDisconnect = onDisconnect;\r\n this.onMessage = onMessage;\r\n this.log_('Websocket connecting to ' + this.connURL);\r\n this.everConnected_ = false;\r\n // Assume failure until proven otherwise.\r\n PersistentStorage.set('previous_websocket_failure', true);\r\n try {\r\n let options;\r\n if (isNodeSdk()) {\r\n const device = this.nodeAdmin ? 'AdminNode' : 'Node';\r\n // UA Format: Firebase////\r\n options = {\r\n headers: {\r\n 'User-Agent': `Firebase/${PROTOCOL_VERSION}/${SDK_VERSION}/${process.platform}/${device}`,\r\n 'X-Firebase-GMPID': this.applicationId || ''\r\n }\r\n };\r\n // If using Node with admin creds, AppCheck-related checks are unnecessary.\r\n // Note that we send the credentials here even if they aren't admin credentials, which is\r\n // not a problem.\r\n // Note that this header is just used to bypass appcheck, and the token should still be sent\r\n // through the websocket connection once it is established.\r\n if (this.authToken) {\r\n options.headers['Authorization'] = `Bearer ${this.authToken}`;\r\n }\r\n if (this.appCheckToken) {\r\n options.headers['X-Firebase-AppCheck'] = this.appCheckToken;\r\n }\r\n // Plumb appropriate http_proxy environment variable into faye-websocket if it exists.\r\n const env = process['env'];\r\n const proxy = this.connURL.indexOf('wss://') === 0\r\n ? env['HTTPS_PROXY'] || env['https_proxy']\r\n : env['HTTP_PROXY'] || env['http_proxy'];\r\n if (proxy) {\r\n options['proxy'] = { origin: proxy };\r\n }\r\n }\r\n this.mySock = new WebSocketImpl(this.connURL, [], options);\r\n }\r\n catch (e) {\r\n this.log_('Error instantiating WebSocket.');\r\n const error = e.message || e.data;\r\n if (error) {\r\n this.log_(error);\r\n }\r\n this.onClosed_();\r\n return;\r\n }\r\n this.mySock.onopen = () => {\r\n this.log_('Websocket connected.');\r\n this.everConnected_ = true;\r\n };\r\n this.mySock.onclose = () => {\r\n this.log_('Websocket connection was disconnected.');\r\n this.mySock = null;\r\n this.onClosed_();\r\n };\r\n this.mySock.onmessage = m => {\r\n this.handleIncomingFrame(m);\r\n };\r\n this.mySock.onerror = e => {\r\n this.log_('WebSocket error. Closing connection.');\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n const error = e.message || e.data;\r\n if (error) {\r\n this.log_(error);\r\n }\r\n this.onClosed_();\r\n };\r\n }\r\n /**\r\n * No-op for websockets, we don't need to do anything once the connection is confirmed as open\r\n */\r\n start() { }\r\n static forceDisallow() {\r\n WebSocketConnection.forceDisallow_ = true;\r\n }\r\n static isAvailable() {\r\n let isOldAndroid = false;\r\n if (typeof navigator !== 'undefined' && navigator.userAgent) {\r\n const oldAndroidRegex = /Android ([0-9]{0,}\\.[0-9]{0,})/;\r\n const oldAndroidMatch = navigator.userAgent.match(oldAndroidRegex);\r\n if (oldAndroidMatch && oldAndroidMatch.length > 1) {\r\n if (parseFloat(oldAndroidMatch[1]) < 4.4) {\r\n isOldAndroid = true;\r\n }\r\n }\r\n }\r\n return (!isOldAndroid &&\r\n WebSocketImpl !== null &&\r\n !WebSocketConnection.forceDisallow_);\r\n }\r\n /**\r\n * Returns true if we previously failed to connect with this transport.\r\n */\r\n static previouslyFailed() {\r\n // If our persistent storage is actually only in-memory storage,\r\n // we default to assuming that it previously failed to be safe.\r\n return (PersistentStorage.isInMemoryStorage ||\r\n PersistentStorage.get('previous_websocket_failure') === true);\r\n }\r\n markConnectionHealthy() {\r\n PersistentStorage.remove('previous_websocket_failure');\r\n }\r\n appendFrame_(data) {\r\n this.frames.push(data);\r\n if (this.frames.length === this.totalFrames) {\r\n const fullMess = this.frames.join('');\r\n this.frames = null;\r\n const jsonMess = jsonEval(fullMess);\r\n //handle the message\r\n this.onMessage(jsonMess);\r\n }\r\n }\r\n /**\r\n * @param frameCount - The number of frames we are expecting from the server\r\n */\r\n handleNewFrameCount_(frameCount) {\r\n this.totalFrames = frameCount;\r\n this.frames = [];\r\n }\r\n /**\r\n * Attempts to parse a frame count out of some text. If it can't, assumes a value of 1\r\n * @returns Any remaining data to be process, or null if there is none\r\n */\r\n extractFrameCount_(data) {\r\n assert(this.frames === null, 'We already have a frame buffer');\r\n // TODO: The server is only supposed to send up to 9999 frames (i.e. length <= 4), but that isn't being enforced\r\n // currently. So allowing larger frame counts (length <= 6). See https://app.asana.com/0/search/8688598998380/8237608042508\r\n if (data.length <= 6) {\r\n const frameCount = Number(data);\r\n if (!isNaN(frameCount)) {\r\n this.handleNewFrameCount_(frameCount);\r\n return null;\r\n }\r\n }\r\n this.handleNewFrameCount_(1);\r\n return data;\r\n }\r\n /**\r\n * Process a websocket frame that has arrived from the server.\r\n * @param mess - The frame data\r\n */\r\n handleIncomingFrame(mess) {\r\n if (this.mySock === null) {\r\n return; // Chrome apparently delivers incoming packets even after we .close() the connection sometimes.\r\n }\r\n const data = mess['data'];\r\n this.bytesReceived += data.length;\r\n this.stats_.incrementCounter('bytes_received', data.length);\r\n this.resetKeepAlive();\r\n if (this.frames !== null) {\r\n // we're buffering\r\n this.appendFrame_(data);\r\n }\r\n else {\r\n // try to parse out a frame count, otherwise, assume 1 and process it\r\n const remainingData = this.extractFrameCount_(data);\r\n if (remainingData !== null) {\r\n this.appendFrame_(remainingData);\r\n }\r\n }\r\n }\r\n /**\r\n * Send a message to the server\r\n * @param data - The JSON object to transmit\r\n */\r\n send(data) {\r\n this.resetKeepAlive();\r\n const dataStr = stringify(data);\r\n this.bytesSent += dataStr.length;\r\n this.stats_.incrementCounter('bytes_sent', dataStr.length);\r\n //We can only fit a certain amount in each websocket frame, so we need to split this request\r\n //up into multiple pieces if it doesn't fit in one request.\r\n const dataSegs = splitStringBySize(dataStr, WEBSOCKET_MAX_FRAME_SIZE);\r\n //Send the length header\r\n if (dataSegs.length > 1) {\r\n this.sendString_(String(dataSegs.length));\r\n }\r\n //Send the actual data in segments.\r\n for (let i = 0; i < dataSegs.length; i++) {\r\n this.sendString_(dataSegs[i]);\r\n }\r\n }\r\n shutdown_() {\r\n this.isClosed_ = true;\r\n if (this.keepaliveTimer) {\r\n clearInterval(this.keepaliveTimer);\r\n this.keepaliveTimer = null;\r\n }\r\n if (this.mySock) {\r\n this.mySock.close();\r\n this.mySock = null;\r\n }\r\n }\r\n onClosed_() {\r\n if (!this.isClosed_) {\r\n this.log_('WebSocket is closing itself');\r\n this.shutdown_();\r\n // since this is an internal close, trigger the close listener\r\n if (this.onDisconnect) {\r\n this.onDisconnect(this.everConnected_);\r\n this.onDisconnect = null;\r\n }\r\n }\r\n }\r\n /**\r\n * External-facing close handler.\r\n * Close the websocket and kill the connection.\r\n */\r\n close() {\r\n if (!this.isClosed_) {\r\n this.log_('WebSocket is being closed');\r\n this.shutdown_();\r\n }\r\n }\r\n /**\r\n * Kill the current keepalive timer and start a new one, to ensure that it always fires N seconds after\r\n * the last activity.\r\n */\r\n resetKeepAlive() {\r\n clearInterval(this.keepaliveTimer);\r\n this.keepaliveTimer = setInterval(() => {\r\n //If there has been no websocket activity for a while, send a no-op\r\n if (this.mySock) {\r\n this.sendString_('0');\r\n }\r\n this.resetKeepAlive();\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n }, Math.floor(WEBSOCKET_KEEPALIVE_INTERVAL));\r\n }\r\n /**\r\n * Send a string over the websocket.\r\n *\r\n * @param str - String to send.\r\n */\r\n sendString_(str) {\r\n // Firefox seems to sometimes throw exceptions (NS_ERROR_UNEXPECTED) from websocket .send()\r\n // calls for some unknown reason. We treat these as an error and disconnect.\r\n // See https://app.asana.com/0/58926111402292/68021340250410\r\n try {\r\n this.mySock.send(str);\r\n }\r\n catch (e) {\r\n this.log_('Exception thrown from WebSocket.send():', e.message || e.data, 'Closing connection.');\r\n setTimeout(this.onClosed_.bind(this), 0);\r\n }\r\n }\r\n}\r\n/**\r\n * Number of response before we consider the connection \"healthy.\"\r\n */\r\nWebSocketConnection.responsesRequiredToBeHealthy = 2;\r\n/**\r\n * Time to wait for the connection te become healthy before giving up.\r\n */\r\nWebSocketConnection.healthyTimeout = 30000;\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * Currently simplistic, this class manages what transport a Connection should use at various stages of its\r\n * lifecycle.\r\n *\r\n * It starts with longpolling in a browser, and httppolling on node. It then upgrades to websockets if\r\n * they are available.\r\n */\r\nclass TransportManager {\r\n /**\r\n * @param repoInfo - Metadata around the namespace we're connecting to\r\n */\r\n constructor(repoInfo) {\r\n this.initTransports_(repoInfo);\r\n }\r\n static get ALL_TRANSPORTS() {\r\n return [BrowserPollConnection, WebSocketConnection];\r\n }\r\n /**\r\n * Returns whether transport has been selected to ensure WebSocketConnection or BrowserPollConnection are not called after\r\n * TransportManager has already set up transports_\r\n */\r\n static get IS_TRANSPORT_INITIALIZED() {\r\n return this.globalTransportInitialized_;\r\n }\r\n initTransports_(repoInfo) {\r\n const isWebSocketsAvailable = WebSocketConnection && WebSocketConnection['isAvailable']();\r\n let isSkipPollConnection = isWebSocketsAvailable && !WebSocketConnection.previouslyFailed();\r\n if (repoInfo.webSocketOnly) {\r\n if (!isWebSocketsAvailable) {\r\n warn(\"wss:// URL used, but browser isn't known to support websockets. Trying anyway.\");\r\n }\r\n isSkipPollConnection = true;\r\n }\r\n if (isSkipPollConnection) {\r\n this.transports_ = [WebSocketConnection];\r\n }\r\n else {\r\n const transports = (this.transports_ = []);\r\n for (const transport of TransportManager.ALL_TRANSPORTS) {\r\n if (transport && transport['isAvailable']()) {\r\n transports.push(transport);\r\n }\r\n }\r\n TransportManager.globalTransportInitialized_ = true;\r\n }\r\n }\r\n /**\r\n * @returns The constructor for the initial transport to use\r\n */\r\n initialTransport() {\r\n if (this.transports_.length > 0) {\r\n return this.transports_[0];\r\n }\r\n else {\r\n throw new Error('No transports available');\r\n }\r\n }\r\n /**\r\n * @returns The constructor for the next transport, or null\r\n */\r\n upgradeTransport() {\r\n if (this.transports_.length > 1) {\r\n return this.transports_[1];\r\n }\r\n else {\r\n return null;\r\n }\r\n }\r\n}\r\n// Keeps track of whether the TransportManager has already chosen a transport to use\r\nTransportManager.globalTransportInitialized_ = false;\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n// Abort upgrade attempt if it takes longer than 60s.\r\nconst UPGRADE_TIMEOUT = 60000;\r\n// For some transports (WebSockets), we need to \"validate\" the transport by exchanging a few requests and responses.\r\n// If we haven't sent enough requests within 5s, we'll start sending noop ping requests.\r\nconst DELAY_BEFORE_SENDING_EXTRA_REQUESTS = 5000;\r\n// If the initial data sent triggers a lot of bandwidth (i.e. it's a large put or a listen for a large amount of data)\r\n// then we may not be able to exchange our ping/pong requests within the healthy timeout. So if we reach the timeout\r\n// but we've sent/received enough bytes, we don't cancel the connection.\r\nconst BYTES_SENT_HEALTHY_OVERRIDE = 10 * 1024;\r\nconst BYTES_RECEIVED_HEALTHY_OVERRIDE = 100 * 1024;\r\nconst MESSAGE_TYPE = 't';\r\nconst MESSAGE_DATA = 'd';\r\nconst CONTROL_SHUTDOWN = 's';\r\nconst CONTROL_RESET = 'r';\r\nconst CONTROL_ERROR = 'e';\r\nconst CONTROL_PONG = 'o';\r\nconst SWITCH_ACK = 'a';\r\nconst END_TRANSMISSION = 'n';\r\nconst PING = 'p';\r\nconst SERVER_HELLO = 'h';\r\n/**\r\n * Creates a new real-time connection to the server using whichever method works\r\n * best in the current browser.\r\n */\r\nclass Connection {\r\n /**\r\n * @param id - an id for this connection\r\n * @param repoInfo_ - the info for the endpoint to connect to\r\n * @param applicationId_ - the Firebase App ID for this project\r\n * @param appCheckToken_ - The App Check Token for this device.\r\n * @param authToken_ - The auth token for this session.\r\n * @param onMessage_ - the callback to be triggered when a server-push message arrives\r\n * @param onReady_ - the callback to be triggered when this connection is ready to send messages.\r\n * @param onDisconnect_ - the callback to be triggered when a connection was lost\r\n * @param onKill_ - the callback to be triggered when this connection has permanently shut down.\r\n * @param lastSessionId - last session id in persistent connection. is used to clean up old session in real-time server\r\n */\r\n constructor(id, repoInfo_, applicationId_, appCheckToken_, authToken_, onMessage_, onReady_, onDisconnect_, onKill_, lastSessionId) {\r\n this.id = id;\r\n this.repoInfo_ = repoInfo_;\r\n this.applicationId_ = applicationId_;\r\n this.appCheckToken_ = appCheckToken_;\r\n this.authToken_ = authToken_;\r\n this.onMessage_ = onMessage_;\r\n this.onReady_ = onReady_;\r\n this.onDisconnect_ = onDisconnect_;\r\n this.onKill_ = onKill_;\r\n this.lastSessionId = lastSessionId;\r\n this.connectionCount = 0;\r\n this.pendingDataMessages = [];\r\n this.state_ = 0 /* RealtimeState.CONNECTING */;\r\n this.log_ = logWrapper('c:' + this.id + ':');\r\n this.transportManager_ = new TransportManager(repoInfo_);\r\n this.log_('Connection created');\r\n this.start_();\r\n }\r\n /**\r\n * Starts a connection attempt\r\n */\r\n start_() {\r\n const conn = this.transportManager_.initialTransport();\r\n this.conn_ = new conn(this.nextTransportId_(), this.repoInfo_, this.applicationId_, this.appCheckToken_, this.authToken_, null, this.lastSessionId);\r\n // For certain transports (WebSockets), we need to send and receive several messages back and forth before we\r\n // can consider the transport healthy.\r\n this.primaryResponsesRequired_ = conn['responsesRequiredToBeHealthy'] || 0;\r\n const onMessageReceived = this.connReceiver_(this.conn_);\r\n const onConnectionLost = this.disconnReceiver_(this.conn_);\r\n this.tx_ = this.conn_;\r\n this.rx_ = this.conn_;\r\n this.secondaryConn_ = null;\r\n this.isHealthy_ = false;\r\n /*\r\n * Firefox doesn't like when code from one iframe tries to create another iframe by way of the parent frame.\r\n * This can occur in the case of a redirect, i.e. we guessed wrong on what server to connect to and received a reset.\r\n * Somehow, setTimeout seems to make this ok. That doesn't make sense from a security perspective, since you should\r\n * still have the context of your originating frame.\r\n */\r\n setTimeout(() => {\r\n // this.conn_ gets set to null in some of the tests. Check to make sure it still exists before using it\r\n this.conn_ && this.conn_.open(onMessageReceived, onConnectionLost);\r\n }, Math.floor(0));\r\n const healthyTimeoutMS = conn['healthyTimeout'] || 0;\r\n if (healthyTimeoutMS > 0) {\r\n this.healthyTimeout_ = setTimeoutNonBlocking(() => {\r\n this.healthyTimeout_ = null;\r\n if (!this.isHealthy_) {\r\n if (this.conn_ &&\r\n this.conn_.bytesReceived > BYTES_RECEIVED_HEALTHY_OVERRIDE) {\r\n this.log_('Connection exceeded healthy timeout but has received ' +\r\n this.conn_.bytesReceived +\r\n ' bytes. Marking connection healthy.');\r\n this.isHealthy_ = true;\r\n this.conn_.markConnectionHealthy();\r\n }\r\n else if (this.conn_ &&\r\n this.conn_.bytesSent > BYTES_SENT_HEALTHY_OVERRIDE) {\r\n this.log_('Connection exceeded healthy timeout but has sent ' +\r\n this.conn_.bytesSent +\r\n ' bytes. Leaving connection alive.');\r\n // NOTE: We don't want to mark it healthy, since we have no guarantee that the bytes have made it to\r\n // the server.\r\n }\r\n else {\r\n this.log_('Closing unhealthy connection after timeout.');\r\n this.close();\r\n }\r\n }\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n }, Math.floor(healthyTimeoutMS));\r\n }\r\n }\r\n nextTransportId_() {\r\n return 'c:' + this.id + ':' + this.connectionCount++;\r\n }\r\n disconnReceiver_(conn) {\r\n return everConnected => {\r\n if (conn === this.conn_) {\r\n this.onConnectionLost_(everConnected);\r\n }\r\n else if (conn === this.secondaryConn_) {\r\n this.log_('Secondary connection lost.');\r\n this.onSecondaryConnectionLost_();\r\n }\r\n else {\r\n this.log_('closing an old connection');\r\n }\r\n };\r\n }\r\n connReceiver_(conn) {\r\n return (message) => {\r\n if (this.state_ !== 2 /* RealtimeState.DISCONNECTED */) {\r\n if (conn === this.rx_) {\r\n this.onPrimaryMessageReceived_(message);\r\n }\r\n else if (conn === this.secondaryConn_) {\r\n this.onSecondaryMessageReceived_(message);\r\n }\r\n else {\r\n this.log_('message on old connection');\r\n }\r\n }\r\n };\r\n }\r\n /**\r\n * @param dataMsg - An arbitrary data message to be sent to the server\r\n */\r\n sendRequest(dataMsg) {\r\n // wrap in a data message envelope and send it on\r\n const msg = { t: 'd', d: dataMsg };\r\n this.sendData_(msg);\r\n }\r\n tryCleanupConnection() {\r\n if (this.tx_ === this.secondaryConn_ && this.rx_ === this.secondaryConn_) {\r\n this.log_('cleaning up and promoting a connection: ' + this.secondaryConn_.connId);\r\n this.conn_ = this.secondaryConn_;\r\n this.secondaryConn_ = null;\r\n // the server will shutdown the old connection\r\n }\r\n }\r\n onSecondaryControl_(controlData) {\r\n if (MESSAGE_TYPE in controlData) {\r\n const cmd = controlData[MESSAGE_TYPE];\r\n if (cmd === SWITCH_ACK) {\r\n this.upgradeIfSecondaryHealthy_();\r\n }\r\n else if (cmd === CONTROL_RESET) {\r\n // Most likely the session wasn't valid. Abandon the switch attempt\r\n this.log_('Got a reset on secondary, closing it');\r\n this.secondaryConn_.close();\r\n // If we were already using this connection for something, than we need to fully close\r\n if (this.tx_ === this.secondaryConn_ ||\r\n this.rx_ === this.secondaryConn_) {\r\n this.close();\r\n }\r\n }\r\n else if (cmd === CONTROL_PONG) {\r\n this.log_('got pong on secondary.');\r\n this.secondaryResponsesRequired_--;\r\n this.upgradeIfSecondaryHealthy_();\r\n }\r\n }\r\n }\r\n onSecondaryMessageReceived_(parsedData) {\r\n const layer = requireKey('t', parsedData);\r\n const data = requireKey('d', parsedData);\r\n if (layer === 'c') {\r\n this.onSecondaryControl_(data);\r\n }\r\n else if (layer === 'd') {\r\n // got a data message, but we're still second connection. Need to buffer it up\r\n this.pendingDataMessages.push(data);\r\n }\r\n else {\r\n throw new Error('Unknown protocol layer: ' + layer);\r\n }\r\n }\r\n upgradeIfSecondaryHealthy_() {\r\n if (this.secondaryResponsesRequired_ <= 0) {\r\n this.log_('Secondary connection is healthy.');\r\n this.isHealthy_ = true;\r\n this.secondaryConn_.markConnectionHealthy();\r\n this.proceedWithUpgrade_();\r\n }\r\n else {\r\n // Send a ping to make sure the connection is healthy.\r\n this.log_('sending ping on secondary.');\r\n this.secondaryConn_.send({ t: 'c', d: { t: PING, d: {} } });\r\n }\r\n }\r\n proceedWithUpgrade_() {\r\n // tell this connection to consider itself open\r\n this.secondaryConn_.start();\r\n // send ack\r\n this.log_('sending client ack on secondary');\r\n this.secondaryConn_.send({ t: 'c', d: { t: SWITCH_ACK, d: {} } });\r\n // send end packet on primary transport, switch to sending on this one\r\n // can receive on this one, buffer responses until end received on primary transport\r\n this.log_('Ending transmission on primary');\r\n this.conn_.send({ t: 'c', d: { t: END_TRANSMISSION, d: {} } });\r\n this.tx_ = this.secondaryConn_;\r\n this.tryCleanupConnection();\r\n }\r\n onPrimaryMessageReceived_(parsedData) {\r\n // Must refer to parsedData properties in quotes, so closure doesn't touch them.\r\n const layer = requireKey('t', parsedData);\r\n const data = requireKey('d', parsedData);\r\n if (layer === 'c') {\r\n this.onControl_(data);\r\n }\r\n else if (layer === 'd') {\r\n this.onDataMessage_(data);\r\n }\r\n }\r\n onDataMessage_(message) {\r\n this.onPrimaryResponse_();\r\n // We don't do anything with data messages, just kick them up a level\r\n this.onMessage_(message);\r\n }\r\n onPrimaryResponse_() {\r\n if (!this.isHealthy_) {\r\n this.primaryResponsesRequired_--;\r\n if (this.primaryResponsesRequired_ <= 0) {\r\n this.log_('Primary connection is healthy.');\r\n this.isHealthy_ = true;\r\n this.conn_.markConnectionHealthy();\r\n }\r\n }\r\n }\r\n onControl_(controlData) {\r\n const cmd = requireKey(MESSAGE_TYPE, controlData);\r\n if (MESSAGE_DATA in controlData) {\r\n const payload = controlData[MESSAGE_DATA];\r\n if (cmd === SERVER_HELLO) {\r\n const handshakePayload = Object.assign({}, payload);\r\n if (this.repoInfo_.isUsingEmulator) {\r\n // Upon connecting, the emulator will pass the hostname that it's aware of, but we prefer the user's set hostname via `connectDatabaseEmulator` over what the emulator passes.\r\n handshakePayload.h = this.repoInfo_.host;\r\n }\r\n this.onHandshake_(handshakePayload);\r\n }\r\n else if (cmd === END_TRANSMISSION) {\r\n this.log_('recvd end transmission on primary');\r\n this.rx_ = this.secondaryConn_;\r\n for (let i = 0; i < this.pendingDataMessages.length; ++i) {\r\n this.onDataMessage_(this.pendingDataMessages[i]);\r\n }\r\n this.pendingDataMessages = [];\r\n this.tryCleanupConnection();\r\n }\r\n else if (cmd === CONTROL_SHUTDOWN) {\r\n // This was previously the 'onKill' callback passed to the lower-level connection\r\n // payload in this case is the reason for the shutdown. Generally a human-readable error\r\n this.onConnectionShutdown_(payload);\r\n }\r\n else if (cmd === CONTROL_RESET) {\r\n // payload in this case is the host we should contact\r\n this.onReset_(payload);\r\n }\r\n else if (cmd === CONTROL_ERROR) {\r\n error('Server Error: ' + payload);\r\n }\r\n else if (cmd === CONTROL_PONG) {\r\n this.log_('got pong on primary.');\r\n this.onPrimaryResponse_();\r\n this.sendPingOnPrimaryIfNecessary_();\r\n }\r\n else {\r\n error('Unknown control packet command: ' + cmd);\r\n }\r\n }\r\n }\r\n /**\r\n * @param handshake - The handshake data returned from the server\r\n */\r\n onHandshake_(handshake) {\r\n const timestamp = handshake.ts;\r\n const version = handshake.v;\r\n const host = handshake.h;\r\n this.sessionId = handshake.s;\r\n this.repoInfo_.host = host;\r\n // if we've already closed the connection, then don't bother trying to progress further\r\n if (this.state_ === 0 /* RealtimeState.CONNECTING */) {\r\n this.conn_.start();\r\n this.onConnectionEstablished_(this.conn_, timestamp);\r\n if (PROTOCOL_VERSION !== version) {\r\n warn('Protocol version mismatch detected');\r\n }\r\n // TODO: do we want to upgrade? when? maybe a delay?\r\n this.tryStartUpgrade_();\r\n }\r\n }\r\n tryStartUpgrade_() {\r\n const conn = this.transportManager_.upgradeTransport();\r\n if (conn) {\r\n this.startUpgrade_(conn);\r\n }\r\n }\r\n startUpgrade_(conn) {\r\n this.secondaryConn_ = new conn(this.nextTransportId_(), this.repoInfo_, this.applicationId_, this.appCheckToken_, this.authToken_, this.sessionId);\r\n // For certain transports (WebSockets), we need to send and receive several messages back and forth before we\r\n // can consider the transport healthy.\r\n this.secondaryResponsesRequired_ =\r\n conn['responsesRequiredToBeHealthy'] || 0;\r\n const onMessage = this.connReceiver_(this.secondaryConn_);\r\n const onDisconnect = this.disconnReceiver_(this.secondaryConn_);\r\n this.secondaryConn_.open(onMessage, onDisconnect);\r\n // If we haven't successfully upgraded after UPGRADE_TIMEOUT, give up and kill the secondary.\r\n setTimeoutNonBlocking(() => {\r\n if (this.secondaryConn_) {\r\n this.log_('Timed out trying to upgrade.');\r\n this.secondaryConn_.close();\r\n }\r\n }, Math.floor(UPGRADE_TIMEOUT));\r\n }\r\n onReset_(host) {\r\n this.log_('Reset packet received. New host: ' + host);\r\n this.repoInfo_.host = host;\r\n // TODO: if we're already \"connected\", we need to trigger a disconnect at the next layer up.\r\n // We don't currently support resets after the connection has already been established\r\n if (this.state_ === 1 /* RealtimeState.CONNECTED */) {\r\n this.close();\r\n }\r\n else {\r\n // Close whatever connections we have open and start again.\r\n this.closeConnections_();\r\n this.start_();\r\n }\r\n }\r\n onConnectionEstablished_(conn, timestamp) {\r\n this.log_('Realtime connection established.');\r\n this.conn_ = conn;\r\n this.state_ = 1 /* RealtimeState.CONNECTED */;\r\n if (this.onReady_) {\r\n this.onReady_(timestamp, this.sessionId);\r\n this.onReady_ = null;\r\n }\r\n // If after 5 seconds we haven't sent enough requests to the server to get the connection healthy,\r\n // send some pings.\r\n if (this.primaryResponsesRequired_ === 0) {\r\n this.log_('Primary connection is healthy.');\r\n this.isHealthy_ = true;\r\n }\r\n else {\r\n setTimeoutNonBlocking(() => {\r\n this.sendPingOnPrimaryIfNecessary_();\r\n }, Math.floor(DELAY_BEFORE_SENDING_EXTRA_REQUESTS));\r\n }\r\n }\r\n sendPingOnPrimaryIfNecessary_() {\r\n // If the connection isn't considered healthy yet, we'll send a noop ping packet request.\r\n if (!this.isHealthy_ && this.state_ === 1 /* RealtimeState.CONNECTED */) {\r\n this.log_('sending ping on primary.');\r\n this.sendData_({ t: 'c', d: { t: PING, d: {} } });\r\n }\r\n }\r\n onSecondaryConnectionLost_() {\r\n const conn = this.secondaryConn_;\r\n this.secondaryConn_ = null;\r\n if (this.tx_ === conn || this.rx_ === conn) {\r\n // we are relying on this connection already in some capacity. Therefore, a failure is real\r\n this.close();\r\n }\r\n }\r\n /**\r\n * @param everConnected - Whether or not the connection ever reached a server. Used to determine if\r\n * we should flush the host cache\r\n */\r\n onConnectionLost_(everConnected) {\r\n this.conn_ = null;\r\n // NOTE: IF you're seeing a Firefox error for this line, I think it might be because it's getting\r\n // called on window close and RealtimeState.CONNECTING is no longer defined. Just a guess.\r\n if (!everConnected && this.state_ === 0 /* RealtimeState.CONNECTING */) {\r\n this.log_('Realtime connection failed.');\r\n // Since we failed to connect at all, clear any cached entry for this namespace in case the machine went away\r\n if (this.repoInfo_.isCacheableHost()) {\r\n PersistentStorage.remove('host:' + this.repoInfo_.host);\r\n // reset the internal host to what we would show the user, i.e. .firebaseio.com\r\n this.repoInfo_.internalHost = this.repoInfo_.host;\r\n }\r\n }\r\n else if (this.state_ === 1 /* RealtimeState.CONNECTED */) {\r\n this.log_('Realtime connection lost.');\r\n }\r\n this.close();\r\n }\r\n onConnectionShutdown_(reason) {\r\n this.log_('Connection shutdown command received. Shutting down...');\r\n if (this.onKill_) {\r\n this.onKill_(reason);\r\n this.onKill_ = null;\r\n }\r\n // We intentionally don't want to fire onDisconnect (kill is a different case),\r\n // so clear the callback.\r\n this.onDisconnect_ = null;\r\n this.close();\r\n }\r\n sendData_(data) {\r\n if (this.state_ !== 1 /* RealtimeState.CONNECTED */) {\r\n throw 'Connection is not connected';\r\n }\r\n else {\r\n this.tx_.send(data);\r\n }\r\n }\r\n /**\r\n * Cleans up this connection, calling the appropriate callbacks\r\n */\r\n close() {\r\n if (this.state_ !== 2 /* RealtimeState.DISCONNECTED */) {\r\n this.log_('Closing realtime connection.');\r\n this.state_ = 2 /* RealtimeState.DISCONNECTED */;\r\n this.closeConnections_();\r\n if (this.onDisconnect_) {\r\n this.onDisconnect_();\r\n this.onDisconnect_ = null;\r\n }\r\n }\r\n }\r\n closeConnections_() {\r\n this.log_('Shutting down all connections');\r\n if (this.conn_) {\r\n this.conn_.close();\r\n this.conn_ = null;\r\n }\r\n if (this.secondaryConn_) {\r\n this.secondaryConn_.close();\r\n this.secondaryConn_ = null;\r\n }\r\n if (this.healthyTimeout_) {\r\n clearTimeout(this.healthyTimeout_);\r\n this.healthyTimeout_ = null;\r\n }\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * Interface defining the set of actions that can be performed against the Firebase server\r\n * (basically corresponds to our wire protocol).\r\n *\r\n * @interface\r\n */\r\nclass ServerActions {\r\n put(pathString, data, onComplete, hash) { }\r\n merge(pathString, data, onComplete, hash) { }\r\n /**\r\n * Refreshes the auth token for the current connection.\r\n * @param token - The authentication token\r\n */\r\n refreshAuthToken(token) { }\r\n /**\r\n * Refreshes the app check token for the current connection.\r\n * @param token The app check token\r\n */\r\n refreshAppCheckToken(token) { }\r\n onDisconnectPut(pathString, data, onComplete) { }\r\n onDisconnectMerge(pathString, data, onComplete) { }\r\n onDisconnectCancel(pathString, onComplete) { }\r\n reportStats(stats) { }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * Base class to be used if you want to emit events. Call the constructor with\r\n * the set of allowed event names.\r\n */\r\nclass EventEmitter {\r\n constructor(allowedEvents_) {\r\n this.allowedEvents_ = allowedEvents_;\r\n this.listeners_ = {};\r\n assert(Array.isArray(allowedEvents_) && allowedEvents_.length > 0, 'Requires a non-empty array');\r\n }\r\n /**\r\n * To be called by derived classes to trigger events.\r\n */\r\n trigger(eventType, ...varArgs) {\r\n if (Array.isArray(this.listeners_[eventType])) {\r\n // Clone the list, since callbacks could add/remove listeners.\r\n const listeners = [...this.listeners_[eventType]];\r\n for (let i = 0; i < listeners.length; i++) {\r\n listeners[i].callback.apply(listeners[i].context, varArgs);\r\n }\r\n }\r\n }\r\n on(eventType, callback, context) {\r\n this.validateEventType_(eventType);\r\n this.listeners_[eventType] = this.listeners_[eventType] || [];\r\n this.listeners_[eventType].push({ callback, context });\r\n const eventData = this.getInitialEvent(eventType);\r\n if (eventData) {\r\n callback.apply(context, eventData);\r\n }\r\n }\r\n off(eventType, callback, context) {\r\n this.validateEventType_(eventType);\r\n const listeners = this.listeners_[eventType] || [];\r\n for (let i = 0; i < listeners.length; i++) {\r\n if (listeners[i].callback === callback &&\r\n (!context || context === listeners[i].context)) {\r\n listeners.splice(i, 1);\r\n return;\r\n }\r\n }\r\n }\r\n validateEventType_(eventType) {\r\n assert(this.allowedEvents_.find(et => {\r\n return et === eventType;\r\n }), 'Unknown event: ' + eventType);\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * Monitors online state (as reported by window.online/offline events).\r\n *\r\n * The expectation is that this could have many false positives (thinks we are online\r\n * when we're not), but no false negatives. So we can safely use it to determine when\r\n * we definitely cannot reach the internet.\r\n */\r\nclass OnlineMonitor extends EventEmitter {\r\n constructor() {\r\n super(['online']);\r\n this.online_ = true;\r\n // We've had repeated complaints that Cordova apps can get stuck \"offline\", e.g.\r\n // https://forum.ionicframework.com/t/firebase-connection-is-lost-and-never-come-back/43810\r\n // It would seem that the 'online' event does not always fire consistently. So we disable it\r\n // for Cordova.\r\n if (typeof window !== 'undefined' &&\r\n typeof window.addEventListener !== 'undefined' &&\r\n !isMobileCordova()) {\r\n window.addEventListener('online', () => {\r\n if (!this.online_) {\r\n this.online_ = true;\r\n this.trigger('online', true);\r\n }\r\n }, false);\r\n window.addEventListener('offline', () => {\r\n if (this.online_) {\r\n this.online_ = false;\r\n this.trigger('online', false);\r\n }\r\n }, false);\r\n }\r\n }\r\n static getInstance() {\r\n return new OnlineMonitor();\r\n }\r\n getInitialEvent(eventType) {\r\n assert(eventType === 'online', 'Unknown event type: ' + eventType);\r\n return [this.online_];\r\n }\r\n currentlyOnline() {\r\n return this.online_;\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/** Maximum key depth. */\r\nconst MAX_PATH_DEPTH = 32;\r\n/** Maximum number of (UTF8) bytes in a Firebase path. */\r\nconst MAX_PATH_LENGTH_BYTES = 768;\r\n/**\r\n * An immutable object representing a parsed path. It's immutable so that you\r\n * can pass them around to other functions without worrying about them changing\r\n * it.\r\n */\r\nclass Path {\r\n /**\r\n * @param pathOrString - Path string to parse, or another path, or the raw\r\n * tokens array\r\n */\r\n constructor(pathOrString, pieceNum) {\r\n if (pieceNum === void 0) {\r\n this.pieces_ = pathOrString.split('/');\r\n // Remove empty pieces.\r\n let copyTo = 0;\r\n for (let i = 0; i < this.pieces_.length; i++) {\r\n if (this.pieces_[i].length > 0) {\r\n this.pieces_[copyTo] = this.pieces_[i];\r\n copyTo++;\r\n }\r\n }\r\n this.pieces_.length = copyTo;\r\n this.pieceNum_ = 0;\r\n }\r\n else {\r\n this.pieces_ = pathOrString;\r\n this.pieceNum_ = pieceNum;\r\n }\r\n }\r\n toString() {\r\n let pathString = '';\r\n for (let i = this.pieceNum_; i < this.pieces_.length; i++) {\r\n if (this.pieces_[i] !== '') {\r\n pathString += '/' + this.pieces_[i];\r\n }\r\n }\r\n return pathString || '/';\r\n }\r\n}\r\nfunction newEmptyPath() {\r\n return new Path('');\r\n}\r\nfunction pathGetFront(path) {\r\n if (path.pieceNum_ >= path.pieces_.length) {\r\n return null;\r\n }\r\n return path.pieces_[path.pieceNum_];\r\n}\r\n/**\r\n * @returns The number of segments in this path\r\n */\r\nfunction pathGetLength(path) {\r\n return path.pieces_.length - path.pieceNum_;\r\n}\r\nfunction pathPopFront(path) {\r\n let pieceNum = path.pieceNum_;\r\n if (pieceNum < path.pieces_.length) {\r\n pieceNum++;\r\n }\r\n return new Path(path.pieces_, pieceNum);\r\n}\r\nfunction pathGetBack(path) {\r\n if (path.pieceNum_ < path.pieces_.length) {\r\n return path.pieces_[path.pieces_.length - 1];\r\n }\r\n return null;\r\n}\r\nfunction pathToUrlEncodedString(path) {\r\n let pathString = '';\r\n for (let i = path.pieceNum_; i < path.pieces_.length; i++) {\r\n if (path.pieces_[i] !== '') {\r\n pathString += '/' + encodeURIComponent(String(path.pieces_[i]));\r\n }\r\n }\r\n return pathString || '/';\r\n}\r\n/**\r\n * Shallow copy of the parts of the path.\r\n *\r\n */\r\nfunction pathSlice(path, begin = 0) {\r\n return path.pieces_.slice(path.pieceNum_ + begin);\r\n}\r\nfunction pathParent(path) {\r\n if (path.pieceNum_ >= path.pieces_.length) {\r\n return null;\r\n }\r\n const pieces = [];\r\n for (let i = path.pieceNum_; i < path.pieces_.length - 1; i++) {\r\n pieces.push(path.pieces_[i]);\r\n }\r\n return new Path(pieces, 0);\r\n}\r\nfunction pathChild(path, childPathObj) {\r\n const pieces = [];\r\n for (let i = path.pieceNum_; i < path.pieces_.length; i++) {\r\n pieces.push(path.pieces_[i]);\r\n }\r\n if (childPathObj instanceof Path) {\r\n for (let i = childPathObj.pieceNum_; i < childPathObj.pieces_.length; i++) {\r\n pieces.push(childPathObj.pieces_[i]);\r\n }\r\n }\r\n else {\r\n const childPieces = childPathObj.split('/');\r\n for (let i = 0; i < childPieces.length; i++) {\r\n if (childPieces[i].length > 0) {\r\n pieces.push(childPieces[i]);\r\n }\r\n }\r\n }\r\n return new Path(pieces, 0);\r\n}\r\n/**\r\n * @returns True if there are no segments in this path\r\n */\r\nfunction pathIsEmpty(path) {\r\n return path.pieceNum_ >= path.pieces_.length;\r\n}\r\n/**\r\n * @returns The path from outerPath to innerPath\r\n */\r\nfunction newRelativePath(outerPath, innerPath) {\r\n const outer = pathGetFront(outerPath), inner = pathGetFront(innerPath);\r\n if (outer === null) {\r\n return innerPath;\r\n }\r\n else if (outer === inner) {\r\n return newRelativePath(pathPopFront(outerPath), pathPopFront(innerPath));\r\n }\r\n else {\r\n throw new Error('INTERNAL ERROR: innerPath (' +\r\n innerPath +\r\n ') is not within ' +\r\n 'outerPath (' +\r\n outerPath +\r\n ')');\r\n }\r\n}\r\n/**\r\n * @returns -1, 0, 1 if left is less, equal, or greater than the right.\r\n */\r\nfunction pathCompare(left, right) {\r\n const leftKeys = pathSlice(left, 0);\r\n const rightKeys = pathSlice(right, 0);\r\n for (let i = 0; i < leftKeys.length && i < rightKeys.length; i++) {\r\n const cmp = nameCompare(leftKeys[i], rightKeys[i]);\r\n if (cmp !== 0) {\r\n return cmp;\r\n }\r\n }\r\n if (leftKeys.length === rightKeys.length) {\r\n return 0;\r\n }\r\n return leftKeys.length < rightKeys.length ? -1 : 1;\r\n}\r\n/**\r\n * @returns true if paths are the same.\r\n */\r\nfunction pathEquals(path, other) {\r\n if (pathGetLength(path) !== pathGetLength(other)) {\r\n return false;\r\n }\r\n for (let i = path.pieceNum_, j = other.pieceNum_; i <= path.pieces_.length; i++, j++) {\r\n if (path.pieces_[i] !== other.pieces_[j]) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n}\r\n/**\r\n * @returns True if this path is a parent of (or the same as) other\r\n */\r\nfunction pathContains(path, other) {\r\n let i = path.pieceNum_;\r\n let j = other.pieceNum_;\r\n if (pathGetLength(path) > pathGetLength(other)) {\r\n return false;\r\n }\r\n while (i < path.pieces_.length) {\r\n if (path.pieces_[i] !== other.pieces_[j]) {\r\n return false;\r\n }\r\n ++i;\r\n ++j;\r\n }\r\n return true;\r\n}\r\n/**\r\n * Dynamic (mutable) path used to count path lengths.\r\n *\r\n * This class is used to efficiently check paths for valid\r\n * length (in UTF8 bytes) and depth (used in path validation).\r\n *\r\n * Throws Error exception if path is ever invalid.\r\n *\r\n * The definition of a path always begins with '/'.\r\n */\r\nclass ValidationPath {\r\n /**\r\n * @param path - Initial Path.\r\n * @param errorPrefix_ - Prefix for any error messages.\r\n */\r\n constructor(path, errorPrefix_) {\r\n this.errorPrefix_ = errorPrefix_;\r\n this.parts_ = pathSlice(path, 0);\r\n /** Initialize to number of '/' chars needed in path. */\r\n this.byteLength_ = Math.max(1, this.parts_.length);\r\n for (let i = 0; i < this.parts_.length; i++) {\r\n this.byteLength_ += stringLength(this.parts_[i]);\r\n }\r\n validationPathCheckValid(this);\r\n }\r\n}\r\nfunction validationPathPush(validationPath, child) {\r\n // Count the needed '/'\r\n if (validationPath.parts_.length > 0) {\r\n validationPath.byteLength_ += 1;\r\n }\r\n validationPath.parts_.push(child);\r\n validationPath.byteLength_ += stringLength(child);\r\n validationPathCheckValid(validationPath);\r\n}\r\nfunction validationPathPop(validationPath) {\r\n const last = validationPath.parts_.pop();\r\n validationPath.byteLength_ -= stringLength(last);\r\n // Un-count the previous '/'\r\n if (validationPath.parts_.length > 0) {\r\n validationPath.byteLength_ -= 1;\r\n }\r\n}\r\nfunction validationPathCheckValid(validationPath) {\r\n if (validationPath.byteLength_ > MAX_PATH_LENGTH_BYTES) {\r\n throw new Error(validationPath.errorPrefix_ +\r\n 'has a key path longer than ' +\r\n MAX_PATH_LENGTH_BYTES +\r\n ' bytes (' +\r\n validationPath.byteLength_ +\r\n ').');\r\n }\r\n if (validationPath.parts_.length > MAX_PATH_DEPTH) {\r\n throw new Error(validationPath.errorPrefix_ +\r\n 'path specified exceeds the maximum depth that can be written (' +\r\n MAX_PATH_DEPTH +\r\n ') or object contains a cycle ' +\r\n validationPathToErrorString(validationPath));\r\n }\r\n}\r\n/**\r\n * String for use in error messages - uses '.' notation for path.\r\n */\r\nfunction validationPathToErrorString(validationPath) {\r\n if (validationPath.parts_.length === 0) {\r\n return '';\r\n }\r\n return \"in property '\" + validationPath.parts_.join('.') + \"'\";\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nclass VisibilityMonitor extends EventEmitter {\r\n constructor() {\r\n super(['visible']);\r\n let hidden;\r\n let visibilityChange;\r\n if (typeof document !== 'undefined' &&\r\n typeof document.addEventListener !== 'undefined') {\r\n if (typeof document['hidden'] !== 'undefined') {\r\n // Opera 12.10 and Firefox 18 and later support\r\n visibilityChange = 'visibilitychange';\r\n hidden = 'hidden';\r\n }\r\n else if (typeof document['mozHidden'] !== 'undefined') {\r\n visibilityChange = 'mozvisibilitychange';\r\n hidden = 'mozHidden';\r\n }\r\n else if (typeof document['msHidden'] !== 'undefined') {\r\n visibilityChange = 'msvisibilitychange';\r\n hidden = 'msHidden';\r\n }\r\n else if (typeof document['webkitHidden'] !== 'undefined') {\r\n visibilityChange = 'webkitvisibilitychange';\r\n hidden = 'webkitHidden';\r\n }\r\n }\r\n // Initially, we always assume we are visible. This ensures that in browsers\r\n // without page visibility support or in cases where we are never visible\r\n // (e.g. chrome extension), we act as if we are visible, i.e. don't delay\r\n // reconnects\r\n this.visible_ = true;\r\n if (visibilityChange) {\r\n document.addEventListener(visibilityChange, () => {\r\n const visible = !document[hidden];\r\n if (visible !== this.visible_) {\r\n this.visible_ = visible;\r\n this.trigger('visible', visible);\r\n }\r\n }, false);\r\n }\r\n }\r\n static getInstance() {\r\n return new VisibilityMonitor();\r\n }\r\n getInitialEvent(eventType) {\r\n assert(eventType === 'visible', 'Unknown event type: ' + eventType);\r\n return [this.visible_];\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nconst RECONNECT_MIN_DELAY = 1000;\r\nconst RECONNECT_MAX_DELAY_DEFAULT = 60 * 5 * 1000; // 5 minutes in milliseconds (Case: 1858)\r\nconst RECONNECT_MAX_DELAY_FOR_ADMINS = 30 * 1000; // 30 seconds for admin clients (likely to be a backend server)\r\nconst RECONNECT_DELAY_MULTIPLIER = 1.3;\r\nconst RECONNECT_DELAY_RESET_TIMEOUT = 30000; // Reset delay back to MIN_DELAY after being connected for 30sec.\r\nconst SERVER_KILL_INTERRUPT_REASON = 'server_kill';\r\n// If auth fails repeatedly, we'll assume something is wrong and log a warning / back off.\r\nconst INVALID_TOKEN_THRESHOLD = 3;\r\n/**\r\n * Firebase connection. Abstracts wire protocol and handles reconnecting.\r\n *\r\n * NOTE: All JSON objects sent to the realtime connection must have property names enclosed\r\n * in quotes to make sure the closure compiler does not minify them.\r\n */\r\nclass PersistentConnection extends ServerActions {\r\n /**\r\n * @param repoInfo_ - Data about the namespace we are connecting to\r\n * @param applicationId_ - The Firebase App ID for this project\r\n * @param onDataUpdate_ - A callback for new data from the server\r\n */\r\n constructor(repoInfo_, applicationId_, onDataUpdate_, onConnectStatus_, onServerInfoUpdate_, authTokenProvider_, appCheckTokenProvider_, authOverride_) {\r\n super();\r\n this.repoInfo_ = repoInfo_;\r\n this.applicationId_ = applicationId_;\r\n this.onDataUpdate_ = onDataUpdate_;\r\n this.onConnectStatus_ = onConnectStatus_;\r\n this.onServerInfoUpdate_ = onServerInfoUpdate_;\r\n this.authTokenProvider_ = authTokenProvider_;\r\n this.appCheckTokenProvider_ = appCheckTokenProvider_;\r\n this.authOverride_ = authOverride_;\r\n // Used for diagnostic logging.\r\n this.id = PersistentConnection.nextPersistentConnectionId_++;\r\n this.log_ = logWrapper('p:' + this.id + ':');\r\n this.interruptReasons_ = {};\r\n this.listens = new Map();\r\n this.outstandingPuts_ = [];\r\n this.outstandingGets_ = [];\r\n this.outstandingPutCount_ = 0;\r\n this.outstandingGetCount_ = 0;\r\n this.onDisconnectRequestQueue_ = [];\r\n this.connected_ = false;\r\n this.reconnectDelay_ = RECONNECT_MIN_DELAY;\r\n this.maxReconnectDelay_ = RECONNECT_MAX_DELAY_DEFAULT;\r\n this.securityDebugCallback_ = null;\r\n this.lastSessionId = null;\r\n this.establishConnectionTimer_ = null;\r\n this.visible_ = false;\r\n // Before we get connected, we keep a queue of pending messages to send.\r\n this.requestCBHash_ = {};\r\n this.requestNumber_ = 0;\r\n this.realtime_ = null;\r\n this.authToken_ = null;\r\n this.appCheckToken_ = null;\r\n this.forceTokenRefresh_ = false;\r\n this.invalidAuthTokenCount_ = 0;\r\n this.invalidAppCheckTokenCount_ = 0;\r\n this.firstConnection_ = true;\r\n this.lastConnectionAttemptTime_ = null;\r\n this.lastConnectionEstablishedTime_ = null;\r\n if (authOverride_ && !isNodeSdk()) {\r\n throw new Error('Auth override specified in options, but not supported on non Node.js platforms');\r\n }\r\n VisibilityMonitor.getInstance().on('visible', this.onVisible_, this);\r\n if (repoInfo_.host.indexOf('fblocal') === -1) {\r\n OnlineMonitor.getInstance().on('online', this.onOnline_, this);\r\n }\r\n }\r\n sendRequest(action, body, onResponse) {\r\n const curReqNum = ++this.requestNumber_;\r\n const msg = { r: curReqNum, a: action, b: body };\r\n this.log_(stringify(msg));\r\n assert(this.connected_, \"sendRequest call when we're not connected not allowed.\");\r\n this.realtime_.sendRequest(msg);\r\n if (onResponse) {\r\n this.requestCBHash_[curReqNum] = onResponse;\r\n }\r\n }\r\n get(query) {\r\n this.initConnection_();\r\n const deferred = new Deferred();\r\n const request = {\r\n p: query._path.toString(),\r\n q: query._queryObject\r\n };\r\n const outstandingGet = {\r\n action: 'g',\r\n request,\r\n onComplete: (message) => {\r\n const payload = message['d'];\r\n if (message['s'] === 'ok') {\r\n deferred.resolve(payload);\r\n }\r\n else {\r\n deferred.reject(payload);\r\n }\r\n }\r\n };\r\n this.outstandingGets_.push(outstandingGet);\r\n this.outstandingGetCount_++;\r\n const index = this.outstandingGets_.length - 1;\r\n if (this.connected_) {\r\n this.sendGet_(index);\r\n }\r\n return deferred.promise;\r\n }\r\n listen(query, currentHashFn, tag, onComplete) {\r\n this.initConnection_();\r\n const queryId = query._queryIdentifier;\r\n const pathString = query._path.toString();\r\n this.log_('Listen called for ' + pathString + ' ' + queryId);\r\n if (!this.listens.has(pathString)) {\r\n this.listens.set(pathString, new Map());\r\n }\r\n assert(query._queryParams.isDefault() || !query._queryParams.loadsAllData(), 'listen() called for non-default but complete query');\r\n assert(!this.listens.get(pathString).has(queryId), `listen() called twice for same path/queryId.`);\r\n const listenSpec = {\r\n onComplete,\r\n hashFn: currentHashFn,\r\n query,\r\n tag\r\n };\r\n this.listens.get(pathString).set(queryId, listenSpec);\r\n if (this.connected_) {\r\n this.sendListen_(listenSpec);\r\n }\r\n }\r\n sendGet_(index) {\r\n const get = this.outstandingGets_[index];\r\n this.sendRequest('g', get.request, (message) => {\r\n delete this.outstandingGets_[index];\r\n this.outstandingGetCount_--;\r\n if (this.outstandingGetCount_ === 0) {\r\n this.outstandingGets_ = [];\r\n }\r\n if (get.onComplete) {\r\n get.onComplete(message);\r\n }\r\n });\r\n }\r\n sendListen_(listenSpec) {\r\n const query = listenSpec.query;\r\n const pathString = query._path.toString();\r\n const queryId = query._queryIdentifier;\r\n this.log_('Listen on ' + pathString + ' for ' + queryId);\r\n const req = { /*path*/ p: pathString };\r\n const action = 'q';\r\n // Only bother to send query if it's non-default.\r\n if (listenSpec.tag) {\r\n req['q'] = query._queryObject;\r\n req['t'] = listenSpec.tag;\r\n }\r\n req[ /*hash*/'h'] = listenSpec.hashFn();\r\n this.sendRequest(action, req, (message) => {\r\n const payload = message[ /*data*/'d'];\r\n const status = message[ /*status*/'s'];\r\n // print warnings in any case...\r\n PersistentConnection.warnOnListenWarnings_(payload, query);\r\n const currentListenSpec = this.listens.get(pathString) &&\r\n this.listens.get(pathString).get(queryId);\r\n // only trigger actions if the listen hasn't been removed and readded\r\n if (currentListenSpec === listenSpec) {\r\n this.log_('listen response', message);\r\n if (status !== 'ok') {\r\n this.removeListen_(pathString, queryId);\r\n }\r\n if (listenSpec.onComplete) {\r\n listenSpec.onComplete(status, payload);\r\n }\r\n }\r\n });\r\n }\r\n static warnOnListenWarnings_(payload, query) {\r\n if (payload && typeof payload === 'object' && contains(payload, 'w')) {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n const warnings = safeGet(payload, 'w');\r\n if (Array.isArray(warnings) && ~warnings.indexOf('no_index')) {\r\n const indexSpec = '\".indexOn\": \"' + query._queryParams.getIndex().toString() + '\"';\r\n const indexPath = query._path.toString();\r\n warn(`Using an unspecified index. Your data will be downloaded and ` +\r\n `filtered on the client. Consider adding ${indexSpec} at ` +\r\n `${indexPath} to your security rules for better performance.`);\r\n }\r\n }\r\n }\r\n refreshAuthToken(token) {\r\n this.authToken_ = token;\r\n this.log_('Auth token refreshed');\r\n if (this.authToken_) {\r\n this.tryAuth();\r\n }\r\n else {\r\n //If we're connected we want to let the server know to unauthenticate us. If we're not connected, simply delete\r\n //the credential so we dont become authenticated next time we connect.\r\n if (this.connected_) {\r\n this.sendRequest('unauth', {}, () => { });\r\n }\r\n }\r\n this.reduceReconnectDelayIfAdminCredential_(token);\r\n }\r\n reduceReconnectDelayIfAdminCredential_(credential) {\r\n // NOTE: This isn't intended to be bulletproof (a malicious developer can always just modify the client).\r\n // Additionally, we don't bother resetting the max delay back to the default if auth fails / expires.\r\n const isFirebaseSecret = credential && credential.length === 40;\r\n if (isFirebaseSecret || isAdmin(credential)) {\r\n this.log_('Admin auth credential detected. Reducing max reconnect time.');\r\n this.maxReconnectDelay_ = RECONNECT_MAX_DELAY_FOR_ADMINS;\r\n }\r\n }\r\n refreshAppCheckToken(token) {\r\n this.appCheckToken_ = token;\r\n this.log_('App check token refreshed');\r\n if (this.appCheckToken_) {\r\n this.tryAppCheck();\r\n }\r\n else {\r\n //If we're connected we want to let the server know to unauthenticate us.\r\n //If we're not connected, simply delete the credential so we dont become\r\n // authenticated next time we connect.\r\n if (this.connected_) {\r\n this.sendRequest('unappeck', {}, () => { });\r\n }\r\n }\r\n }\r\n /**\r\n * Attempts to authenticate with the given credentials. If the authentication attempt fails, it's triggered like\r\n * a auth revoked (the connection is closed).\r\n */\r\n tryAuth() {\r\n if (this.connected_ && this.authToken_) {\r\n const token = this.authToken_;\r\n const authMethod = isValidFormat(token) ? 'auth' : 'gauth';\r\n const requestData = { cred: token };\r\n if (this.authOverride_ === null) {\r\n requestData['noauth'] = true;\r\n }\r\n else if (typeof this.authOverride_ === 'object') {\r\n requestData['authvar'] = this.authOverride_;\r\n }\r\n this.sendRequest(authMethod, requestData, (res) => {\r\n const status = res[ /*status*/'s'];\r\n const data = res[ /*data*/'d'] || 'error';\r\n if (this.authToken_ === token) {\r\n if (status === 'ok') {\r\n this.invalidAuthTokenCount_ = 0;\r\n }\r\n else {\r\n // Triggers reconnect and force refresh for auth token\r\n this.onAuthRevoked_(status, data);\r\n }\r\n }\r\n });\r\n }\r\n }\r\n /**\r\n * Attempts to authenticate with the given token. If the authentication\r\n * attempt fails, it's triggered like the token was revoked (the connection is\r\n * closed).\r\n */\r\n tryAppCheck() {\r\n if (this.connected_ && this.appCheckToken_) {\r\n this.sendRequest('appcheck', { 'token': this.appCheckToken_ }, (res) => {\r\n const status = res[ /*status*/'s'];\r\n const data = res[ /*data*/'d'] || 'error';\r\n if (status === 'ok') {\r\n this.invalidAppCheckTokenCount_ = 0;\r\n }\r\n else {\r\n this.onAppCheckRevoked_(status, data);\r\n }\r\n });\r\n }\r\n }\r\n /**\r\n * @inheritDoc\r\n */\r\n unlisten(query, tag) {\r\n const pathString = query._path.toString();\r\n const queryId = query._queryIdentifier;\r\n this.log_('Unlisten called for ' + pathString + ' ' + queryId);\r\n assert(query._queryParams.isDefault() || !query._queryParams.loadsAllData(), 'unlisten() called for non-default but complete query');\r\n const listen = this.removeListen_(pathString, queryId);\r\n if (listen && this.connected_) {\r\n this.sendUnlisten_(pathString, queryId, query._queryObject, tag);\r\n }\r\n }\r\n sendUnlisten_(pathString, queryId, queryObj, tag) {\r\n this.log_('Unlisten on ' + pathString + ' for ' + queryId);\r\n const req = { /*path*/ p: pathString };\r\n const action = 'n';\r\n // Only bother sending queryId if it's non-default.\r\n if (tag) {\r\n req['q'] = queryObj;\r\n req['t'] = tag;\r\n }\r\n this.sendRequest(action, req);\r\n }\r\n onDisconnectPut(pathString, data, onComplete) {\r\n this.initConnection_();\r\n if (this.connected_) {\r\n this.sendOnDisconnect_('o', pathString, data, onComplete);\r\n }\r\n else {\r\n this.onDisconnectRequestQueue_.push({\r\n pathString,\r\n action: 'o',\r\n data,\r\n onComplete\r\n });\r\n }\r\n }\r\n onDisconnectMerge(pathString, data, onComplete) {\r\n this.initConnection_();\r\n if (this.connected_) {\r\n this.sendOnDisconnect_('om', pathString, data, onComplete);\r\n }\r\n else {\r\n this.onDisconnectRequestQueue_.push({\r\n pathString,\r\n action: 'om',\r\n data,\r\n onComplete\r\n });\r\n }\r\n }\r\n onDisconnectCancel(pathString, onComplete) {\r\n this.initConnection_();\r\n if (this.connected_) {\r\n this.sendOnDisconnect_('oc', pathString, null, onComplete);\r\n }\r\n else {\r\n this.onDisconnectRequestQueue_.push({\r\n pathString,\r\n action: 'oc',\r\n data: null,\r\n onComplete\r\n });\r\n }\r\n }\r\n sendOnDisconnect_(action, pathString, data, onComplete) {\r\n const request = { /*path*/ p: pathString, /*data*/ d: data };\r\n this.log_('onDisconnect ' + action, request);\r\n this.sendRequest(action, request, (response) => {\r\n if (onComplete) {\r\n setTimeout(() => {\r\n onComplete(response[ /*status*/'s'], response[ /* data */'d']);\r\n }, Math.floor(0));\r\n }\r\n });\r\n }\r\n put(pathString, data, onComplete, hash) {\r\n this.putInternal('p', pathString, data, onComplete, hash);\r\n }\r\n merge(pathString, data, onComplete, hash) {\r\n this.putInternal('m', pathString, data, onComplete, hash);\r\n }\r\n putInternal(action, pathString, data, onComplete, hash) {\r\n this.initConnection_();\r\n const request = {\r\n /*path*/ p: pathString,\r\n /*data*/ d: data\r\n };\r\n if (hash !== undefined) {\r\n request[ /*hash*/'h'] = hash;\r\n }\r\n // TODO: Only keep track of the most recent put for a given path?\r\n this.outstandingPuts_.push({\r\n action,\r\n request,\r\n onComplete\r\n });\r\n this.outstandingPutCount_++;\r\n const index = this.outstandingPuts_.length - 1;\r\n if (this.connected_) {\r\n this.sendPut_(index);\r\n }\r\n else {\r\n this.log_('Buffering put: ' + pathString);\r\n }\r\n }\r\n sendPut_(index) {\r\n const action = this.outstandingPuts_[index].action;\r\n const request = this.outstandingPuts_[index].request;\r\n const onComplete = this.outstandingPuts_[index].onComplete;\r\n this.outstandingPuts_[index].queued = this.connected_;\r\n this.sendRequest(action, request, (message) => {\r\n this.log_(action + ' response', message);\r\n delete this.outstandingPuts_[index];\r\n this.outstandingPutCount_--;\r\n // Clean up array occasionally.\r\n if (this.outstandingPutCount_ === 0) {\r\n this.outstandingPuts_ = [];\r\n }\r\n if (onComplete) {\r\n onComplete(message[ /*status*/'s'], message[ /* data */'d']);\r\n }\r\n });\r\n }\r\n reportStats(stats) {\r\n // If we're not connected, we just drop the stats.\r\n if (this.connected_) {\r\n const request = { /*counters*/ c: stats };\r\n this.log_('reportStats', request);\r\n this.sendRequest(/*stats*/ 's', request, result => {\r\n const status = result[ /*status*/'s'];\r\n if (status !== 'ok') {\r\n const errorReason = result[ /* data */'d'];\r\n this.log_('reportStats', 'Error sending stats: ' + errorReason);\r\n }\r\n });\r\n }\r\n }\r\n onDataMessage_(message) {\r\n if ('r' in message) {\r\n // this is a response\r\n this.log_('from server: ' + stringify(message));\r\n const reqNum = message['r'];\r\n const onResponse = this.requestCBHash_[reqNum];\r\n if (onResponse) {\r\n delete this.requestCBHash_[reqNum];\r\n onResponse(message[ /*body*/'b']);\r\n }\r\n }\r\n else if ('error' in message) {\r\n throw 'A server-side error has occurred: ' + message['error'];\r\n }\r\n else if ('a' in message) {\r\n // a and b are action and body, respectively\r\n this.onDataPush_(message['a'], message['b']);\r\n }\r\n }\r\n onDataPush_(action, body) {\r\n this.log_('handleServerMessage', action, body);\r\n if (action === 'd') {\r\n this.onDataUpdate_(body[ /*path*/'p'], body[ /*data*/'d'], \r\n /*isMerge*/ false, body['t']);\r\n }\r\n else if (action === 'm') {\r\n this.onDataUpdate_(body[ /*path*/'p'], body[ /*data*/'d'], \r\n /*isMerge=*/ true, body['t']);\r\n }\r\n else if (action === 'c') {\r\n this.onListenRevoked_(body[ /*path*/'p'], body[ /*query*/'q']);\r\n }\r\n else if (action === 'ac') {\r\n this.onAuthRevoked_(body[ /*status code*/'s'], body[ /* explanation */'d']);\r\n }\r\n else if (action === 'apc') {\r\n this.onAppCheckRevoked_(body[ /*status code*/'s'], body[ /* explanation */'d']);\r\n }\r\n else if (action === 'sd') {\r\n this.onSecurityDebugPacket_(body);\r\n }\r\n else {\r\n error('Unrecognized action received from server: ' +\r\n stringify(action) +\r\n '\\nAre you using the latest client?');\r\n }\r\n }\r\n onReady_(timestamp, sessionId) {\r\n this.log_('connection ready');\r\n this.connected_ = true;\r\n this.lastConnectionEstablishedTime_ = new Date().getTime();\r\n this.handleTimestamp_(timestamp);\r\n this.lastSessionId = sessionId;\r\n if (this.firstConnection_) {\r\n this.sendConnectStats_();\r\n }\r\n this.restoreState_();\r\n this.firstConnection_ = false;\r\n this.onConnectStatus_(true);\r\n }\r\n scheduleConnect_(timeout) {\r\n assert(!this.realtime_, \"Scheduling a connect when we're already connected/ing?\");\r\n if (this.establishConnectionTimer_) {\r\n clearTimeout(this.establishConnectionTimer_);\r\n }\r\n // NOTE: Even when timeout is 0, it's important to do a setTimeout to work around an infuriating \"Security Error\" in\r\n // Firefox when trying to write to our long-polling iframe in some scenarios (e.g. Forge or our unit tests).\r\n this.establishConnectionTimer_ = setTimeout(() => {\r\n this.establishConnectionTimer_ = null;\r\n this.establishConnection_();\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n }, Math.floor(timeout));\r\n }\r\n initConnection_() {\r\n if (!this.realtime_ && this.firstConnection_) {\r\n this.scheduleConnect_(0);\r\n }\r\n }\r\n onVisible_(visible) {\r\n // NOTE: Tabbing away and back to a window will defeat our reconnect backoff, but I think that's fine.\r\n if (visible &&\r\n !this.visible_ &&\r\n this.reconnectDelay_ === this.maxReconnectDelay_) {\r\n this.log_('Window became visible. Reducing delay.');\r\n this.reconnectDelay_ = RECONNECT_MIN_DELAY;\r\n if (!this.realtime_) {\r\n this.scheduleConnect_(0);\r\n }\r\n }\r\n this.visible_ = visible;\r\n }\r\n onOnline_(online) {\r\n if (online) {\r\n this.log_('Browser went online.');\r\n this.reconnectDelay_ = RECONNECT_MIN_DELAY;\r\n if (!this.realtime_) {\r\n this.scheduleConnect_(0);\r\n }\r\n }\r\n else {\r\n this.log_('Browser went offline. Killing connection.');\r\n if (this.realtime_) {\r\n this.realtime_.close();\r\n }\r\n }\r\n }\r\n onRealtimeDisconnect_() {\r\n this.log_('data client disconnected');\r\n this.connected_ = false;\r\n this.realtime_ = null;\r\n // Since we don't know if our sent transactions succeeded or not, we need to cancel them.\r\n this.cancelSentTransactions_();\r\n // Clear out the pending requests.\r\n this.requestCBHash_ = {};\r\n if (this.shouldReconnect_()) {\r\n if (!this.visible_) {\r\n this.log_(\"Window isn't visible. Delaying reconnect.\");\r\n this.reconnectDelay_ = this.maxReconnectDelay_;\r\n this.lastConnectionAttemptTime_ = new Date().getTime();\r\n }\r\n else if (this.lastConnectionEstablishedTime_) {\r\n // If we've been connected long enough, reset reconnect delay to minimum.\r\n const timeSinceLastConnectSucceeded = new Date().getTime() - this.lastConnectionEstablishedTime_;\r\n if (timeSinceLastConnectSucceeded > RECONNECT_DELAY_RESET_TIMEOUT) {\r\n this.reconnectDelay_ = RECONNECT_MIN_DELAY;\r\n }\r\n this.lastConnectionEstablishedTime_ = null;\r\n }\r\n const timeSinceLastConnectAttempt = new Date().getTime() - this.lastConnectionAttemptTime_;\r\n let reconnectDelay = Math.max(0, this.reconnectDelay_ - timeSinceLastConnectAttempt);\r\n reconnectDelay = Math.random() * reconnectDelay;\r\n this.log_('Trying to reconnect in ' + reconnectDelay + 'ms');\r\n this.scheduleConnect_(reconnectDelay);\r\n // Adjust reconnect delay for next time.\r\n this.reconnectDelay_ = Math.min(this.maxReconnectDelay_, this.reconnectDelay_ * RECONNECT_DELAY_MULTIPLIER);\r\n }\r\n this.onConnectStatus_(false);\r\n }\r\n async establishConnection_() {\r\n if (this.shouldReconnect_()) {\r\n this.log_('Making a connection attempt');\r\n this.lastConnectionAttemptTime_ = new Date().getTime();\r\n this.lastConnectionEstablishedTime_ = null;\r\n const onDataMessage = this.onDataMessage_.bind(this);\r\n const onReady = this.onReady_.bind(this);\r\n const onDisconnect = this.onRealtimeDisconnect_.bind(this);\r\n const connId = this.id + ':' + PersistentConnection.nextConnectionId_++;\r\n const lastSessionId = this.lastSessionId;\r\n let canceled = false;\r\n let connection = null;\r\n const closeFn = function () {\r\n if (connection) {\r\n connection.close();\r\n }\r\n else {\r\n canceled = true;\r\n onDisconnect();\r\n }\r\n };\r\n const sendRequestFn = function (msg) {\r\n assert(connection, \"sendRequest call when we're not connected not allowed.\");\r\n connection.sendRequest(msg);\r\n };\r\n this.realtime_ = {\r\n close: closeFn,\r\n sendRequest: sendRequestFn\r\n };\r\n const forceRefresh = this.forceTokenRefresh_;\r\n this.forceTokenRefresh_ = false;\r\n try {\r\n // First fetch auth and app check token, and establish connection after\r\n // fetching the token was successful\r\n const [authToken, appCheckToken] = await Promise.all([\r\n this.authTokenProvider_.getToken(forceRefresh),\r\n this.appCheckTokenProvider_.getToken(forceRefresh)\r\n ]);\r\n if (!canceled) {\r\n log('getToken() completed. Creating connection.');\r\n this.authToken_ = authToken && authToken.accessToken;\r\n this.appCheckToken_ = appCheckToken && appCheckToken.token;\r\n connection = new Connection(connId, this.repoInfo_, this.applicationId_, this.appCheckToken_, this.authToken_, onDataMessage, onReady, onDisconnect, \r\n /* onKill= */ reason => {\r\n warn(reason + ' (' + this.repoInfo_.toString() + ')');\r\n this.interrupt(SERVER_KILL_INTERRUPT_REASON);\r\n }, lastSessionId);\r\n }\r\n else {\r\n log('getToken() completed but was canceled');\r\n }\r\n }\r\n catch (error) {\r\n this.log_('Failed to get token: ' + error);\r\n if (!canceled) {\r\n if (this.repoInfo_.nodeAdmin) {\r\n // This may be a critical error for the Admin Node.js SDK, so log a warning.\r\n // But getToken() may also just have temporarily failed, so we still want to\r\n // continue retrying.\r\n warn(error);\r\n }\r\n closeFn();\r\n }\r\n }\r\n }\r\n }\r\n interrupt(reason) {\r\n log('Interrupting connection for reason: ' + reason);\r\n this.interruptReasons_[reason] = true;\r\n if (this.realtime_) {\r\n this.realtime_.close();\r\n }\r\n else {\r\n if (this.establishConnectionTimer_) {\r\n clearTimeout(this.establishConnectionTimer_);\r\n this.establishConnectionTimer_ = null;\r\n }\r\n if (this.connected_) {\r\n this.onRealtimeDisconnect_();\r\n }\r\n }\r\n }\r\n resume(reason) {\r\n log('Resuming connection for reason: ' + reason);\r\n delete this.interruptReasons_[reason];\r\n if (isEmpty(this.interruptReasons_)) {\r\n this.reconnectDelay_ = RECONNECT_MIN_DELAY;\r\n if (!this.realtime_) {\r\n this.scheduleConnect_(0);\r\n }\r\n }\r\n }\r\n handleTimestamp_(timestamp) {\r\n const delta = timestamp - new Date().getTime();\r\n this.onServerInfoUpdate_({ serverTimeOffset: delta });\r\n }\r\n cancelSentTransactions_() {\r\n for (let i = 0; i < this.outstandingPuts_.length; i++) {\r\n const put = this.outstandingPuts_[i];\r\n if (put && /*hash*/ 'h' in put.request && put.queued) {\r\n if (put.onComplete) {\r\n put.onComplete('disconnect');\r\n }\r\n delete this.outstandingPuts_[i];\r\n this.outstandingPutCount_--;\r\n }\r\n }\r\n // Clean up array occasionally.\r\n if (this.outstandingPutCount_ === 0) {\r\n this.outstandingPuts_ = [];\r\n }\r\n }\r\n onListenRevoked_(pathString, query) {\r\n // Remove the listen and manufacture a \"permission_denied\" error for the failed listen.\r\n let queryId;\r\n if (!query) {\r\n queryId = 'default';\r\n }\r\n else {\r\n queryId = query.map(q => ObjectToUniqueKey(q)).join('$');\r\n }\r\n const listen = this.removeListen_(pathString, queryId);\r\n if (listen && listen.onComplete) {\r\n listen.onComplete('permission_denied');\r\n }\r\n }\r\n removeListen_(pathString, queryId) {\r\n const normalizedPathString = new Path(pathString).toString(); // normalize path.\r\n let listen;\r\n if (this.listens.has(normalizedPathString)) {\r\n const map = this.listens.get(normalizedPathString);\r\n listen = map.get(queryId);\r\n map.delete(queryId);\r\n if (map.size === 0) {\r\n this.listens.delete(normalizedPathString);\r\n }\r\n }\r\n else {\r\n // all listens for this path has already been removed\r\n listen = undefined;\r\n }\r\n return listen;\r\n }\r\n onAuthRevoked_(statusCode, explanation) {\r\n log('Auth token revoked: ' + statusCode + '/' + explanation);\r\n this.authToken_ = null;\r\n this.forceTokenRefresh_ = true;\r\n this.realtime_.close();\r\n if (statusCode === 'invalid_token' || statusCode === 'permission_denied') {\r\n // We'll wait a couple times before logging the warning / increasing the\r\n // retry period since oauth tokens will report as \"invalid\" if they're\r\n // just expired. Plus there may be transient issues that resolve themselves.\r\n this.invalidAuthTokenCount_++;\r\n if (this.invalidAuthTokenCount_ >= INVALID_TOKEN_THRESHOLD) {\r\n // Set a long reconnect delay because recovery is unlikely\r\n this.reconnectDelay_ = RECONNECT_MAX_DELAY_FOR_ADMINS;\r\n // Notify the auth token provider that the token is invalid, which will log\r\n // a warning\r\n this.authTokenProvider_.notifyForInvalidToken();\r\n }\r\n }\r\n }\r\n onAppCheckRevoked_(statusCode, explanation) {\r\n log('App check token revoked: ' + statusCode + '/' + explanation);\r\n this.appCheckToken_ = null;\r\n this.forceTokenRefresh_ = true;\r\n // Note: We don't close the connection as the developer may not have\r\n // enforcement enabled. The backend closes connections with enforcements.\r\n if (statusCode === 'invalid_token' || statusCode === 'permission_denied') {\r\n // We'll wait a couple times before logging the warning / increasing the\r\n // retry period since oauth tokens will report as \"invalid\" if they're\r\n // just expired. Plus there may be transient issues that resolve themselves.\r\n this.invalidAppCheckTokenCount_++;\r\n if (this.invalidAppCheckTokenCount_ >= INVALID_TOKEN_THRESHOLD) {\r\n this.appCheckTokenProvider_.notifyForInvalidToken();\r\n }\r\n }\r\n }\r\n onSecurityDebugPacket_(body) {\r\n if (this.securityDebugCallback_) {\r\n this.securityDebugCallback_(body);\r\n }\r\n else {\r\n if ('msg' in body) {\r\n console.log('FIREBASE: ' + body['msg'].replace('\\n', '\\nFIREBASE: '));\r\n }\r\n }\r\n }\r\n restoreState_() {\r\n //Re-authenticate ourselves if we have a credential stored.\r\n this.tryAuth();\r\n this.tryAppCheck();\r\n // Puts depend on having received the corresponding data update from the server before they complete, so we must\r\n // make sure to send listens before puts.\r\n for (const queries of this.listens.values()) {\r\n for (const listenSpec of queries.values()) {\r\n this.sendListen_(listenSpec);\r\n }\r\n }\r\n for (let i = 0; i < this.outstandingPuts_.length; i++) {\r\n if (this.outstandingPuts_[i]) {\r\n this.sendPut_(i);\r\n }\r\n }\r\n while (this.onDisconnectRequestQueue_.length) {\r\n const request = this.onDisconnectRequestQueue_.shift();\r\n this.sendOnDisconnect_(request.action, request.pathString, request.data, request.onComplete);\r\n }\r\n for (let i = 0; i < this.outstandingGets_.length; i++) {\r\n if (this.outstandingGets_[i]) {\r\n this.sendGet_(i);\r\n }\r\n }\r\n }\r\n /**\r\n * Sends client stats for first connection\r\n */\r\n sendConnectStats_() {\r\n const stats = {};\r\n let clientName = 'js';\r\n if (isNodeSdk()) {\r\n if (this.repoInfo_.nodeAdmin) {\r\n clientName = 'admin_node';\r\n }\r\n else {\r\n clientName = 'node';\r\n }\r\n }\r\n stats['sdk.' + clientName + '.' + SDK_VERSION.replace(/\\./g, '-')] = 1;\r\n if (isMobileCordova()) {\r\n stats['framework.cordova'] = 1;\r\n }\r\n else if (isReactNative()) {\r\n stats['framework.reactnative'] = 1;\r\n }\r\n this.reportStats(stats);\r\n }\r\n shouldReconnect_() {\r\n const online = OnlineMonitor.getInstance().currentlyOnline();\r\n return isEmpty(this.interruptReasons_) && online;\r\n }\r\n}\r\nPersistentConnection.nextPersistentConnectionId_ = 0;\r\n/**\r\n * Counter for number of connections created. Mainly used for tagging in the logs\r\n */\r\nPersistentConnection.nextConnectionId_ = 0;\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nclass NamedNode {\r\n constructor(name, node) {\r\n this.name = name;\r\n this.node = node;\r\n }\r\n static Wrap(name, node) {\r\n return new NamedNode(name, node);\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nclass Index {\r\n /**\r\n * @returns A standalone comparison function for\r\n * this index\r\n */\r\n getCompare() {\r\n return this.compare.bind(this);\r\n }\r\n /**\r\n * Given a before and after value for a node, determine if the indexed value has changed. Even if they are different,\r\n * it's possible that the changes are isolated to parts of the snapshot that are not indexed.\r\n *\r\n *\r\n * @returns True if the portion of the snapshot being indexed changed between oldNode and newNode\r\n */\r\n indexedValueChanged(oldNode, newNode) {\r\n const oldWrapped = new NamedNode(MIN_NAME, oldNode);\r\n const newWrapped = new NamedNode(MIN_NAME, newNode);\r\n return this.compare(oldWrapped, newWrapped) !== 0;\r\n }\r\n /**\r\n * @returns a node wrapper that will sort equal to or less than\r\n * any other node wrapper, using this index\r\n */\r\n minPost() {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n return NamedNode.MIN;\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nlet __EMPTY_NODE;\r\nclass KeyIndex extends Index {\r\n static get __EMPTY_NODE() {\r\n return __EMPTY_NODE;\r\n }\r\n static set __EMPTY_NODE(val) {\r\n __EMPTY_NODE = val;\r\n }\r\n compare(a, b) {\r\n return nameCompare(a.name, b.name);\r\n }\r\n isDefinedOn(node) {\r\n // We could probably return true here (since every node has a key), but it's never called\r\n // so just leaving unimplemented for now.\r\n throw assertionError('KeyIndex.isDefinedOn not expected to be called.');\r\n }\r\n indexedValueChanged(oldNode, newNode) {\r\n return false; // The key for a node never changes.\r\n }\r\n minPost() {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n return NamedNode.MIN;\r\n }\r\n maxPost() {\r\n // TODO: This should really be created once and cached in a static property, but\r\n // NamedNode isn't defined yet, so I can't use it in a static. Bleh.\r\n return new NamedNode(MAX_NAME, __EMPTY_NODE);\r\n }\r\n makePost(indexValue, name) {\r\n assert(typeof indexValue === 'string', 'KeyIndex indexValue must always be a string.');\r\n // We just use empty node, but it'll never be compared, since our comparator only looks at name.\r\n return new NamedNode(indexValue, __EMPTY_NODE);\r\n }\r\n /**\r\n * @returns String representation for inclusion in a query spec\r\n */\r\n toString() {\r\n return '.key';\r\n }\r\n}\r\nconst KEY_INDEX = new KeyIndex();\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * An iterator over an LLRBNode.\r\n */\r\nclass SortedMapIterator {\r\n /**\r\n * @param node - Node to iterate.\r\n * @param isReverse_ - Whether or not to iterate in reverse\r\n */\r\n constructor(node, startKey, comparator, isReverse_, resultGenerator_ = null) {\r\n this.isReverse_ = isReverse_;\r\n this.resultGenerator_ = resultGenerator_;\r\n this.nodeStack_ = [];\r\n let cmp = 1;\r\n while (!node.isEmpty()) {\r\n node = node;\r\n cmp = startKey ? comparator(node.key, startKey) : 1;\r\n // flip the comparison if we're going in reverse\r\n if (isReverse_) {\r\n cmp *= -1;\r\n }\r\n if (cmp < 0) {\r\n // This node is less than our start key. ignore it\r\n if (this.isReverse_) {\r\n node = node.left;\r\n }\r\n else {\r\n node = node.right;\r\n }\r\n }\r\n else if (cmp === 0) {\r\n // This node is exactly equal to our start key. Push it on the stack, but stop iterating;\r\n this.nodeStack_.push(node);\r\n break;\r\n }\r\n else {\r\n // This node is greater than our start key, add it to the stack and move to the next one\r\n this.nodeStack_.push(node);\r\n if (this.isReverse_) {\r\n node = node.right;\r\n }\r\n else {\r\n node = node.left;\r\n }\r\n }\r\n }\r\n }\r\n getNext() {\r\n if (this.nodeStack_.length === 0) {\r\n return null;\r\n }\r\n let node = this.nodeStack_.pop();\r\n let result;\r\n if (this.resultGenerator_) {\r\n result = this.resultGenerator_(node.key, node.value);\r\n }\r\n else {\r\n result = { key: node.key, value: node.value };\r\n }\r\n if (this.isReverse_) {\r\n node = node.left;\r\n while (!node.isEmpty()) {\r\n this.nodeStack_.push(node);\r\n node = node.right;\r\n }\r\n }\r\n else {\r\n node = node.right;\r\n while (!node.isEmpty()) {\r\n this.nodeStack_.push(node);\r\n node = node.left;\r\n }\r\n }\r\n return result;\r\n }\r\n hasNext() {\r\n return this.nodeStack_.length > 0;\r\n }\r\n peek() {\r\n if (this.nodeStack_.length === 0) {\r\n return null;\r\n }\r\n const node = this.nodeStack_[this.nodeStack_.length - 1];\r\n if (this.resultGenerator_) {\r\n return this.resultGenerator_(node.key, node.value);\r\n }\r\n else {\r\n return { key: node.key, value: node.value };\r\n }\r\n }\r\n}\r\n/**\r\n * Represents a node in a Left-leaning Red-Black tree.\r\n */\r\nclass LLRBNode {\r\n /**\r\n * @param key - Key associated with this node.\r\n * @param value - Value associated with this node.\r\n * @param color - Whether this node is red.\r\n * @param left - Left child.\r\n * @param right - Right child.\r\n */\r\n constructor(key, value, color, left, right) {\r\n this.key = key;\r\n this.value = value;\r\n this.color = color != null ? color : LLRBNode.RED;\r\n this.left =\r\n left != null ? left : SortedMap.EMPTY_NODE;\r\n this.right =\r\n right != null ? right : SortedMap.EMPTY_NODE;\r\n }\r\n /**\r\n * Returns a copy of the current node, optionally replacing pieces of it.\r\n *\r\n * @param key - New key for the node, or null.\r\n * @param value - New value for the node, or null.\r\n * @param color - New color for the node, or null.\r\n * @param left - New left child for the node, or null.\r\n * @param right - New right child for the node, or null.\r\n * @returns The node copy.\r\n */\r\n copy(key, value, color, left, right) {\r\n return new LLRBNode(key != null ? key : this.key, value != null ? value : this.value, color != null ? color : this.color, left != null ? left : this.left, right != null ? right : this.right);\r\n }\r\n /**\r\n * @returns The total number of nodes in the tree.\r\n */\r\n count() {\r\n return this.left.count() + 1 + this.right.count();\r\n }\r\n /**\r\n * @returns True if the tree is empty.\r\n */\r\n isEmpty() {\r\n return false;\r\n }\r\n /**\r\n * Traverses the tree in key order and calls the specified action function\r\n * for each node.\r\n *\r\n * @param action - Callback function to be called for each\r\n * node. If it returns true, traversal is aborted.\r\n * @returns The first truthy value returned by action, or the last falsey\r\n * value returned by action\r\n */\r\n inorderTraversal(action) {\r\n return (this.left.inorderTraversal(action) ||\r\n !!action(this.key, this.value) ||\r\n this.right.inorderTraversal(action));\r\n }\r\n /**\r\n * Traverses the tree in reverse key order and calls the specified action function\r\n * for each node.\r\n *\r\n * @param action - Callback function to be called for each\r\n * node. If it returns true, traversal is aborted.\r\n * @returns True if traversal was aborted.\r\n */\r\n reverseTraversal(action) {\r\n return (this.right.reverseTraversal(action) ||\r\n action(this.key, this.value) ||\r\n this.left.reverseTraversal(action));\r\n }\r\n /**\r\n * @returns The minimum node in the tree.\r\n */\r\n min_() {\r\n if (this.left.isEmpty()) {\r\n return this;\r\n }\r\n else {\r\n return this.left.min_();\r\n }\r\n }\r\n /**\r\n * @returns The maximum key in the tree.\r\n */\r\n minKey() {\r\n return this.min_().key;\r\n }\r\n /**\r\n * @returns The maximum key in the tree.\r\n */\r\n maxKey() {\r\n if (this.right.isEmpty()) {\r\n return this.key;\r\n }\r\n else {\r\n return this.right.maxKey();\r\n }\r\n }\r\n /**\r\n * @param key - Key to insert.\r\n * @param value - Value to insert.\r\n * @param comparator - Comparator.\r\n * @returns New tree, with the key/value added.\r\n */\r\n insert(key, value, comparator) {\r\n let n = this;\r\n const cmp = comparator(key, n.key);\r\n if (cmp < 0) {\r\n n = n.copy(null, null, null, n.left.insert(key, value, comparator), null);\r\n }\r\n else if (cmp === 0) {\r\n n = n.copy(null, value, null, null, null);\r\n }\r\n else {\r\n n = n.copy(null, null, null, null, n.right.insert(key, value, comparator));\r\n }\r\n return n.fixUp_();\r\n }\r\n /**\r\n * @returns New tree, with the minimum key removed.\r\n */\r\n removeMin_() {\r\n if (this.left.isEmpty()) {\r\n return SortedMap.EMPTY_NODE;\r\n }\r\n let n = this;\r\n if (!n.left.isRed_() && !n.left.left.isRed_()) {\r\n n = n.moveRedLeft_();\r\n }\r\n n = n.copy(null, null, null, n.left.removeMin_(), null);\r\n return n.fixUp_();\r\n }\r\n /**\r\n * @param key - The key of the item to remove.\r\n * @param comparator - Comparator.\r\n * @returns New tree, with the specified item removed.\r\n */\r\n remove(key, comparator) {\r\n let n, smallest;\r\n n = this;\r\n if (comparator(key, n.key) < 0) {\r\n if (!n.left.isEmpty() && !n.left.isRed_() && !n.left.left.isRed_()) {\r\n n = n.moveRedLeft_();\r\n }\r\n n = n.copy(null, null, null, n.left.remove(key, comparator), null);\r\n }\r\n else {\r\n if (n.left.isRed_()) {\r\n n = n.rotateRight_();\r\n }\r\n if (!n.right.isEmpty() && !n.right.isRed_() && !n.right.left.isRed_()) {\r\n n = n.moveRedRight_();\r\n }\r\n if (comparator(key, n.key) === 0) {\r\n if (n.right.isEmpty()) {\r\n return SortedMap.EMPTY_NODE;\r\n }\r\n else {\r\n smallest = n.right.min_();\r\n n = n.copy(smallest.key, smallest.value, null, null, n.right.removeMin_());\r\n }\r\n }\r\n n = n.copy(null, null, null, null, n.right.remove(key, comparator));\r\n }\r\n return n.fixUp_();\r\n }\r\n /**\r\n * @returns Whether this is a RED node.\r\n */\r\n isRed_() {\r\n return this.color;\r\n }\r\n /**\r\n * @returns New tree after performing any needed rotations.\r\n */\r\n fixUp_() {\r\n let n = this;\r\n if (n.right.isRed_() && !n.left.isRed_()) {\r\n n = n.rotateLeft_();\r\n }\r\n if (n.left.isRed_() && n.left.left.isRed_()) {\r\n n = n.rotateRight_();\r\n }\r\n if (n.left.isRed_() && n.right.isRed_()) {\r\n n = n.colorFlip_();\r\n }\r\n return n;\r\n }\r\n /**\r\n * @returns New tree, after moveRedLeft.\r\n */\r\n moveRedLeft_() {\r\n let n = this.colorFlip_();\r\n if (n.right.left.isRed_()) {\r\n n = n.copy(null, null, null, null, n.right.rotateRight_());\r\n n = n.rotateLeft_();\r\n n = n.colorFlip_();\r\n }\r\n return n;\r\n }\r\n /**\r\n * @returns New tree, after moveRedRight.\r\n */\r\n moveRedRight_() {\r\n let n = this.colorFlip_();\r\n if (n.left.left.isRed_()) {\r\n n = n.rotateRight_();\r\n n = n.colorFlip_();\r\n }\r\n return n;\r\n }\r\n /**\r\n * @returns New tree, after rotateLeft.\r\n */\r\n rotateLeft_() {\r\n const nl = this.copy(null, null, LLRBNode.RED, null, this.right.left);\r\n return this.right.copy(null, null, this.color, nl, null);\r\n }\r\n /**\r\n * @returns New tree, after rotateRight.\r\n */\r\n rotateRight_() {\r\n const nr = this.copy(null, null, LLRBNode.RED, this.left.right, null);\r\n return this.left.copy(null, null, this.color, null, nr);\r\n }\r\n /**\r\n * @returns Newt ree, after colorFlip.\r\n */\r\n colorFlip_() {\r\n const left = this.left.copy(null, null, !this.left.color, null, null);\r\n const right = this.right.copy(null, null, !this.right.color, null, null);\r\n return this.copy(null, null, !this.color, left, right);\r\n }\r\n /**\r\n * For testing.\r\n *\r\n * @returns True if all is well.\r\n */\r\n checkMaxDepth_() {\r\n const blackDepth = this.check_();\r\n return Math.pow(2.0, blackDepth) <= this.count() + 1;\r\n }\r\n check_() {\r\n if (this.isRed_() && this.left.isRed_()) {\r\n throw new Error('Red node has red child(' + this.key + ',' + this.value + ')');\r\n }\r\n if (this.right.isRed_()) {\r\n throw new Error('Right child of (' + this.key + ',' + this.value + ') is red');\r\n }\r\n const blackDepth = this.left.check_();\r\n if (blackDepth !== this.right.check_()) {\r\n throw new Error('Black depths differ');\r\n }\r\n else {\r\n return blackDepth + (this.isRed_() ? 0 : 1);\r\n }\r\n }\r\n}\r\nLLRBNode.RED = true;\r\nLLRBNode.BLACK = false;\r\n/**\r\n * Represents an empty node (a leaf node in the Red-Black Tree).\r\n */\r\nclass LLRBEmptyNode {\r\n /**\r\n * Returns a copy of the current node.\r\n *\r\n * @returns The node copy.\r\n */\r\n copy(key, value, color, left, right) {\r\n return this;\r\n }\r\n /**\r\n * Returns a copy of the tree, with the specified key/value added.\r\n *\r\n * @param key - Key to be added.\r\n * @param value - Value to be added.\r\n * @param comparator - Comparator.\r\n * @returns New tree, with item added.\r\n */\r\n insert(key, value, comparator) {\r\n return new LLRBNode(key, value, null);\r\n }\r\n /**\r\n * Returns a copy of the tree, with the specified key removed.\r\n *\r\n * @param key - The key to remove.\r\n * @param comparator - Comparator.\r\n * @returns New tree, with item removed.\r\n */\r\n remove(key, comparator) {\r\n return this;\r\n }\r\n /**\r\n * @returns The total number of nodes in the tree.\r\n */\r\n count() {\r\n return 0;\r\n }\r\n /**\r\n * @returns True if the tree is empty.\r\n */\r\n isEmpty() {\r\n return true;\r\n }\r\n /**\r\n * Traverses the tree in key order and calls the specified action function\r\n * for each node.\r\n *\r\n * @param action - Callback function to be called for each\r\n * node. If it returns true, traversal is aborted.\r\n * @returns True if traversal was aborted.\r\n */\r\n inorderTraversal(action) {\r\n return false;\r\n }\r\n /**\r\n * Traverses the tree in reverse key order and calls the specified action function\r\n * for each node.\r\n *\r\n * @param action - Callback function to be called for each\r\n * node. If it returns true, traversal is aborted.\r\n * @returns True if traversal was aborted.\r\n */\r\n reverseTraversal(action) {\r\n return false;\r\n }\r\n minKey() {\r\n return null;\r\n }\r\n maxKey() {\r\n return null;\r\n }\r\n check_() {\r\n return 0;\r\n }\r\n /**\r\n * @returns Whether this node is red.\r\n */\r\n isRed_() {\r\n return false;\r\n }\r\n}\r\n/**\r\n * An immutable sorted map implementation, based on a Left-leaning Red-Black\r\n * tree.\r\n */\r\nclass SortedMap {\r\n /**\r\n * @param comparator_ - Key comparator.\r\n * @param root_ - Optional root node for the map.\r\n */\r\n constructor(comparator_, root_ = SortedMap.EMPTY_NODE) {\r\n this.comparator_ = comparator_;\r\n this.root_ = root_;\r\n }\r\n /**\r\n * Returns a copy of the map, with the specified key/value added or replaced.\r\n * (TODO: We should perhaps rename this method to 'put')\r\n *\r\n * @param key - Key to be added.\r\n * @param value - Value to be added.\r\n * @returns New map, with item added.\r\n */\r\n insert(key, value) {\r\n return new SortedMap(this.comparator_, this.root_\r\n .insert(key, value, this.comparator_)\r\n .copy(null, null, LLRBNode.BLACK, null, null));\r\n }\r\n /**\r\n * Returns a copy of the map, with the specified key removed.\r\n *\r\n * @param key - The key to remove.\r\n * @returns New map, with item removed.\r\n */\r\n remove(key) {\r\n return new SortedMap(this.comparator_, this.root_\r\n .remove(key, this.comparator_)\r\n .copy(null, null, LLRBNode.BLACK, null, null));\r\n }\r\n /**\r\n * Returns the value of the node with the given key, or null.\r\n *\r\n * @param key - The key to look up.\r\n * @returns The value of the node with the given key, or null if the\r\n * key doesn't exist.\r\n */\r\n get(key) {\r\n let cmp;\r\n let node = this.root_;\r\n while (!node.isEmpty()) {\r\n cmp = this.comparator_(key, node.key);\r\n if (cmp === 0) {\r\n return node.value;\r\n }\r\n else if (cmp < 0) {\r\n node = node.left;\r\n }\r\n else if (cmp > 0) {\r\n node = node.right;\r\n }\r\n }\r\n return null;\r\n }\r\n /**\r\n * Returns the key of the item *before* the specified key, or null if key is the first item.\r\n * @param key - The key to find the predecessor of\r\n * @returns The predecessor key.\r\n */\r\n getPredecessorKey(key) {\r\n let cmp, node = this.root_, rightParent = null;\r\n while (!node.isEmpty()) {\r\n cmp = this.comparator_(key, node.key);\r\n if (cmp === 0) {\r\n if (!node.left.isEmpty()) {\r\n node = node.left;\r\n while (!node.right.isEmpty()) {\r\n node = node.right;\r\n }\r\n return node.key;\r\n }\r\n else if (rightParent) {\r\n return rightParent.key;\r\n }\r\n else {\r\n return null; // first item.\r\n }\r\n }\r\n else if (cmp < 0) {\r\n node = node.left;\r\n }\r\n else if (cmp > 0) {\r\n rightParent = node;\r\n node = node.right;\r\n }\r\n }\r\n throw new Error('Attempted to find predecessor key for a nonexistent key. What gives?');\r\n }\r\n /**\r\n * @returns True if the map is empty.\r\n */\r\n isEmpty() {\r\n return this.root_.isEmpty();\r\n }\r\n /**\r\n * @returns The total number of nodes in the map.\r\n */\r\n count() {\r\n return this.root_.count();\r\n }\r\n /**\r\n * @returns The minimum key in the map.\r\n */\r\n minKey() {\r\n return this.root_.minKey();\r\n }\r\n /**\r\n * @returns The maximum key in the map.\r\n */\r\n maxKey() {\r\n return this.root_.maxKey();\r\n }\r\n /**\r\n * Traverses the map in key order and calls the specified action function\r\n * for each key/value pair.\r\n *\r\n * @param action - Callback function to be called\r\n * for each key/value pair. If action returns true, traversal is aborted.\r\n * @returns The first truthy value returned by action, or the last falsey\r\n * value returned by action\r\n */\r\n inorderTraversal(action) {\r\n return this.root_.inorderTraversal(action);\r\n }\r\n /**\r\n * Traverses the map in reverse key order and calls the specified action function\r\n * for each key/value pair.\r\n *\r\n * @param action - Callback function to be called\r\n * for each key/value pair. If action returns true, traversal is aborted.\r\n * @returns True if the traversal was aborted.\r\n */\r\n reverseTraversal(action) {\r\n return this.root_.reverseTraversal(action);\r\n }\r\n /**\r\n * Returns an iterator over the SortedMap.\r\n * @returns The iterator.\r\n */\r\n getIterator(resultGenerator) {\r\n return new SortedMapIterator(this.root_, null, this.comparator_, false, resultGenerator);\r\n }\r\n getIteratorFrom(key, resultGenerator) {\r\n return new SortedMapIterator(this.root_, key, this.comparator_, false, resultGenerator);\r\n }\r\n getReverseIteratorFrom(key, resultGenerator) {\r\n return new SortedMapIterator(this.root_, key, this.comparator_, true, resultGenerator);\r\n }\r\n getReverseIterator(resultGenerator) {\r\n return new SortedMapIterator(this.root_, null, this.comparator_, true, resultGenerator);\r\n }\r\n}\r\n/**\r\n * Always use the same empty node, to reduce memory.\r\n */\r\nSortedMap.EMPTY_NODE = new LLRBEmptyNode();\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nfunction NAME_ONLY_COMPARATOR(left, right) {\r\n return nameCompare(left.name, right.name);\r\n}\r\nfunction NAME_COMPARATOR(left, right) {\r\n return nameCompare(left, right);\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nlet MAX_NODE$2;\r\nfunction setMaxNode$1(val) {\r\n MAX_NODE$2 = val;\r\n}\r\nconst priorityHashText = function (priority) {\r\n if (typeof priority === 'number') {\r\n return 'number:' + doubleToIEEE754String(priority);\r\n }\r\n else {\r\n return 'string:' + priority;\r\n }\r\n};\r\n/**\r\n * Validates that a priority snapshot Node is valid.\r\n */\r\nconst validatePriorityNode = function (priorityNode) {\r\n if (priorityNode.isLeafNode()) {\r\n const val = priorityNode.val();\r\n assert(typeof val === 'string' ||\r\n typeof val === 'number' ||\r\n (typeof val === 'object' && contains(val, '.sv')), 'Priority must be a string or number.');\r\n }\r\n else {\r\n assert(priorityNode === MAX_NODE$2 || priorityNode.isEmpty(), 'priority of unexpected type.');\r\n }\r\n // Don't call getPriority() on MAX_NODE to avoid hitting assertion.\r\n assert(priorityNode === MAX_NODE$2 || priorityNode.getPriority().isEmpty(), \"Priority nodes can't have a priority of their own.\");\r\n};\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nlet __childrenNodeConstructor;\r\n/**\r\n * LeafNode is a class for storing leaf nodes in a DataSnapshot. It\r\n * implements Node and stores the value of the node (a string,\r\n * number, or boolean) accessible via getValue().\r\n */\r\nclass LeafNode {\r\n /**\r\n * @param value_ - The value to store in this leaf node. The object type is\r\n * possible in the event of a deferred value\r\n * @param priorityNode_ - The priority of this node.\r\n */\r\n constructor(value_, priorityNode_ = LeafNode.__childrenNodeConstructor.EMPTY_NODE) {\r\n this.value_ = value_;\r\n this.priorityNode_ = priorityNode_;\r\n this.lazyHash_ = null;\r\n assert(this.value_ !== undefined && this.value_ !== null, \"LeafNode shouldn't be created with null/undefined value.\");\r\n validatePriorityNode(this.priorityNode_);\r\n }\r\n static set __childrenNodeConstructor(val) {\r\n __childrenNodeConstructor = val;\r\n }\r\n static get __childrenNodeConstructor() {\r\n return __childrenNodeConstructor;\r\n }\r\n /** @inheritDoc */\r\n isLeafNode() {\r\n return true;\r\n }\r\n /** @inheritDoc */\r\n getPriority() {\r\n return this.priorityNode_;\r\n }\r\n /** @inheritDoc */\r\n updatePriority(newPriorityNode) {\r\n return new LeafNode(this.value_, newPriorityNode);\r\n }\r\n /** @inheritDoc */\r\n getImmediateChild(childName) {\r\n // Hack to treat priority as a regular child\r\n if (childName === '.priority') {\r\n return this.priorityNode_;\r\n }\r\n else {\r\n return LeafNode.__childrenNodeConstructor.EMPTY_NODE;\r\n }\r\n }\r\n /** @inheritDoc */\r\n getChild(path) {\r\n if (pathIsEmpty(path)) {\r\n return this;\r\n }\r\n else if (pathGetFront(path) === '.priority') {\r\n return this.priorityNode_;\r\n }\r\n else {\r\n return LeafNode.__childrenNodeConstructor.EMPTY_NODE;\r\n }\r\n }\r\n hasChild() {\r\n return false;\r\n }\r\n /** @inheritDoc */\r\n getPredecessorChildName(childName, childNode) {\r\n return null;\r\n }\r\n /** @inheritDoc */\r\n updateImmediateChild(childName, newChildNode) {\r\n if (childName === '.priority') {\r\n return this.updatePriority(newChildNode);\r\n }\r\n else if (newChildNode.isEmpty() && childName !== '.priority') {\r\n return this;\r\n }\r\n else {\r\n return LeafNode.__childrenNodeConstructor.EMPTY_NODE.updateImmediateChild(childName, newChildNode).updatePriority(this.priorityNode_);\r\n }\r\n }\r\n /** @inheritDoc */\r\n updateChild(path, newChildNode) {\r\n const front = pathGetFront(path);\r\n if (front === null) {\r\n return newChildNode;\r\n }\r\n else if (newChildNode.isEmpty() && front !== '.priority') {\r\n return this;\r\n }\r\n else {\r\n assert(front !== '.priority' || pathGetLength(path) === 1, '.priority must be the last token in a path');\r\n return this.updateImmediateChild(front, LeafNode.__childrenNodeConstructor.EMPTY_NODE.updateChild(pathPopFront(path), newChildNode));\r\n }\r\n }\r\n /** @inheritDoc */\r\n isEmpty() {\r\n return false;\r\n }\r\n /** @inheritDoc */\r\n numChildren() {\r\n return 0;\r\n }\r\n /** @inheritDoc */\r\n forEachChild(index, action) {\r\n return false;\r\n }\r\n val(exportFormat) {\r\n if (exportFormat && !this.getPriority().isEmpty()) {\r\n return {\r\n '.value': this.getValue(),\r\n '.priority': this.getPriority().val()\r\n };\r\n }\r\n else {\r\n return this.getValue();\r\n }\r\n }\r\n /** @inheritDoc */\r\n hash() {\r\n if (this.lazyHash_ === null) {\r\n let toHash = '';\r\n if (!this.priorityNode_.isEmpty()) {\r\n toHash +=\r\n 'priority:' +\r\n priorityHashText(this.priorityNode_.val()) +\r\n ':';\r\n }\r\n const type = typeof this.value_;\r\n toHash += type + ':';\r\n if (type === 'number') {\r\n toHash += doubleToIEEE754String(this.value_);\r\n }\r\n else {\r\n toHash += this.value_;\r\n }\r\n this.lazyHash_ = sha1(toHash);\r\n }\r\n return this.lazyHash_;\r\n }\r\n /**\r\n * Returns the value of the leaf node.\r\n * @returns The value of the node.\r\n */\r\n getValue() {\r\n return this.value_;\r\n }\r\n compareTo(other) {\r\n if (other === LeafNode.__childrenNodeConstructor.EMPTY_NODE) {\r\n return 1;\r\n }\r\n else if (other instanceof LeafNode.__childrenNodeConstructor) {\r\n return -1;\r\n }\r\n else {\r\n assert(other.isLeafNode(), 'Unknown node type');\r\n return this.compareToLeafNode_(other);\r\n }\r\n }\r\n /**\r\n * Comparison specifically for two leaf nodes\r\n */\r\n compareToLeafNode_(otherLeaf) {\r\n const otherLeafType = typeof otherLeaf.value_;\r\n const thisLeafType = typeof this.value_;\r\n const otherIndex = LeafNode.VALUE_TYPE_ORDER.indexOf(otherLeafType);\r\n const thisIndex = LeafNode.VALUE_TYPE_ORDER.indexOf(thisLeafType);\r\n assert(otherIndex >= 0, 'Unknown leaf type: ' + otherLeafType);\r\n assert(thisIndex >= 0, 'Unknown leaf type: ' + thisLeafType);\r\n if (otherIndex === thisIndex) {\r\n // Same type, compare values\r\n if (thisLeafType === 'object') {\r\n // Deferred value nodes are all equal, but we should also never get to this point...\r\n return 0;\r\n }\r\n else {\r\n // Note that this works because true > false, all others are number or string comparisons\r\n if (this.value_ < otherLeaf.value_) {\r\n return -1;\r\n }\r\n else if (this.value_ === otherLeaf.value_) {\r\n return 0;\r\n }\r\n else {\r\n return 1;\r\n }\r\n }\r\n }\r\n else {\r\n return thisIndex - otherIndex;\r\n }\r\n }\r\n withIndex() {\r\n return this;\r\n }\r\n isIndexed() {\r\n return true;\r\n }\r\n equals(other) {\r\n if (other === this) {\r\n return true;\r\n }\r\n else if (other.isLeafNode()) {\r\n const otherLeaf = other;\r\n return (this.value_ === otherLeaf.value_ &&\r\n this.priorityNode_.equals(otherLeaf.priorityNode_));\r\n }\r\n else {\r\n return false;\r\n }\r\n }\r\n}\r\n/**\r\n * The sort order for comparing leaf nodes of different types. If two leaf nodes have\r\n * the same type, the comparison falls back to their value\r\n */\r\nLeafNode.VALUE_TYPE_ORDER = ['object', 'boolean', 'number', 'string'];\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nlet nodeFromJSON$1;\r\nlet MAX_NODE$1;\r\nfunction setNodeFromJSON(val) {\r\n nodeFromJSON$1 = val;\r\n}\r\nfunction setMaxNode(val) {\r\n MAX_NODE$1 = val;\r\n}\r\nclass PriorityIndex extends Index {\r\n compare(a, b) {\r\n const aPriority = a.node.getPriority();\r\n const bPriority = b.node.getPriority();\r\n const indexCmp = aPriority.compareTo(bPriority);\r\n if (indexCmp === 0) {\r\n return nameCompare(a.name, b.name);\r\n }\r\n else {\r\n return indexCmp;\r\n }\r\n }\r\n isDefinedOn(node) {\r\n return !node.getPriority().isEmpty();\r\n }\r\n indexedValueChanged(oldNode, newNode) {\r\n return !oldNode.getPriority().equals(newNode.getPriority());\r\n }\r\n minPost() {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n return NamedNode.MIN;\r\n }\r\n maxPost() {\r\n return new NamedNode(MAX_NAME, new LeafNode('[PRIORITY-POST]', MAX_NODE$1));\r\n }\r\n makePost(indexValue, name) {\r\n const priorityNode = nodeFromJSON$1(indexValue);\r\n return new NamedNode(name, new LeafNode('[PRIORITY-POST]', priorityNode));\r\n }\r\n /**\r\n * @returns String representation for inclusion in a query spec\r\n */\r\n toString() {\r\n return '.priority';\r\n }\r\n}\r\nconst PRIORITY_INDEX = new PriorityIndex();\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nconst LOG_2 = Math.log(2);\r\nclass Base12Num {\r\n constructor(length) {\r\n const logBase2 = (num) => \r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n parseInt((Math.log(num) / LOG_2), 10);\r\n const bitMask = (bits) => parseInt(Array(bits + 1).join('1'), 2);\r\n this.count = logBase2(length + 1);\r\n this.current_ = this.count - 1;\r\n const mask = bitMask(this.count);\r\n this.bits_ = (length + 1) & mask;\r\n }\r\n nextBitIsOne() {\r\n //noinspection JSBitwiseOperatorUsage\r\n const result = !(this.bits_ & (0x1 << this.current_));\r\n this.current_--;\r\n return result;\r\n }\r\n}\r\n/**\r\n * Takes a list of child nodes and constructs a SortedSet using the given comparison\r\n * function\r\n *\r\n * Uses the algorithm described in the paper linked here:\r\n * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.46.1458\r\n *\r\n * @param childList - Unsorted list of children\r\n * @param cmp - The comparison method to be used\r\n * @param keyFn - An optional function to extract K from a node wrapper, if K's\r\n * type is not NamedNode\r\n * @param mapSortFn - An optional override for comparator used by the generated sorted map\r\n */\r\nconst buildChildSet = function (childList, cmp, keyFn, mapSortFn) {\r\n childList.sort(cmp);\r\n const buildBalancedTree = function (low, high) {\r\n const length = high - low;\r\n let namedNode;\r\n let key;\r\n if (length === 0) {\r\n return null;\r\n }\r\n else if (length === 1) {\r\n namedNode = childList[low];\r\n key = keyFn ? keyFn(namedNode) : namedNode;\r\n return new LLRBNode(key, namedNode.node, LLRBNode.BLACK, null, null);\r\n }\r\n else {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n const middle = parseInt((length / 2), 10) + low;\r\n const left = buildBalancedTree(low, middle);\r\n const right = buildBalancedTree(middle + 1, high);\r\n namedNode = childList[middle];\r\n key = keyFn ? keyFn(namedNode) : namedNode;\r\n return new LLRBNode(key, namedNode.node, LLRBNode.BLACK, left, right);\r\n }\r\n };\r\n const buildFrom12Array = function (base12) {\r\n let node = null;\r\n let root = null;\r\n let index = childList.length;\r\n const buildPennant = function (chunkSize, color) {\r\n const low = index - chunkSize;\r\n const high = index;\r\n index -= chunkSize;\r\n const childTree = buildBalancedTree(low + 1, high);\r\n const namedNode = childList[low];\r\n const key = keyFn ? keyFn(namedNode) : namedNode;\r\n attachPennant(new LLRBNode(key, namedNode.node, color, null, childTree));\r\n };\r\n const attachPennant = function (pennant) {\r\n if (node) {\r\n node.left = pennant;\r\n node = pennant;\r\n }\r\n else {\r\n root = pennant;\r\n node = pennant;\r\n }\r\n };\r\n for (let i = 0; i < base12.count; ++i) {\r\n const isOne = base12.nextBitIsOne();\r\n // The number of nodes taken in each slice is 2^(arr.length - (i + 1))\r\n const chunkSize = Math.pow(2, base12.count - (i + 1));\r\n if (isOne) {\r\n buildPennant(chunkSize, LLRBNode.BLACK);\r\n }\r\n else {\r\n // current == 2\r\n buildPennant(chunkSize, LLRBNode.BLACK);\r\n buildPennant(chunkSize, LLRBNode.RED);\r\n }\r\n }\r\n return root;\r\n };\r\n const base12 = new Base12Num(childList.length);\r\n const root = buildFrom12Array(base12);\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n return new SortedMap(mapSortFn || cmp, root);\r\n};\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nlet _defaultIndexMap;\r\nconst fallbackObject = {};\r\nclass IndexMap {\r\n constructor(indexes_, indexSet_) {\r\n this.indexes_ = indexes_;\r\n this.indexSet_ = indexSet_;\r\n }\r\n /**\r\n * The default IndexMap for nodes without a priority\r\n */\r\n static get Default() {\r\n assert(fallbackObject && PRIORITY_INDEX, 'ChildrenNode.ts has not been loaded');\r\n _defaultIndexMap =\r\n _defaultIndexMap ||\r\n new IndexMap({ '.priority': fallbackObject }, { '.priority': PRIORITY_INDEX });\r\n return _defaultIndexMap;\r\n }\r\n get(indexKey) {\r\n const sortedMap = safeGet(this.indexes_, indexKey);\r\n if (!sortedMap) {\r\n throw new Error('No index defined for ' + indexKey);\r\n }\r\n if (sortedMap instanceof SortedMap) {\r\n return sortedMap;\r\n }\r\n else {\r\n // The index exists, but it falls back to just name comparison. Return null so that the calling code uses the\r\n // regular child map\r\n return null;\r\n }\r\n }\r\n hasIndex(indexDefinition) {\r\n return contains(this.indexSet_, indexDefinition.toString());\r\n }\r\n addIndex(indexDefinition, existingChildren) {\r\n assert(indexDefinition !== KEY_INDEX, \"KeyIndex always exists and isn't meant to be added to the IndexMap.\");\r\n const childList = [];\r\n let sawIndexedValue = false;\r\n const iter = existingChildren.getIterator(NamedNode.Wrap);\r\n let next = iter.getNext();\r\n while (next) {\r\n sawIndexedValue =\r\n sawIndexedValue || indexDefinition.isDefinedOn(next.node);\r\n childList.push(next);\r\n next = iter.getNext();\r\n }\r\n let newIndex;\r\n if (sawIndexedValue) {\r\n newIndex = buildChildSet(childList, indexDefinition.getCompare());\r\n }\r\n else {\r\n newIndex = fallbackObject;\r\n }\r\n const indexName = indexDefinition.toString();\r\n const newIndexSet = Object.assign({}, this.indexSet_);\r\n newIndexSet[indexName] = indexDefinition;\r\n const newIndexes = Object.assign({}, this.indexes_);\r\n newIndexes[indexName] = newIndex;\r\n return new IndexMap(newIndexes, newIndexSet);\r\n }\r\n /**\r\n * Ensure that this node is properly tracked in any indexes that we're maintaining\r\n */\r\n addToIndexes(namedNode, existingChildren) {\r\n const newIndexes = map(this.indexes_, (indexedChildren, indexName) => {\r\n const index = safeGet(this.indexSet_, indexName);\r\n assert(index, 'Missing index implementation for ' + indexName);\r\n if (indexedChildren === fallbackObject) {\r\n // Check to see if we need to index everything\r\n if (index.isDefinedOn(namedNode.node)) {\r\n // We need to build this index\r\n const childList = [];\r\n const iter = existingChildren.getIterator(NamedNode.Wrap);\r\n let next = iter.getNext();\r\n while (next) {\r\n if (next.name !== namedNode.name) {\r\n childList.push(next);\r\n }\r\n next = iter.getNext();\r\n }\r\n childList.push(namedNode);\r\n return buildChildSet(childList, index.getCompare());\r\n }\r\n else {\r\n // No change, this remains a fallback\r\n return fallbackObject;\r\n }\r\n }\r\n else {\r\n const existingSnap = existingChildren.get(namedNode.name);\r\n let newChildren = indexedChildren;\r\n if (existingSnap) {\r\n newChildren = newChildren.remove(new NamedNode(namedNode.name, existingSnap));\r\n }\r\n return newChildren.insert(namedNode, namedNode.node);\r\n }\r\n });\r\n return new IndexMap(newIndexes, this.indexSet_);\r\n }\r\n /**\r\n * Create a new IndexMap instance with the given value removed\r\n */\r\n removeFromIndexes(namedNode, existingChildren) {\r\n const newIndexes = map(this.indexes_, (indexedChildren) => {\r\n if (indexedChildren === fallbackObject) {\r\n // This is the fallback. Just return it, nothing to do in this case\r\n return indexedChildren;\r\n }\r\n else {\r\n const existingSnap = existingChildren.get(namedNode.name);\r\n if (existingSnap) {\r\n return indexedChildren.remove(new NamedNode(namedNode.name, existingSnap));\r\n }\r\n else {\r\n // No record of this child\r\n return indexedChildren;\r\n }\r\n }\r\n });\r\n return new IndexMap(newIndexes, this.indexSet_);\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n// TODO: For memory savings, don't store priorityNode_ if it's empty.\r\nlet EMPTY_NODE;\r\n/**\r\n * ChildrenNode is a class for storing internal nodes in a DataSnapshot\r\n * (i.e. nodes with children). It implements Node and stores the\r\n * list of children in the children property, sorted by child name.\r\n */\r\nclass ChildrenNode {\r\n /**\r\n * @param children_ - List of children of this node..\r\n * @param priorityNode_ - The priority of this node (as a snapshot node).\r\n */\r\n constructor(children_, priorityNode_, indexMap_) {\r\n this.children_ = children_;\r\n this.priorityNode_ = priorityNode_;\r\n this.indexMap_ = indexMap_;\r\n this.lazyHash_ = null;\r\n /**\r\n * Note: The only reason we allow null priority is for EMPTY_NODE, since we can't use\r\n * EMPTY_NODE as the priority of EMPTY_NODE. We might want to consider making EMPTY_NODE its own\r\n * class instead of an empty ChildrenNode.\r\n */\r\n if (this.priorityNode_) {\r\n validatePriorityNode(this.priorityNode_);\r\n }\r\n if (this.children_.isEmpty()) {\r\n assert(!this.priorityNode_ || this.priorityNode_.isEmpty(), 'An empty node cannot have a priority');\r\n }\r\n }\r\n static get EMPTY_NODE() {\r\n return (EMPTY_NODE ||\r\n (EMPTY_NODE = new ChildrenNode(new SortedMap(NAME_COMPARATOR), null, IndexMap.Default)));\r\n }\r\n /** @inheritDoc */\r\n isLeafNode() {\r\n return false;\r\n }\r\n /** @inheritDoc */\r\n getPriority() {\r\n return this.priorityNode_ || EMPTY_NODE;\r\n }\r\n /** @inheritDoc */\r\n updatePriority(newPriorityNode) {\r\n if (this.children_.isEmpty()) {\r\n // Don't allow priorities on empty nodes\r\n return this;\r\n }\r\n else {\r\n return new ChildrenNode(this.children_, newPriorityNode, this.indexMap_);\r\n }\r\n }\r\n /** @inheritDoc */\r\n getImmediateChild(childName) {\r\n // Hack to treat priority as a regular child\r\n if (childName === '.priority') {\r\n return this.getPriority();\r\n }\r\n else {\r\n const child = this.children_.get(childName);\r\n return child === null ? EMPTY_NODE : child;\r\n }\r\n }\r\n /** @inheritDoc */\r\n getChild(path) {\r\n const front = pathGetFront(path);\r\n if (front === null) {\r\n return this;\r\n }\r\n return this.getImmediateChild(front).getChild(pathPopFront(path));\r\n }\r\n /** @inheritDoc */\r\n hasChild(childName) {\r\n return this.children_.get(childName) !== null;\r\n }\r\n /** @inheritDoc */\r\n updateImmediateChild(childName, newChildNode) {\r\n assert(newChildNode, 'We should always be passing snapshot nodes');\r\n if (childName === '.priority') {\r\n return this.updatePriority(newChildNode);\r\n }\r\n else {\r\n const namedNode = new NamedNode(childName, newChildNode);\r\n let newChildren, newIndexMap;\r\n if (newChildNode.isEmpty()) {\r\n newChildren = this.children_.remove(childName);\r\n newIndexMap = this.indexMap_.removeFromIndexes(namedNode, this.children_);\r\n }\r\n else {\r\n newChildren = this.children_.insert(childName, newChildNode);\r\n newIndexMap = this.indexMap_.addToIndexes(namedNode, this.children_);\r\n }\r\n const newPriority = newChildren.isEmpty()\r\n ? EMPTY_NODE\r\n : this.priorityNode_;\r\n return new ChildrenNode(newChildren, newPriority, newIndexMap);\r\n }\r\n }\r\n /** @inheritDoc */\r\n updateChild(path, newChildNode) {\r\n const front = pathGetFront(path);\r\n if (front === null) {\r\n return newChildNode;\r\n }\r\n else {\r\n assert(pathGetFront(path) !== '.priority' || pathGetLength(path) === 1, '.priority must be the last token in a path');\r\n const newImmediateChild = this.getImmediateChild(front).updateChild(pathPopFront(path), newChildNode);\r\n return this.updateImmediateChild(front, newImmediateChild);\r\n }\r\n }\r\n /** @inheritDoc */\r\n isEmpty() {\r\n return this.children_.isEmpty();\r\n }\r\n /** @inheritDoc */\r\n numChildren() {\r\n return this.children_.count();\r\n }\r\n /** @inheritDoc */\r\n val(exportFormat) {\r\n if (this.isEmpty()) {\r\n return null;\r\n }\r\n const obj = {};\r\n let numKeys = 0, maxKey = 0, allIntegerKeys = true;\r\n this.forEachChild(PRIORITY_INDEX, (key, childNode) => {\r\n obj[key] = childNode.val(exportFormat);\r\n numKeys++;\r\n if (allIntegerKeys && ChildrenNode.INTEGER_REGEXP_.test(key)) {\r\n maxKey = Math.max(maxKey, Number(key));\r\n }\r\n else {\r\n allIntegerKeys = false;\r\n }\r\n });\r\n if (!exportFormat && allIntegerKeys && maxKey < 2 * numKeys) {\r\n // convert to array.\r\n const array = [];\r\n // eslint-disable-next-line guard-for-in\r\n for (const key in obj) {\r\n array[key] = obj[key];\r\n }\r\n return array;\r\n }\r\n else {\r\n if (exportFormat && !this.getPriority().isEmpty()) {\r\n obj['.priority'] = this.getPriority().val();\r\n }\r\n return obj;\r\n }\r\n }\r\n /** @inheritDoc */\r\n hash() {\r\n if (this.lazyHash_ === null) {\r\n let toHash = '';\r\n if (!this.getPriority().isEmpty()) {\r\n toHash +=\r\n 'priority:' +\r\n priorityHashText(this.getPriority().val()) +\r\n ':';\r\n }\r\n this.forEachChild(PRIORITY_INDEX, (key, childNode) => {\r\n const childHash = childNode.hash();\r\n if (childHash !== '') {\r\n toHash += ':' + key + ':' + childHash;\r\n }\r\n });\r\n this.lazyHash_ = toHash === '' ? '' : sha1(toHash);\r\n }\r\n return this.lazyHash_;\r\n }\r\n /** @inheritDoc */\r\n getPredecessorChildName(childName, childNode, index) {\r\n const idx = this.resolveIndex_(index);\r\n if (idx) {\r\n const predecessor = idx.getPredecessorKey(new NamedNode(childName, childNode));\r\n return predecessor ? predecessor.name : null;\r\n }\r\n else {\r\n return this.children_.getPredecessorKey(childName);\r\n }\r\n }\r\n getFirstChildName(indexDefinition) {\r\n const idx = this.resolveIndex_(indexDefinition);\r\n if (idx) {\r\n const minKey = idx.minKey();\r\n return minKey && minKey.name;\r\n }\r\n else {\r\n return this.children_.minKey();\r\n }\r\n }\r\n getFirstChild(indexDefinition) {\r\n const minKey = this.getFirstChildName(indexDefinition);\r\n if (minKey) {\r\n return new NamedNode(minKey, this.children_.get(minKey));\r\n }\r\n else {\r\n return null;\r\n }\r\n }\r\n /**\r\n * Given an index, return the key name of the largest value we have, according to that index\r\n */\r\n getLastChildName(indexDefinition) {\r\n const idx = this.resolveIndex_(indexDefinition);\r\n if (idx) {\r\n const maxKey = idx.maxKey();\r\n return maxKey && maxKey.name;\r\n }\r\n else {\r\n return this.children_.maxKey();\r\n }\r\n }\r\n getLastChild(indexDefinition) {\r\n const maxKey = this.getLastChildName(indexDefinition);\r\n if (maxKey) {\r\n return new NamedNode(maxKey, this.children_.get(maxKey));\r\n }\r\n else {\r\n return null;\r\n }\r\n }\r\n forEachChild(index, action) {\r\n const idx = this.resolveIndex_(index);\r\n if (idx) {\r\n return idx.inorderTraversal(wrappedNode => {\r\n return action(wrappedNode.name, wrappedNode.node);\r\n });\r\n }\r\n else {\r\n return this.children_.inorderTraversal(action);\r\n }\r\n }\r\n getIterator(indexDefinition) {\r\n return this.getIteratorFrom(indexDefinition.minPost(), indexDefinition);\r\n }\r\n getIteratorFrom(startPost, indexDefinition) {\r\n const idx = this.resolveIndex_(indexDefinition);\r\n if (idx) {\r\n return idx.getIteratorFrom(startPost, key => key);\r\n }\r\n else {\r\n const iterator = this.children_.getIteratorFrom(startPost.name, NamedNode.Wrap);\r\n let next = iterator.peek();\r\n while (next != null && indexDefinition.compare(next, startPost) < 0) {\r\n iterator.getNext();\r\n next = iterator.peek();\r\n }\r\n return iterator;\r\n }\r\n }\r\n getReverseIterator(indexDefinition) {\r\n return this.getReverseIteratorFrom(indexDefinition.maxPost(), indexDefinition);\r\n }\r\n getReverseIteratorFrom(endPost, indexDefinition) {\r\n const idx = this.resolveIndex_(indexDefinition);\r\n if (idx) {\r\n return idx.getReverseIteratorFrom(endPost, key => {\r\n return key;\r\n });\r\n }\r\n else {\r\n const iterator = this.children_.getReverseIteratorFrom(endPost.name, NamedNode.Wrap);\r\n let next = iterator.peek();\r\n while (next != null && indexDefinition.compare(next, endPost) > 0) {\r\n iterator.getNext();\r\n next = iterator.peek();\r\n }\r\n return iterator;\r\n }\r\n }\r\n compareTo(other) {\r\n if (this.isEmpty()) {\r\n if (other.isEmpty()) {\r\n return 0;\r\n }\r\n else {\r\n return -1;\r\n }\r\n }\r\n else if (other.isLeafNode() || other.isEmpty()) {\r\n return 1;\r\n }\r\n else if (other === MAX_NODE) {\r\n return -1;\r\n }\r\n else {\r\n // Must be another node with children.\r\n return 0;\r\n }\r\n }\r\n withIndex(indexDefinition) {\r\n if (indexDefinition === KEY_INDEX ||\r\n this.indexMap_.hasIndex(indexDefinition)) {\r\n return this;\r\n }\r\n else {\r\n const newIndexMap = this.indexMap_.addIndex(indexDefinition, this.children_);\r\n return new ChildrenNode(this.children_, this.priorityNode_, newIndexMap);\r\n }\r\n }\r\n isIndexed(index) {\r\n return index === KEY_INDEX || this.indexMap_.hasIndex(index);\r\n }\r\n equals(other) {\r\n if (other === this) {\r\n return true;\r\n }\r\n else if (other.isLeafNode()) {\r\n return false;\r\n }\r\n else {\r\n const otherChildrenNode = other;\r\n if (!this.getPriority().equals(otherChildrenNode.getPriority())) {\r\n return false;\r\n }\r\n else if (this.children_.count() === otherChildrenNode.children_.count()) {\r\n const thisIter = this.getIterator(PRIORITY_INDEX);\r\n const otherIter = otherChildrenNode.getIterator(PRIORITY_INDEX);\r\n let thisCurrent = thisIter.getNext();\r\n let otherCurrent = otherIter.getNext();\r\n while (thisCurrent && otherCurrent) {\r\n if (thisCurrent.name !== otherCurrent.name ||\r\n !thisCurrent.node.equals(otherCurrent.node)) {\r\n return false;\r\n }\r\n thisCurrent = thisIter.getNext();\r\n otherCurrent = otherIter.getNext();\r\n }\r\n return thisCurrent === null && otherCurrent === null;\r\n }\r\n else {\r\n return false;\r\n }\r\n }\r\n }\r\n /**\r\n * Returns a SortedMap ordered by index, or null if the default (by-key) ordering can be used\r\n * instead.\r\n *\r\n */\r\n resolveIndex_(indexDefinition) {\r\n if (indexDefinition === KEY_INDEX) {\r\n return null;\r\n }\r\n else {\r\n return this.indexMap_.get(indexDefinition.toString());\r\n }\r\n }\r\n}\r\nChildrenNode.INTEGER_REGEXP_ = /^(0|[1-9]\\d*)$/;\r\nclass MaxNode extends ChildrenNode {\r\n constructor() {\r\n super(new SortedMap(NAME_COMPARATOR), ChildrenNode.EMPTY_NODE, IndexMap.Default);\r\n }\r\n compareTo(other) {\r\n if (other === this) {\r\n return 0;\r\n }\r\n else {\r\n return 1;\r\n }\r\n }\r\n equals(other) {\r\n // Not that we every compare it, but MAX_NODE is only ever equal to itself\r\n return other === this;\r\n }\r\n getPriority() {\r\n return this;\r\n }\r\n getImmediateChild(childName) {\r\n return ChildrenNode.EMPTY_NODE;\r\n }\r\n isEmpty() {\r\n return false;\r\n }\r\n}\r\n/**\r\n * Marker that will sort higher than any other snapshot.\r\n */\r\nconst MAX_NODE = new MaxNode();\r\nObject.defineProperties(NamedNode, {\r\n MIN: {\r\n value: new NamedNode(MIN_NAME, ChildrenNode.EMPTY_NODE)\r\n },\r\n MAX: {\r\n value: new NamedNode(MAX_NAME, MAX_NODE)\r\n }\r\n});\r\n/**\r\n * Reference Extensions\r\n */\r\nKeyIndex.__EMPTY_NODE = ChildrenNode.EMPTY_NODE;\r\nLeafNode.__childrenNodeConstructor = ChildrenNode;\r\nsetMaxNode$1(MAX_NODE);\r\nsetMaxNode(MAX_NODE);\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nconst USE_HINZE = true;\r\n/**\r\n * Constructs a snapshot node representing the passed JSON and returns it.\r\n * @param json - JSON to create a node for.\r\n * @param priority - Optional priority to use. This will be ignored if the\r\n * passed JSON contains a .priority property.\r\n */\r\nfunction nodeFromJSON(json, priority = null) {\r\n if (json === null) {\r\n return ChildrenNode.EMPTY_NODE;\r\n }\r\n if (typeof json === 'object' && '.priority' in json) {\r\n priority = json['.priority'];\r\n }\r\n assert(priority === null ||\r\n typeof priority === 'string' ||\r\n typeof priority === 'number' ||\r\n (typeof priority === 'object' && '.sv' in priority), 'Invalid priority type found: ' + typeof priority);\r\n if (typeof json === 'object' && '.value' in json && json['.value'] !== null) {\r\n json = json['.value'];\r\n }\r\n // Valid leaf nodes include non-objects or server-value wrapper objects\r\n if (typeof json !== 'object' || '.sv' in json) {\r\n const jsonLeaf = json;\r\n return new LeafNode(jsonLeaf, nodeFromJSON(priority));\r\n }\r\n if (!(json instanceof Array) && USE_HINZE) {\r\n const children = [];\r\n let childrenHavePriority = false;\r\n const hinzeJsonObj = json;\r\n each(hinzeJsonObj, (key, child) => {\r\n if (key.substring(0, 1) !== '.') {\r\n // Ignore metadata nodes\r\n const childNode = nodeFromJSON(child);\r\n if (!childNode.isEmpty()) {\r\n childrenHavePriority =\r\n childrenHavePriority || !childNode.getPriority().isEmpty();\r\n children.push(new NamedNode(key, childNode));\r\n }\r\n }\r\n });\r\n if (children.length === 0) {\r\n return ChildrenNode.EMPTY_NODE;\r\n }\r\n const childSet = buildChildSet(children, NAME_ONLY_COMPARATOR, namedNode => namedNode.name, NAME_COMPARATOR);\r\n if (childrenHavePriority) {\r\n const sortedChildSet = buildChildSet(children, PRIORITY_INDEX.getCompare());\r\n return new ChildrenNode(childSet, nodeFromJSON(priority), new IndexMap({ '.priority': sortedChildSet }, { '.priority': PRIORITY_INDEX }));\r\n }\r\n else {\r\n return new ChildrenNode(childSet, nodeFromJSON(priority), IndexMap.Default);\r\n }\r\n }\r\n else {\r\n let node = ChildrenNode.EMPTY_NODE;\r\n each(json, (key, childData) => {\r\n if (contains(json, key)) {\r\n if (key.substring(0, 1) !== '.') {\r\n // ignore metadata nodes.\r\n const childNode = nodeFromJSON(childData);\r\n if (childNode.isLeafNode() || !childNode.isEmpty()) {\r\n node = node.updateImmediateChild(key, childNode);\r\n }\r\n }\r\n }\r\n });\r\n return node.updatePriority(nodeFromJSON(priority));\r\n }\r\n}\r\nsetNodeFromJSON(nodeFromJSON);\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nclass PathIndex extends Index {\r\n constructor(indexPath_) {\r\n super();\r\n this.indexPath_ = indexPath_;\r\n assert(!pathIsEmpty(indexPath_) && pathGetFront(indexPath_) !== '.priority', \"Can't create PathIndex with empty path or .priority key\");\r\n }\r\n extractChild(snap) {\r\n return snap.getChild(this.indexPath_);\r\n }\r\n isDefinedOn(node) {\r\n return !node.getChild(this.indexPath_).isEmpty();\r\n }\r\n compare(a, b) {\r\n const aChild = this.extractChild(a.node);\r\n const bChild = this.extractChild(b.node);\r\n const indexCmp = aChild.compareTo(bChild);\r\n if (indexCmp === 0) {\r\n return nameCompare(a.name, b.name);\r\n }\r\n else {\r\n return indexCmp;\r\n }\r\n }\r\n makePost(indexValue, name) {\r\n const valueNode = nodeFromJSON(indexValue);\r\n const node = ChildrenNode.EMPTY_NODE.updateChild(this.indexPath_, valueNode);\r\n return new NamedNode(name, node);\r\n }\r\n maxPost() {\r\n const node = ChildrenNode.EMPTY_NODE.updateChild(this.indexPath_, MAX_NODE);\r\n return new NamedNode(MAX_NAME, node);\r\n }\r\n toString() {\r\n return pathSlice(this.indexPath_, 0).join('/');\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nclass ValueIndex extends Index {\r\n compare(a, b) {\r\n const indexCmp = a.node.compareTo(b.node);\r\n if (indexCmp === 0) {\r\n return nameCompare(a.name, b.name);\r\n }\r\n else {\r\n return indexCmp;\r\n }\r\n }\r\n isDefinedOn(node) {\r\n return true;\r\n }\r\n indexedValueChanged(oldNode, newNode) {\r\n return !oldNode.equals(newNode);\r\n }\r\n minPost() {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n return NamedNode.MIN;\r\n }\r\n maxPost() {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n return NamedNode.MAX;\r\n }\r\n makePost(indexValue, name) {\r\n const valueNode = nodeFromJSON(indexValue);\r\n return new NamedNode(name, valueNode);\r\n }\r\n /**\r\n * @returns String representation for inclusion in a query spec\r\n */\r\n toString() {\r\n return '.value';\r\n }\r\n}\r\nconst VALUE_INDEX = new ValueIndex();\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nfunction changeValue(snapshotNode) {\r\n return { type: \"value\" /* ChangeType.VALUE */, snapshotNode };\r\n}\r\nfunction changeChildAdded(childName, snapshotNode) {\r\n return { type: \"child_added\" /* ChangeType.CHILD_ADDED */, snapshotNode, childName };\r\n}\r\nfunction changeChildRemoved(childName, snapshotNode) {\r\n return { type: \"child_removed\" /* ChangeType.CHILD_REMOVED */, snapshotNode, childName };\r\n}\r\nfunction changeChildChanged(childName, snapshotNode, oldSnap) {\r\n return {\r\n type: \"child_changed\" /* ChangeType.CHILD_CHANGED */,\r\n snapshotNode,\r\n childName,\r\n oldSnap\r\n };\r\n}\r\nfunction changeChildMoved(childName, snapshotNode) {\r\n return { type: \"child_moved\" /* ChangeType.CHILD_MOVED */, snapshotNode, childName };\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * Doesn't really filter nodes but applies an index to the node and keeps track of any changes\r\n */\r\nclass IndexedFilter {\r\n constructor(index_) {\r\n this.index_ = index_;\r\n }\r\n updateChild(snap, key, newChild, affectedPath, source, optChangeAccumulator) {\r\n assert(snap.isIndexed(this.index_), 'A node must be indexed if only a child is updated');\r\n const oldChild = snap.getImmediateChild(key);\r\n // Check if anything actually changed.\r\n if (oldChild.getChild(affectedPath).equals(newChild.getChild(affectedPath))) {\r\n // There's an edge case where a child can enter or leave the view because affectedPath was set to null.\r\n // In this case, affectedPath will appear null in both the old and new snapshots. So we need\r\n // to avoid treating these cases as \"nothing changed.\"\r\n if (oldChild.isEmpty() === newChild.isEmpty()) {\r\n // Nothing changed.\r\n // This assert should be valid, but it's expensive (can dominate perf testing) so don't actually do it.\r\n //assert(oldChild.equals(newChild), 'Old and new snapshots should be equal.');\r\n return snap;\r\n }\r\n }\r\n if (optChangeAccumulator != null) {\r\n if (newChild.isEmpty()) {\r\n if (snap.hasChild(key)) {\r\n optChangeAccumulator.trackChildChange(changeChildRemoved(key, oldChild));\r\n }\r\n else {\r\n assert(snap.isLeafNode(), 'A child remove without an old child only makes sense on a leaf node');\r\n }\r\n }\r\n else if (oldChild.isEmpty()) {\r\n optChangeAccumulator.trackChildChange(changeChildAdded(key, newChild));\r\n }\r\n else {\r\n optChangeAccumulator.trackChildChange(changeChildChanged(key, newChild, oldChild));\r\n }\r\n }\r\n if (snap.isLeafNode() && newChild.isEmpty()) {\r\n return snap;\r\n }\r\n else {\r\n // Make sure the node is indexed\r\n return snap.updateImmediateChild(key, newChild).withIndex(this.index_);\r\n }\r\n }\r\n updateFullNode(oldSnap, newSnap, optChangeAccumulator) {\r\n if (optChangeAccumulator != null) {\r\n if (!oldSnap.isLeafNode()) {\r\n oldSnap.forEachChild(PRIORITY_INDEX, (key, childNode) => {\r\n if (!newSnap.hasChild(key)) {\r\n optChangeAccumulator.trackChildChange(changeChildRemoved(key, childNode));\r\n }\r\n });\r\n }\r\n if (!newSnap.isLeafNode()) {\r\n newSnap.forEachChild(PRIORITY_INDEX, (key, childNode) => {\r\n if (oldSnap.hasChild(key)) {\r\n const oldChild = oldSnap.getImmediateChild(key);\r\n if (!oldChild.equals(childNode)) {\r\n optChangeAccumulator.trackChildChange(changeChildChanged(key, childNode, oldChild));\r\n }\r\n }\r\n else {\r\n optChangeAccumulator.trackChildChange(changeChildAdded(key, childNode));\r\n }\r\n });\r\n }\r\n }\r\n return newSnap.withIndex(this.index_);\r\n }\r\n updatePriority(oldSnap, newPriority) {\r\n if (oldSnap.isEmpty()) {\r\n return ChildrenNode.EMPTY_NODE;\r\n }\r\n else {\r\n return oldSnap.updatePriority(newPriority);\r\n }\r\n }\r\n filtersNodes() {\r\n return false;\r\n }\r\n getIndexedFilter() {\r\n return this;\r\n }\r\n getIndex() {\r\n return this.index_;\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * Filters nodes by range and uses an IndexFilter to track any changes after filtering the node\r\n */\r\nclass RangedFilter {\r\n constructor(params) {\r\n this.indexedFilter_ = new IndexedFilter(params.getIndex());\r\n this.index_ = params.getIndex();\r\n this.startPost_ = RangedFilter.getStartPost_(params);\r\n this.endPost_ = RangedFilter.getEndPost_(params);\r\n this.startIsInclusive_ = !params.startAfterSet_;\r\n this.endIsInclusive_ = !params.endBeforeSet_;\r\n }\r\n getStartPost() {\r\n return this.startPost_;\r\n }\r\n getEndPost() {\r\n return this.endPost_;\r\n }\r\n matches(node) {\r\n const isWithinStart = this.startIsInclusive_\r\n ? this.index_.compare(this.getStartPost(), node) <= 0\r\n : this.index_.compare(this.getStartPost(), node) < 0;\r\n const isWithinEnd = this.endIsInclusive_\r\n ? this.index_.compare(node, this.getEndPost()) <= 0\r\n : this.index_.compare(node, this.getEndPost()) < 0;\r\n return isWithinStart && isWithinEnd;\r\n }\r\n updateChild(snap, key, newChild, affectedPath, source, optChangeAccumulator) {\r\n if (!this.matches(new NamedNode(key, newChild))) {\r\n newChild = ChildrenNode.EMPTY_NODE;\r\n }\r\n return this.indexedFilter_.updateChild(snap, key, newChild, affectedPath, source, optChangeAccumulator);\r\n }\r\n updateFullNode(oldSnap, newSnap, optChangeAccumulator) {\r\n if (newSnap.isLeafNode()) {\r\n // Make sure we have a children node with the correct index, not a leaf node;\r\n newSnap = ChildrenNode.EMPTY_NODE;\r\n }\r\n let filtered = newSnap.withIndex(this.index_);\r\n // Don't support priorities on queries\r\n filtered = filtered.updatePriority(ChildrenNode.EMPTY_NODE);\r\n const self = this;\r\n newSnap.forEachChild(PRIORITY_INDEX, (key, childNode) => {\r\n if (!self.matches(new NamedNode(key, childNode))) {\r\n filtered = filtered.updateImmediateChild(key, ChildrenNode.EMPTY_NODE);\r\n }\r\n });\r\n return this.indexedFilter_.updateFullNode(oldSnap, filtered, optChangeAccumulator);\r\n }\r\n updatePriority(oldSnap, newPriority) {\r\n // Don't support priorities on queries\r\n return oldSnap;\r\n }\r\n filtersNodes() {\r\n return true;\r\n }\r\n getIndexedFilter() {\r\n return this.indexedFilter_;\r\n }\r\n getIndex() {\r\n return this.index_;\r\n }\r\n static getStartPost_(params) {\r\n if (params.hasStart()) {\r\n const startName = params.getIndexStartName();\r\n return params.getIndex().makePost(params.getIndexStartValue(), startName);\r\n }\r\n else {\r\n return params.getIndex().minPost();\r\n }\r\n }\r\n static getEndPost_(params) {\r\n if (params.hasEnd()) {\r\n const endName = params.getIndexEndName();\r\n return params.getIndex().makePost(params.getIndexEndValue(), endName);\r\n }\r\n else {\r\n return params.getIndex().maxPost();\r\n }\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * Applies a limit and a range to a node and uses RangedFilter to do the heavy lifting where possible\r\n */\r\nclass LimitedFilter {\r\n constructor(params) {\r\n this.withinDirectionalStart = (node) => this.reverse_ ? this.withinEndPost(node) : this.withinStartPost(node);\r\n this.withinDirectionalEnd = (node) => this.reverse_ ? this.withinStartPost(node) : this.withinEndPost(node);\r\n this.withinStartPost = (node) => {\r\n const compareRes = this.index_.compare(this.rangedFilter_.getStartPost(), node);\r\n return this.startIsInclusive_ ? compareRes <= 0 : compareRes < 0;\r\n };\r\n this.withinEndPost = (node) => {\r\n const compareRes = this.index_.compare(node, this.rangedFilter_.getEndPost());\r\n return this.endIsInclusive_ ? compareRes <= 0 : compareRes < 0;\r\n };\r\n this.rangedFilter_ = new RangedFilter(params);\r\n this.index_ = params.getIndex();\r\n this.limit_ = params.getLimit();\r\n this.reverse_ = !params.isViewFromLeft();\r\n this.startIsInclusive_ = !params.startAfterSet_;\r\n this.endIsInclusive_ = !params.endBeforeSet_;\r\n }\r\n updateChild(snap, key, newChild, affectedPath, source, optChangeAccumulator) {\r\n if (!this.rangedFilter_.matches(new NamedNode(key, newChild))) {\r\n newChild = ChildrenNode.EMPTY_NODE;\r\n }\r\n if (snap.getImmediateChild(key).equals(newChild)) {\r\n // No change\r\n return snap;\r\n }\r\n else if (snap.numChildren() < this.limit_) {\r\n return this.rangedFilter_\r\n .getIndexedFilter()\r\n .updateChild(snap, key, newChild, affectedPath, source, optChangeAccumulator);\r\n }\r\n else {\r\n return this.fullLimitUpdateChild_(snap, key, newChild, source, optChangeAccumulator);\r\n }\r\n }\r\n updateFullNode(oldSnap, newSnap, optChangeAccumulator) {\r\n let filtered;\r\n if (newSnap.isLeafNode() || newSnap.isEmpty()) {\r\n // Make sure we have a children node with the correct index, not a leaf node;\r\n filtered = ChildrenNode.EMPTY_NODE.withIndex(this.index_);\r\n }\r\n else {\r\n if (this.limit_ * 2 < newSnap.numChildren() &&\r\n newSnap.isIndexed(this.index_)) {\r\n // Easier to build up a snapshot, since what we're given has more than twice the elements we want\r\n filtered = ChildrenNode.EMPTY_NODE.withIndex(this.index_);\r\n // anchor to the startPost, endPost, or last element as appropriate\r\n let iterator;\r\n if (this.reverse_) {\r\n iterator = newSnap.getReverseIteratorFrom(this.rangedFilter_.getEndPost(), this.index_);\r\n }\r\n else {\r\n iterator = newSnap.getIteratorFrom(this.rangedFilter_.getStartPost(), this.index_);\r\n }\r\n let count = 0;\r\n while (iterator.hasNext() && count < this.limit_) {\r\n const next = iterator.getNext();\r\n if (!this.withinDirectionalStart(next)) {\r\n // if we have not reached the start, skip to the next element\r\n continue;\r\n }\r\n else if (!this.withinDirectionalEnd(next)) {\r\n // if we have reached the end, stop adding elements\r\n break;\r\n }\r\n else {\r\n filtered = filtered.updateImmediateChild(next.name, next.node);\r\n count++;\r\n }\r\n }\r\n }\r\n else {\r\n // The snap contains less than twice the limit. Faster to delete from the snap than build up a new one\r\n filtered = newSnap.withIndex(this.index_);\r\n // Don't support priorities on queries\r\n filtered = filtered.updatePriority(ChildrenNode.EMPTY_NODE);\r\n let iterator;\r\n if (this.reverse_) {\r\n iterator = filtered.getReverseIterator(this.index_);\r\n }\r\n else {\r\n iterator = filtered.getIterator(this.index_);\r\n }\r\n let count = 0;\r\n while (iterator.hasNext()) {\r\n const next = iterator.getNext();\r\n const inRange = count < this.limit_ &&\r\n this.withinDirectionalStart(next) &&\r\n this.withinDirectionalEnd(next);\r\n if (inRange) {\r\n count++;\r\n }\r\n else {\r\n filtered = filtered.updateImmediateChild(next.name, ChildrenNode.EMPTY_NODE);\r\n }\r\n }\r\n }\r\n }\r\n return this.rangedFilter_\r\n .getIndexedFilter()\r\n .updateFullNode(oldSnap, filtered, optChangeAccumulator);\r\n }\r\n updatePriority(oldSnap, newPriority) {\r\n // Don't support priorities on queries\r\n return oldSnap;\r\n }\r\n filtersNodes() {\r\n return true;\r\n }\r\n getIndexedFilter() {\r\n return this.rangedFilter_.getIndexedFilter();\r\n }\r\n getIndex() {\r\n return this.index_;\r\n }\r\n fullLimitUpdateChild_(snap, childKey, childSnap, source, changeAccumulator) {\r\n // TODO: rename all cache stuff etc to general snap terminology\r\n let cmp;\r\n if (this.reverse_) {\r\n const indexCmp = this.index_.getCompare();\r\n cmp = (a, b) => indexCmp(b, a);\r\n }\r\n else {\r\n cmp = this.index_.getCompare();\r\n }\r\n const oldEventCache = snap;\r\n assert(oldEventCache.numChildren() === this.limit_, '');\r\n const newChildNamedNode = new NamedNode(childKey, childSnap);\r\n const windowBoundary = this.reverse_\r\n ? oldEventCache.getFirstChild(this.index_)\r\n : oldEventCache.getLastChild(this.index_);\r\n const inRange = this.rangedFilter_.matches(newChildNamedNode);\r\n if (oldEventCache.hasChild(childKey)) {\r\n const oldChildSnap = oldEventCache.getImmediateChild(childKey);\r\n let nextChild = source.getChildAfterChild(this.index_, windowBoundary, this.reverse_);\r\n while (nextChild != null &&\r\n (nextChild.name === childKey || oldEventCache.hasChild(nextChild.name))) {\r\n // There is a weird edge case where a node is updated as part of a merge in the write tree, but hasn't\r\n // been applied to the limited filter yet. Ignore this next child which will be updated later in\r\n // the limited filter...\r\n nextChild = source.getChildAfterChild(this.index_, nextChild, this.reverse_);\r\n }\r\n const compareNext = nextChild == null ? 1 : cmp(nextChild, newChildNamedNode);\r\n const remainsInWindow = inRange && !childSnap.isEmpty() && compareNext >= 0;\r\n if (remainsInWindow) {\r\n if (changeAccumulator != null) {\r\n changeAccumulator.trackChildChange(changeChildChanged(childKey, childSnap, oldChildSnap));\r\n }\r\n return oldEventCache.updateImmediateChild(childKey, childSnap);\r\n }\r\n else {\r\n if (changeAccumulator != null) {\r\n changeAccumulator.trackChildChange(changeChildRemoved(childKey, oldChildSnap));\r\n }\r\n const newEventCache = oldEventCache.updateImmediateChild(childKey, ChildrenNode.EMPTY_NODE);\r\n const nextChildInRange = nextChild != null && this.rangedFilter_.matches(nextChild);\r\n if (nextChildInRange) {\r\n if (changeAccumulator != null) {\r\n changeAccumulator.trackChildChange(changeChildAdded(nextChild.name, nextChild.node));\r\n }\r\n return newEventCache.updateImmediateChild(nextChild.name, nextChild.node);\r\n }\r\n else {\r\n return newEventCache;\r\n }\r\n }\r\n }\r\n else if (childSnap.isEmpty()) {\r\n // we're deleting a node, but it was not in the window, so ignore it\r\n return snap;\r\n }\r\n else if (inRange) {\r\n if (cmp(windowBoundary, newChildNamedNode) >= 0) {\r\n if (changeAccumulator != null) {\r\n changeAccumulator.trackChildChange(changeChildRemoved(windowBoundary.name, windowBoundary.node));\r\n changeAccumulator.trackChildChange(changeChildAdded(childKey, childSnap));\r\n }\r\n return oldEventCache\r\n .updateImmediateChild(childKey, childSnap)\r\n .updateImmediateChild(windowBoundary.name, ChildrenNode.EMPTY_NODE);\r\n }\r\n else {\r\n return snap;\r\n }\r\n }\r\n else {\r\n return snap;\r\n }\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * This class is an immutable-from-the-public-api struct containing a set of query parameters defining a\r\n * range to be returned for a particular location. It is assumed that validation of parameters is done at the\r\n * user-facing API level, so it is not done here.\r\n *\r\n * @internal\r\n */\r\nclass QueryParams {\r\n constructor() {\r\n this.limitSet_ = false;\r\n this.startSet_ = false;\r\n this.startNameSet_ = false;\r\n this.startAfterSet_ = false; // can only be true if startSet_ is true\r\n this.endSet_ = false;\r\n this.endNameSet_ = false;\r\n this.endBeforeSet_ = false; // can only be true if endSet_ is true\r\n this.limit_ = 0;\r\n this.viewFrom_ = '';\r\n this.indexStartValue_ = null;\r\n this.indexStartName_ = '';\r\n this.indexEndValue_ = null;\r\n this.indexEndName_ = '';\r\n this.index_ = PRIORITY_INDEX;\r\n }\r\n hasStart() {\r\n return this.startSet_;\r\n }\r\n /**\r\n * @returns True if it would return from left.\r\n */\r\n isViewFromLeft() {\r\n if (this.viewFrom_ === '') {\r\n // limit(), rather than limitToFirst or limitToLast was called.\r\n // This means that only one of startSet_ and endSet_ is true. Use them\r\n // to calculate which side of the view to anchor to. If neither is set,\r\n // anchor to the end.\r\n return this.startSet_;\r\n }\r\n else {\r\n return this.viewFrom_ === \"l\" /* WIRE_PROTOCOL_CONSTANTS.VIEW_FROM_LEFT */;\r\n }\r\n }\r\n /**\r\n * Only valid to call if hasStart() returns true\r\n */\r\n getIndexStartValue() {\r\n assert(this.startSet_, 'Only valid if start has been set');\r\n return this.indexStartValue_;\r\n }\r\n /**\r\n * Only valid to call if hasStart() returns true.\r\n * Returns the starting key name for the range defined by these query parameters\r\n */\r\n getIndexStartName() {\r\n assert(this.startSet_, 'Only valid if start has been set');\r\n if (this.startNameSet_) {\r\n return this.indexStartName_;\r\n }\r\n else {\r\n return MIN_NAME;\r\n }\r\n }\r\n hasEnd() {\r\n return this.endSet_;\r\n }\r\n /**\r\n * Only valid to call if hasEnd() returns true.\r\n */\r\n getIndexEndValue() {\r\n assert(this.endSet_, 'Only valid if end has been set');\r\n return this.indexEndValue_;\r\n }\r\n /**\r\n * Only valid to call if hasEnd() returns true.\r\n * Returns the end key name for the range defined by these query parameters\r\n */\r\n getIndexEndName() {\r\n assert(this.endSet_, 'Only valid if end has been set');\r\n if (this.endNameSet_) {\r\n return this.indexEndName_;\r\n }\r\n else {\r\n return MAX_NAME;\r\n }\r\n }\r\n hasLimit() {\r\n return this.limitSet_;\r\n }\r\n /**\r\n * @returns True if a limit has been set and it has been explicitly anchored\r\n */\r\n hasAnchoredLimit() {\r\n return this.limitSet_ && this.viewFrom_ !== '';\r\n }\r\n /**\r\n * Only valid to call if hasLimit() returns true\r\n */\r\n getLimit() {\r\n assert(this.limitSet_, 'Only valid if limit has been set');\r\n return this.limit_;\r\n }\r\n getIndex() {\r\n return this.index_;\r\n }\r\n loadsAllData() {\r\n return !(this.startSet_ || this.endSet_ || this.limitSet_);\r\n }\r\n isDefault() {\r\n return this.loadsAllData() && this.index_ === PRIORITY_INDEX;\r\n }\r\n copy() {\r\n const copy = new QueryParams();\r\n copy.limitSet_ = this.limitSet_;\r\n copy.limit_ = this.limit_;\r\n copy.startSet_ = this.startSet_;\r\n copy.startAfterSet_ = this.startAfterSet_;\r\n copy.indexStartValue_ = this.indexStartValue_;\r\n copy.startNameSet_ = this.startNameSet_;\r\n copy.indexStartName_ = this.indexStartName_;\r\n copy.endSet_ = this.endSet_;\r\n copy.endBeforeSet_ = this.endBeforeSet_;\r\n copy.indexEndValue_ = this.indexEndValue_;\r\n copy.endNameSet_ = this.endNameSet_;\r\n copy.indexEndName_ = this.indexEndName_;\r\n copy.index_ = this.index_;\r\n copy.viewFrom_ = this.viewFrom_;\r\n return copy;\r\n }\r\n}\r\nfunction queryParamsGetNodeFilter(queryParams) {\r\n if (queryParams.loadsAllData()) {\r\n return new IndexedFilter(queryParams.getIndex());\r\n }\r\n else if (queryParams.hasLimit()) {\r\n return new LimitedFilter(queryParams);\r\n }\r\n else {\r\n return new RangedFilter(queryParams);\r\n }\r\n}\r\nfunction queryParamsLimitToFirst(queryParams, newLimit) {\r\n const newParams = queryParams.copy();\r\n newParams.limitSet_ = true;\r\n newParams.limit_ = newLimit;\r\n newParams.viewFrom_ = \"l\" /* WIRE_PROTOCOL_CONSTANTS.VIEW_FROM_LEFT */;\r\n return newParams;\r\n}\r\nfunction queryParamsLimitToLast(queryParams, newLimit) {\r\n const newParams = queryParams.copy();\r\n newParams.limitSet_ = true;\r\n newParams.limit_ = newLimit;\r\n newParams.viewFrom_ = \"r\" /* WIRE_PROTOCOL_CONSTANTS.VIEW_FROM_RIGHT */;\r\n return newParams;\r\n}\r\nfunction queryParamsStartAt(queryParams, indexValue, key) {\r\n const newParams = queryParams.copy();\r\n newParams.startSet_ = true;\r\n if (indexValue === undefined) {\r\n indexValue = null;\r\n }\r\n newParams.indexStartValue_ = indexValue;\r\n if (key != null) {\r\n newParams.startNameSet_ = true;\r\n newParams.indexStartName_ = key;\r\n }\r\n else {\r\n newParams.startNameSet_ = false;\r\n newParams.indexStartName_ = '';\r\n }\r\n return newParams;\r\n}\r\nfunction queryParamsStartAfter(queryParams, indexValue, key) {\r\n let params;\r\n if (queryParams.index_ === KEY_INDEX || !!key) {\r\n params = queryParamsStartAt(queryParams, indexValue, key);\r\n }\r\n else {\r\n params = queryParamsStartAt(queryParams, indexValue, MAX_NAME);\r\n }\r\n params.startAfterSet_ = true;\r\n return params;\r\n}\r\nfunction queryParamsEndAt(queryParams, indexValue, key) {\r\n const newParams = queryParams.copy();\r\n newParams.endSet_ = true;\r\n if (indexValue === undefined) {\r\n indexValue = null;\r\n }\r\n newParams.indexEndValue_ = indexValue;\r\n if (key !== undefined) {\r\n newParams.endNameSet_ = true;\r\n newParams.indexEndName_ = key;\r\n }\r\n else {\r\n newParams.endNameSet_ = false;\r\n newParams.indexEndName_ = '';\r\n }\r\n return newParams;\r\n}\r\nfunction queryParamsEndBefore(queryParams, indexValue, key) {\r\n let params;\r\n if (queryParams.index_ === KEY_INDEX || !!key) {\r\n params = queryParamsEndAt(queryParams, indexValue, key);\r\n }\r\n else {\r\n params = queryParamsEndAt(queryParams, indexValue, MIN_NAME);\r\n }\r\n params.endBeforeSet_ = true;\r\n return params;\r\n}\r\nfunction queryParamsOrderBy(queryParams, index) {\r\n const newParams = queryParams.copy();\r\n newParams.index_ = index;\r\n return newParams;\r\n}\r\n/**\r\n * Returns a set of REST query string parameters representing this query.\r\n *\r\n * @returns query string parameters\r\n */\r\nfunction queryParamsToRestQueryStringParameters(queryParams) {\r\n const qs = {};\r\n if (queryParams.isDefault()) {\r\n return qs;\r\n }\r\n let orderBy;\r\n if (queryParams.index_ === PRIORITY_INDEX) {\r\n orderBy = \"$priority\" /* REST_QUERY_CONSTANTS.PRIORITY_INDEX */;\r\n }\r\n else if (queryParams.index_ === VALUE_INDEX) {\r\n orderBy = \"$value\" /* REST_QUERY_CONSTANTS.VALUE_INDEX */;\r\n }\r\n else if (queryParams.index_ === KEY_INDEX) {\r\n orderBy = \"$key\" /* REST_QUERY_CONSTANTS.KEY_INDEX */;\r\n }\r\n else {\r\n assert(queryParams.index_ instanceof PathIndex, 'Unrecognized index type!');\r\n orderBy = queryParams.index_.toString();\r\n }\r\n qs[\"orderBy\" /* REST_QUERY_CONSTANTS.ORDER_BY */] = stringify(orderBy);\r\n if (queryParams.startSet_) {\r\n const startParam = queryParams.startAfterSet_\r\n ? \"startAfter\" /* REST_QUERY_CONSTANTS.START_AFTER */\r\n : \"startAt\" /* REST_QUERY_CONSTANTS.START_AT */;\r\n qs[startParam] = stringify(queryParams.indexStartValue_);\r\n if (queryParams.startNameSet_) {\r\n qs[startParam] += ',' + stringify(queryParams.indexStartName_);\r\n }\r\n }\r\n if (queryParams.endSet_) {\r\n const endParam = queryParams.endBeforeSet_\r\n ? \"endBefore\" /* REST_QUERY_CONSTANTS.END_BEFORE */\r\n : \"endAt\" /* REST_QUERY_CONSTANTS.END_AT */;\r\n qs[endParam] = stringify(queryParams.indexEndValue_);\r\n if (queryParams.endNameSet_) {\r\n qs[endParam] += ',' + stringify(queryParams.indexEndName_);\r\n }\r\n }\r\n if (queryParams.limitSet_) {\r\n if (queryParams.isViewFromLeft()) {\r\n qs[\"limitToFirst\" /* REST_QUERY_CONSTANTS.LIMIT_TO_FIRST */] = queryParams.limit_;\r\n }\r\n else {\r\n qs[\"limitToLast\" /* REST_QUERY_CONSTANTS.LIMIT_TO_LAST */] = queryParams.limit_;\r\n }\r\n }\r\n return qs;\r\n}\r\nfunction queryParamsGetQueryObject(queryParams) {\r\n const obj = {};\r\n if (queryParams.startSet_) {\r\n obj[\"sp\" /* WIRE_PROTOCOL_CONSTANTS.INDEX_START_VALUE */] =\r\n queryParams.indexStartValue_;\r\n if (queryParams.startNameSet_) {\r\n obj[\"sn\" /* WIRE_PROTOCOL_CONSTANTS.INDEX_START_NAME */] =\r\n queryParams.indexStartName_;\r\n }\r\n obj[\"sin\" /* WIRE_PROTOCOL_CONSTANTS.INDEX_START_IS_INCLUSIVE */] =\r\n !queryParams.startAfterSet_;\r\n }\r\n if (queryParams.endSet_) {\r\n obj[\"ep\" /* WIRE_PROTOCOL_CONSTANTS.INDEX_END_VALUE */] = queryParams.indexEndValue_;\r\n if (queryParams.endNameSet_) {\r\n obj[\"en\" /* WIRE_PROTOCOL_CONSTANTS.INDEX_END_NAME */] = queryParams.indexEndName_;\r\n }\r\n obj[\"ein\" /* WIRE_PROTOCOL_CONSTANTS.INDEX_END_IS_INCLUSIVE */] =\r\n !queryParams.endBeforeSet_;\r\n }\r\n if (queryParams.limitSet_) {\r\n obj[\"l\" /* WIRE_PROTOCOL_CONSTANTS.LIMIT */] = queryParams.limit_;\r\n let viewFrom = queryParams.viewFrom_;\r\n if (viewFrom === '') {\r\n if (queryParams.isViewFromLeft()) {\r\n viewFrom = \"l\" /* WIRE_PROTOCOL_CONSTANTS.VIEW_FROM_LEFT */;\r\n }\r\n else {\r\n viewFrom = \"r\" /* WIRE_PROTOCOL_CONSTANTS.VIEW_FROM_RIGHT */;\r\n }\r\n }\r\n obj[\"vf\" /* WIRE_PROTOCOL_CONSTANTS.VIEW_FROM */] = viewFrom;\r\n }\r\n // For now, priority index is the default, so we only specify if it's some other index\r\n if (queryParams.index_ !== PRIORITY_INDEX) {\r\n obj[\"i\" /* WIRE_PROTOCOL_CONSTANTS.INDEX */] = queryParams.index_.toString();\r\n }\r\n return obj;\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * An implementation of ServerActions that communicates with the server via REST requests.\r\n * This is mostly useful for compatibility with crawlers, where we don't want to spin up a full\r\n * persistent connection (using WebSockets or long-polling)\r\n */\r\nclass ReadonlyRestClient extends ServerActions {\r\n /**\r\n * @param repoInfo_ - Data about the namespace we are connecting to\r\n * @param onDataUpdate_ - A callback for new data from the server\r\n */\r\n constructor(repoInfo_, onDataUpdate_, authTokenProvider_, appCheckTokenProvider_) {\r\n super();\r\n this.repoInfo_ = repoInfo_;\r\n this.onDataUpdate_ = onDataUpdate_;\r\n this.authTokenProvider_ = authTokenProvider_;\r\n this.appCheckTokenProvider_ = appCheckTokenProvider_;\r\n /** @private {function(...[*])} */\r\n this.log_ = logWrapper('p:rest:');\r\n /**\r\n * We don't actually need to track listens, except to prevent us calling an onComplete for a listen\r\n * that's been removed. :-/\r\n */\r\n this.listens_ = {};\r\n }\r\n reportStats(stats) {\r\n throw new Error('Method not implemented.');\r\n }\r\n static getListenId_(query, tag) {\r\n if (tag !== undefined) {\r\n return 'tag$' + tag;\r\n }\r\n else {\r\n assert(query._queryParams.isDefault(), \"should have a tag if it's not a default query.\");\r\n return query._path.toString();\r\n }\r\n }\r\n /** @inheritDoc */\r\n listen(query, currentHashFn, tag, onComplete) {\r\n const pathString = query._path.toString();\r\n this.log_('Listen called for ' + pathString + ' ' + query._queryIdentifier);\r\n // Mark this listener so we can tell if it's removed.\r\n const listenId = ReadonlyRestClient.getListenId_(query, tag);\r\n const thisListen = {};\r\n this.listens_[listenId] = thisListen;\r\n const queryStringParameters = queryParamsToRestQueryStringParameters(query._queryParams);\r\n this.restRequest_(pathString + '.json', queryStringParameters, (error, result) => {\r\n let data = result;\r\n if (error === 404) {\r\n data = null;\r\n error = null;\r\n }\r\n if (error === null) {\r\n this.onDataUpdate_(pathString, data, /*isMerge=*/ false, tag);\r\n }\r\n if (safeGet(this.listens_, listenId) === thisListen) {\r\n let status;\r\n if (!error) {\r\n status = 'ok';\r\n }\r\n else if (error === 401) {\r\n status = 'permission_denied';\r\n }\r\n else {\r\n status = 'rest_error:' + error;\r\n }\r\n onComplete(status, null);\r\n }\r\n });\r\n }\r\n /** @inheritDoc */\r\n unlisten(query, tag) {\r\n const listenId = ReadonlyRestClient.getListenId_(query, tag);\r\n delete this.listens_[listenId];\r\n }\r\n get(query) {\r\n const queryStringParameters = queryParamsToRestQueryStringParameters(query._queryParams);\r\n const pathString = query._path.toString();\r\n const deferred = new Deferred();\r\n this.restRequest_(pathString + '.json', queryStringParameters, (error, result) => {\r\n let data = result;\r\n if (error === 404) {\r\n data = null;\r\n error = null;\r\n }\r\n if (error === null) {\r\n this.onDataUpdate_(pathString, data, \r\n /*isMerge=*/ false, \r\n /*tag=*/ null);\r\n deferred.resolve(data);\r\n }\r\n else {\r\n deferred.reject(new Error(data));\r\n }\r\n });\r\n return deferred.promise;\r\n }\r\n /** @inheritDoc */\r\n refreshAuthToken(token) {\r\n // no-op since we just always call getToken.\r\n }\r\n /**\r\n * Performs a REST request to the given path, with the provided query string parameters,\r\n * and any auth credentials we have.\r\n */\r\n restRequest_(pathString, queryStringParameters = {}, callback) {\r\n queryStringParameters['format'] = 'export';\r\n return Promise.all([\r\n this.authTokenProvider_.getToken(/*forceRefresh=*/ false),\r\n this.appCheckTokenProvider_.getToken(/*forceRefresh=*/ false)\r\n ]).then(([authToken, appCheckToken]) => {\r\n if (authToken && authToken.accessToken) {\r\n queryStringParameters['auth'] = authToken.accessToken;\r\n }\r\n if (appCheckToken && appCheckToken.token) {\r\n queryStringParameters['ac'] = appCheckToken.token;\r\n }\r\n const url = (this.repoInfo_.secure ? 'https://' : 'http://') +\r\n this.repoInfo_.host +\r\n pathString +\r\n '?' +\r\n 'ns=' +\r\n this.repoInfo_.namespace +\r\n querystring(queryStringParameters);\r\n this.log_('Sending REST request for ' + url);\r\n const xhr = new XMLHttpRequest();\r\n xhr.onreadystatechange = () => {\r\n if (callback && xhr.readyState === 4) {\r\n this.log_('REST Response for ' + url + ' received. status:', xhr.status, 'response:', xhr.responseText);\r\n let res = null;\r\n if (xhr.status >= 200 && xhr.status < 300) {\r\n try {\r\n res = jsonEval(xhr.responseText);\r\n }\r\n catch (e) {\r\n warn('Failed to parse JSON response for ' +\r\n url +\r\n ': ' +\r\n xhr.responseText);\r\n }\r\n callback(null, res);\r\n }\r\n else {\r\n // 401 and 404 are expected.\r\n if (xhr.status !== 401 && xhr.status !== 404) {\r\n warn('Got unsuccessful REST response for ' +\r\n url +\r\n ' Status: ' +\r\n xhr.status);\r\n }\r\n callback(xhr.status);\r\n }\r\n callback = null;\r\n }\r\n };\r\n xhr.open('GET', url, /*asynchronous=*/ true);\r\n xhr.send();\r\n });\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * Mutable object which basically just stores a reference to the \"latest\" immutable snapshot.\r\n */\r\nclass SnapshotHolder {\r\n constructor() {\r\n this.rootNode_ = ChildrenNode.EMPTY_NODE;\r\n }\r\n getNode(path) {\r\n return this.rootNode_.getChild(path);\r\n }\r\n updateSnapshot(path, newSnapshotNode) {\r\n this.rootNode_ = this.rootNode_.updateChild(path, newSnapshotNode);\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nfunction newSparseSnapshotTree() {\r\n return {\r\n value: null,\r\n children: new Map()\r\n };\r\n}\r\n/**\r\n * Stores the given node at the specified path. If there is already a node\r\n * at a shallower path, it merges the new data into that snapshot node.\r\n *\r\n * @param path - Path to look up snapshot for.\r\n * @param data - The new data, or null.\r\n */\r\nfunction sparseSnapshotTreeRemember(sparseSnapshotTree, path, data) {\r\n if (pathIsEmpty(path)) {\r\n sparseSnapshotTree.value = data;\r\n sparseSnapshotTree.children.clear();\r\n }\r\n else if (sparseSnapshotTree.value !== null) {\r\n sparseSnapshotTree.value = sparseSnapshotTree.value.updateChild(path, data);\r\n }\r\n else {\r\n const childKey = pathGetFront(path);\r\n if (!sparseSnapshotTree.children.has(childKey)) {\r\n sparseSnapshotTree.children.set(childKey, newSparseSnapshotTree());\r\n }\r\n const child = sparseSnapshotTree.children.get(childKey);\r\n path = pathPopFront(path);\r\n sparseSnapshotTreeRemember(child, path, data);\r\n }\r\n}\r\n/**\r\n * Purge the data at path from the cache.\r\n *\r\n * @param path - Path to look up snapshot for.\r\n * @returns True if this node should now be removed.\r\n */\r\nfunction sparseSnapshotTreeForget(sparseSnapshotTree, path) {\r\n if (pathIsEmpty(path)) {\r\n sparseSnapshotTree.value = null;\r\n sparseSnapshotTree.children.clear();\r\n return true;\r\n }\r\n else {\r\n if (sparseSnapshotTree.value !== null) {\r\n if (sparseSnapshotTree.value.isLeafNode()) {\r\n // We're trying to forget a node that doesn't exist\r\n return false;\r\n }\r\n else {\r\n const value = sparseSnapshotTree.value;\r\n sparseSnapshotTree.value = null;\r\n value.forEachChild(PRIORITY_INDEX, (key, tree) => {\r\n sparseSnapshotTreeRemember(sparseSnapshotTree, new Path(key), tree);\r\n });\r\n return sparseSnapshotTreeForget(sparseSnapshotTree, path);\r\n }\r\n }\r\n else if (sparseSnapshotTree.children.size > 0) {\r\n const childKey = pathGetFront(path);\r\n path = pathPopFront(path);\r\n if (sparseSnapshotTree.children.has(childKey)) {\r\n const safeToRemove = sparseSnapshotTreeForget(sparseSnapshotTree.children.get(childKey), path);\r\n if (safeToRemove) {\r\n sparseSnapshotTree.children.delete(childKey);\r\n }\r\n }\r\n return sparseSnapshotTree.children.size === 0;\r\n }\r\n else {\r\n return true;\r\n }\r\n }\r\n}\r\n/**\r\n * Recursively iterates through all of the stored tree and calls the\r\n * callback on each one.\r\n *\r\n * @param prefixPath - Path to look up node for.\r\n * @param func - The function to invoke for each tree.\r\n */\r\nfunction sparseSnapshotTreeForEachTree(sparseSnapshotTree, prefixPath, func) {\r\n if (sparseSnapshotTree.value !== null) {\r\n func(prefixPath, sparseSnapshotTree.value);\r\n }\r\n else {\r\n sparseSnapshotTreeForEachChild(sparseSnapshotTree, (key, tree) => {\r\n const path = new Path(prefixPath.toString() + '/' + key);\r\n sparseSnapshotTreeForEachTree(tree, path, func);\r\n });\r\n }\r\n}\r\n/**\r\n * Iterates through each immediate child and triggers the callback.\r\n * Only seems to be used in tests.\r\n *\r\n * @param func - The function to invoke for each child.\r\n */\r\nfunction sparseSnapshotTreeForEachChild(sparseSnapshotTree, func) {\r\n sparseSnapshotTree.children.forEach((tree, key) => {\r\n func(key, tree);\r\n });\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * Returns the delta from the previous call to get stats.\r\n *\r\n * @param collection_ - The collection to \"listen\" to.\r\n */\r\nclass StatsListener {\r\n constructor(collection_) {\r\n this.collection_ = collection_;\r\n this.last_ = null;\r\n }\r\n get() {\r\n const newStats = this.collection_.get();\r\n const delta = Object.assign({}, newStats);\r\n if (this.last_) {\r\n each(this.last_, (stat, value) => {\r\n delta[stat] = delta[stat] - value;\r\n });\r\n }\r\n this.last_ = newStats;\r\n return delta;\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n// Assuming some apps may have a short amount of time on page, and a bulk of firebase operations probably\r\n// happen on page load, we try to report our first set of stats pretty quickly, but we wait at least 10\r\n// seconds to try to ensure the Firebase connection is established / settled.\r\nconst FIRST_STATS_MIN_TIME = 10 * 1000;\r\nconst FIRST_STATS_MAX_TIME = 30 * 1000;\r\n// We'll continue to report stats on average every 5 minutes.\r\nconst REPORT_STATS_INTERVAL = 5 * 60 * 1000;\r\nclass StatsReporter {\r\n constructor(collection, server_) {\r\n this.server_ = server_;\r\n this.statsToReport_ = {};\r\n this.statsListener_ = new StatsListener(collection);\r\n const timeout = FIRST_STATS_MIN_TIME +\r\n (FIRST_STATS_MAX_TIME - FIRST_STATS_MIN_TIME) * Math.random();\r\n setTimeoutNonBlocking(this.reportStats_.bind(this), Math.floor(timeout));\r\n }\r\n reportStats_() {\r\n const stats = this.statsListener_.get();\r\n const reportedStats = {};\r\n let haveStatsToReport = false;\r\n each(stats, (stat, value) => {\r\n if (value > 0 && contains(this.statsToReport_, stat)) {\r\n reportedStats[stat] = value;\r\n haveStatsToReport = true;\r\n }\r\n });\r\n if (haveStatsToReport) {\r\n this.server_.reportStats(reportedStats);\r\n }\r\n // queue our next run.\r\n setTimeoutNonBlocking(this.reportStats_.bind(this), Math.floor(Math.random() * 2 * REPORT_STATS_INTERVAL));\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n *\r\n * @enum\r\n */\r\nvar OperationType;\r\n(function (OperationType) {\r\n OperationType[OperationType[\"OVERWRITE\"] = 0] = \"OVERWRITE\";\r\n OperationType[OperationType[\"MERGE\"] = 1] = \"MERGE\";\r\n OperationType[OperationType[\"ACK_USER_WRITE\"] = 2] = \"ACK_USER_WRITE\";\r\n OperationType[OperationType[\"LISTEN_COMPLETE\"] = 3] = \"LISTEN_COMPLETE\";\r\n})(OperationType || (OperationType = {}));\r\nfunction newOperationSourceUser() {\r\n return {\r\n fromUser: true,\r\n fromServer: false,\r\n queryId: null,\r\n tagged: false\r\n };\r\n}\r\nfunction newOperationSourceServer() {\r\n return {\r\n fromUser: false,\r\n fromServer: true,\r\n queryId: null,\r\n tagged: false\r\n };\r\n}\r\nfunction newOperationSourceServerTaggedQuery(queryId) {\r\n return {\r\n fromUser: false,\r\n fromServer: true,\r\n queryId,\r\n tagged: true\r\n };\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nclass AckUserWrite {\r\n /**\r\n * @param affectedTree - A tree containing true for each affected path. Affected paths can't overlap.\r\n */\r\n constructor(\r\n /** @inheritDoc */ path, \r\n /** @inheritDoc */ affectedTree, \r\n /** @inheritDoc */ revert) {\r\n this.path = path;\r\n this.affectedTree = affectedTree;\r\n this.revert = revert;\r\n /** @inheritDoc */\r\n this.type = OperationType.ACK_USER_WRITE;\r\n /** @inheritDoc */\r\n this.source = newOperationSourceUser();\r\n }\r\n operationForChild(childName) {\r\n if (!pathIsEmpty(this.path)) {\r\n assert(pathGetFront(this.path) === childName, 'operationForChild called for unrelated child.');\r\n return new AckUserWrite(pathPopFront(this.path), this.affectedTree, this.revert);\r\n }\r\n else if (this.affectedTree.value != null) {\r\n assert(this.affectedTree.children.isEmpty(), 'affectedTree should not have overlapping affected paths.');\r\n // All child locations are affected as well; just return same operation.\r\n return this;\r\n }\r\n else {\r\n const childTree = this.affectedTree.subtree(new Path(childName));\r\n return new AckUserWrite(newEmptyPath(), childTree, this.revert);\r\n }\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nclass ListenComplete {\r\n constructor(source, path) {\r\n this.source = source;\r\n this.path = path;\r\n /** @inheritDoc */\r\n this.type = OperationType.LISTEN_COMPLETE;\r\n }\r\n operationForChild(childName) {\r\n if (pathIsEmpty(this.path)) {\r\n return new ListenComplete(this.source, newEmptyPath());\r\n }\r\n else {\r\n return new ListenComplete(this.source, pathPopFront(this.path));\r\n }\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nclass Overwrite {\r\n constructor(source, path, snap) {\r\n this.source = source;\r\n this.path = path;\r\n this.snap = snap;\r\n /** @inheritDoc */\r\n this.type = OperationType.OVERWRITE;\r\n }\r\n operationForChild(childName) {\r\n if (pathIsEmpty(this.path)) {\r\n return new Overwrite(this.source, newEmptyPath(), this.snap.getImmediateChild(childName));\r\n }\r\n else {\r\n return new Overwrite(this.source, pathPopFront(this.path), this.snap);\r\n }\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nclass Merge {\r\n constructor(\r\n /** @inheritDoc */ source, \r\n /** @inheritDoc */ path, \r\n /** @inheritDoc */ children) {\r\n this.source = source;\r\n this.path = path;\r\n this.children = children;\r\n /** @inheritDoc */\r\n this.type = OperationType.MERGE;\r\n }\r\n operationForChild(childName) {\r\n if (pathIsEmpty(this.path)) {\r\n const childTree = this.children.subtree(new Path(childName));\r\n if (childTree.isEmpty()) {\r\n // This child is unaffected\r\n return null;\r\n }\r\n else if (childTree.value) {\r\n // We have a snapshot for the child in question. This becomes an overwrite of the child.\r\n return new Overwrite(this.source, newEmptyPath(), childTree.value);\r\n }\r\n else {\r\n // This is a merge at a deeper level\r\n return new Merge(this.source, newEmptyPath(), childTree);\r\n }\r\n }\r\n else {\r\n assert(pathGetFront(this.path) === childName, \"Can't get a merge for a child not on the path of the operation\");\r\n return new Merge(this.source, pathPopFront(this.path), this.children);\r\n }\r\n }\r\n toString() {\r\n return ('Operation(' +\r\n this.path +\r\n ': ' +\r\n this.source.toString() +\r\n ' merge: ' +\r\n this.children.toString() +\r\n ')');\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * A cache node only stores complete children. Additionally it holds a flag whether the node can be considered fully\r\n * initialized in the sense that we know at one point in time this represented a valid state of the world, e.g.\r\n * initialized with data from the server, or a complete overwrite by the client. The filtered flag also tracks\r\n * whether a node potentially had children removed due to a filter.\r\n */\r\nclass CacheNode {\r\n constructor(node_, fullyInitialized_, filtered_) {\r\n this.node_ = node_;\r\n this.fullyInitialized_ = fullyInitialized_;\r\n this.filtered_ = filtered_;\r\n }\r\n /**\r\n * Returns whether this node was fully initialized with either server data or a complete overwrite by the client\r\n */\r\n isFullyInitialized() {\r\n return this.fullyInitialized_;\r\n }\r\n /**\r\n * Returns whether this node is potentially missing children due to a filter applied to the node\r\n */\r\n isFiltered() {\r\n return this.filtered_;\r\n }\r\n isCompleteForPath(path) {\r\n if (pathIsEmpty(path)) {\r\n return this.isFullyInitialized() && !this.filtered_;\r\n }\r\n const childKey = pathGetFront(path);\r\n return this.isCompleteForChild(childKey);\r\n }\r\n isCompleteForChild(key) {\r\n return ((this.isFullyInitialized() && !this.filtered_) || this.node_.hasChild(key));\r\n }\r\n getNode() {\r\n return this.node_;\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * An EventGenerator is used to convert \"raw\" changes (Change) as computed by the\r\n * CacheDiffer into actual events (Event) that can be raised. See generateEventsForChanges()\r\n * for details.\r\n *\r\n */\r\nclass EventGenerator {\r\n constructor(query_) {\r\n this.query_ = query_;\r\n this.index_ = this.query_._queryParams.getIndex();\r\n }\r\n}\r\n/**\r\n * Given a set of raw changes (no moved events and prevName not specified yet), and a set of\r\n * EventRegistrations that should be notified of these changes, generate the actual events to be raised.\r\n *\r\n * Notes:\r\n * - child_moved events will be synthesized at this time for any child_changed events that affect\r\n * our index.\r\n * - prevName will be calculated based on the index ordering.\r\n */\r\nfunction eventGeneratorGenerateEventsForChanges(eventGenerator, changes, eventCache, eventRegistrations) {\r\n const events = [];\r\n const moves = [];\r\n changes.forEach(change => {\r\n if (change.type === \"child_changed\" /* ChangeType.CHILD_CHANGED */ &&\r\n eventGenerator.index_.indexedValueChanged(change.oldSnap, change.snapshotNode)) {\r\n moves.push(changeChildMoved(change.childName, change.snapshotNode));\r\n }\r\n });\r\n eventGeneratorGenerateEventsForType(eventGenerator, events, \"child_removed\" /* ChangeType.CHILD_REMOVED */, changes, eventRegistrations, eventCache);\r\n eventGeneratorGenerateEventsForType(eventGenerator, events, \"child_added\" /* ChangeType.CHILD_ADDED */, changes, eventRegistrations, eventCache);\r\n eventGeneratorGenerateEventsForType(eventGenerator, events, \"child_moved\" /* ChangeType.CHILD_MOVED */, moves, eventRegistrations, eventCache);\r\n eventGeneratorGenerateEventsForType(eventGenerator, events, \"child_changed\" /* ChangeType.CHILD_CHANGED */, changes, eventRegistrations, eventCache);\r\n eventGeneratorGenerateEventsForType(eventGenerator, events, \"value\" /* ChangeType.VALUE */, changes, eventRegistrations, eventCache);\r\n return events;\r\n}\r\n/**\r\n * Given changes of a single change type, generate the corresponding events.\r\n */\r\nfunction eventGeneratorGenerateEventsForType(eventGenerator, events, eventType, changes, registrations, eventCache) {\r\n const filteredChanges = changes.filter(change => change.type === eventType);\r\n filteredChanges.sort((a, b) => eventGeneratorCompareChanges(eventGenerator, a, b));\r\n filteredChanges.forEach(change => {\r\n const materializedChange = eventGeneratorMaterializeSingleChange(eventGenerator, change, eventCache);\r\n registrations.forEach(registration => {\r\n if (registration.respondsTo(change.type)) {\r\n events.push(registration.createEvent(materializedChange, eventGenerator.query_));\r\n }\r\n });\r\n });\r\n}\r\nfunction eventGeneratorMaterializeSingleChange(eventGenerator, change, eventCache) {\r\n if (change.type === 'value' || change.type === 'child_removed') {\r\n return change;\r\n }\r\n else {\r\n change.prevName = eventCache.getPredecessorChildName(change.childName, change.snapshotNode, eventGenerator.index_);\r\n return change;\r\n }\r\n}\r\nfunction eventGeneratorCompareChanges(eventGenerator, a, b) {\r\n if (a.childName == null || b.childName == null) {\r\n throw assertionError('Should only compare child_ events.');\r\n }\r\n const aWrapped = new NamedNode(a.childName, a.snapshotNode);\r\n const bWrapped = new NamedNode(b.childName, b.snapshotNode);\r\n return eventGenerator.index_.compare(aWrapped, bWrapped);\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nfunction newViewCache(eventCache, serverCache) {\r\n return { eventCache, serverCache };\r\n}\r\nfunction viewCacheUpdateEventSnap(viewCache, eventSnap, complete, filtered) {\r\n return newViewCache(new CacheNode(eventSnap, complete, filtered), viewCache.serverCache);\r\n}\r\nfunction viewCacheUpdateServerSnap(viewCache, serverSnap, complete, filtered) {\r\n return newViewCache(viewCache.eventCache, new CacheNode(serverSnap, complete, filtered));\r\n}\r\nfunction viewCacheGetCompleteEventSnap(viewCache) {\r\n return viewCache.eventCache.isFullyInitialized()\r\n ? viewCache.eventCache.getNode()\r\n : null;\r\n}\r\nfunction viewCacheGetCompleteServerSnap(viewCache) {\r\n return viewCache.serverCache.isFullyInitialized()\r\n ? viewCache.serverCache.getNode()\r\n : null;\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nlet emptyChildrenSingleton;\r\n/**\r\n * Singleton empty children collection.\r\n *\r\n */\r\nconst EmptyChildren = () => {\r\n if (!emptyChildrenSingleton) {\r\n emptyChildrenSingleton = new SortedMap(stringCompare);\r\n }\r\n return emptyChildrenSingleton;\r\n};\r\n/**\r\n * A tree with immutable elements.\r\n */\r\nclass ImmutableTree {\r\n constructor(value, children = EmptyChildren()) {\r\n this.value = value;\r\n this.children = children;\r\n }\r\n static fromObject(obj) {\r\n let tree = new ImmutableTree(null);\r\n each(obj, (childPath, childSnap) => {\r\n tree = tree.set(new Path(childPath), childSnap);\r\n });\r\n return tree;\r\n }\r\n /**\r\n * True if the value is empty and there are no children\r\n */\r\n isEmpty() {\r\n return this.value === null && this.children.isEmpty();\r\n }\r\n /**\r\n * Given a path and predicate, return the first node and the path to that node\r\n * where the predicate returns true.\r\n *\r\n * TODO Do a perf test -- If we're creating a bunch of `{path: value:}`\r\n * objects on the way back out, it may be better to pass down a pathSoFar obj.\r\n *\r\n * @param relativePath - The remainder of the path\r\n * @param predicate - The predicate to satisfy to return a node\r\n */\r\n findRootMostMatchingPathAndValue(relativePath, predicate) {\r\n if (this.value != null && predicate(this.value)) {\r\n return { path: newEmptyPath(), value: this.value };\r\n }\r\n else {\r\n if (pathIsEmpty(relativePath)) {\r\n return null;\r\n }\r\n else {\r\n const front = pathGetFront(relativePath);\r\n const child = this.children.get(front);\r\n if (child !== null) {\r\n const childExistingPathAndValue = child.findRootMostMatchingPathAndValue(pathPopFront(relativePath), predicate);\r\n if (childExistingPathAndValue != null) {\r\n const fullPath = pathChild(new Path(front), childExistingPathAndValue.path);\r\n return { path: fullPath, value: childExistingPathAndValue.value };\r\n }\r\n else {\r\n return null;\r\n }\r\n }\r\n else {\r\n return null;\r\n }\r\n }\r\n }\r\n }\r\n /**\r\n * Find, if it exists, the shortest subpath of the given path that points a defined\r\n * value in the tree\r\n */\r\n findRootMostValueAndPath(relativePath) {\r\n return this.findRootMostMatchingPathAndValue(relativePath, () => true);\r\n }\r\n /**\r\n * @returns The subtree at the given path\r\n */\r\n subtree(relativePath) {\r\n if (pathIsEmpty(relativePath)) {\r\n return this;\r\n }\r\n else {\r\n const front = pathGetFront(relativePath);\r\n const childTree = this.children.get(front);\r\n if (childTree !== null) {\r\n return childTree.subtree(pathPopFront(relativePath));\r\n }\r\n else {\r\n return new ImmutableTree(null);\r\n }\r\n }\r\n }\r\n /**\r\n * Sets a value at the specified path.\r\n *\r\n * @param relativePath - Path to set value at.\r\n * @param toSet - Value to set.\r\n * @returns Resulting tree.\r\n */\r\n set(relativePath, toSet) {\r\n if (pathIsEmpty(relativePath)) {\r\n return new ImmutableTree(toSet, this.children);\r\n }\r\n else {\r\n const front = pathGetFront(relativePath);\r\n const child = this.children.get(front) || new ImmutableTree(null);\r\n const newChild = child.set(pathPopFront(relativePath), toSet);\r\n const newChildren = this.children.insert(front, newChild);\r\n return new ImmutableTree(this.value, newChildren);\r\n }\r\n }\r\n /**\r\n * Removes the value at the specified path.\r\n *\r\n * @param relativePath - Path to value to remove.\r\n * @returns Resulting tree.\r\n */\r\n remove(relativePath) {\r\n if (pathIsEmpty(relativePath)) {\r\n if (this.children.isEmpty()) {\r\n return new ImmutableTree(null);\r\n }\r\n else {\r\n return new ImmutableTree(null, this.children);\r\n }\r\n }\r\n else {\r\n const front = pathGetFront(relativePath);\r\n const child = this.children.get(front);\r\n if (child) {\r\n const newChild = child.remove(pathPopFront(relativePath));\r\n let newChildren;\r\n if (newChild.isEmpty()) {\r\n newChildren = this.children.remove(front);\r\n }\r\n else {\r\n newChildren = this.children.insert(front, newChild);\r\n }\r\n if (this.value === null && newChildren.isEmpty()) {\r\n return new ImmutableTree(null);\r\n }\r\n else {\r\n return new ImmutableTree(this.value, newChildren);\r\n }\r\n }\r\n else {\r\n return this;\r\n }\r\n }\r\n }\r\n /**\r\n * Gets a value from the tree.\r\n *\r\n * @param relativePath - Path to get value for.\r\n * @returns Value at path, or null.\r\n */\r\n get(relativePath) {\r\n if (pathIsEmpty(relativePath)) {\r\n return this.value;\r\n }\r\n else {\r\n const front = pathGetFront(relativePath);\r\n const child = this.children.get(front);\r\n if (child) {\r\n return child.get(pathPopFront(relativePath));\r\n }\r\n else {\r\n return null;\r\n }\r\n }\r\n }\r\n /**\r\n * Replace the subtree at the specified path with the given new tree.\r\n *\r\n * @param relativePath - Path to replace subtree for.\r\n * @param newTree - New tree.\r\n * @returns Resulting tree.\r\n */\r\n setTree(relativePath, newTree) {\r\n if (pathIsEmpty(relativePath)) {\r\n return newTree;\r\n }\r\n else {\r\n const front = pathGetFront(relativePath);\r\n const child = this.children.get(front) || new ImmutableTree(null);\r\n const newChild = child.setTree(pathPopFront(relativePath), newTree);\r\n let newChildren;\r\n if (newChild.isEmpty()) {\r\n newChildren = this.children.remove(front);\r\n }\r\n else {\r\n newChildren = this.children.insert(front, newChild);\r\n }\r\n return new ImmutableTree(this.value, newChildren);\r\n }\r\n }\r\n /**\r\n * Performs a depth first fold on this tree. Transforms a tree into a single\r\n * value, given a function that operates on the path to a node, an optional\r\n * current value, and a map of child names to folded subtrees\r\n */\r\n fold(fn) {\r\n return this.fold_(newEmptyPath(), fn);\r\n }\r\n /**\r\n * Recursive helper for public-facing fold() method\r\n */\r\n fold_(pathSoFar, fn) {\r\n const accum = {};\r\n this.children.inorderTraversal((childKey, childTree) => {\r\n accum[childKey] = childTree.fold_(pathChild(pathSoFar, childKey), fn);\r\n });\r\n return fn(pathSoFar, this.value, accum);\r\n }\r\n /**\r\n * Find the first matching value on the given path. Return the result of applying f to it.\r\n */\r\n findOnPath(path, f) {\r\n return this.findOnPath_(path, newEmptyPath(), f);\r\n }\r\n findOnPath_(pathToFollow, pathSoFar, f) {\r\n const result = this.value ? f(pathSoFar, this.value) : false;\r\n if (result) {\r\n return result;\r\n }\r\n else {\r\n if (pathIsEmpty(pathToFollow)) {\r\n return null;\r\n }\r\n else {\r\n const front = pathGetFront(pathToFollow);\r\n const nextChild = this.children.get(front);\r\n if (nextChild) {\r\n return nextChild.findOnPath_(pathPopFront(pathToFollow), pathChild(pathSoFar, front), f);\r\n }\r\n else {\r\n return null;\r\n }\r\n }\r\n }\r\n }\r\n foreachOnPath(path, f) {\r\n return this.foreachOnPath_(path, newEmptyPath(), f);\r\n }\r\n foreachOnPath_(pathToFollow, currentRelativePath, f) {\r\n if (pathIsEmpty(pathToFollow)) {\r\n return this;\r\n }\r\n else {\r\n if (this.value) {\r\n f(currentRelativePath, this.value);\r\n }\r\n const front = pathGetFront(pathToFollow);\r\n const nextChild = this.children.get(front);\r\n if (nextChild) {\r\n return nextChild.foreachOnPath_(pathPopFront(pathToFollow), pathChild(currentRelativePath, front), f);\r\n }\r\n else {\r\n return new ImmutableTree(null);\r\n }\r\n }\r\n }\r\n /**\r\n * Calls the given function for each node in the tree that has a value.\r\n *\r\n * @param f - A function to be called with the path from the root of the tree to\r\n * a node, and the value at that node. Called in depth-first order.\r\n */\r\n foreach(f) {\r\n this.foreach_(newEmptyPath(), f);\r\n }\r\n foreach_(currentRelativePath, f) {\r\n this.children.inorderTraversal((childName, childTree) => {\r\n childTree.foreach_(pathChild(currentRelativePath, childName), f);\r\n });\r\n if (this.value) {\r\n f(currentRelativePath, this.value);\r\n }\r\n }\r\n foreachChild(f) {\r\n this.children.inorderTraversal((childName, childTree) => {\r\n if (childTree.value) {\r\n f(childName, childTree.value);\r\n }\r\n });\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * This class holds a collection of writes that can be applied to nodes in unison. It abstracts away the logic with\r\n * dealing with priority writes and multiple nested writes. At any given path there is only allowed to be one write\r\n * modifying that path. Any write to an existing path or shadowing an existing path will modify that existing write\r\n * to reflect the write added.\r\n */\r\nclass CompoundWrite {\r\n constructor(writeTree_) {\r\n this.writeTree_ = writeTree_;\r\n }\r\n static empty() {\r\n return new CompoundWrite(new ImmutableTree(null));\r\n }\r\n}\r\nfunction compoundWriteAddWrite(compoundWrite, path, node) {\r\n if (pathIsEmpty(path)) {\r\n return new CompoundWrite(new ImmutableTree(node));\r\n }\r\n else {\r\n const rootmost = compoundWrite.writeTree_.findRootMostValueAndPath(path);\r\n if (rootmost != null) {\r\n const rootMostPath = rootmost.path;\r\n let value = rootmost.value;\r\n const relativePath = newRelativePath(rootMostPath, path);\r\n value = value.updateChild(relativePath, node);\r\n return new CompoundWrite(compoundWrite.writeTree_.set(rootMostPath, value));\r\n }\r\n else {\r\n const subtree = new ImmutableTree(node);\r\n const newWriteTree = compoundWrite.writeTree_.setTree(path, subtree);\r\n return new CompoundWrite(newWriteTree);\r\n }\r\n }\r\n}\r\nfunction compoundWriteAddWrites(compoundWrite, path, updates) {\r\n let newWrite = compoundWrite;\r\n each(updates, (childKey, node) => {\r\n newWrite = compoundWriteAddWrite(newWrite, pathChild(path, childKey), node);\r\n });\r\n return newWrite;\r\n}\r\n/**\r\n * Will remove a write at the given path and deeper paths. This will not modify a write at a higher\r\n * location, which must be removed by calling this method with that path.\r\n *\r\n * @param compoundWrite - The CompoundWrite to remove.\r\n * @param path - The path at which a write and all deeper writes should be removed\r\n * @returns The new CompoundWrite with the removed path\r\n */\r\nfunction compoundWriteRemoveWrite(compoundWrite, path) {\r\n if (pathIsEmpty(path)) {\r\n return CompoundWrite.empty();\r\n }\r\n else {\r\n const newWriteTree = compoundWrite.writeTree_.setTree(path, new ImmutableTree(null));\r\n return new CompoundWrite(newWriteTree);\r\n }\r\n}\r\n/**\r\n * Returns whether this CompoundWrite will fully overwrite a node at a given location and can therefore be\r\n * considered \"complete\".\r\n *\r\n * @param compoundWrite - The CompoundWrite to check.\r\n * @param path - The path to check for\r\n * @returns Whether there is a complete write at that path\r\n */\r\nfunction compoundWriteHasCompleteWrite(compoundWrite, path) {\r\n return compoundWriteGetCompleteNode(compoundWrite, path) != null;\r\n}\r\n/**\r\n * Returns a node for a path if and only if the node is a \"complete\" overwrite at that path. This will not aggregate\r\n * writes from deeper paths, but will return child nodes from a more shallow path.\r\n *\r\n * @param compoundWrite - The CompoundWrite to get the node from.\r\n * @param path - The path to get a complete write\r\n * @returns The node if complete at that path, or null otherwise.\r\n */\r\nfunction compoundWriteGetCompleteNode(compoundWrite, path) {\r\n const rootmost = compoundWrite.writeTree_.findRootMostValueAndPath(path);\r\n if (rootmost != null) {\r\n return compoundWrite.writeTree_\r\n .get(rootmost.path)\r\n .getChild(newRelativePath(rootmost.path, path));\r\n }\r\n else {\r\n return null;\r\n }\r\n}\r\n/**\r\n * Returns all children that are guaranteed to be a complete overwrite.\r\n *\r\n * @param compoundWrite - The CompoundWrite to get children from.\r\n * @returns A list of all complete children.\r\n */\r\nfunction compoundWriteGetCompleteChildren(compoundWrite) {\r\n const children = [];\r\n const node = compoundWrite.writeTree_.value;\r\n if (node != null) {\r\n // If it's a leaf node, it has no children; so nothing to do.\r\n if (!node.isLeafNode()) {\r\n node.forEachChild(PRIORITY_INDEX, (childName, childNode) => {\r\n children.push(new NamedNode(childName, childNode));\r\n });\r\n }\r\n }\r\n else {\r\n compoundWrite.writeTree_.children.inorderTraversal((childName, childTree) => {\r\n if (childTree.value != null) {\r\n children.push(new NamedNode(childName, childTree.value));\r\n }\r\n });\r\n }\r\n return children;\r\n}\r\nfunction compoundWriteChildCompoundWrite(compoundWrite, path) {\r\n if (pathIsEmpty(path)) {\r\n return compoundWrite;\r\n }\r\n else {\r\n const shadowingNode = compoundWriteGetCompleteNode(compoundWrite, path);\r\n if (shadowingNode != null) {\r\n return new CompoundWrite(new ImmutableTree(shadowingNode));\r\n }\r\n else {\r\n return new CompoundWrite(compoundWrite.writeTree_.subtree(path));\r\n }\r\n }\r\n}\r\n/**\r\n * Returns true if this CompoundWrite is empty and therefore does not modify any nodes.\r\n * @returns Whether this CompoundWrite is empty\r\n */\r\nfunction compoundWriteIsEmpty(compoundWrite) {\r\n return compoundWrite.writeTree_.isEmpty();\r\n}\r\n/**\r\n * Applies this CompoundWrite to a node. The node is returned with all writes from this CompoundWrite applied to the\r\n * node\r\n * @param node - The node to apply this CompoundWrite to\r\n * @returns The node with all writes applied\r\n */\r\nfunction compoundWriteApply(compoundWrite, node) {\r\n return applySubtreeWrite(newEmptyPath(), compoundWrite.writeTree_, node);\r\n}\r\nfunction applySubtreeWrite(relativePath, writeTree, node) {\r\n if (writeTree.value != null) {\r\n // Since there a write is always a leaf, we're done here\r\n return node.updateChild(relativePath, writeTree.value);\r\n }\r\n else {\r\n let priorityWrite = null;\r\n writeTree.children.inorderTraversal((childKey, childTree) => {\r\n if (childKey === '.priority') {\r\n // Apply priorities at the end so we don't update priorities for either empty nodes or forget\r\n // to apply priorities to empty nodes that are later filled\r\n assert(childTree.value !== null, 'Priority writes must always be leaf nodes');\r\n priorityWrite = childTree.value;\r\n }\r\n else {\r\n node = applySubtreeWrite(pathChild(relativePath, childKey), childTree, node);\r\n }\r\n });\r\n // If there was a priority write, we only apply it if the node is not empty\r\n if (!node.getChild(relativePath).isEmpty() && priorityWrite !== null) {\r\n node = node.updateChild(pathChild(relativePath, '.priority'), priorityWrite);\r\n }\r\n return node;\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * Create a new WriteTreeRef for the given path. For use with a new sync point at the given path.\r\n *\r\n */\r\nfunction writeTreeChildWrites(writeTree, path) {\r\n return newWriteTreeRef(path, writeTree);\r\n}\r\n/**\r\n * Record a new overwrite from user code.\r\n *\r\n * @param visible - This is set to false by some transactions. It should be excluded from event caches\r\n */\r\nfunction writeTreeAddOverwrite(writeTree, path, snap, writeId, visible) {\r\n assert(writeId > writeTree.lastWriteId, 'Stacking an older write on top of newer ones');\r\n if (visible === undefined) {\r\n visible = true;\r\n }\r\n writeTree.allWrites.push({\r\n path,\r\n snap,\r\n writeId,\r\n visible\r\n });\r\n if (visible) {\r\n writeTree.visibleWrites = compoundWriteAddWrite(writeTree.visibleWrites, path, snap);\r\n }\r\n writeTree.lastWriteId = writeId;\r\n}\r\n/**\r\n * Record a new merge from user code.\r\n */\r\nfunction writeTreeAddMerge(writeTree, path, changedChildren, writeId) {\r\n assert(writeId > writeTree.lastWriteId, 'Stacking an older merge on top of newer ones');\r\n writeTree.allWrites.push({\r\n path,\r\n children: changedChildren,\r\n writeId,\r\n visible: true\r\n });\r\n writeTree.visibleWrites = compoundWriteAddWrites(writeTree.visibleWrites, path, changedChildren);\r\n writeTree.lastWriteId = writeId;\r\n}\r\nfunction writeTreeGetWrite(writeTree, writeId) {\r\n for (let i = 0; i < writeTree.allWrites.length; i++) {\r\n const record = writeTree.allWrites[i];\r\n if (record.writeId === writeId) {\r\n return record;\r\n }\r\n }\r\n return null;\r\n}\r\n/**\r\n * Remove a write (either an overwrite or merge) that has been successfully acknowledge by the server. Recalculates\r\n * the tree if necessary. We return true if it may have been visible, meaning views need to reevaluate.\r\n *\r\n * @returns true if the write may have been visible (meaning we'll need to reevaluate / raise\r\n * events as a result).\r\n */\r\nfunction writeTreeRemoveWrite(writeTree, writeId) {\r\n // Note: disabling this check. It could be a transaction that preempted another transaction, and thus was applied\r\n // out of order.\r\n //const validClear = revert || this.allWrites_.length === 0 || writeId <= this.allWrites_[0].writeId;\r\n //assert(validClear, \"Either we don't have this write, or it's the first one in the queue\");\r\n const idx = writeTree.allWrites.findIndex(s => {\r\n return s.writeId === writeId;\r\n });\r\n assert(idx >= 0, 'removeWrite called with nonexistent writeId.');\r\n const writeToRemove = writeTree.allWrites[idx];\r\n writeTree.allWrites.splice(idx, 1);\r\n let removedWriteWasVisible = writeToRemove.visible;\r\n let removedWriteOverlapsWithOtherWrites = false;\r\n let i = writeTree.allWrites.length - 1;\r\n while (removedWriteWasVisible && i >= 0) {\r\n const currentWrite = writeTree.allWrites[i];\r\n if (currentWrite.visible) {\r\n if (i >= idx &&\r\n writeTreeRecordContainsPath_(currentWrite, writeToRemove.path)) {\r\n // The removed write was completely shadowed by a subsequent write.\r\n removedWriteWasVisible = false;\r\n }\r\n else if (pathContains(writeToRemove.path, currentWrite.path)) {\r\n // Either we're covering some writes or they're covering part of us (depending on which came first).\r\n removedWriteOverlapsWithOtherWrites = true;\r\n }\r\n }\r\n i--;\r\n }\r\n if (!removedWriteWasVisible) {\r\n return false;\r\n }\r\n else if (removedWriteOverlapsWithOtherWrites) {\r\n // There's some shadowing going on. Just rebuild the visible writes from scratch.\r\n writeTreeResetTree_(writeTree);\r\n return true;\r\n }\r\n else {\r\n // There's no shadowing. We can safely just remove the write(s) from visibleWrites.\r\n if (writeToRemove.snap) {\r\n writeTree.visibleWrites = compoundWriteRemoveWrite(writeTree.visibleWrites, writeToRemove.path);\r\n }\r\n else {\r\n const children = writeToRemove.children;\r\n each(children, (childName) => {\r\n writeTree.visibleWrites = compoundWriteRemoveWrite(writeTree.visibleWrites, pathChild(writeToRemove.path, childName));\r\n });\r\n }\r\n return true;\r\n }\r\n}\r\nfunction writeTreeRecordContainsPath_(writeRecord, path) {\r\n if (writeRecord.snap) {\r\n return pathContains(writeRecord.path, path);\r\n }\r\n else {\r\n for (const childName in writeRecord.children) {\r\n if (writeRecord.children.hasOwnProperty(childName) &&\r\n pathContains(pathChild(writeRecord.path, childName), path)) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n}\r\n/**\r\n * Re-layer the writes and merges into a tree so we can efficiently calculate event snapshots\r\n */\r\nfunction writeTreeResetTree_(writeTree) {\r\n writeTree.visibleWrites = writeTreeLayerTree_(writeTree.allWrites, writeTreeDefaultFilter_, newEmptyPath());\r\n if (writeTree.allWrites.length > 0) {\r\n writeTree.lastWriteId =\r\n writeTree.allWrites[writeTree.allWrites.length - 1].writeId;\r\n }\r\n else {\r\n writeTree.lastWriteId = -1;\r\n }\r\n}\r\n/**\r\n * The default filter used when constructing the tree. Keep everything that's visible.\r\n */\r\nfunction writeTreeDefaultFilter_(write) {\r\n return write.visible;\r\n}\r\n/**\r\n * Static method. Given an array of WriteRecords, a filter for which ones to include, and a path, construct the tree of\r\n * event data at that path.\r\n */\r\nfunction writeTreeLayerTree_(writes, filter, treeRoot) {\r\n let compoundWrite = CompoundWrite.empty();\r\n for (let i = 0; i < writes.length; ++i) {\r\n const write = writes[i];\r\n // Theory, a later set will either:\r\n // a) abort a relevant transaction, so no need to worry about excluding it from calculating that transaction\r\n // b) not be relevant to a transaction (separate branch), so again will not affect the data for that transaction\r\n if (filter(write)) {\r\n const writePath = write.path;\r\n let relativePath;\r\n if (write.snap) {\r\n if (pathContains(treeRoot, writePath)) {\r\n relativePath = newRelativePath(treeRoot, writePath);\r\n compoundWrite = compoundWriteAddWrite(compoundWrite, relativePath, write.snap);\r\n }\r\n else if (pathContains(writePath, treeRoot)) {\r\n relativePath = newRelativePath(writePath, treeRoot);\r\n compoundWrite = compoundWriteAddWrite(compoundWrite, newEmptyPath(), write.snap.getChild(relativePath));\r\n }\r\n else ;\r\n }\r\n else if (write.children) {\r\n if (pathContains(treeRoot, writePath)) {\r\n relativePath = newRelativePath(treeRoot, writePath);\r\n compoundWrite = compoundWriteAddWrites(compoundWrite, relativePath, write.children);\r\n }\r\n else if (pathContains(writePath, treeRoot)) {\r\n relativePath = newRelativePath(writePath, treeRoot);\r\n if (pathIsEmpty(relativePath)) {\r\n compoundWrite = compoundWriteAddWrites(compoundWrite, newEmptyPath(), write.children);\r\n }\r\n else {\r\n const child = safeGet(write.children, pathGetFront(relativePath));\r\n if (child) {\r\n // There exists a child in this node that matches the root path\r\n const deepNode = child.getChild(pathPopFront(relativePath));\r\n compoundWrite = compoundWriteAddWrite(compoundWrite, newEmptyPath(), deepNode);\r\n }\r\n }\r\n }\r\n else ;\r\n }\r\n else {\r\n throw assertionError('WriteRecord should have .snap or .children');\r\n }\r\n }\r\n }\r\n return compoundWrite;\r\n}\r\n/**\r\n * Given optional, underlying server data, and an optional set of constraints (exclude some sets, include hidden\r\n * writes), attempt to calculate a complete snapshot for the given path\r\n *\r\n * @param writeIdsToExclude - An optional set to be excluded\r\n * @param includeHiddenWrites - Defaults to false, whether or not to layer on writes with visible set to false\r\n */\r\nfunction writeTreeCalcCompleteEventCache(writeTree, treePath, completeServerCache, writeIdsToExclude, includeHiddenWrites) {\r\n if (!writeIdsToExclude && !includeHiddenWrites) {\r\n const shadowingNode = compoundWriteGetCompleteNode(writeTree.visibleWrites, treePath);\r\n if (shadowingNode != null) {\r\n return shadowingNode;\r\n }\r\n else {\r\n const subMerge = compoundWriteChildCompoundWrite(writeTree.visibleWrites, treePath);\r\n if (compoundWriteIsEmpty(subMerge)) {\r\n return completeServerCache;\r\n }\r\n else if (completeServerCache == null &&\r\n !compoundWriteHasCompleteWrite(subMerge, newEmptyPath())) {\r\n // We wouldn't have a complete snapshot, since there's no underlying data and no complete shadow\r\n return null;\r\n }\r\n else {\r\n const layeredCache = completeServerCache || ChildrenNode.EMPTY_NODE;\r\n return compoundWriteApply(subMerge, layeredCache);\r\n }\r\n }\r\n }\r\n else {\r\n const merge = compoundWriteChildCompoundWrite(writeTree.visibleWrites, treePath);\r\n if (!includeHiddenWrites && compoundWriteIsEmpty(merge)) {\r\n return completeServerCache;\r\n }\r\n else {\r\n // If the server cache is null, and we don't have a complete cache, we need to return null\r\n if (!includeHiddenWrites &&\r\n completeServerCache == null &&\r\n !compoundWriteHasCompleteWrite(merge, newEmptyPath())) {\r\n return null;\r\n }\r\n else {\r\n const filter = function (write) {\r\n return ((write.visible || includeHiddenWrites) &&\r\n (!writeIdsToExclude ||\r\n !~writeIdsToExclude.indexOf(write.writeId)) &&\r\n (pathContains(write.path, treePath) ||\r\n pathContains(treePath, write.path)));\r\n };\r\n const mergeAtPath = writeTreeLayerTree_(writeTree.allWrites, filter, treePath);\r\n const layeredCache = completeServerCache || ChildrenNode.EMPTY_NODE;\r\n return compoundWriteApply(mergeAtPath, layeredCache);\r\n }\r\n }\r\n }\r\n}\r\n/**\r\n * With optional, underlying server data, attempt to return a children node of children that we have complete data for.\r\n * Used when creating new views, to pre-fill their complete event children snapshot.\r\n */\r\nfunction writeTreeCalcCompleteEventChildren(writeTree, treePath, completeServerChildren) {\r\n let completeChildren = ChildrenNode.EMPTY_NODE;\r\n const topLevelSet = compoundWriteGetCompleteNode(writeTree.visibleWrites, treePath);\r\n if (topLevelSet) {\r\n if (!topLevelSet.isLeafNode()) {\r\n // we're shadowing everything. Return the children.\r\n topLevelSet.forEachChild(PRIORITY_INDEX, (childName, childSnap) => {\r\n completeChildren = completeChildren.updateImmediateChild(childName, childSnap);\r\n });\r\n }\r\n return completeChildren;\r\n }\r\n else if (completeServerChildren) {\r\n // Layer any children we have on top of this\r\n // We know we don't have a top-level set, so just enumerate existing children\r\n const merge = compoundWriteChildCompoundWrite(writeTree.visibleWrites, treePath);\r\n completeServerChildren.forEachChild(PRIORITY_INDEX, (childName, childNode) => {\r\n const node = compoundWriteApply(compoundWriteChildCompoundWrite(merge, new Path(childName)), childNode);\r\n completeChildren = completeChildren.updateImmediateChild(childName, node);\r\n });\r\n // Add any complete children we have from the set\r\n compoundWriteGetCompleteChildren(merge).forEach(namedNode => {\r\n completeChildren = completeChildren.updateImmediateChild(namedNode.name, namedNode.node);\r\n });\r\n return completeChildren;\r\n }\r\n else {\r\n // We don't have anything to layer on top of. Layer on any children we have\r\n // Note that we can return an empty snap if we have a defined delete\r\n const merge = compoundWriteChildCompoundWrite(writeTree.visibleWrites, treePath);\r\n compoundWriteGetCompleteChildren(merge).forEach(namedNode => {\r\n completeChildren = completeChildren.updateImmediateChild(namedNode.name, namedNode.node);\r\n });\r\n return completeChildren;\r\n }\r\n}\r\n/**\r\n * Given that the underlying server data has updated, determine what, if anything, needs to be\r\n * applied to the event cache.\r\n *\r\n * Possibilities:\r\n *\r\n * 1. No writes are shadowing. Events should be raised, the snap to be applied comes from the server data\r\n *\r\n * 2. Some write is completely shadowing. No events to be raised\r\n *\r\n * 3. Is partially shadowed. Events\r\n *\r\n * Either existingEventSnap or existingServerSnap must exist\r\n */\r\nfunction writeTreeCalcEventCacheAfterServerOverwrite(writeTree, treePath, childPath, existingEventSnap, existingServerSnap) {\r\n assert(existingEventSnap || existingServerSnap, 'Either existingEventSnap or existingServerSnap must exist');\r\n const path = pathChild(treePath, childPath);\r\n if (compoundWriteHasCompleteWrite(writeTree.visibleWrites, path)) {\r\n // At this point we can probably guarantee that we're in case 2, meaning no events\r\n // May need to check visibility while doing the findRootMostValueAndPath call\r\n return null;\r\n }\r\n else {\r\n // No complete shadowing. We're either partially shadowing or not shadowing at all.\r\n const childMerge = compoundWriteChildCompoundWrite(writeTree.visibleWrites, path);\r\n if (compoundWriteIsEmpty(childMerge)) {\r\n // We're not shadowing at all. Case 1\r\n return existingServerSnap.getChild(childPath);\r\n }\r\n else {\r\n // This could be more efficient if the serverNode + updates doesn't change the eventSnap\r\n // However this is tricky to find out, since user updates don't necessary change the server\r\n // snap, e.g. priority updates on empty nodes, or deep deletes. Another special case is if the server\r\n // adds nodes, but doesn't change any existing writes. It is therefore not enough to\r\n // only check if the updates change the serverNode.\r\n // Maybe check if the merge tree contains these special cases and only do a full overwrite in that case?\r\n return compoundWriteApply(childMerge, existingServerSnap.getChild(childPath));\r\n }\r\n }\r\n}\r\n/**\r\n * Returns a complete child for a given server snap after applying all user writes or null if there is no\r\n * complete child for this ChildKey.\r\n */\r\nfunction writeTreeCalcCompleteChild(writeTree, treePath, childKey, existingServerSnap) {\r\n const path = pathChild(treePath, childKey);\r\n const shadowingNode = compoundWriteGetCompleteNode(writeTree.visibleWrites, path);\r\n if (shadowingNode != null) {\r\n return shadowingNode;\r\n }\r\n else {\r\n if (existingServerSnap.isCompleteForChild(childKey)) {\r\n const childMerge = compoundWriteChildCompoundWrite(writeTree.visibleWrites, path);\r\n return compoundWriteApply(childMerge, existingServerSnap.getNode().getImmediateChild(childKey));\r\n }\r\n else {\r\n return null;\r\n }\r\n }\r\n}\r\n/**\r\n * Returns a node if there is a complete overwrite for this path. More specifically, if there is a write at\r\n * a higher path, this will return the child of that write relative to the write and this path.\r\n * Returns null if there is no write at this path.\r\n */\r\nfunction writeTreeShadowingWrite(writeTree, path) {\r\n return compoundWriteGetCompleteNode(writeTree.visibleWrites, path);\r\n}\r\n/**\r\n * This method is used when processing child remove events on a query. If we can, we pull in children that were outside\r\n * the window, but may now be in the window.\r\n */\r\nfunction writeTreeCalcIndexedSlice(writeTree, treePath, completeServerData, startPost, count, reverse, index) {\r\n let toIterate;\r\n const merge = compoundWriteChildCompoundWrite(writeTree.visibleWrites, treePath);\r\n const shadowingNode = compoundWriteGetCompleteNode(merge, newEmptyPath());\r\n if (shadowingNode != null) {\r\n toIterate = shadowingNode;\r\n }\r\n else if (completeServerData != null) {\r\n toIterate = compoundWriteApply(merge, completeServerData);\r\n }\r\n else {\r\n // no children to iterate on\r\n return [];\r\n }\r\n toIterate = toIterate.withIndex(index);\r\n if (!toIterate.isEmpty() && !toIterate.isLeafNode()) {\r\n const nodes = [];\r\n const cmp = index.getCompare();\r\n const iter = reverse\r\n ? toIterate.getReverseIteratorFrom(startPost, index)\r\n : toIterate.getIteratorFrom(startPost, index);\r\n let next = iter.getNext();\r\n while (next && nodes.length < count) {\r\n if (cmp(next, startPost) !== 0) {\r\n nodes.push(next);\r\n }\r\n next = iter.getNext();\r\n }\r\n return nodes;\r\n }\r\n else {\r\n return [];\r\n }\r\n}\r\nfunction newWriteTree() {\r\n return {\r\n visibleWrites: CompoundWrite.empty(),\r\n allWrites: [],\r\n lastWriteId: -1\r\n };\r\n}\r\n/**\r\n * If possible, returns a complete event cache, using the underlying server data if possible. In addition, can be used\r\n * to get a cache that includes hidden writes, and excludes arbitrary writes. Note that customizing the returned node\r\n * can lead to a more expensive calculation.\r\n *\r\n * @param writeIdsToExclude - Optional writes to exclude.\r\n * @param includeHiddenWrites - Defaults to false, whether or not to layer on writes with visible set to false\r\n */\r\nfunction writeTreeRefCalcCompleteEventCache(writeTreeRef, completeServerCache, writeIdsToExclude, includeHiddenWrites) {\r\n return writeTreeCalcCompleteEventCache(writeTreeRef.writeTree, writeTreeRef.treePath, completeServerCache, writeIdsToExclude, includeHiddenWrites);\r\n}\r\n/**\r\n * If possible, returns a children node containing all of the complete children we have data for. The returned data is a\r\n * mix of the given server data and write data.\r\n *\r\n */\r\nfunction writeTreeRefCalcCompleteEventChildren(writeTreeRef, completeServerChildren) {\r\n return writeTreeCalcCompleteEventChildren(writeTreeRef.writeTree, writeTreeRef.treePath, completeServerChildren);\r\n}\r\n/**\r\n * Given that either the underlying server data has updated or the outstanding writes have updated, determine what,\r\n * if anything, needs to be applied to the event cache.\r\n *\r\n * Possibilities:\r\n *\r\n * 1. No writes are shadowing. Events should be raised, the snap to be applied comes from the server data\r\n *\r\n * 2. Some write is completely shadowing. No events to be raised\r\n *\r\n * 3. Is partially shadowed. Events should be raised\r\n *\r\n * Either existingEventSnap or existingServerSnap must exist, this is validated via an assert\r\n *\r\n *\r\n */\r\nfunction writeTreeRefCalcEventCacheAfterServerOverwrite(writeTreeRef, path, existingEventSnap, existingServerSnap) {\r\n return writeTreeCalcEventCacheAfterServerOverwrite(writeTreeRef.writeTree, writeTreeRef.treePath, path, existingEventSnap, existingServerSnap);\r\n}\r\n/**\r\n * Returns a node if there is a complete overwrite for this path. More specifically, if there is a write at\r\n * a higher path, this will return the child of that write relative to the write and this path.\r\n * Returns null if there is no write at this path.\r\n *\r\n */\r\nfunction writeTreeRefShadowingWrite(writeTreeRef, path) {\r\n return writeTreeShadowingWrite(writeTreeRef.writeTree, pathChild(writeTreeRef.treePath, path));\r\n}\r\n/**\r\n * This method is used when processing child remove events on a query. If we can, we pull in children that were outside\r\n * the window, but may now be in the window\r\n */\r\nfunction writeTreeRefCalcIndexedSlice(writeTreeRef, completeServerData, startPost, count, reverse, index) {\r\n return writeTreeCalcIndexedSlice(writeTreeRef.writeTree, writeTreeRef.treePath, completeServerData, startPost, count, reverse, index);\r\n}\r\n/**\r\n * Returns a complete child for a given server snap after applying all user writes or null if there is no\r\n * complete child for this ChildKey.\r\n */\r\nfunction writeTreeRefCalcCompleteChild(writeTreeRef, childKey, existingServerCache) {\r\n return writeTreeCalcCompleteChild(writeTreeRef.writeTree, writeTreeRef.treePath, childKey, existingServerCache);\r\n}\r\n/**\r\n * Return a WriteTreeRef for a child.\r\n */\r\nfunction writeTreeRefChild(writeTreeRef, childName) {\r\n return newWriteTreeRef(pathChild(writeTreeRef.treePath, childName), writeTreeRef.writeTree);\r\n}\r\nfunction newWriteTreeRef(path, writeTree) {\r\n return {\r\n treePath: path,\r\n writeTree\r\n };\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nclass ChildChangeAccumulator {\r\n constructor() {\r\n this.changeMap = new Map();\r\n }\r\n trackChildChange(change) {\r\n const type = change.type;\r\n const childKey = change.childName;\r\n assert(type === \"child_added\" /* ChangeType.CHILD_ADDED */ ||\r\n type === \"child_changed\" /* ChangeType.CHILD_CHANGED */ ||\r\n type === \"child_removed\" /* ChangeType.CHILD_REMOVED */, 'Only child changes supported for tracking');\r\n assert(childKey !== '.priority', 'Only non-priority child changes can be tracked.');\r\n const oldChange = this.changeMap.get(childKey);\r\n if (oldChange) {\r\n const oldType = oldChange.type;\r\n if (type === \"child_added\" /* ChangeType.CHILD_ADDED */ &&\r\n oldType === \"child_removed\" /* ChangeType.CHILD_REMOVED */) {\r\n this.changeMap.set(childKey, changeChildChanged(childKey, change.snapshotNode, oldChange.snapshotNode));\r\n }\r\n else if (type === \"child_removed\" /* ChangeType.CHILD_REMOVED */ &&\r\n oldType === \"child_added\" /* ChangeType.CHILD_ADDED */) {\r\n this.changeMap.delete(childKey);\r\n }\r\n else if (type === \"child_removed\" /* ChangeType.CHILD_REMOVED */ &&\r\n oldType === \"child_changed\" /* ChangeType.CHILD_CHANGED */) {\r\n this.changeMap.set(childKey, changeChildRemoved(childKey, oldChange.oldSnap));\r\n }\r\n else if (type === \"child_changed\" /* ChangeType.CHILD_CHANGED */ &&\r\n oldType === \"child_added\" /* ChangeType.CHILD_ADDED */) {\r\n this.changeMap.set(childKey, changeChildAdded(childKey, change.snapshotNode));\r\n }\r\n else if (type === \"child_changed\" /* ChangeType.CHILD_CHANGED */ &&\r\n oldType === \"child_changed\" /* ChangeType.CHILD_CHANGED */) {\r\n this.changeMap.set(childKey, changeChildChanged(childKey, change.snapshotNode, oldChange.oldSnap));\r\n }\r\n else {\r\n throw assertionError('Illegal combination of changes: ' +\r\n change +\r\n ' occurred after ' +\r\n oldChange);\r\n }\r\n }\r\n else {\r\n this.changeMap.set(childKey, change);\r\n }\r\n }\r\n getChanges() {\r\n return Array.from(this.changeMap.values());\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * An implementation of CompleteChildSource that never returns any additional children\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nclass NoCompleteChildSource_ {\r\n getCompleteChild(childKey) {\r\n return null;\r\n }\r\n getChildAfterChild(index, child, reverse) {\r\n return null;\r\n }\r\n}\r\n/**\r\n * Singleton instance.\r\n */\r\nconst NO_COMPLETE_CHILD_SOURCE = new NoCompleteChildSource_();\r\n/**\r\n * An implementation of CompleteChildSource that uses a WriteTree in addition to any other server data or\r\n * old event caches available to calculate complete children.\r\n */\r\nclass WriteTreeCompleteChildSource {\r\n constructor(writes_, viewCache_, optCompleteServerCache_ = null) {\r\n this.writes_ = writes_;\r\n this.viewCache_ = viewCache_;\r\n this.optCompleteServerCache_ = optCompleteServerCache_;\r\n }\r\n getCompleteChild(childKey) {\r\n const node = this.viewCache_.eventCache;\r\n if (node.isCompleteForChild(childKey)) {\r\n return node.getNode().getImmediateChild(childKey);\r\n }\r\n else {\r\n const serverNode = this.optCompleteServerCache_ != null\r\n ? new CacheNode(this.optCompleteServerCache_, true, false)\r\n : this.viewCache_.serverCache;\r\n return writeTreeRefCalcCompleteChild(this.writes_, childKey, serverNode);\r\n }\r\n }\r\n getChildAfterChild(index, child, reverse) {\r\n const completeServerData = this.optCompleteServerCache_ != null\r\n ? this.optCompleteServerCache_\r\n : viewCacheGetCompleteServerSnap(this.viewCache_);\r\n const nodes = writeTreeRefCalcIndexedSlice(this.writes_, completeServerData, child, 1, reverse, index);\r\n if (nodes.length === 0) {\r\n return null;\r\n }\r\n else {\r\n return nodes[0];\r\n }\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nfunction newViewProcessor(filter) {\r\n return { filter };\r\n}\r\nfunction viewProcessorAssertIndexed(viewProcessor, viewCache) {\r\n assert(viewCache.eventCache.getNode().isIndexed(viewProcessor.filter.getIndex()), 'Event snap not indexed');\r\n assert(viewCache.serverCache.getNode().isIndexed(viewProcessor.filter.getIndex()), 'Server snap not indexed');\r\n}\r\nfunction viewProcessorApplyOperation(viewProcessor, oldViewCache, operation, writesCache, completeCache) {\r\n const accumulator = new ChildChangeAccumulator();\r\n let newViewCache, filterServerNode;\r\n if (operation.type === OperationType.OVERWRITE) {\r\n const overwrite = operation;\r\n if (overwrite.source.fromUser) {\r\n newViewCache = viewProcessorApplyUserOverwrite(viewProcessor, oldViewCache, overwrite.path, overwrite.snap, writesCache, completeCache, accumulator);\r\n }\r\n else {\r\n assert(overwrite.source.fromServer, 'Unknown source.');\r\n // We filter the node if it's a tagged update or the node has been previously filtered and the\r\n // update is not at the root in which case it is ok (and necessary) to mark the node unfiltered\r\n // again\r\n filterServerNode =\r\n overwrite.source.tagged ||\r\n (oldViewCache.serverCache.isFiltered() && !pathIsEmpty(overwrite.path));\r\n newViewCache = viewProcessorApplyServerOverwrite(viewProcessor, oldViewCache, overwrite.path, overwrite.snap, writesCache, completeCache, filterServerNode, accumulator);\r\n }\r\n }\r\n else if (operation.type === OperationType.MERGE) {\r\n const merge = operation;\r\n if (merge.source.fromUser) {\r\n newViewCache = viewProcessorApplyUserMerge(viewProcessor, oldViewCache, merge.path, merge.children, writesCache, completeCache, accumulator);\r\n }\r\n else {\r\n assert(merge.source.fromServer, 'Unknown source.');\r\n // We filter the node if it's a tagged update or the node has been previously filtered\r\n filterServerNode =\r\n merge.source.tagged || oldViewCache.serverCache.isFiltered();\r\n newViewCache = viewProcessorApplyServerMerge(viewProcessor, oldViewCache, merge.path, merge.children, writesCache, completeCache, filterServerNode, accumulator);\r\n }\r\n }\r\n else if (operation.type === OperationType.ACK_USER_WRITE) {\r\n const ackUserWrite = operation;\r\n if (!ackUserWrite.revert) {\r\n newViewCache = viewProcessorAckUserWrite(viewProcessor, oldViewCache, ackUserWrite.path, ackUserWrite.affectedTree, writesCache, completeCache, accumulator);\r\n }\r\n else {\r\n newViewCache = viewProcessorRevertUserWrite(viewProcessor, oldViewCache, ackUserWrite.path, writesCache, completeCache, accumulator);\r\n }\r\n }\r\n else if (operation.type === OperationType.LISTEN_COMPLETE) {\r\n newViewCache = viewProcessorListenComplete(viewProcessor, oldViewCache, operation.path, writesCache, accumulator);\r\n }\r\n else {\r\n throw assertionError('Unknown operation type: ' + operation.type);\r\n }\r\n const changes = accumulator.getChanges();\r\n viewProcessorMaybeAddValueEvent(oldViewCache, newViewCache, changes);\r\n return { viewCache: newViewCache, changes };\r\n}\r\nfunction viewProcessorMaybeAddValueEvent(oldViewCache, newViewCache, accumulator) {\r\n const eventSnap = newViewCache.eventCache;\r\n if (eventSnap.isFullyInitialized()) {\r\n const isLeafOrEmpty = eventSnap.getNode().isLeafNode() || eventSnap.getNode().isEmpty();\r\n const oldCompleteSnap = viewCacheGetCompleteEventSnap(oldViewCache);\r\n if (accumulator.length > 0 ||\r\n !oldViewCache.eventCache.isFullyInitialized() ||\r\n (isLeafOrEmpty && !eventSnap.getNode().equals(oldCompleteSnap)) ||\r\n !eventSnap.getNode().getPriority().equals(oldCompleteSnap.getPriority())) {\r\n accumulator.push(changeValue(viewCacheGetCompleteEventSnap(newViewCache)));\r\n }\r\n }\r\n}\r\nfunction viewProcessorGenerateEventCacheAfterServerEvent(viewProcessor, viewCache, changePath, writesCache, source, accumulator) {\r\n const oldEventSnap = viewCache.eventCache;\r\n if (writeTreeRefShadowingWrite(writesCache, changePath) != null) {\r\n // we have a shadowing write, ignore changes\r\n return viewCache;\r\n }\r\n else {\r\n let newEventCache, serverNode;\r\n if (pathIsEmpty(changePath)) {\r\n // TODO: figure out how this plays with \"sliding ack windows\"\r\n assert(viewCache.serverCache.isFullyInitialized(), 'If change path is empty, we must have complete server data');\r\n if (viewCache.serverCache.isFiltered()) {\r\n // We need to special case this, because we need to only apply writes to complete children, or\r\n // we might end up raising events for incomplete children. If the server data is filtered deep\r\n // writes cannot be guaranteed to be complete\r\n const serverCache = viewCacheGetCompleteServerSnap(viewCache);\r\n const completeChildren = serverCache instanceof ChildrenNode\r\n ? serverCache\r\n : ChildrenNode.EMPTY_NODE;\r\n const completeEventChildren = writeTreeRefCalcCompleteEventChildren(writesCache, completeChildren);\r\n newEventCache = viewProcessor.filter.updateFullNode(viewCache.eventCache.getNode(), completeEventChildren, accumulator);\r\n }\r\n else {\r\n const completeNode = writeTreeRefCalcCompleteEventCache(writesCache, viewCacheGetCompleteServerSnap(viewCache));\r\n newEventCache = viewProcessor.filter.updateFullNode(viewCache.eventCache.getNode(), completeNode, accumulator);\r\n }\r\n }\r\n else {\r\n const childKey = pathGetFront(changePath);\r\n if (childKey === '.priority') {\r\n assert(pathGetLength(changePath) === 1, \"Can't have a priority with additional path components\");\r\n const oldEventNode = oldEventSnap.getNode();\r\n serverNode = viewCache.serverCache.getNode();\r\n // we might have overwrites for this priority\r\n const updatedPriority = writeTreeRefCalcEventCacheAfterServerOverwrite(writesCache, changePath, oldEventNode, serverNode);\r\n if (updatedPriority != null) {\r\n newEventCache = viewProcessor.filter.updatePriority(oldEventNode, updatedPriority);\r\n }\r\n else {\r\n // priority didn't change, keep old node\r\n newEventCache = oldEventSnap.getNode();\r\n }\r\n }\r\n else {\r\n const childChangePath = pathPopFront(changePath);\r\n // update child\r\n let newEventChild;\r\n if (oldEventSnap.isCompleteForChild(childKey)) {\r\n serverNode = viewCache.serverCache.getNode();\r\n const eventChildUpdate = writeTreeRefCalcEventCacheAfterServerOverwrite(writesCache, changePath, oldEventSnap.getNode(), serverNode);\r\n if (eventChildUpdate != null) {\r\n newEventChild = oldEventSnap\r\n .getNode()\r\n .getImmediateChild(childKey)\r\n .updateChild(childChangePath, eventChildUpdate);\r\n }\r\n else {\r\n // Nothing changed, just keep the old child\r\n newEventChild = oldEventSnap.getNode().getImmediateChild(childKey);\r\n }\r\n }\r\n else {\r\n newEventChild = writeTreeRefCalcCompleteChild(writesCache, childKey, viewCache.serverCache);\r\n }\r\n if (newEventChild != null) {\r\n newEventCache = viewProcessor.filter.updateChild(oldEventSnap.getNode(), childKey, newEventChild, childChangePath, source, accumulator);\r\n }\r\n else {\r\n // no complete child available or no change\r\n newEventCache = oldEventSnap.getNode();\r\n }\r\n }\r\n }\r\n return viewCacheUpdateEventSnap(viewCache, newEventCache, oldEventSnap.isFullyInitialized() || pathIsEmpty(changePath), viewProcessor.filter.filtersNodes());\r\n }\r\n}\r\nfunction viewProcessorApplyServerOverwrite(viewProcessor, oldViewCache, changePath, changedSnap, writesCache, completeCache, filterServerNode, accumulator) {\r\n const oldServerSnap = oldViewCache.serverCache;\r\n let newServerCache;\r\n const serverFilter = filterServerNode\r\n ? viewProcessor.filter\r\n : viewProcessor.filter.getIndexedFilter();\r\n if (pathIsEmpty(changePath)) {\r\n newServerCache = serverFilter.updateFullNode(oldServerSnap.getNode(), changedSnap, null);\r\n }\r\n else if (serverFilter.filtersNodes() && !oldServerSnap.isFiltered()) {\r\n // we want to filter the server node, but we didn't filter the server node yet, so simulate a full update\r\n const newServerNode = oldServerSnap\r\n .getNode()\r\n .updateChild(changePath, changedSnap);\r\n newServerCache = serverFilter.updateFullNode(oldServerSnap.getNode(), newServerNode, null);\r\n }\r\n else {\r\n const childKey = pathGetFront(changePath);\r\n if (!oldServerSnap.isCompleteForPath(changePath) &&\r\n pathGetLength(changePath) > 1) {\r\n // We don't update incomplete nodes with updates intended for other listeners\r\n return oldViewCache;\r\n }\r\n const childChangePath = pathPopFront(changePath);\r\n const childNode = oldServerSnap.getNode().getImmediateChild(childKey);\r\n const newChildNode = childNode.updateChild(childChangePath, changedSnap);\r\n if (childKey === '.priority') {\r\n newServerCache = serverFilter.updatePriority(oldServerSnap.getNode(), newChildNode);\r\n }\r\n else {\r\n newServerCache = serverFilter.updateChild(oldServerSnap.getNode(), childKey, newChildNode, childChangePath, NO_COMPLETE_CHILD_SOURCE, null);\r\n }\r\n }\r\n const newViewCache = viewCacheUpdateServerSnap(oldViewCache, newServerCache, oldServerSnap.isFullyInitialized() || pathIsEmpty(changePath), serverFilter.filtersNodes());\r\n const source = new WriteTreeCompleteChildSource(writesCache, newViewCache, completeCache);\r\n return viewProcessorGenerateEventCacheAfterServerEvent(viewProcessor, newViewCache, changePath, writesCache, source, accumulator);\r\n}\r\nfunction viewProcessorApplyUserOverwrite(viewProcessor, oldViewCache, changePath, changedSnap, writesCache, completeCache, accumulator) {\r\n const oldEventSnap = oldViewCache.eventCache;\r\n let newViewCache, newEventCache;\r\n const source = new WriteTreeCompleteChildSource(writesCache, oldViewCache, completeCache);\r\n if (pathIsEmpty(changePath)) {\r\n newEventCache = viewProcessor.filter.updateFullNode(oldViewCache.eventCache.getNode(), changedSnap, accumulator);\r\n newViewCache = viewCacheUpdateEventSnap(oldViewCache, newEventCache, true, viewProcessor.filter.filtersNodes());\r\n }\r\n else {\r\n const childKey = pathGetFront(changePath);\r\n if (childKey === '.priority') {\r\n newEventCache = viewProcessor.filter.updatePriority(oldViewCache.eventCache.getNode(), changedSnap);\r\n newViewCache = viewCacheUpdateEventSnap(oldViewCache, newEventCache, oldEventSnap.isFullyInitialized(), oldEventSnap.isFiltered());\r\n }\r\n else {\r\n const childChangePath = pathPopFront(changePath);\r\n const oldChild = oldEventSnap.getNode().getImmediateChild(childKey);\r\n let newChild;\r\n if (pathIsEmpty(childChangePath)) {\r\n // Child overwrite, we can replace the child\r\n newChild = changedSnap;\r\n }\r\n else {\r\n const childNode = source.getCompleteChild(childKey);\r\n if (childNode != null) {\r\n if (pathGetBack(childChangePath) === '.priority' &&\r\n childNode.getChild(pathParent(childChangePath)).isEmpty()) {\r\n // This is a priority update on an empty node. If this node exists on the server, the\r\n // server will send down the priority in the update, so ignore for now\r\n newChild = childNode;\r\n }\r\n else {\r\n newChild = childNode.updateChild(childChangePath, changedSnap);\r\n }\r\n }\r\n else {\r\n // There is no complete child node available\r\n newChild = ChildrenNode.EMPTY_NODE;\r\n }\r\n }\r\n if (!oldChild.equals(newChild)) {\r\n const newEventSnap = viewProcessor.filter.updateChild(oldEventSnap.getNode(), childKey, newChild, childChangePath, source, accumulator);\r\n newViewCache = viewCacheUpdateEventSnap(oldViewCache, newEventSnap, oldEventSnap.isFullyInitialized(), viewProcessor.filter.filtersNodes());\r\n }\r\n else {\r\n newViewCache = oldViewCache;\r\n }\r\n }\r\n }\r\n return newViewCache;\r\n}\r\nfunction viewProcessorCacheHasChild(viewCache, childKey) {\r\n return viewCache.eventCache.isCompleteForChild(childKey);\r\n}\r\nfunction viewProcessorApplyUserMerge(viewProcessor, viewCache, path, changedChildren, writesCache, serverCache, accumulator) {\r\n // HACK: In the case of a limit query, there may be some changes that bump things out of the\r\n // window leaving room for new items. It's important we process these changes first, so we\r\n // iterate the changes twice, first processing any that affect items currently in view.\r\n // TODO: I consider an item \"in view\" if cacheHasChild is true, which checks both the server\r\n // and event snap. I'm not sure if this will result in edge cases when a child is in one but\r\n // not the other.\r\n let curViewCache = viewCache;\r\n changedChildren.foreach((relativePath, childNode) => {\r\n const writePath = pathChild(path, relativePath);\r\n if (viewProcessorCacheHasChild(viewCache, pathGetFront(writePath))) {\r\n curViewCache = viewProcessorApplyUserOverwrite(viewProcessor, curViewCache, writePath, childNode, writesCache, serverCache, accumulator);\r\n }\r\n });\r\n changedChildren.foreach((relativePath, childNode) => {\r\n const writePath = pathChild(path, relativePath);\r\n if (!viewProcessorCacheHasChild(viewCache, pathGetFront(writePath))) {\r\n curViewCache = viewProcessorApplyUserOverwrite(viewProcessor, curViewCache, writePath, childNode, writesCache, serverCache, accumulator);\r\n }\r\n });\r\n return curViewCache;\r\n}\r\nfunction viewProcessorApplyMerge(viewProcessor, node, merge) {\r\n merge.foreach((relativePath, childNode) => {\r\n node = node.updateChild(relativePath, childNode);\r\n });\r\n return node;\r\n}\r\nfunction viewProcessorApplyServerMerge(viewProcessor, viewCache, path, changedChildren, writesCache, serverCache, filterServerNode, accumulator) {\r\n // If we don't have a cache yet, this merge was intended for a previously listen in the same location. Ignore it and\r\n // wait for the complete data update coming soon.\r\n if (viewCache.serverCache.getNode().isEmpty() &&\r\n !viewCache.serverCache.isFullyInitialized()) {\r\n return viewCache;\r\n }\r\n // HACK: In the case of a limit query, there may be some changes that bump things out of the\r\n // window leaving room for new items. It's important we process these changes first, so we\r\n // iterate the changes twice, first processing any that affect items currently in view.\r\n // TODO: I consider an item \"in view\" if cacheHasChild is true, which checks both the server\r\n // and event snap. I'm not sure if this will result in edge cases when a child is in one but\r\n // not the other.\r\n let curViewCache = viewCache;\r\n let viewMergeTree;\r\n if (pathIsEmpty(path)) {\r\n viewMergeTree = changedChildren;\r\n }\r\n else {\r\n viewMergeTree = new ImmutableTree(null).setTree(path, changedChildren);\r\n }\r\n const serverNode = viewCache.serverCache.getNode();\r\n viewMergeTree.children.inorderTraversal((childKey, childTree) => {\r\n if (serverNode.hasChild(childKey)) {\r\n const serverChild = viewCache.serverCache\r\n .getNode()\r\n .getImmediateChild(childKey);\r\n const newChild = viewProcessorApplyMerge(viewProcessor, serverChild, childTree);\r\n curViewCache = viewProcessorApplyServerOverwrite(viewProcessor, curViewCache, new Path(childKey), newChild, writesCache, serverCache, filterServerNode, accumulator);\r\n }\r\n });\r\n viewMergeTree.children.inorderTraversal((childKey, childMergeTree) => {\r\n const isUnknownDeepMerge = !viewCache.serverCache.isCompleteForChild(childKey) &&\r\n childMergeTree.value === null;\r\n if (!serverNode.hasChild(childKey) && !isUnknownDeepMerge) {\r\n const serverChild = viewCache.serverCache\r\n .getNode()\r\n .getImmediateChild(childKey);\r\n const newChild = viewProcessorApplyMerge(viewProcessor, serverChild, childMergeTree);\r\n curViewCache = viewProcessorApplyServerOverwrite(viewProcessor, curViewCache, new Path(childKey), newChild, writesCache, serverCache, filterServerNode, accumulator);\r\n }\r\n });\r\n return curViewCache;\r\n}\r\nfunction viewProcessorAckUserWrite(viewProcessor, viewCache, ackPath, affectedTree, writesCache, completeCache, accumulator) {\r\n if (writeTreeRefShadowingWrite(writesCache, ackPath) != null) {\r\n return viewCache;\r\n }\r\n // Only filter server node if it is currently filtered\r\n const filterServerNode = viewCache.serverCache.isFiltered();\r\n // Essentially we'll just get our existing server cache for the affected paths and re-apply it as a server update\r\n // now that it won't be shadowed.\r\n const serverCache = viewCache.serverCache;\r\n if (affectedTree.value != null) {\r\n // This is an overwrite.\r\n if ((pathIsEmpty(ackPath) && serverCache.isFullyInitialized()) ||\r\n serverCache.isCompleteForPath(ackPath)) {\r\n return viewProcessorApplyServerOverwrite(viewProcessor, viewCache, ackPath, serverCache.getNode().getChild(ackPath), writesCache, completeCache, filterServerNode, accumulator);\r\n }\r\n else if (pathIsEmpty(ackPath)) {\r\n // This is a goofy edge case where we are acking data at this location but don't have full data. We\r\n // should just re-apply whatever we have in our cache as a merge.\r\n let changedChildren = new ImmutableTree(null);\r\n serverCache.getNode().forEachChild(KEY_INDEX, (name, node) => {\r\n changedChildren = changedChildren.set(new Path(name), node);\r\n });\r\n return viewProcessorApplyServerMerge(viewProcessor, viewCache, ackPath, changedChildren, writesCache, completeCache, filterServerNode, accumulator);\r\n }\r\n else {\r\n return viewCache;\r\n }\r\n }\r\n else {\r\n // This is a merge.\r\n let changedChildren = new ImmutableTree(null);\r\n affectedTree.foreach((mergePath, value) => {\r\n const serverCachePath = pathChild(ackPath, mergePath);\r\n if (serverCache.isCompleteForPath(serverCachePath)) {\r\n changedChildren = changedChildren.set(mergePath, serverCache.getNode().getChild(serverCachePath));\r\n }\r\n });\r\n return viewProcessorApplyServerMerge(viewProcessor, viewCache, ackPath, changedChildren, writesCache, completeCache, filterServerNode, accumulator);\r\n }\r\n}\r\nfunction viewProcessorListenComplete(viewProcessor, viewCache, path, writesCache, accumulator) {\r\n const oldServerNode = viewCache.serverCache;\r\n const newViewCache = viewCacheUpdateServerSnap(viewCache, oldServerNode.getNode(), oldServerNode.isFullyInitialized() || pathIsEmpty(path), oldServerNode.isFiltered());\r\n return viewProcessorGenerateEventCacheAfterServerEvent(viewProcessor, newViewCache, path, writesCache, NO_COMPLETE_CHILD_SOURCE, accumulator);\r\n}\r\nfunction viewProcessorRevertUserWrite(viewProcessor, viewCache, path, writesCache, completeServerCache, accumulator) {\r\n let complete;\r\n if (writeTreeRefShadowingWrite(writesCache, path) != null) {\r\n return viewCache;\r\n }\r\n else {\r\n const source = new WriteTreeCompleteChildSource(writesCache, viewCache, completeServerCache);\r\n const oldEventCache = viewCache.eventCache.getNode();\r\n let newEventCache;\r\n if (pathIsEmpty(path) || pathGetFront(path) === '.priority') {\r\n let newNode;\r\n if (viewCache.serverCache.isFullyInitialized()) {\r\n newNode = writeTreeRefCalcCompleteEventCache(writesCache, viewCacheGetCompleteServerSnap(viewCache));\r\n }\r\n else {\r\n const serverChildren = viewCache.serverCache.getNode();\r\n assert(serverChildren instanceof ChildrenNode, 'serverChildren would be complete if leaf node');\r\n newNode = writeTreeRefCalcCompleteEventChildren(writesCache, serverChildren);\r\n }\r\n newNode = newNode;\r\n newEventCache = viewProcessor.filter.updateFullNode(oldEventCache, newNode, accumulator);\r\n }\r\n else {\r\n const childKey = pathGetFront(path);\r\n let newChild = writeTreeRefCalcCompleteChild(writesCache, childKey, viewCache.serverCache);\r\n if (newChild == null &&\r\n viewCache.serverCache.isCompleteForChild(childKey)) {\r\n newChild = oldEventCache.getImmediateChild(childKey);\r\n }\r\n if (newChild != null) {\r\n newEventCache = viewProcessor.filter.updateChild(oldEventCache, childKey, newChild, pathPopFront(path), source, accumulator);\r\n }\r\n else if (viewCache.eventCache.getNode().hasChild(childKey)) {\r\n // No complete child available, delete the existing one, if any\r\n newEventCache = viewProcessor.filter.updateChild(oldEventCache, childKey, ChildrenNode.EMPTY_NODE, pathPopFront(path), source, accumulator);\r\n }\r\n else {\r\n newEventCache = oldEventCache;\r\n }\r\n if (newEventCache.isEmpty() &&\r\n viewCache.serverCache.isFullyInitialized()) {\r\n // We might have reverted all child writes. Maybe the old event was a leaf node\r\n complete = writeTreeRefCalcCompleteEventCache(writesCache, viewCacheGetCompleteServerSnap(viewCache));\r\n if (complete.isLeafNode()) {\r\n newEventCache = viewProcessor.filter.updateFullNode(newEventCache, complete, accumulator);\r\n }\r\n }\r\n }\r\n complete =\r\n viewCache.serverCache.isFullyInitialized() ||\r\n writeTreeRefShadowingWrite(writesCache, newEmptyPath()) != null;\r\n return viewCacheUpdateEventSnap(viewCache, newEventCache, complete, viewProcessor.filter.filtersNodes());\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * A view represents a specific location and query that has 1 or more event registrations.\r\n *\r\n * It does several things:\r\n * - Maintains the list of event registrations for this location/query.\r\n * - Maintains a cache of the data visible for this location/query.\r\n * - Applies new operations (via applyOperation), updates the cache, and based on the event\r\n * registrations returns the set of events to be raised.\r\n */\r\nclass View {\r\n constructor(query_, initialViewCache) {\r\n this.query_ = query_;\r\n this.eventRegistrations_ = [];\r\n const params = this.query_._queryParams;\r\n const indexFilter = new IndexedFilter(params.getIndex());\r\n const filter = queryParamsGetNodeFilter(params);\r\n this.processor_ = newViewProcessor(filter);\r\n const initialServerCache = initialViewCache.serverCache;\r\n const initialEventCache = initialViewCache.eventCache;\r\n // Don't filter server node with other filter than index, wait for tagged listen\r\n const serverSnap = indexFilter.updateFullNode(ChildrenNode.EMPTY_NODE, initialServerCache.getNode(), null);\r\n const eventSnap = filter.updateFullNode(ChildrenNode.EMPTY_NODE, initialEventCache.getNode(), null);\r\n const newServerCache = new CacheNode(serverSnap, initialServerCache.isFullyInitialized(), indexFilter.filtersNodes());\r\n const newEventCache = new CacheNode(eventSnap, initialEventCache.isFullyInitialized(), filter.filtersNodes());\r\n this.viewCache_ = newViewCache(newEventCache, newServerCache);\r\n this.eventGenerator_ = new EventGenerator(this.query_);\r\n }\r\n get query() {\r\n return this.query_;\r\n }\r\n}\r\nfunction viewGetServerCache(view) {\r\n return view.viewCache_.serverCache.getNode();\r\n}\r\nfunction viewGetCompleteNode(view) {\r\n return viewCacheGetCompleteEventSnap(view.viewCache_);\r\n}\r\nfunction viewGetCompleteServerCache(view, path) {\r\n const cache = viewCacheGetCompleteServerSnap(view.viewCache_);\r\n if (cache) {\r\n // If this isn't a \"loadsAllData\" view, then cache isn't actually a complete cache and\r\n // we need to see if it contains the child we're interested in.\r\n if (view.query._queryParams.loadsAllData() ||\r\n (!pathIsEmpty(path) &&\r\n !cache.getImmediateChild(pathGetFront(path)).isEmpty())) {\r\n return cache.getChild(path);\r\n }\r\n }\r\n return null;\r\n}\r\nfunction viewIsEmpty(view) {\r\n return view.eventRegistrations_.length === 0;\r\n}\r\nfunction viewAddEventRegistration(view, eventRegistration) {\r\n view.eventRegistrations_.push(eventRegistration);\r\n}\r\n/**\r\n * @param eventRegistration - If null, remove all callbacks.\r\n * @param cancelError - If a cancelError is provided, appropriate cancel events will be returned.\r\n * @returns Cancel events, if cancelError was provided.\r\n */\r\nfunction viewRemoveEventRegistration(view, eventRegistration, cancelError) {\r\n const cancelEvents = [];\r\n if (cancelError) {\r\n assert(eventRegistration == null, 'A cancel should cancel all event registrations.');\r\n const path = view.query._path;\r\n view.eventRegistrations_.forEach(registration => {\r\n const maybeEvent = registration.createCancelEvent(cancelError, path);\r\n if (maybeEvent) {\r\n cancelEvents.push(maybeEvent);\r\n }\r\n });\r\n }\r\n if (eventRegistration) {\r\n let remaining = [];\r\n for (let i = 0; i < view.eventRegistrations_.length; ++i) {\r\n const existing = view.eventRegistrations_[i];\r\n if (!existing.matches(eventRegistration)) {\r\n remaining.push(existing);\r\n }\r\n else if (eventRegistration.hasAnyCallback()) {\r\n // We're removing just this one\r\n remaining = remaining.concat(view.eventRegistrations_.slice(i + 1));\r\n break;\r\n }\r\n }\r\n view.eventRegistrations_ = remaining;\r\n }\r\n else {\r\n view.eventRegistrations_ = [];\r\n }\r\n return cancelEvents;\r\n}\r\n/**\r\n * Applies the given Operation, updates our cache, and returns the appropriate events.\r\n */\r\nfunction viewApplyOperation(view, operation, writesCache, completeServerCache) {\r\n if (operation.type === OperationType.MERGE &&\r\n operation.source.queryId !== null) {\r\n assert(viewCacheGetCompleteServerSnap(view.viewCache_), 'We should always have a full cache before handling merges');\r\n assert(viewCacheGetCompleteEventSnap(view.viewCache_), 'Missing event cache, even though we have a server cache');\r\n }\r\n const oldViewCache = view.viewCache_;\r\n const result = viewProcessorApplyOperation(view.processor_, oldViewCache, operation, writesCache, completeServerCache);\r\n viewProcessorAssertIndexed(view.processor_, result.viewCache);\r\n assert(result.viewCache.serverCache.isFullyInitialized() ||\r\n !oldViewCache.serverCache.isFullyInitialized(), 'Once a server snap is complete, it should never go back');\r\n view.viewCache_ = result.viewCache;\r\n return viewGenerateEventsForChanges_(view, result.changes, result.viewCache.eventCache.getNode(), null);\r\n}\r\nfunction viewGetInitialEvents(view, registration) {\r\n const eventSnap = view.viewCache_.eventCache;\r\n const initialChanges = [];\r\n if (!eventSnap.getNode().isLeafNode()) {\r\n const eventNode = eventSnap.getNode();\r\n eventNode.forEachChild(PRIORITY_INDEX, (key, childNode) => {\r\n initialChanges.push(changeChildAdded(key, childNode));\r\n });\r\n }\r\n if (eventSnap.isFullyInitialized()) {\r\n initialChanges.push(changeValue(eventSnap.getNode()));\r\n }\r\n return viewGenerateEventsForChanges_(view, initialChanges, eventSnap.getNode(), registration);\r\n}\r\nfunction viewGenerateEventsForChanges_(view, changes, eventCache, eventRegistration) {\r\n const registrations = eventRegistration\r\n ? [eventRegistration]\r\n : view.eventRegistrations_;\r\n return eventGeneratorGenerateEventsForChanges(view.eventGenerator_, changes, eventCache, registrations);\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nlet referenceConstructor$1;\r\n/**\r\n * SyncPoint represents a single location in a SyncTree with 1 or more event registrations, meaning we need to\r\n * maintain 1 or more Views at this location to cache server data and raise appropriate events for server changes\r\n * and user writes (set, transaction, update).\r\n *\r\n * It's responsible for:\r\n * - Maintaining the set of 1 or more views necessary at this location (a SyncPoint with 0 views should be removed).\r\n * - Proxying user / server operations to the views as appropriate (i.e. applyServerOverwrite,\r\n * applyUserOverwrite, etc.)\r\n */\r\nclass SyncPoint {\r\n constructor() {\r\n /**\r\n * The Views being tracked at this location in the tree, stored as a map where the key is a\r\n * queryId and the value is the View for that query.\r\n *\r\n * NOTE: This list will be quite small (usually 1, but perhaps 2 or 3; any more is an odd use case).\r\n */\r\n this.views = new Map();\r\n }\r\n}\r\nfunction syncPointSetReferenceConstructor(val) {\r\n assert(!referenceConstructor$1, '__referenceConstructor has already been defined');\r\n referenceConstructor$1 = val;\r\n}\r\nfunction syncPointGetReferenceConstructor() {\r\n assert(referenceConstructor$1, 'Reference.ts has not been loaded');\r\n return referenceConstructor$1;\r\n}\r\nfunction syncPointIsEmpty(syncPoint) {\r\n return syncPoint.views.size === 0;\r\n}\r\nfunction syncPointApplyOperation(syncPoint, operation, writesCache, optCompleteServerCache) {\r\n const queryId = operation.source.queryId;\r\n if (queryId !== null) {\r\n const view = syncPoint.views.get(queryId);\r\n assert(view != null, 'SyncTree gave us an op for an invalid query.');\r\n return viewApplyOperation(view, operation, writesCache, optCompleteServerCache);\r\n }\r\n else {\r\n let events = [];\r\n for (const view of syncPoint.views.values()) {\r\n events = events.concat(viewApplyOperation(view, operation, writesCache, optCompleteServerCache));\r\n }\r\n return events;\r\n }\r\n}\r\n/**\r\n * Get a view for the specified query.\r\n *\r\n * @param query - The query to return a view for\r\n * @param writesCache\r\n * @param serverCache\r\n * @param serverCacheComplete\r\n * @returns Events to raise.\r\n */\r\nfunction syncPointGetView(syncPoint, query, writesCache, serverCache, serverCacheComplete) {\r\n const queryId = query._queryIdentifier;\r\n const view = syncPoint.views.get(queryId);\r\n if (!view) {\r\n // TODO: make writesCache take flag for complete server node\r\n let eventCache = writeTreeRefCalcCompleteEventCache(writesCache, serverCacheComplete ? serverCache : null);\r\n let eventCacheComplete = false;\r\n if (eventCache) {\r\n eventCacheComplete = true;\r\n }\r\n else if (serverCache instanceof ChildrenNode) {\r\n eventCache = writeTreeRefCalcCompleteEventChildren(writesCache, serverCache);\r\n eventCacheComplete = false;\r\n }\r\n else {\r\n eventCache = ChildrenNode.EMPTY_NODE;\r\n eventCacheComplete = false;\r\n }\r\n const viewCache = newViewCache(new CacheNode(eventCache, eventCacheComplete, false), new CacheNode(serverCache, serverCacheComplete, false));\r\n return new View(query, viewCache);\r\n }\r\n return view;\r\n}\r\n/**\r\n * Add an event callback for the specified query.\r\n *\r\n * @param query\r\n * @param eventRegistration\r\n * @param writesCache\r\n * @param serverCache - Complete server cache, if we have it.\r\n * @param serverCacheComplete\r\n * @returns Events to raise.\r\n */\r\nfunction syncPointAddEventRegistration(syncPoint, query, eventRegistration, writesCache, serverCache, serverCacheComplete) {\r\n const view = syncPointGetView(syncPoint, query, writesCache, serverCache, serverCacheComplete);\r\n if (!syncPoint.views.has(query._queryIdentifier)) {\r\n syncPoint.views.set(query._queryIdentifier, view);\r\n }\r\n // This is guaranteed to exist now, we just created anything that was missing\r\n viewAddEventRegistration(view, eventRegistration);\r\n return viewGetInitialEvents(view, eventRegistration);\r\n}\r\n/**\r\n * Remove event callback(s). Return cancelEvents if a cancelError is specified.\r\n *\r\n * If query is the default query, we'll check all views for the specified eventRegistration.\r\n * If eventRegistration is null, we'll remove all callbacks for the specified view(s).\r\n *\r\n * @param eventRegistration - If null, remove all callbacks.\r\n * @param cancelError - If a cancelError is provided, appropriate cancel events will be returned.\r\n * @returns removed queries and any cancel events\r\n */\r\nfunction syncPointRemoveEventRegistration(syncPoint, query, eventRegistration, cancelError) {\r\n const queryId = query._queryIdentifier;\r\n const removed = [];\r\n let cancelEvents = [];\r\n const hadCompleteView = syncPointHasCompleteView(syncPoint);\r\n if (queryId === 'default') {\r\n // When you do ref.off(...), we search all views for the registration to remove.\r\n for (const [viewQueryId, view] of syncPoint.views.entries()) {\r\n cancelEvents = cancelEvents.concat(viewRemoveEventRegistration(view, eventRegistration, cancelError));\r\n if (viewIsEmpty(view)) {\r\n syncPoint.views.delete(viewQueryId);\r\n // We'll deal with complete views later.\r\n if (!view.query._queryParams.loadsAllData()) {\r\n removed.push(view.query);\r\n }\r\n }\r\n }\r\n }\r\n else {\r\n // remove the callback from the specific view.\r\n const view = syncPoint.views.get(queryId);\r\n if (view) {\r\n cancelEvents = cancelEvents.concat(viewRemoveEventRegistration(view, eventRegistration, cancelError));\r\n if (viewIsEmpty(view)) {\r\n syncPoint.views.delete(queryId);\r\n // We'll deal with complete views later.\r\n if (!view.query._queryParams.loadsAllData()) {\r\n removed.push(view.query);\r\n }\r\n }\r\n }\r\n }\r\n if (hadCompleteView && !syncPointHasCompleteView(syncPoint)) {\r\n // We removed our last complete view.\r\n removed.push(new (syncPointGetReferenceConstructor())(query._repo, query._path));\r\n }\r\n return { removed, events: cancelEvents };\r\n}\r\nfunction syncPointGetQueryViews(syncPoint) {\r\n const result = [];\r\n for (const view of syncPoint.views.values()) {\r\n if (!view.query._queryParams.loadsAllData()) {\r\n result.push(view);\r\n }\r\n }\r\n return result;\r\n}\r\n/**\r\n * @param path - The path to the desired complete snapshot\r\n * @returns A complete cache, if it exists\r\n */\r\nfunction syncPointGetCompleteServerCache(syncPoint, path) {\r\n let serverCache = null;\r\n for (const view of syncPoint.views.values()) {\r\n serverCache = serverCache || viewGetCompleteServerCache(view, path);\r\n }\r\n return serverCache;\r\n}\r\nfunction syncPointViewForQuery(syncPoint, query) {\r\n const params = query._queryParams;\r\n if (params.loadsAllData()) {\r\n return syncPointGetCompleteView(syncPoint);\r\n }\r\n else {\r\n const queryId = query._queryIdentifier;\r\n return syncPoint.views.get(queryId);\r\n }\r\n}\r\nfunction syncPointViewExistsForQuery(syncPoint, query) {\r\n return syncPointViewForQuery(syncPoint, query) != null;\r\n}\r\nfunction syncPointHasCompleteView(syncPoint) {\r\n return syncPointGetCompleteView(syncPoint) != null;\r\n}\r\nfunction syncPointGetCompleteView(syncPoint) {\r\n for (const view of syncPoint.views.values()) {\r\n if (view.query._queryParams.loadsAllData()) {\r\n return view;\r\n }\r\n }\r\n return null;\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nlet referenceConstructor;\r\nfunction syncTreeSetReferenceConstructor(val) {\r\n assert(!referenceConstructor, '__referenceConstructor has already been defined');\r\n referenceConstructor = val;\r\n}\r\nfunction syncTreeGetReferenceConstructor() {\r\n assert(referenceConstructor, 'Reference.ts has not been loaded');\r\n return referenceConstructor;\r\n}\r\n/**\r\n * Static tracker for next query tag.\r\n */\r\nlet syncTreeNextQueryTag_ = 1;\r\n/**\r\n * SyncTree is the central class for managing event callback registration, data caching, views\r\n * (query processing), and event generation. There are typically two SyncTree instances for\r\n * each Repo, one for the normal Firebase data, and one for the .info data.\r\n *\r\n * It has a number of responsibilities, including:\r\n * - Tracking all user event callbacks (registered via addEventRegistration() and removeEventRegistration()).\r\n * - Applying and caching data changes for user set(), transaction(), and update() calls\r\n * (applyUserOverwrite(), applyUserMerge()).\r\n * - Applying and caching data changes for server data changes (applyServerOverwrite(),\r\n * applyServerMerge()).\r\n * - Generating user-facing events for server and user changes (all of the apply* methods\r\n * return the set of events that need to be raised as a result).\r\n * - Maintaining the appropriate set of server listens to ensure we are always subscribed\r\n * to the correct set of paths and queries to satisfy the current set of user event\r\n * callbacks (listens are started/stopped using the provided listenProvider).\r\n *\r\n * NOTE: Although SyncTree tracks event callbacks and calculates events to raise, the actual\r\n * events are returned to the caller rather than raised synchronously.\r\n *\r\n */\r\nclass SyncTree {\r\n /**\r\n * @param listenProvider_ - Used by SyncTree to start / stop listening\r\n * to server data.\r\n */\r\n constructor(listenProvider_) {\r\n this.listenProvider_ = listenProvider_;\r\n /**\r\n * Tree of SyncPoints. There's a SyncPoint at any location that has 1 or more views.\r\n */\r\n this.syncPointTree_ = new ImmutableTree(null);\r\n /**\r\n * A tree of all pending user writes (user-initiated set()'s, transaction()'s, update()'s, etc.).\r\n */\r\n this.pendingWriteTree_ = newWriteTree();\r\n this.tagToQueryMap = new Map();\r\n this.queryToTagMap = new Map();\r\n }\r\n}\r\n/**\r\n * Apply the data changes for a user-generated set() or transaction() call.\r\n *\r\n * @returns Events to raise.\r\n */\r\nfunction syncTreeApplyUserOverwrite(syncTree, path, newData, writeId, visible) {\r\n // Record pending write.\r\n writeTreeAddOverwrite(syncTree.pendingWriteTree_, path, newData, writeId, visible);\r\n if (!visible) {\r\n return [];\r\n }\r\n else {\r\n return syncTreeApplyOperationToSyncPoints_(syncTree, new Overwrite(newOperationSourceUser(), path, newData));\r\n }\r\n}\r\n/**\r\n * Apply the data from a user-generated update() call\r\n *\r\n * @returns Events to raise.\r\n */\r\nfunction syncTreeApplyUserMerge(syncTree, path, changedChildren, writeId) {\r\n // Record pending merge.\r\n writeTreeAddMerge(syncTree.pendingWriteTree_, path, changedChildren, writeId);\r\n const changeTree = ImmutableTree.fromObject(changedChildren);\r\n return syncTreeApplyOperationToSyncPoints_(syncTree, new Merge(newOperationSourceUser(), path, changeTree));\r\n}\r\n/**\r\n * Acknowledge a pending user write that was previously registered with applyUserOverwrite() or applyUserMerge().\r\n *\r\n * @param revert - True if the given write failed and needs to be reverted\r\n * @returns Events to raise.\r\n */\r\nfunction syncTreeAckUserWrite(syncTree, writeId, revert = false) {\r\n const write = writeTreeGetWrite(syncTree.pendingWriteTree_, writeId);\r\n const needToReevaluate = writeTreeRemoveWrite(syncTree.pendingWriteTree_, writeId);\r\n if (!needToReevaluate) {\r\n return [];\r\n }\r\n else {\r\n let affectedTree = new ImmutableTree(null);\r\n if (write.snap != null) {\r\n // overwrite\r\n affectedTree = affectedTree.set(newEmptyPath(), true);\r\n }\r\n else {\r\n each(write.children, (pathString) => {\r\n affectedTree = affectedTree.set(new Path(pathString), true);\r\n });\r\n }\r\n return syncTreeApplyOperationToSyncPoints_(syncTree, new AckUserWrite(write.path, affectedTree, revert));\r\n }\r\n}\r\n/**\r\n * Apply new server data for the specified path..\r\n *\r\n * @returns Events to raise.\r\n */\r\nfunction syncTreeApplyServerOverwrite(syncTree, path, newData) {\r\n return syncTreeApplyOperationToSyncPoints_(syncTree, new Overwrite(newOperationSourceServer(), path, newData));\r\n}\r\n/**\r\n * Apply new server data to be merged in at the specified path.\r\n *\r\n * @returns Events to raise.\r\n */\r\nfunction syncTreeApplyServerMerge(syncTree, path, changedChildren) {\r\n const changeTree = ImmutableTree.fromObject(changedChildren);\r\n return syncTreeApplyOperationToSyncPoints_(syncTree, new Merge(newOperationSourceServer(), path, changeTree));\r\n}\r\n/**\r\n * Apply a listen complete for a query\r\n *\r\n * @returns Events to raise.\r\n */\r\nfunction syncTreeApplyListenComplete(syncTree, path) {\r\n return syncTreeApplyOperationToSyncPoints_(syncTree, new ListenComplete(newOperationSourceServer(), path));\r\n}\r\n/**\r\n * Apply a listen complete for a tagged query\r\n *\r\n * @returns Events to raise.\r\n */\r\nfunction syncTreeApplyTaggedListenComplete(syncTree, path, tag) {\r\n const queryKey = syncTreeQueryKeyForTag_(syncTree, tag);\r\n if (queryKey) {\r\n const r = syncTreeParseQueryKey_(queryKey);\r\n const queryPath = r.path, queryId = r.queryId;\r\n const relativePath = newRelativePath(queryPath, path);\r\n const op = new ListenComplete(newOperationSourceServerTaggedQuery(queryId), relativePath);\r\n return syncTreeApplyTaggedOperation_(syncTree, queryPath, op);\r\n }\r\n else {\r\n // We've already removed the query. No big deal, ignore the update\r\n return [];\r\n }\r\n}\r\n/**\r\n * Remove event callback(s).\r\n *\r\n * If query is the default query, we'll check all queries for the specified eventRegistration.\r\n * If eventRegistration is null, we'll remove all callbacks for the specified query/queries.\r\n *\r\n * @param eventRegistration - If null, all callbacks are removed.\r\n * @param cancelError - If a cancelError is provided, appropriate cancel events will be returned.\r\n * @param skipListenerDedup - When performing a `get()`, we don't add any new listeners, so no\r\n * deduping needs to take place. This flag allows toggling of that behavior\r\n * @returns Cancel events, if cancelError was provided.\r\n */\r\nfunction syncTreeRemoveEventRegistration(syncTree, query, eventRegistration, cancelError, skipListenerDedup = false) {\r\n // Find the syncPoint first. Then deal with whether or not it has matching listeners\r\n const path = query._path;\r\n const maybeSyncPoint = syncTree.syncPointTree_.get(path);\r\n let cancelEvents = [];\r\n // A removal on a default query affects all queries at that location. A removal on an indexed query, even one without\r\n // other query constraints, does *not* affect all queries at that location. So this check must be for 'default', and\r\n // not loadsAllData().\r\n if (maybeSyncPoint &&\r\n (query._queryIdentifier === 'default' ||\r\n syncPointViewExistsForQuery(maybeSyncPoint, query))) {\r\n const removedAndEvents = syncPointRemoveEventRegistration(maybeSyncPoint, query, eventRegistration, cancelError);\r\n if (syncPointIsEmpty(maybeSyncPoint)) {\r\n syncTree.syncPointTree_ = syncTree.syncPointTree_.remove(path);\r\n }\r\n const removed = removedAndEvents.removed;\r\n cancelEvents = removedAndEvents.events;\r\n if (!skipListenerDedup) {\r\n /**\r\n * We may have just removed one of many listeners and can short-circuit this whole process\r\n * We may also not have removed a default listener, in which case all of the descendant listeners should already be\r\n * properly set up.\r\n */\r\n // Since indexed queries can shadow if they don't have other query constraints, check for loadsAllData(), instead of\r\n // queryId === 'default'\r\n const removingDefault = -1 !==\r\n removed.findIndex(query => {\r\n return query._queryParams.loadsAllData();\r\n });\r\n const covered = syncTree.syncPointTree_.findOnPath(path, (relativePath, parentSyncPoint) => syncPointHasCompleteView(parentSyncPoint));\r\n if (removingDefault && !covered) {\r\n const subtree = syncTree.syncPointTree_.subtree(path);\r\n // There are potentially child listeners. Determine what if any listens we need to send before executing the\r\n // removal\r\n if (!subtree.isEmpty()) {\r\n // We need to fold over our subtree and collect the listeners to send\r\n const newViews = syncTreeCollectDistinctViewsForSubTree_(subtree);\r\n // Ok, we've collected all the listens we need. Set them up.\r\n for (let i = 0; i < newViews.length; ++i) {\r\n const view = newViews[i], newQuery = view.query;\r\n const listener = syncTreeCreateListenerForView_(syncTree, view);\r\n syncTree.listenProvider_.startListening(syncTreeQueryForListening_(newQuery), syncTreeTagForQuery(syncTree, newQuery), listener.hashFn, listener.onComplete);\r\n }\r\n }\r\n // Otherwise there's nothing below us, so nothing we need to start listening on\r\n }\r\n // If we removed anything and we're not covered by a higher up listen, we need to stop listening on this query\r\n // The above block has us covered in terms of making sure we're set up on listens lower in the tree.\r\n // Also, note that if we have a cancelError, it's already been removed at the provider level.\r\n if (!covered && removed.length > 0 && !cancelError) {\r\n // If we removed a default, then we weren't listening on any of the other queries here. Just cancel the one\r\n // default. Otherwise, we need to iterate through and cancel each individual query\r\n if (removingDefault) {\r\n // We don't tag default listeners\r\n const defaultTag = null;\r\n syncTree.listenProvider_.stopListening(syncTreeQueryForListening_(query), defaultTag);\r\n }\r\n else {\r\n removed.forEach((queryToRemove) => {\r\n const tagToRemove = syncTree.queryToTagMap.get(syncTreeMakeQueryKey_(queryToRemove));\r\n syncTree.listenProvider_.stopListening(syncTreeQueryForListening_(queryToRemove), tagToRemove);\r\n });\r\n }\r\n }\r\n }\r\n // Now, clear all of the tags we're tracking for the removed listens\r\n syncTreeRemoveTags_(syncTree, removed);\r\n }\r\n return cancelEvents;\r\n}\r\n/**\r\n * Apply new server data for the specified tagged query.\r\n *\r\n * @returns Events to raise.\r\n */\r\nfunction syncTreeApplyTaggedQueryOverwrite(syncTree, path, snap, tag) {\r\n const queryKey = syncTreeQueryKeyForTag_(syncTree, tag);\r\n if (queryKey != null) {\r\n const r = syncTreeParseQueryKey_(queryKey);\r\n const queryPath = r.path, queryId = r.queryId;\r\n const relativePath = newRelativePath(queryPath, path);\r\n const op = new Overwrite(newOperationSourceServerTaggedQuery(queryId), relativePath, snap);\r\n return syncTreeApplyTaggedOperation_(syncTree, queryPath, op);\r\n }\r\n else {\r\n // Query must have been removed already\r\n return [];\r\n }\r\n}\r\n/**\r\n * Apply server data to be merged in for the specified tagged query.\r\n *\r\n * @returns Events to raise.\r\n */\r\nfunction syncTreeApplyTaggedQueryMerge(syncTree, path, changedChildren, tag) {\r\n const queryKey = syncTreeQueryKeyForTag_(syncTree, tag);\r\n if (queryKey) {\r\n const r = syncTreeParseQueryKey_(queryKey);\r\n const queryPath = r.path, queryId = r.queryId;\r\n const relativePath = newRelativePath(queryPath, path);\r\n const changeTree = ImmutableTree.fromObject(changedChildren);\r\n const op = new Merge(newOperationSourceServerTaggedQuery(queryId), relativePath, changeTree);\r\n return syncTreeApplyTaggedOperation_(syncTree, queryPath, op);\r\n }\r\n else {\r\n // We've already removed the query. No big deal, ignore the update\r\n return [];\r\n }\r\n}\r\n/**\r\n * Add an event callback for the specified query.\r\n *\r\n * @returns Events to raise.\r\n */\r\nfunction syncTreeAddEventRegistration(syncTree, query, eventRegistration, skipSetupListener = false) {\r\n const path = query._path;\r\n let serverCache = null;\r\n let foundAncestorDefaultView = false;\r\n // Any covering writes will necessarily be at the root, so really all we need to find is the server cache.\r\n // Consider optimizing this once there's a better understanding of what actual behavior will be.\r\n syncTree.syncPointTree_.foreachOnPath(path, (pathToSyncPoint, sp) => {\r\n const relativePath = newRelativePath(pathToSyncPoint, path);\r\n serverCache =\r\n serverCache || syncPointGetCompleteServerCache(sp, relativePath);\r\n foundAncestorDefaultView =\r\n foundAncestorDefaultView || syncPointHasCompleteView(sp);\r\n });\r\n let syncPoint = syncTree.syncPointTree_.get(path);\r\n if (!syncPoint) {\r\n syncPoint = new SyncPoint();\r\n syncTree.syncPointTree_ = syncTree.syncPointTree_.set(path, syncPoint);\r\n }\r\n else {\r\n foundAncestorDefaultView =\r\n foundAncestorDefaultView || syncPointHasCompleteView(syncPoint);\r\n serverCache =\r\n serverCache || syncPointGetCompleteServerCache(syncPoint, newEmptyPath());\r\n }\r\n let serverCacheComplete;\r\n if (serverCache != null) {\r\n serverCacheComplete = true;\r\n }\r\n else {\r\n serverCacheComplete = false;\r\n serverCache = ChildrenNode.EMPTY_NODE;\r\n const subtree = syncTree.syncPointTree_.subtree(path);\r\n subtree.foreachChild((childName, childSyncPoint) => {\r\n const completeCache = syncPointGetCompleteServerCache(childSyncPoint, newEmptyPath());\r\n if (completeCache) {\r\n serverCache = serverCache.updateImmediateChild(childName, completeCache);\r\n }\r\n });\r\n }\r\n const viewAlreadyExists = syncPointViewExistsForQuery(syncPoint, query);\r\n if (!viewAlreadyExists && !query._queryParams.loadsAllData()) {\r\n // We need to track a tag for this query\r\n const queryKey = syncTreeMakeQueryKey_(query);\r\n assert(!syncTree.queryToTagMap.has(queryKey), 'View does not exist, but we have a tag');\r\n const tag = syncTreeGetNextQueryTag_();\r\n syncTree.queryToTagMap.set(queryKey, tag);\r\n syncTree.tagToQueryMap.set(tag, queryKey);\r\n }\r\n const writesCache = writeTreeChildWrites(syncTree.pendingWriteTree_, path);\r\n let events = syncPointAddEventRegistration(syncPoint, query, eventRegistration, writesCache, serverCache, serverCacheComplete);\r\n if (!viewAlreadyExists && !foundAncestorDefaultView && !skipSetupListener) {\r\n const view = syncPointViewForQuery(syncPoint, query);\r\n events = events.concat(syncTreeSetupListener_(syncTree, query, view));\r\n }\r\n return events;\r\n}\r\n/**\r\n * Returns a complete cache, if we have one, of the data at a particular path. If the location does not have a\r\n * listener above it, we will get a false \"null\". This shouldn't be a problem because transactions will always\r\n * have a listener above, and atomic operations would correctly show a jitter of ->\r\n * as the write is applied locally and then acknowledged at the server.\r\n *\r\n * Note: this method will *include* hidden writes from transaction with applyLocally set to false.\r\n *\r\n * @param path - The path to the data we want\r\n * @param writeIdsToExclude - A specific set to be excluded\r\n */\r\nfunction syncTreeCalcCompleteEventCache(syncTree, path, writeIdsToExclude) {\r\n const includeHiddenSets = true;\r\n const writeTree = syncTree.pendingWriteTree_;\r\n const serverCache = syncTree.syncPointTree_.findOnPath(path, (pathSoFar, syncPoint) => {\r\n const relativePath = newRelativePath(pathSoFar, path);\r\n const serverCache = syncPointGetCompleteServerCache(syncPoint, relativePath);\r\n if (serverCache) {\r\n return serverCache;\r\n }\r\n });\r\n return writeTreeCalcCompleteEventCache(writeTree, path, serverCache, writeIdsToExclude, includeHiddenSets);\r\n}\r\nfunction syncTreeGetServerValue(syncTree, query) {\r\n const path = query._path;\r\n let serverCache = null;\r\n // Any covering writes will necessarily be at the root, so really all we need to find is the server cache.\r\n // Consider optimizing this once there's a better understanding of what actual behavior will be.\r\n syncTree.syncPointTree_.foreachOnPath(path, (pathToSyncPoint, sp) => {\r\n const relativePath = newRelativePath(pathToSyncPoint, path);\r\n serverCache =\r\n serverCache || syncPointGetCompleteServerCache(sp, relativePath);\r\n });\r\n let syncPoint = syncTree.syncPointTree_.get(path);\r\n if (!syncPoint) {\r\n syncPoint = new SyncPoint();\r\n syncTree.syncPointTree_ = syncTree.syncPointTree_.set(path, syncPoint);\r\n }\r\n else {\r\n serverCache =\r\n serverCache || syncPointGetCompleteServerCache(syncPoint, newEmptyPath());\r\n }\r\n const serverCacheComplete = serverCache != null;\r\n const serverCacheNode = serverCacheComplete\r\n ? new CacheNode(serverCache, true, false)\r\n : null;\r\n const writesCache = writeTreeChildWrites(syncTree.pendingWriteTree_, query._path);\r\n const view = syncPointGetView(syncPoint, query, writesCache, serverCacheComplete ? serverCacheNode.getNode() : ChildrenNode.EMPTY_NODE, serverCacheComplete);\r\n return viewGetCompleteNode(view);\r\n}\r\n/**\r\n * A helper method that visits all descendant and ancestor SyncPoints, applying the operation.\r\n *\r\n * NOTES:\r\n * - Descendant SyncPoints will be visited first (since we raise events depth-first).\r\n *\r\n * - We call applyOperation() on each SyncPoint passing three things:\r\n * 1. A version of the Operation that has been made relative to the SyncPoint location.\r\n * 2. A WriteTreeRef of any writes we have cached at the SyncPoint location.\r\n * 3. A snapshot Node with cached server data, if we have it.\r\n *\r\n * - We concatenate all of the events returned by each SyncPoint and return the result.\r\n */\r\nfunction syncTreeApplyOperationToSyncPoints_(syncTree, operation) {\r\n return syncTreeApplyOperationHelper_(operation, syncTree.syncPointTree_, \r\n /*serverCache=*/ null, writeTreeChildWrites(syncTree.pendingWriteTree_, newEmptyPath()));\r\n}\r\n/**\r\n * Recursive helper for applyOperationToSyncPoints_\r\n */\r\nfunction syncTreeApplyOperationHelper_(operation, syncPointTree, serverCache, writesCache) {\r\n if (pathIsEmpty(operation.path)) {\r\n return syncTreeApplyOperationDescendantsHelper_(operation, syncPointTree, serverCache, writesCache);\r\n }\r\n else {\r\n const syncPoint = syncPointTree.get(newEmptyPath());\r\n // If we don't have cached server data, see if we can get it from this SyncPoint.\r\n if (serverCache == null && syncPoint != null) {\r\n serverCache = syncPointGetCompleteServerCache(syncPoint, newEmptyPath());\r\n }\r\n let events = [];\r\n const childName = pathGetFront(operation.path);\r\n const childOperation = operation.operationForChild(childName);\r\n const childTree = syncPointTree.children.get(childName);\r\n if (childTree && childOperation) {\r\n const childServerCache = serverCache\r\n ? serverCache.getImmediateChild(childName)\r\n : null;\r\n const childWritesCache = writeTreeRefChild(writesCache, childName);\r\n events = events.concat(syncTreeApplyOperationHelper_(childOperation, childTree, childServerCache, childWritesCache));\r\n }\r\n if (syncPoint) {\r\n events = events.concat(syncPointApplyOperation(syncPoint, operation, writesCache, serverCache));\r\n }\r\n return events;\r\n }\r\n}\r\n/**\r\n * Recursive helper for applyOperationToSyncPoints_\r\n */\r\nfunction syncTreeApplyOperationDescendantsHelper_(operation, syncPointTree, serverCache, writesCache) {\r\n const syncPoint = syncPointTree.get(newEmptyPath());\r\n // If we don't have cached server data, see if we can get it from this SyncPoint.\r\n if (serverCache == null && syncPoint != null) {\r\n serverCache = syncPointGetCompleteServerCache(syncPoint, newEmptyPath());\r\n }\r\n let events = [];\r\n syncPointTree.children.inorderTraversal((childName, childTree) => {\r\n const childServerCache = serverCache\r\n ? serverCache.getImmediateChild(childName)\r\n : null;\r\n const childWritesCache = writeTreeRefChild(writesCache, childName);\r\n const childOperation = operation.operationForChild(childName);\r\n if (childOperation) {\r\n events = events.concat(syncTreeApplyOperationDescendantsHelper_(childOperation, childTree, childServerCache, childWritesCache));\r\n }\r\n });\r\n if (syncPoint) {\r\n events = events.concat(syncPointApplyOperation(syncPoint, operation, writesCache, serverCache));\r\n }\r\n return events;\r\n}\r\nfunction syncTreeCreateListenerForView_(syncTree, view) {\r\n const query = view.query;\r\n const tag = syncTreeTagForQuery(syncTree, query);\r\n return {\r\n hashFn: () => {\r\n const cache = viewGetServerCache(view) || ChildrenNode.EMPTY_NODE;\r\n return cache.hash();\r\n },\r\n onComplete: (status) => {\r\n if (status === 'ok') {\r\n if (tag) {\r\n return syncTreeApplyTaggedListenComplete(syncTree, query._path, tag);\r\n }\r\n else {\r\n return syncTreeApplyListenComplete(syncTree, query._path);\r\n }\r\n }\r\n else {\r\n // If a listen failed, kill all of the listeners here, not just the one that triggered the error.\r\n // Note that this may need to be scoped to just this listener if we change permissions on filtered children\r\n const error = errorForServerCode(status, query);\r\n return syncTreeRemoveEventRegistration(syncTree, query, \r\n /*eventRegistration*/ null, error);\r\n }\r\n }\r\n };\r\n}\r\n/**\r\n * Return the tag associated with the given query.\r\n */\r\nfunction syncTreeTagForQuery(syncTree, query) {\r\n const queryKey = syncTreeMakeQueryKey_(query);\r\n return syncTree.queryToTagMap.get(queryKey);\r\n}\r\n/**\r\n * Given a query, computes a \"queryKey\" suitable for use in our queryToTagMap_.\r\n */\r\nfunction syncTreeMakeQueryKey_(query) {\r\n return query._path.toString() + '$' + query._queryIdentifier;\r\n}\r\n/**\r\n * Return the query associated with the given tag, if we have one\r\n */\r\nfunction syncTreeQueryKeyForTag_(syncTree, tag) {\r\n return syncTree.tagToQueryMap.get(tag);\r\n}\r\n/**\r\n * Given a queryKey (created by makeQueryKey), parse it back into a path and queryId.\r\n */\r\nfunction syncTreeParseQueryKey_(queryKey) {\r\n const splitIndex = queryKey.indexOf('$');\r\n assert(splitIndex !== -1 && splitIndex < queryKey.length - 1, 'Bad queryKey.');\r\n return {\r\n queryId: queryKey.substr(splitIndex + 1),\r\n path: new Path(queryKey.substr(0, splitIndex))\r\n };\r\n}\r\n/**\r\n * A helper method to apply tagged operations\r\n */\r\nfunction syncTreeApplyTaggedOperation_(syncTree, queryPath, operation) {\r\n const syncPoint = syncTree.syncPointTree_.get(queryPath);\r\n assert(syncPoint, \"Missing sync point for query tag that we're tracking\");\r\n const writesCache = writeTreeChildWrites(syncTree.pendingWriteTree_, queryPath);\r\n return syncPointApplyOperation(syncPoint, operation, writesCache, null);\r\n}\r\n/**\r\n * This collapses multiple unfiltered views into a single view, since we only need a single\r\n * listener for them.\r\n */\r\nfunction syncTreeCollectDistinctViewsForSubTree_(subtree) {\r\n return subtree.fold((relativePath, maybeChildSyncPoint, childMap) => {\r\n if (maybeChildSyncPoint && syncPointHasCompleteView(maybeChildSyncPoint)) {\r\n const completeView = syncPointGetCompleteView(maybeChildSyncPoint);\r\n return [completeView];\r\n }\r\n else {\r\n // No complete view here, flatten any deeper listens into an array\r\n let views = [];\r\n if (maybeChildSyncPoint) {\r\n views = syncPointGetQueryViews(maybeChildSyncPoint);\r\n }\r\n each(childMap, (_key, childViews) => {\r\n views = views.concat(childViews);\r\n });\r\n return views;\r\n }\r\n });\r\n}\r\n/**\r\n * Normalizes a query to a query we send the server for listening\r\n *\r\n * @returns The normalized query\r\n */\r\nfunction syncTreeQueryForListening_(query) {\r\n if (query._queryParams.loadsAllData() && !query._queryParams.isDefault()) {\r\n // We treat queries that load all data as default queries\r\n // Cast is necessary because ref() technically returns Firebase which is actually fb.api.Firebase which inherits\r\n // from Query\r\n return new (syncTreeGetReferenceConstructor())(query._repo, query._path);\r\n }\r\n else {\r\n return query;\r\n }\r\n}\r\nfunction syncTreeRemoveTags_(syncTree, queries) {\r\n for (let j = 0; j < queries.length; ++j) {\r\n const removedQuery = queries[j];\r\n if (!removedQuery._queryParams.loadsAllData()) {\r\n // We should have a tag for this\r\n const removedQueryKey = syncTreeMakeQueryKey_(removedQuery);\r\n const removedQueryTag = syncTree.queryToTagMap.get(removedQueryKey);\r\n syncTree.queryToTagMap.delete(removedQueryKey);\r\n syncTree.tagToQueryMap.delete(removedQueryTag);\r\n }\r\n }\r\n}\r\n/**\r\n * Static accessor for query tags.\r\n */\r\nfunction syncTreeGetNextQueryTag_() {\r\n return syncTreeNextQueryTag_++;\r\n}\r\n/**\r\n * For a given new listen, manage the de-duplication of outstanding subscriptions.\r\n *\r\n * @returns This method can return events to support synchronous data sources\r\n */\r\nfunction syncTreeSetupListener_(syncTree, query, view) {\r\n const path = query._path;\r\n const tag = syncTreeTagForQuery(syncTree, query);\r\n const listener = syncTreeCreateListenerForView_(syncTree, view);\r\n const events = syncTree.listenProvider_.startListening(syncTreeQueryForListening_(query), tag, listener.hashFn, listener.onComplete);\r\n const subtree = syncTree.syncPointTree_.subtree(path);\r\n // The root of this subtree has our query. We're here because we definitely need to send a listen for that, but we\r\n // may need to shadow other listens as well.\r\n if (tag) {\r\n assert(!syncPointHasCompleteView(subtree.value), \"If we're adding a query, it shouldn't be shadowed\");\r\n }\r\n else {\r\n // Shadow everything at or below this location, this is a default listener.\r\n const queriesToStop = subtree.fold((relativePath, maybeChildSyncPoint, childMap) => {\r\n if (!pathIsEmpty(relativePath) &&\r\n maybeChildSyncPoint &&\r\n syncPointHasCompleteView(maybeChildSyncPoint)) {\r\n return [syncPointGetCompleteView(maybeChildSyncPoint).query];\r\n }\r\n else {\r\n // No default listener here, flatten any deeper queries into an array\r\n let queries = [];\r\n if (maybeChildSyncPoint) {\r\n queries = queries.concat(syncPointGetQueryViews(maybeChildSyncPoint).map(view => view.query));\r\n }\r\n each(childMap, (_key, childQueries) => {\r\n queries = queries.concat(childQueries);\r\n });\r\n return queries;\r\n }\r\n });\r\n for (let i = 0; i < queriesToStop.length; ++i) {\r\n const queryToStop = queriesToStop[i];\r\n syncTree.listenProvider_.stopListening(syncTreeQueryForListening_(queryToStop), syncTreeTagForQuery(syncTree, queryToStop));\r\n }\r\n }\r\n return events;\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nclass ExistingValueProvider {\r\n constructor(node_) {\r\n this.node_ = node_;\r\n }\r\n getImmediateChild(childName) {\r\n const child = this.node_.getImmediateChild(childName);\r\n return new ExistingValueProvider(child);\r\n }\r\n node() {\r\n return this.node_;\r\n }\r\n}\r\nclass DeferredValueProvider {\r\n constructor(syncTree, path) {\r\n this.syncTree_ = syncTree;\r\n this.path_ = path;\r\n }\r\n getImmediateChild(childName) {\r\n const childPath = pathChild(this.path_, childName);\r\n return new DeferredValueProvider(this.syncTree_, childPath);\r\n }\r\n node() {\r\n return syncTreeCalcCompleteEventCache(this.syncTree_, this.path_);\r\n }\r\n}\r\n/**\r\n * Generate placeholders for deferred values.\r\n */\r\nconst generateWithValues = function (values) {\r\n values = values || {};\r\n values['timestamp'] = values['timestamp'] || new Date().getTime();\r\n return values;\r\n};\r\n/**\r\n * Value to use when firing local events. When writing server values, fire\r\n * local events with an approximate value, otherwise return value as-is.\r\n */\r\nconst resolveDeferredLeafValue = function (value, existingVal, serverValues) {\r\n if (!value || typeof value !== 'object') {\r\n return value;\r\n }\r\n assert('.sv' in value, 'Unexpected leaf node or priority contents');\r\n if (typeof value['.sv'] === 'string') {\r\n return resolveScalarDeferredValue(value['.sv'], existingVal, serverValues);\r\n }\r\n else if (typeof value['.sv'] === 'object') {\r\n return resolveComplexDeferredValue(value['.sv'], existingVal);\r\n }\r\n else {\r\n assert(false, 'Unexpected server value: ' + JSON.stringify(value, null, 2));\r\n }\r\n};\r\nconst resolveScalarDeferredValue = function (op, existing, serverValues) {\r\n switch (op) {\r\n case 'timestamp':\r\n return serverValues['timestamp'];\r\n default:\r\n assert(false, 'Unexpected server value: ' + op);\r\n }\r\n};\r\nconst resolveComplexDeferredValue = function (op, existing, unused) {\r\n if (!op.hasOwnProperty('increment')) {\r\n assert(false, 'Unexpected server value: ' + JSON.stringify(op, null, 2));\r\n }\r\n const delta = op['increment'];\r\n if (typeof delta !== 'number') {\r\n assert(false, 'Unexpected increment value: ' + delta);\r\n }\r\n const existingNode = existing.node();\r\n assert(existingNode !== null && typeof existingNode !== 'undefined', 'Expected ChildrenNode.EMPTY_NODE for nulls');\r\n // Incrementing a non-number sets the value to the incremented amount\r\n if (!existingNode.isLeafNode()) {\r\n return delta;\r\n }\r\n const leaf = existingNode;\r\n const existingVal = leaf.getValue();\r\n if (typeof existingVal !== 'number') {\r\n return delta;\r\n }\r\n // No need to do over/underflow arithmetic here because JS only handles floats under the covers\r\n return existingVal + delta;\r\n};\r\n/**\r\n * Recursively replace all deferred values and priorities in the tree with the\r\n * specified generated replacement values.\r\n * @param path - path to which write is relative\r\n * @param node - new data written at path\r\n * @param syncTree - current data\r\n */\r\nconst resolveDeferredValueTree = function (path, node, syncTree, serverValues) {\r\n return resolveDeferredValue(node, new DeferredValueProvider(syncTree, path), serverValues);\r\n};\r\n/**\r\n * Recursively replace all deferred values and priorities in the node with the\r\n * specified generated replacement values. If there are no server values in the node,\r\n * it'll be returned as-is.\r\n */\r\nconst resolveDeferredValueSnapshot = function (node, existing, serverValues) {\r\n return resolveDeferredValue(node, new ExistingValueProvider(existing), serverValues);\r\n};\r\nfunction resolveDeferredValue(node, existingVal, serverValues) {\r\n const rawPri = node.getPriority().val();\r\n const priority = resolveDeferredLeafValue(rawPri, existingVal.getImmediateChild('.priority'), serverValues);\r\n let newNode;\r\n if (node.isLeafNode()) {\r\n const leafNode = node;\r\n const value = resolveDeferredLeafValue(leafNode.getValue(), existingVal, serverValues);\r\n if (value !== leafNode.getValue() ||\r\n priority !== leafNode.getPriority().val()) {\r\n return new LeafNode(value, nodeFromJSON(priority));\r\n }\r\n else {\r\n return node;\r\n }\r\n }\r\n else {\r\n const childrenNode = node;\r\n newNode = childrenNode;\r\n if (priority !== childrenNode.getPriority().val()) {\r\n newNode = newNode.updatePriority(new LeafNode(priority));\r\n }\r\n childrenNode.forEachChild(PRIORITY_INDEX, (childName, childNode) => {\r\n const newChildNode = resolveDeferredValue(childNode, existingVal.getImmediateChild(childName), serverValues);\r\n if (newChildNode !== childNode) {\r\n newNode = newNode.updateImmediateChild(childName, newChildNode);\r\n }\r\n });\r\n return newNode;\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * A light-weight tree, traversable by path. Nodes can have both values and children.\r\n * Nodes are not enumerated (by forEachChild) unless they have a value or non-empty\r\n * children.\r\n */\r\nclass Tree {\r\n /**\r\n * @param name - Optional name of the node.\r\n * @param parent - Optional parent node.\r\n * @param node - Optional node to wrap.\r\n */\r\n constructor(name = '', parent = null, node = { children: {}, childCount: 0 }) {\r\n this.name = name;\r\n this.parent = parent;\r\n this.node = node;\r\n }\r\n}\r\n/**\r\n * Returns a sub-Tree for the given path.\r\n *\r\n * @param pathObj - Path to look up.\r\n * @returns Tree for path.\r\n */\r\nfunction treeSubTree(tree, pathObj) {\r\n // TODO: Require pathObj to be Path?\r\n let path = pathObj instanceof Path ? pathObj : new Path(pathObj);\r\n let child = tree, next = pathGetFront(path);\r\n while (next !== null) {\r\n const childNode = safeGet(child.node.children, next) || {\r\n children: {},\r\n childCount: 0\r\n };\r\n child = new Tree(next, child, childNode);\r\n path = pathPopFront(path);\r\n next = pathGetFront(path);\r\n }\r\n return child;\r\n}\r\n/**\r\n * Returns the data associated with this tree node.\r\n *\r\n * @returns The data or null if no data exists.\r\n */\r\nfunction treeGetValue(tree) {\r\n return tree.node.value;\r\n}\r\n/**\r\n * Sets data to this tree node.\r\n *\r\n * @param value - Value to set.\r\n */\r\nfunction treeSetValue(tree, value) {\r\n tree.node.value = value;\r\n treeUpdateParents(tree);\r\n}\r\n/**\r\n * @returns Whether the tree has any children.\r\n */\r\nfunction treeHasChildren(tree) {\r\n return tree.node.childCount > 0;\r\n}\r\n/**\r\n * @returns Whethe rthe tree is empty (no value or children).\r\n */\r\nfunction treeIsEmpty(tree) {\r\n return treeGetValue(tree) === undefined && !treeHasChildren(tree);\r\n}\r\n/**\r\n * Calls action for each child of this tree node.\r\n *\r\n * @param action - Action to be called for each child.\r\n */\r\nfunction treeForEachChild(tree, action) {\r\n each(tree.node.children, (child, childTree) => {\r\n action(new Tree(child, tree, childTree));\r\n });\r\n}\r\n/**\r\n * Does a depth-first traversal of this node's descendants, calling action for each one.\r\n *\r\n * @param action - Action to be called for each child.\r\n * @param includeSelf - Whether to call action on this node as well. Defaults to\r\n * false.\r\n * @param childrenFirst - Whether to call action on children before calling it on\r\n * parent.\r\n */\r\nfunction treeForEachDescendant(tree, action, includeSelf, childrenFirst) {\r\n if (includeSelf && !childrenFirst) {\r\n action(tree);\r\n }\r\n treeForEachChild(tree, child => {\r\n treeForEachDescendant(child, action, true, childrenFirst);\r\n });\r\n if (includeSelf && childrenFirst) {\r\n action(tree);\r\n }\r\n}\r\n/**\r\n * Calls action on each ancestor node.\r\n *\r\n * @param action - Action to be called on each parent; return\r\n * true to abort.\r\n * @param includeSelf - Whether to call action on this node as well.\r\n * @returns true if the action callback returned true.\r\n */\r\nfunction treeForEachAncestor(tree, action, includeSelf) {\r\n let node = includeSelf ? tree : tree.parent;\r\n while (node !== null) {\r\n if (action(node)) {\r\n return true;\r\n }\r\n node = node.parent;\r\n }\r\n return false;\r\n}\r\n/**\r\n * @returns The path of this tree node, as a Path.\r\n */\r\nfunction treeGetPath(tree) {\r\n return new Path(tree.parent === null\r\n ? tree.name\r\n : treeGetPath(tree.parent) + '/' + tree.name);\r\n}\r\n/**\r\n * Adds or removes this child from its parent based on whether it's empty or not.\r\n */\r\nfunction treeUpdateParents(tree) {\r\n if (tree.parent !== null) {\r\n treeUpdateChild(tree.parent, tree.name, tree);\r\n }\r\n}\r\n/**\r\n * Adds or removes the passed child to this tree node, depending on whether it's empty.\r\n *\r\n * @param childName - The name of the child to update.\r\n * @param child - The child to update.\r\n */\r\nfunction treeUpdateChild(tree, childName, child) {\r\n const childEmpty = treeIsEmpty(child);\r\n const childExists = contains(tree.node.children, childName);\r\n if (childEmpty && childExists) {\r\n delete tree.node.children[childName];\r\n tree.node.childCount--;\r\n treeUpdateParents(tree);\r\n }\r\n else if (!childEmpty && !childExists) {\r\n tree.node.children[childName] = child.node;\r\n tree.node.childCount++;\r\n treeUpdateParents(tree);\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * True for invalid Firebase keys\r\n */\r\nconst INVALID_KEY_REGEX_ = /[\\[\\].#$\\/\\u0000-\\u001F\\u007F]/;\r\n/**\r\n * True for invalid Firebase paths.\r\n * Allows '/' in paths.\r\n */\r\nconst INVALID_PATH_REGEX_ = /[\\[\\].#$\\u0000-\\u001F\\u007F]/;\r\n/**\r\n * Maximum number of characters to allow in leaf value\r\n */\r\nconst MAX_LEAF_SIZE_ = 10 * 1024 * 1024;\r\nconst isValidKey = function (key) {\r\n return (typeof key === 'string' && key.length !== 0 && !INVALID_KEY_REGEX_.test(key));\r\n};\r\nconst isValidPathString = function (pathString) {\r\n return (typeof pathString === 'string' &&\r\n pathString.length !== 0 &&\r\n !INVALID_PATH_REGEX_.test(pathString));\r\n};\r\nconst isValidRootPathString = function (pathString) {\r\n if (pathString) {\r\n // Allow '/.info/' at the beginning.\r\n pathString = pathString.replace(/^\\/*\\.info(\\/|$)/, '/');\r\n }\r\n return isValidPathString(pathString);\r\n};\r\nconst isValidPriority = function (priority) {\r\n return (priority === null ||\r\n typeof priority === 'string' ||\r\n (typeof priority === 'number' && !isInvalidJSONNumber(priority)) ||\r\n (priority &&\r\n typeof priority === 'object' &&\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n contains(priority, '.sv')));\r\n};\r\n/**\r\n * Pre-validate a datum passed as an argument to Firebase function.\r\n */\r\nconst validateFirebaseDataArg = function (fnName, value, path, optional) {\r\n if (optional && value === undefined) {\r\n return;\r\n }\r\n validateFirebaseData(errorPrefix(fnName, 'value'), value, path);\r\n};\r\n/**\r\n * Validate a data object client-side before sending to server.\r\n */\r\nconst validateFirebaseData = function (errorPrefix, data, path_) {\r\n const path = path_ instanceof Path ? new ValidationPath(path_, errorPrefix) : path_;\r\n if (data === undefined) {\r\n throw new Error(errorPrefix + 'contains undefined ' + validationPathToErrorString(path));\r\n }\r\n if (typeof data === 'function') {\r\n throw new Error(errorPrefix +\r\n 'contains a function ' +\r\n validationPathToErrorString(path) +\r\n ' with contents = ' +\r\n data.toString());\r\n }\r\n if (isInvalidJSONNumber(data)) {\r\n throw new Error(errorPrefix +\r\n 'contains ' +\r\n data.toString() +\r\n ' ' +\r\n validationPathToErrorString(path));\r\n }\r\n // Check max leaf size, but try to avoid the utf8 conversion if we can.\r\n if (typeof data === 'string' &&\r\n data.length > MAX_LEAF_SIZE_ / 3 &&\r\n stringLength(data) > MAX_LEAF_SIZE_) {\r\n throw new Error(errorPrefix +\r\n 'contains a string greater than ' +\r\n MAX_LEAF_SIZE_ +\r\n ' utf8 bytes ' +\r\n validationPathToErrorString(path) +\r\n \" ('\" +\r\n data.substring(0, 50) +\r\n \"...')\");\r\n }\r\n // TODO = Perf = Consider combining the recursive validation of keys into NodeFromJSON\r\n // to save extra walking of large objects.\r\n if (data && typeof data === 'object') {\r\n let hasDotValue = false;\r\n let hasActualChild = false;\r\n each(data, (key, value) => {\r\n if (key === '.value') {\r\n hasDotValue = true;\r\n }\r\n else if (key !== '.priority' && key !== '.sv') {\r\n hasActualChild = true;\r\n if (!isValidKey(key)) {\r\n throw new Error(errorPrefix +\r\n ' contains an invalid key (' +\r\n key +\r\n ') ' +\r\n validationPathToErrorString(path) +\r\n '. Keys must be non-empty strings ' +\r\n 'and can\\'t contain \".\", \"#\", \"$\", \"/\", \"[\", or \"]\"');\r\n }\r\n }\r\n validationPathPush(path, key);\r\n validateFirebaseData(errorPrefix, value, path);\r\n validationPathPop(path);\r\n });\r\n if (hasDotValue && hasActualChild) {\r\n throw new Error(errorPrefix +\r\n ' contains \".value\" child ' +\r\n validationPathToErrorString(path) +\r\n ' in addition to actual children.');\r\n }\r\n }\r\n};\r\n/**\r\n * Pre-validate paths passed in the firebase function.\r\n */\r\nconst validateFirebaseMergePaths = function (errorPrefix, mergePaths) {\r\n let i, curPath;\r\n for (i = 0; i < mergePaths.length; i++) {\r\n curPath = mergePaths[i];\r\n const keys = pathSlice(curPath);\r\n for (let j = 0; j < keys.length; j++) {\r\n if (keys[j] === '.priority' && j === keys.length - 1) ;\r\n else if (!isValidKey(keys[j])) {\r\n throw new Error(errorPrefix +\r\n 'contains an invalid key (' +\r\n keys[j] +\r\n ') in path ' +\r\n curPath.toString() +\r\n '. Keys must be non-empty strings ' +\r\n 'and can\\'t contain \".\", \"#\", \"$\", \"/\", \"[\", or \"]\"');\r\n }\r\n }\r\n }\r\n // Check that update keys are not descendants of each other.\r\n // We rely on the property that sorting guarantees that ancestors come\r\n // right before descendants.\r\n mergePaths.sort(pathCompare);\r\n let prevPath = null;\r\n for (i = 0; i < mergePaths.length; i++) {\r\n curPath = mergePaths[i];\r\n if (prevPath !== null && pathContains(prevPath, curPath)) {\r\n throw new Error(errorPrefix +\r\n 'contains a path ' +\r\n prevPath.toString() +\r\n ' that is ancestor of another path ' +\r\n curPath.toString());\r\n }\r\n prevPath = curPath;\r\n }\r\n};\r\n/**\r\n * pre-validate an object passed as an argument to firebase function (\r\n * must be an object - e.g. for firebase.update()).\r\n */\r\nconst validateFirebaseMergeDataArg = function (fnName, data, path, optional) {\r\n if (optional && data === undefined) {\r\n return;\r\n }\r\n const errorPrefix$1 = errorPrefix(fnName, 'values');\r\n if (!(data && typeof data === 'object') || Array.isArray(data)) {\r\n throw new Error(errorPrefix$1 + ' must be an object containing the children to replace.');\r\n }\r\n const mergePaths = [];\r\n each(data, (key, value) => {\r\n const curPath = new Path(key);\r\n validateFirebaseData(errorPrefix$1, value, pathChild(path, curPath));\r\n if (pathGetBack(curPath) === '.priority') {\r\n if (!isValidPriority(value)) {\r\n throw new Error(errorPrefix$1 +\r\n \"contains an invalid value for '\" +\r\n curPath.toString() +\r\n \"', which must be a valid \" +\r\n 'Firebase priority (a string, finite number, server value, or null).');\r\n }\r\n }\r\n mergePaths.push(curPath);\r\n });\r\n validateFirebaseMergePaths(errorPrefix$1, mergePaths);\r\n};\r\nconst validatePriority = function (fnName, priority, optional) {\r\n if (optional && priority === undefined) {\r\n return;\r\n }\r\n if (isInvalidJSONNumber(priority)) {\r\n throw new Error(errorPrefix(fnName, 'priority') +\r\n 'is ' +\r\n priority.toString() +\r\n ', but must be a valid Firebase priority (a string, finite number, ' +\r\n 'server value, or null).');\r\n }\r\n // Special case to allow importing data with a .sv.\r\n if (!isValidPriority(priority)) {\r\n throw new Error(errorPrefix(fnName, 'priority') +\r\n 'must be a valid Firebase priority ' +\r\n '(a string, finite number, server value, or null).');\r\n }\r\n};\r\nconst validateKey = function (fnName, argumentName, key, optional) {\r\n if (optional && key === undefined) {\r\n return;\r\n }\r\n if (!isValidKey(key)) {\r\n throw new Error(errorPrefix(fnName, argumentName) +\r\n 'was an invalid key = \"' +\r\n key +\r\n '\". Firebase keys must be non-empty strings and ' +\r\n 'can\\'t contain \".\", \"#\", \"$\", \"/\", \"[\", or \"]\").');\r\n }\r\n};\r\n/**\r\n * @internal\r\n */\r\nconst validatePathString = function (fnName, argumentName, pathString, optional) {\r\n if (optional && pathString === undefined) {\r\n return;\r\n }\r\n if (!isValidPathString(pathString)) {\r\n throw new Error(errorPrefix(fnName, argumentName) +\r\n 'was an invalid path = \"' +\r\n pathString +\r\n '\". Paths must be non-empty strings and ' +\r\n 'can\\'t contain \".\", \"#\", \"$\", \"[\", or \"]\"');\r\n }\r\n};\r\nconst validateRootPathString = function (fnName, argumentName, pathString, optional) {\r\n if (pathString) {\r\n // Allow '/.info/' at the beginning.\r\n pathString = pathString.replace(/^\\/*\\.info(\\/|$)/, '/');\r\n }\r\n validatePathString(fnName, argumentName, pathString, optional);\r\n};\r\n/**\r\n * @internal\r\n */\r\nconst validateWritablePath = function (fnName, path) {\r\n if (pathGetFront(path) === '.info') {\r\n throw new Error(fnName + \" failed = Can't modify data under /.info/\");\r\n }\r\n};\r\nconst validateUrl = function (fnName, parsedUrl) {\r\n // TODO = Validate server better.\r\n const pathString = parsedUrl.path.toString();\r\n if (!(typeof parsedUrl.repoInfo.host === 'string') ||\r\n parsedUrl.repoInfo.host.length === 0 ||\r\n (!isValidKey(parsedUrl.repoInfo.namespace) &&\r\n parsedUrl.repoInfo.host.split(':')[0] !== 'localhost') ||\r\n (pathString.length !== 0 && !isValidRootPathString(pathString))) {\r\n throw new Error(errorPrefix(fnName, 'url') +\r\n 'must be a valid firebase URL and ' +\r\n 'the path can\\'t contain \".\", \"#\", \"$\", \"[\", or \"]\".');\r\n }\r\n};\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * The event queue serves a few purposes:\r\n * 1. It ensures we maintain event order in the face of event callbacks doing operations that result in more\r\n * events being queued.\r\n * 2. raiseQueuedEvents() handles being called reentrantly nicely. That is, if in the course of raising events,\r\n * raiseQueuedEvents() is called again, the \"inner\" call will pick up raising events where the \"outer\" call\r\n * left off, ensuring that the events are still raised synchronously and in order.\r\n * 3. You can use raiseEventsAtPath and raiseEventsForChangedPath to ensure only relevant previously-queued\r\n * events are raised synchronously.\r\n *\r\n * NOTE: This can all go away if/when we move to async events.\r\n *\r\n */\r\nclass EventQueue {\r\n constructor() {\r\n this.eventLists_ = [];\r\n /**\r\n * Tracks recursion depth of raiseQueuedEvents_, for debugging purposes.\r\n */\r\n this.recursionDepth_ = 0;\r\n }\r\n}\r\n/**\r\n * @param eventDataList - The new events to queue.\r\n */\r\nfunction eventQueueQueueEvents(eventQueue, eventDataList) {\r\n // We group events by path, storing them in a single EventList, to make it easier to skip over them quickly.\r\n let currList = null;\r\n for (let i = 0; i < eventDataList.length; i++) {\r\n const data = eventDataList[i];\r\n const path = data.getPath();\r\n if (currList !== null && !pathEquals(path, currList.path)) {\r\n eventQueue.eventLists_.push(currList);\r\n currList = null;\r\n }\r\n if (currList === null) {\r\n currList = { events: [], path };\r\n }\r\n currList.events.push(data);\r\n }\r\n if (currList) {\r\n eventQueue.eventLists_.push(currList);\r\n }\r\n}\r\n/**\r\n * Queues the specified events and synchronously raises all events (including previously queued ones)\r\n * for the specified path.\r\n *\r\n * It is assumed that the new events are all for the specified path.\r\n *\r\n * @param path - The path to raise events for.\r\n * @param eventDataList - The new events to raise.\r\n */\r\nfunction eventQueueRaiseEventsAtPath(eventQueue, path, eventDataList) {\r\n eventQueueQueueEvents(eventQueue, eventDataList);\r\n eventQueueRaiseQueuedEventsMatchingPredicate(eventQueue, eventPath => pathEquals(eventPath, path));\r\n}\r\n/**\r\n * Queues the specified events and synchronously raises all events (including previously queued ones) for\r\n * locations related to the specified change path (i.e. all ancestors and descendants).\r\n *\r\n * It is assumed that the new events are all related (ancestor or descendant) to the specified path.\r\n *\r\n * @param changedPath - The path to raise events for.\r\n * @param eventDataList - The events to raise\r\n */\r\nfunction eventQueueRaiseEventsForChangedPath(eventQueue, changedPath, eventDataList) {\r\n eventQueueQueueEvents(eventQueue, eventDataList);\r\n eventQueueRaiseQueuedEventsMatchingPredicate(eventQueue, eventPath => pathContains(eventPath, changedPath) ||\r\n pathContains(changedPath, eventPath));\r\n}\r\nfunction eventQueueRaiseQueuedEventsMatchingPredicate(eventQueue, predicate) {\r\n eventQueue.recursionDepth_++;\r\n let sentAll = true;\r\n for (let i = 0; i < eventQueue.eventLists_.length; i++) {\r\n const eventList = eventQueue.eventLists_[i];\r\n if (eventList) {\r\n const eventPath = eventList.path;\r\n if (predicate(eventPath)) {\r\n eventListRaise(eventQueue.eventLists_[i]);\r\n eventQueue.eventLists_[i] = null;\r\n }\r\n else {\r\n sentAll = false;\r\n }\r\n }\r\n }\r\n if (sentAll) {\r\n eventQueue.eventLists_ = [];\r\n }\r\n eventQueue.recursionDepth_--;\r\n}\r\n/**\r\n * Iterates through the list and raises each event\r\n */\r\nfunction eventListRaise(eventList) {\r\n for (let i = 0; i < eventList.events.length; i++) {\r\n const eventData = eventList.events[i];\r\n if (eventData !== null) {\r\n eventList.events[i] = null;\r\n const eventFn = eventData.getEventRunner();\r\n if (logger) {\r\n log('event: ' + eventData.toString());\r\n }\r\n exceptionGuard(eventFn);\r\n }\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nconst INTERRUPT_REASON = 'repo_interrupt';\r\n/**\r\n * If a transaction does not succeed after 25 retries, we abort it. Among other\r\n * things this ensure that if there's ever a bug causing a mismatch between\r\n * client / server hashes for some data, we won't retry indefinitely.\r\n */\r\nconst MAX_TRANSACTION_RETRIES = 25;\r\n/**\r\n * A connection to a single data repository.\r\n */\r\nclass Repo {\r\n constructor(repoInfo_, forceRestClient_, authTokenProvider_, appCheckProvider_) {\r\n this.repoInfo_ = repoInfo_;\r\n this.forceRestClient_ = forceRestClient_;\r\n this.authTokenProvider_ = authTokenProvider_;\r\n this.appCheckProvider_ = appCheckProvider_;\r\n this.dataUpdateCount = 0;\r\n this.statsListener_ = null;\r\n this.eventQueue_ = new EventQueue();\r\n this.nextWriteId_ = 1;\r\n this.interceptServerDataCallback_ = null;\r\n /** A list of data pieces and paths to be set when this client disconnects. */\r\n this.onDisconnect_ = newSparseSnapshotTree();\r\n /** Stores queues of outstanding transactions for Firebase locations. */\r\n this.transactionQueueTree_ = new Tree();\r\n // TODO: This should be @private but it's used by test_access.js and internal.js\r\n this.persistentConnection_ = null;\r\n // This key is intentionally not updated if RepoInfo is later changed or replaced\r\n this.key = this.repoInfo_.toURLString();\r\n }\r\n /**\r\n * @returns The URL corresponding to the root of this Firebase.\r\n */\r\n toString() {\r\n return ((this.repoInfo_.secure ? 'https://' : 'http://') + this.repoInfo_.host);\r\n }\r\n}\r\nfunction repoStart(repo, appId, authOverride) {\r\n repo.stats_ = statsManagerGetCollection(repo.repoInfo_);\r\n if (repo.forceRestClient_ || beingCrawled()) {\r\n repo.server_ = new ReadonlyRestClient(repo.repoInfo_, (pathString, data, isMerge, tag) => {\r\n repoOnDataUpdate(repo, pathString, data, isMerge, tag);\r\n }, repo.authTokenProvider_, repo.appCheckProvider_);\r\n // Minor hack: Fire onConnect immediately, since there's no actual connection.\r\n setTimeout(() => repoOnConnectStatus(repo, /* connectStatus= */ true), 0);\r\n }\r\n else {\r\n // Validate authOverride\r\n if (typeof authOverride !== 'undefined' && authOverride !== null) {\r\n if (typeof authOverride !== 'object') {\r\n throw new Error('Only objects are supported for option databaseAuthVariableOverride');\r\n }\r\n try {\r\n stringify(authOverride);\r\n }\r\n catch (e) {\r\n throw new Error('Invalid authOverride provided: ' + e);\r\n }\r\n }\r\n repo.persistentConnection_ = new PersistentConnection(repo.repoInfo_, appId, (pathString, data, isMerge, tag) => {\r\n repoOnDataUpdate(repo, pathString, data, isMerge, tag);\r\n }, (connectStatus) => {\r\n repoOnConnectStatus(repo, connectStatus);\r\n }, (updates) => {\r\n repoOnServerInfoUpdate(repo, updates);\r\n }, repo.authTokenProvider_, repo.appCheckProvider_, authOverride);\r\n repo.server_ = repo.persistentConnection_;\r\n }\r\n repo.authTokenProvider_.addTokenChangeListener(token => {\r\n repo.server_.refreshAuthToken(token);\r\n });\r\n repo.appCheckProvider_.addTokenChangeListener(result => {\r\n repo.server_.refreshAppCheckToken(result.token);\r\n });\r\n // In the case of multiple Repos for the same repoInfo (i.e. there are multiple Firebase.Contexts being used),\r\n // we only want to create one StatsReporter. As such, we'll report stats over the first Repo created.\r\n repo.statsReporter_ = statsManagerGetOrCreateReporter(repo.repoInfo_, () => new StatsReporter(repo.stats_, repo.server_));\r\n // Used for .info.\r\n repo.infoData_ = new SnapshotHolder();\r\n repo.infoSyncTree_ = new SyncTree({\r\n startListening: (query, tag, currentHashFn, onComplete) => {\r\n let infoEvents = [];\r\n const node = repo.infoData_.getNode(query._path);\r\n // This is possibly a hack, but we have different semantics for .info endpoints. We don't raise null events\r\n // on initial data...\r\n if (!node.isEmpty()) {\r\n infoEvents = syncTreeApplyServerOverwrite(repo.infoSyncTree_, query._path, node);\r\n setTimeout(() => {\r\n onComplete('ok');\r\n }, 0);\r\n }\r\n return infoEvents;\r\n },\r\n stopListening: () => { }\r\n });\r\n repoUpdateInfo(repo, 'connected', false);\r\n repo.serverSyncTree_ = new SyncTree({\r\n startListening: (query, tag, currentHashFn, onComplete) => {\r\n repo.server_.listen(query, currentHashFn, tag, (status, data) => {\r\n const events = onComplete(status, data);\r\n eventQueueRaiseEventsForChangedPath(repo.eventQueue_, query._path, events);\r\n });\r\n // No synchronous events for network-backed sync trees\r\n return [];\r\n },\r\n stopListening: (query, tag) => {\r\n repo.server_.unlisten(query, tag);\r\n }\r\n });\r\n}\r\n/**\r\n * @returns The time in milliseconds, taking the server offset into account if we have one.\r\n */\r\nfunction repoServerTime(repo) {\r\n const offsetNode = repo.infoData_.getNode(new Path('.info/serverTimeOffset'));\r\n const offset = offsetNode.val() || 0;\r\n return new Date().getTime() + offset;\r\n}\r\n/**\r\n * Generate ServerValues using some variables from the repo object.\r\n */\r\nfunction repoGenerateServerValues(repo) {\r\n return generateWithValues({\r\n timestamp: repoServerTime(repo)\r\n });\r\n}\r\n/**\r\n * Called by realtime when we get new messages from the server.\r\n */\r\nfunction repoOnDataUpdate(repo, pathString, data, isMerge, tag) {\r\n // For testing.\r\n repo.dataUpdateCount++;\r\n const path = new Path(pathString);\r\n data = repo.interceptServerDataCallback_\r\n ? repo.interceptServerDataCallback_(pathString, data)\r\n : data;\r\n let events = [];\r\n if (tag) {\r\n if (isMerge) {\r\n const taggedChildren = map(data, (raw) => nodeFromJSON(raw));\r\n events = syncTreeApplyTaggedQueryMerge(repo.serverSyncTree_, path, taggedChildren, tag);\r\n }\r\n else {\r\n const taggedSnap = nodeFromJSON(data);\r\n events = syncTreeApplyTaggedQueryOverwrite(repo.serverSyncTree_, path, taggedSnap, tag);\r\n }\r\n }\r\n else if (isMerge) {\r\n const changedChildren = map(data, (raw) => nodeFromJSON(raw));\r\n events = syncTreeApplyServerMerge(repo.serverSyncTree_, path, changedChildren);\r\n }\r\n else {\r\n const snap = nodeFromJSON(data);\r\n events = syncTreeApplyServerOverwrite(repo.serverSyncTree_, path, snap);\r\n }\r\n let affectedPath = path;\r\n if (events.length > 0) {\r\n // Since we have a listener outstanding for each transaction, receiving any events\r\n // is a proxy for some change having occurred.\r\n affectedPath = repoRerunTransactions(repo, path);\r\n }\r\n eventQueueRaiseEventsForChangedPath(repo.eventQueue_, affectedPath, events);\r\n}\r\nfunction repoOnConnectStatus(repo, connectStatus) {\r\n repoUpdateInfo(repo, 'connected', connectStatus);\r\n if (connectStatus === false) {\r\n repoRunOnDisconnectEvents(repo);\r\n }\r\n}\r\nfunction repoOnServerInfoUpdate(repo, updates) {\r\n each(updates, (key, value) => {\r\n repoUpdateInfo(repo, key, value);\r\n });\r\n}\r\nfunction repoUpdateInfo(repo, pathString, value) {\r\n const path = new Path('/.info/' + pathString);\r\n const newNode = nodeFromJSON(value);\r\n repo.infoData_.updateSnapshot(path, newNode);\r\n const events = syncTreeApplyServerOverwrite(repo.infoSyncTree_, path, newNode);\r\n eventQueueRaiseEventsForChangedPath(repo.eventQueue_, path, events);\r\n}\r\nfunction repoGetNextWriteId(repo) {\r\n return repo.nextWriteId_++;\r\n}\r\n/**\r\n * The purpose of `getValue` is to return the latest known value\r\n * satisfying `query`.\r\n *\r\n * This method will first check for in-memory cached values\r\n * belonging to active listeners. If they are found, such values\r\n * are considered to be the most up-to-date.\r\n *\r\n * If the client is not connected, this method will wait until the\r\n * repo has established a connection and then request the value for `query`.\r\n * If the client is not able to retrieve the query result for another reason,\r\n * it reports an error.\r\n *\r\n * @param query - The query to surface a value for.\r\n */\r\nfunction repoGetValue(repo, query, eventRegistration) {\r\n // Only active queries are cached. There is no persisted cache.\r\n const cached = syncTreeGetServerValue(repo.serverSyncTree_, query);\r\n if (cached != null) {\r\n return Promise.resolve(cached);\r\n }\r\n return repo.server_.get(query).then(payload => {\r\n const node = nodeFromJSON(payload).withIndex(query._queryParams.getIndex());\r\n /**\r\n * Below we simulate the actions of an `onlyOnce` `onValue()` event where:\r\n * Add an event registration,\r\n * Update data at the path,\r\n * Raise any events,\r\n * Cleanup the SyncTree\r\n */\r\n syncTreeAddEventRegistration(repo.serverSyncTree_, query, eventRegistration, true);\r\n let events;\r\n if (query._queryParams.loadsAllData()) {\r\n events = syncTreeApplyServerOverwrite(repo.serverSyncTree_, query._path, node);\r\n }\r\n else {\r\n const tag = syncTreeTagForQuery(repo.serverSyncTree_, query);\r\n events = syncTreeApplyTaggedQueryOverwrite(repo.serverSyncTree_, query._path, node, tag);\r\n }\r\n /*\r\n * We need to raise events in the scenario where `get()` is called at a parent path, and\r\n * while the `get()` is pending, `onValue` is called at a child location. While get() is waiting\r\n * for the data, `onValue` will register a new event. Then, get() will come back, and update the syncTree\r\n * and its corresponding serverCache, including the child location where `onValue` is called. Then,\r\n * `onValue` will receive the event from the server, but look at the syncTree and see that the data received\r\n * from the server is already at the SyncPoint, and so the `onValue` callback will never get fired.\r\n * Calling `eventQueueRaiseEventsForChangedPath()` is the correct way to propagate the events and\r\n * ensure the corresponding child events will get fired.\r\n */\r\n eventQueueRaiseEventsForChangedPath(repo.eventQueue_, query._path, events);\r\n syncTreeRemoveEventRegistration(repo.serverSyncTree_, query, eventRegistration, null, true);\r\n return node;\r\n }, err => {\r\n repoLog(repo, 'get for query ' + stringify(query) + ' failed: ' + err);\r\n return Promise.reject(new Error(err));\r\n });\r\n}\r\nfunction repoSetWithPriority(repo, path, newVal, newPriority, onComplete) {\r\n repoLog(repo, 'set', {\r\n path: path.toString(),\r\n value: newVal,\r\n priority: newPriority\r\n });\r\n // TODO: Optimize this behavior to either (a) store flag to skip resolving where possible and / or\r\n // (b) store unresolved paths on JSON parse\r\n const serverValues = repoGenerateServerValues(repo);\r\n const newNodeUnresolved = nodeFromJSON(newVal, newPriority);\r\n const existing = syncTreeCalcCompleteEventCache(repo.serverSyncTree_, path);\r\n const newNode = resolveDeferredValueSnapshot(newNodeUnresolved, existing, serverValues);\r\n const writeId = repoGetNextWriteId(repo);\r\n const events = syncTreeApplyUserOverwrite(repo.serverSyncTree_, path, newNode, writeId, true);\r\n eventQueueQueueEvents(repo.eventQueue_, events);\r\n repo.server_.put(path.toString(), newNodeUnresolved.val(/*export=*/ true), (status, errorReason) => {\r\n const success = status === 'ok';\r\n if (!success) {\r\n warn('set at ' + path + ' failed: ' + status);\r\n }\r\n const clearEvents = syncTreeAckUserWrite(repo.serverSyncTree_, writeId, !success);\r\n eventQueueRaiseEventsForChangedPath(repo.eventQueue_, path, clearEvents);\r\n repoCallOnCompleteCallback(repo, onComplete, status, errorReason);\r\n });\r\n const affectedPath = repoAbortTransactions(repo, path);\r\n repoRerunTransactions(repo, affectedPath);\r\n // We queued the events above, so just flush the queue here\r\n eventQueueRaiseEventsForChangedPath(repo.eventQueue_, affectedPath, []);\r\n}\r\nfunction repoUpdate(repo, path, childrenToMerge, onComplete) {\r\n repoLog(repo, 'update', { path: path.toString(), value: childrenToMerge });\r\n // Start with our existing data and merge each child into it.\r\n let empty = true;\r\n const serverValues = repoGenerateServerValues(repo);\r\n const changedChildren = {};\r\n each(childrenToMerge, (changedKey, changedValue) => {\r\n empty = false;\r\n changedChildren[changedKey] = resolveDeferredValueTree(pathChild(path, changedKey), nodeFromJSON(changedValue), repo.serverSyncTree_, serverValues);\r\n });\r\n if (!empty) {\r\n const writeId = repoGetNextWriteId(repo);\r\n const events = syncTreeApplyUserMerge(repo.serverSyncTree_, path, changedChildren, writeId);\r\n eventQueueQueueEvents(repo.eventQueue_, events);\r\n repo.server_.merge(path.toString(), childrenToMerge, (status, errorReason) => {\r\n const success = status === 'ok';\r\n if (!success) {\r\n warn('update at ' + path + ' failed: ' + status);\r\n }\r\n const clearEvents = syncTreeAckUserWrite(repo.serverSyncTree_, writeId, !success);\r\n const affectedPath = clearEvents.length > 0 ? repoRerunTransactions(repo, path) : path;\r\n eventQueueRaiseEventsForChangedPath(repo.eventQueue_, affectedPath, clearEvents);\r\n repoCallOnCompleteCallback(repo, onComplete, status, errorReason);\r\n });\r\n each(childrenToMerge, (changedPath) => {\r\n const affectedPath = repoAbortTransactions(repo, pathChild(path, changedPath));\r\n repoRerunTransactions(repo, affectedPath);\r\n });\r\n // We queued the events above, so just flush the queue here\r\n eventQueueRaiseEventsForChangedPath(repo.eventQueue_, path, []);\r\n }\r\n else {\r\n log(\"update() called with empty data. Don't do anything.\");\r\n repoCallOnCompleteCallback(repo, onComplete, 'ok', undefined);\r\n }\r\n}\r\n/**\r\n * Applies all of the changes stored up in the onDisconnect_ tree.\r\n */\r\nfunction repoRunOnDisconnectEvents(repo) {\r\n repoLog(repo, 'onDisconnectEvents');\r\n const serverValues = repoGenerateServerValues(repo);\r\n const resolvedOnDisconnectTree = newSparseSnapshotTree();\r\n sparseSnapshotTreeForEachTree(repo.onDisconnect_, newEmptyPath(), (path, node) => {\r\n const resolved = resolveDeferredValueTree(path, node, repo.serverSyncTree_, serverValues);\r\n sparseSnapshotTreeRemember(resolvedOnDisconnectTree, path, resolved);\r\n });\r\n let events = [];\r\n sparseSnapshotTreeForEachTree(resolvedOnDisconnectTree, newEmptyPath(), (path, snap) => {\r\n events = events.concat(syncTreeApplyServerOverwrite(repo.serverSyncTree_, path, snap));\r\n const affectedPath = repoAbortTransactions(repo, path);\r\n repoRerunTransactions(repo, affectedPath);\r\n });\r\n repo.onDisconnect_ = newSparseSnapshotTree();\r\n eventQueueRaiseEventsForChangedPath(repo.eventQueue_, newEmptyPath(), events);\r\n}\r\nfunction repoOnDisconnectCancel(repo, path, onComplete) {\r\n repo.server_.onDisconnectCancel(path.toString(), (status, errorReason) => {\r\n if (status === 'ok') {\r\n sparseSnapshotTreeForget(repo.onDisconnect_, path);\r\n }\r\n repoCallOnCompleteCallback(repo, onComplete, status, errorReason);\r\n });\r\n}\r\nfunction repoOnDisconnectSet(repo, path, value, onComplete) {\r\n const newNode = nodeFromJSON(value);\r\n repo.server_.onDisconnectPut(path.toString(), newNode.val(/*export=*/ true), (status, errorReason) => {\r\n if (status === 'ok') {\r\n sparseSnapshotTreeRemember(repo.onDisconnect_, path, newNode);\r\n }\r\n repoCallOnCompleteCallback(repo, onComplete, status, errorReason);\r\n });\r\n}\r\nfunction repoOnDisconnectSetWithPriority(repo, path, value, priority, onComplete) {\r\n const newNode = nodeFromJSON(value, priority);\r\n repo.server_.onDisconnectPut(path.toString(), newNode.val(/*export=*/ true), (status, errorReason) => {\r\n if (status === 'ok') {\r\n sparseSnapshotTreeRemember(repo.onDisconnect_, path, newNode);\r\n }\r\n repoCallOnCompleteCallback(repo, onComplete, status, errorReason);\r\n });\r\n}\r\nfunction repoOnDisconnectUpdate(repo, path, childrenToMerge, onComplete) {\r\n if (isEmpty(childrenToMerge)) {\r\n log(\"onDisconnect().update() called with empty data. Don't do anything.\");\r\n repoCallOnCompleteCallback(repo, onComplete, 'ok', undefined);\r\n return;\r\n }\r\n repo.server_.onDisconnectMerge(path.toString(), childrenToMerge, (status, errorReason) => {\r\n if (status === 'ok') {\r\n each(childrenToMerge, (childName, childNode) => {\r\n const newChildNode = nodeFromJSON(childNode);\r\n sparseSnapshotTreeRemember(repo.onDisconnect_, pathChild(path, childName), newChildNode);\r\n });\r\n }\r\n repoCallOnCompleteCallback(repo, onComplete, status, errorReason);\r\n });\r\n}\r\nfunction repoAddEventCallbackForQuery(repo, query, eventRegistration) {\r\n let events;\r\n if (pathGetFront(query._path) === '.info') {\r\n events = syncTreeAddEventRegistration(repo.infoSyncTree_, query, eventRegistration);\r\n }\r\n else {\r\n events = syncTreeAddEventRegistration(repo.serverSyncTree_, query, eventRegistration);\r\n }\r\n eventQueueRaiseEventsAtPath(repo.eventQueue_, query._path, events);\r\n}\r\nfunction repoRemoveEventCallbackForQuery(repo, query, eventRegistration) {\r\n // These are guaranteed not to raise events, since we're not passing in a cancelError. However, we can future-proof\r\n // a little bit by handling the return values anyways.\r\n let events;\r\n if (pathGetFront(query._path) === '.info') {\r\n events = syncTreeRemoveEventRegistration(repo.infoSyncTree_, query, eventRegistration);\r\n }\r\n else {\r\n events = syncTreeRemoveEventRegistration(repo.serverSyncTree_, query, eventRegistration);\r\n }\r\n eventQueueRaiseEventsAtPath(repo.eventQueue_, query._path, events);\r\n}\r\nfunction repoInterrupt(repo) {\r\n if (repo.persistentConnection_) {\r\n repo.persistentConnection_.interrupt(INTERRUPT_REASON);\r\n }\r\n}\r\nfunction repoResume(repo) {\r\n if (repo.persistentConnection_) {\r\n repo.persistentConnection_.resume(INTERRUPT_REASON);\r\n }\r\n}\r\nfunction repoLog(repo, ...varArgs) {\r\n let prefix = '';\r\n if (repo.persistentConnection_) {\r\n prefix = repo.persistentConnection_.id + ':';\r\n }\r\n log(prefix, ...varArgs);\r\n}\r\nfunction repoCallOnCompleteCallback(repo, callback, status, errorReason) {\r\n if (callback) {\r\n exceptionGuard(() => {\r\n if (status === 'ok') {\r\n callback(null);\r\n }\r\n else {\r\n const code = (status || 'error').toUpperCase();\r\n let message = code;\r\n if (errorReason) {\r\n message += ': ' + errorReason;\r\n }\r\n const error = new Error(message);\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n error.code = code;\r\n callback(error);\r\n }\r\n });\r\n }\r\n}\r\n/**\r\n * Creates a new transaction, adds it to the transactions we're tracking, and\r\n * sends it to the server if possible.\r\n *\r\n * @param path - Path at which to do transaction.\r\n * @param transactionUpdate - Update callback.\r\n * @param onComplete - Completion callback.\r\n * @param unwatcher - Function that will be called when the transaction no longer\r\n * need data updates for `path`.\r\n * @param applyLocally - Whether or not to make intermediate results visible\r\n */\r\nfunction repoStartTransaction(repo, path, transactionUpdate, onComplete, unwatcher, applyLocally) {\r\n repoLog(repo, 'transaction on ' + path);\r\n // Initialize transaction.\r\n const transaction = {\r\n path,\r\n update: transactionUpdate,\r\n onComplete,\r\n // One of TransactionStatus enums.\r\n status: null,\r\n // Used when combining transactions at different locations to figure out\r\n // which one goes first.\r\n order: LUIDGenerator(),\r\n // Whether to raise local events for this transaction.\r\n applyLocally,\r\n // Count of how many times we've retried the transaction.\r\n retryCount: 0,\r\n // Function to call to clean up our .on() listener.\r\n unwatcher,\r\n // Stores why a transaction was aborted.\r\n abortReason: null,\r\n currentWriteId: null,\r\n currentInputSnapshot: null,\r\n currentOutputSnapshotRaw: null,\r\n currentOutputSnapshotResolved: null\r\n };\r\n // Run transaction initially.\r\n const currentState = repoGetLatestState(repo, path, undefined);\r\n transaction.currentInputSnapshot = currentState;\r\n const newVal = transaction.update(currentState.val());\r\n if (newVal === undefined) {\r\n // Abort transaction.\r\n transaction.unwatcher();\r\n transaction.currentOutputSnapshotRaw = null;\r\n transaction.currentOutputSnapshotResolved = null;\r\n if (transaction.onComplete) {\r\n transaction.onComplete(null, false, transaction.currentInputSnapshot);\r\n }\r\n }\r\n else {\r\n validateFirebaseData('transaction failed: Data returned ', newVal, transaction.path);\r\n // Mark as run and add to our queue.\r\n transaction.status = 0 /* TransactionStatus.RUN */;\r\n const queueNode = treeSubTree(repo.transactionQueueTree_, path);\r\n const nodeQueue = treeGetValue(queueNode) || [];\r\n nodeQueue.push(transaction);\r\n treeSetValue(queueNode, nodeQueue);\r\n // Update visibleData and raise events\r\n // Note: We intentionally raise events after updating all of our\r\n // transaction state, since the user could start new transactions from the\r\n // event callbacks.\r\n let priorityForNode;\r\n if (typeof newVal === 'object' &&\r\n newVal !== null &&\r\n contains(newVal, '.priority')) {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n priorityForNode = safeGet(newVal, '.priority');\r\n assert(isValidPriority(priorityForNode), 'Invalid priority returned by transaction. ' +\r\n 'Priority must be a valid string, finite number, server value, or null.');\r\n }\r\n else {\r\n const currentNode = syncTreeCalcCompleteEventCache(repo.serverSyncTree_, path) ||\r\n ChildrenNode.EMPTY_NODE;\r\n priorityForNode = currentNode.getPriority().val();\r\n }\r\n const serverValues = repoGenerateServerValues(repo);\r\n const newNodeUnresolved = nodeFromJSON(newVal, priorityForNode);\r\n const newNode = resolveDeferredValueSnapshot(newNodeUnresolved, currentState, serverValues);\r\n transaction.currentOutputSnapshotRaw = newNodeUnresolved;\r\n transaction.currentOutputSnapshotResolved = newNode;\r\n transaction.currentWriteId = repoGetNextWriteId(repo);\r\n const events = syncTreeApplyUserOverwrite(repo.serverSyncTree_, path, newNode, transaction.currentWriteId, transaction.applyLocally);\r\n eventQueueRaiseEventsForChangedPath(repo.eventQueue_, path, events);\r\n repoSendReadyTransactions(repo, repo.transactionQueueTree_);\r\n }\r\n}\r\n/**\r\n * @param excludeSets - A specific set to exclude\r\n */\r\nfunction repoGetLatestState(repo, path, excludeSets) {\r\n return (syncTreeCalcCompleteEventCache(repo.serverSyncTree_, path, excludeSets) ||\r\n ChildrenNode.EMPTY_NODE);\r\n}\r\n/**\r\n * Sends any already-run transactions that aren't waiting for outstanding\r\n * transactions to complete.\r\n *\r\n * Externally it's called with no arguments, but it calls itself recursively\r\n * with a particular transactionQueueTree node to recurse through the tree.\r\n *\r\n * @param node - transactionQueueTree node to start at.\r\n */\r\nfunction repoSendReadyTransactions(repo, node = repo.transactionQueueTree_) {\r\n // Before recursing, make sure any completed transactions are removed.\r\n if (!node) {\r\n repoPruneCompletedTransactionsBelowNode(repo, node);\r\n }\r\n if (treeGetValue(node)) {\r\n const queue = repoBuildTransactionQueue(repo, node);\r\n assert(queue.length > 0, 'Sending zero length transaction queue');\r\n const allRun = queue.every((transaction) => transaction.status === 0 /* TransactionStatus.RUN */);\r\n // If they're all run (and not sent), we can send them. Else, we must wait.\r\n if (allRun) {\r\n repoSendTransactionQueue(repo, treeGetPath(node), queue);\r\n }\r\n }\r\n else if (treeHasChildren(node)) {\r\n treeForEachChild(node, childNode => {\r\n repoSendReadyTransactions(repo, childNode);\r\n });\r\n }\r\n}\r\n/**\r\n * Given a list of run transactions, send them to the server and then handle\r\n * the result (success or failure).\r\n *\r\n * @param path - The location of the queue.\r\n * @param queue - Queue of transactions under the specified location.\r\n */\r\nfunction repoSendTransactionQueue(repo, path, queue) {\r\n // Mark transactions as sent and increment retry count!\r\n const setsToIgnore = queue.map(txn => {\r\n return txn.currentWriteId;\r\n });\r\n const latestState = repoGetLatestState(repo, path, setsToIgnore);\r\n let snapToSend = latestState;\r\n const latestHash = latestState.hash();\r\n for (let i = 0; i < queue.length; i++) {\r\n const txn = queue[i];\r\n assert(txn.status === 0 /* TransactionStatus.RUN */, 'tryToSendTransactionQueue_: items in queue should all be run.');\r\n txn.status = 1 /* TransactionStatus.SENT */;\r\n txn.retryCount++;\r\n const relativePath = newRelativePath(path, txn.path);\r\n // If we've gotten to this point, the output snapshot must be defined.\r\n snapToSend = snapToSend.updateChild(relativePath /** @type {!Node} */, txn.currentOutputSnapshotRaw);\r\n }\r\n const dataToSend = snapToSend.val(true);\r\n const pathToSend = path;\r\n // Send the put.\r\n repo.server_.put(pathToSend.toString(), dataToSend, (status) => {\r\n repoLog(repo, 'transaction put response', {\r\n path: pathToSend.toString(),\r\n status\r\n });\r\n let events = [];\r\n if (status === 'ok') {\r\n // Queue up the callbacks and fire them after cleaning up all of our\r\n // transaction state, since the callback could trigger more\r\n // transactions or sets.\r\n const callbacks = [];\r\n for (let i = 0; i < queue.length; i++) {\r\n queue[i].status = 2 /* TransactionStatus.COMPLETED */;\r\n events = events.concat(syncTreeAckUserWrite(repo.serverSyncTree_, queue[i].currentWriteId));\r\n if (queue[i].onComplete) {\r\n // We never unset the output snapshot, and given that this\r\n // transaction is complete, it should be set\r\n callbacks.push(() => queue[i].onComplete(null, true, queue[i].currentOutputSnapshotResolved));\r\n }\r\n queue[i].unwatcher();\r\n }\r\n // Now remove the completed transactions.\r\n repoPruneCompletedTransactionsBelowNode(repo, treeSubTree(repo.transactionQueueTree_, path));\r\n // There may be pending transactions that we can now send.\r\n repoSendReadyTransactions(repo, repo.transactionQueueTree_);\r\n eventQueueRaiseEventsForChangedPath(repo.eventQueue_, path, events);\r\n // Finally, trigger onComplete callbacks.\r\n for (let i = 0; i < callbacks.length; i++) {\r\n exceptionGuard(callbacks[i]);\r\n }\r\n }\r\n else {\r\n // transactions are no longer sent. Update their status appropriately.\r\n if (status === 'datastale') {\r\n for (let i = 0; i < queue.length; i++) {\r\n if (queue[i].status === 3 /* TransactionStatus.SENT_NEEDS_ABORT */) {\r\n queue[i].status = 4 /* TransactionStatus.NEEDS_ABORT */;\r\n }\r\n else {\r\n queue[i].status = 0 /* TransactionStatus.RUN */;\r\n }\r\n }\r\n }\r\n else {\r\n warn('transaction at ' + pathToSend.toString() + ' failed: ' + status);\r\n for (let i = 0; i < queue.length; i++) {\r\n queue[i].status = 4 /* TransactionStatus.NEEDS_ABORT */;\r\n queue[i].abortReason = status;\r\n }\r\n }\r\n repoRerunTransactions(repo, path);\r\n }\r\n }, latestHash);\r\n}\r\n/**\r\n * Finds all transactions dependent on the data at changedPath and reruns them.\r\n *\r\n * Should be called any time cached data changes.\r\n *\r\n * Return the highest path that was affected by rerunning transactions. This\r\n * is the path at which events need to be raised for.\r\n *\r\n * @param changedPath - The path in mergedData that changed.\r\n * @returns The rootmost path that was affected by rerunning transactions.\r\n */\r\nfunction repoRerunTransactions(repo, changedPath) {\r\n const rootMostTransactionNode = repoGetAncestorTransactionNode(repo, changedPath);\r\n const path = treeGetPath(rootMostTransactionNode);\r\n const queue = repoBuildTransactionQueue(repo, rootMostTransactionNode);\r\n repoRerunTransactionQueue(repo, queue, path);\r\n return path;\r\n}\r\n/**\r\n * Does all the work of rerunning transactions (as well as cleans up aborted\r\n * transactions and whatnot).\r\n *\r\n * @param queue - The queue of transactions to run.\r\n * @param path - The path the queue is for.\r\n */\r\nfunction repoRerunTransactionQueue(repo, queue, path) {\r\n if (queue.length === 0) {\r\n return; // Nothing to do!\r\n }\r\n // Queue up the callbacks and fire them after cleaning up all of our\r\n // transaction state, since the callback could trigger more transactions or\r\n // sets.\r\n const callbacks = [];\r\n let events = [];\r\n // Ignore all of the sets we're going to re-run.\r\n const txnsToRerun = queue.filter(q => {\r\n return q.status === 0 /* TransactionStatus.RUN */;\r\n });\r\n const setsToIgnore = txnsToRerun.map(q => {\r\n return q.currentWriteId;\r\n });\r\n for (let i = 0; i < queue.length; i++) {\r\n const transaction = queue[i];\r\n const relativePath = newRelativePath(path, transaction.path);\r\n let abortTransaction = false, abortReason;\r\n assert(relativePath !== null, 'rerunTransactionsUnderNode_: relativePath should not be null.');\r\n if (transaction.status === 4 /* TransactionStatus.NEEDS_ABORT */) {\r\n abortTransaction = true;\r\n abortReason = transaction.abortReason;\r\n events = events.concat(syncTreeAckUserWrite(repo.serverSyncTree_, transaction.currentWriteId, true));\r\n }\r\n else if (transaction.status === 0 /* TransactionStatus.RUN */) {\r\n if (transaction.retryCount >= MAX_TRANSACTION_RETRIES) {\r\n abortTransaction = true;\r\n abortReason = 'maxretry';\r\n events = events.concat(syncTreeAckUserWrite(repo.serverSyncTree_, transaction.currentWriteId, true));\r\n }\r\n else {\r\n // This code reruns a transaction\r\n const currentNode = repoGetLatestState(repo, transaction.path, setsToIgnore);\r\n transaction.currentInputSnapshot = currentNode;\r\n const newData = queue[i].update(currentNode.val());\r\n if (newData !== undefined) {\r\n validateFirebaseData('transaction failed: Data returned ', newData, transaction.path);\r\n let newDataNode = nodeFromJSON(newData);\r\n const hasExplicitPriority = typeof newData === 'object' &&\r\n newData != null &&\r\n contains(newData, '.priority');\r\n if (!hasExplicitPriority) {\r\n // Keep the old priority if there wasn't a priority explicitly specified.\r\n newDataNode = newDataNode.updatePriority(currentNode.getPriority());\r\n }\r\n const oldWriteId = transaction.currentWriteId;\r\n const serverValues = repoGenerateServerValues(repo);\r\n const newNodeResolved = resolveDeferredValueSnapshot(newDataNode, currentNode, serverValues);\r\n transaction.currentOutputSnapshotRaw = newDataNode;\r\n transaction.currentOutputSnapshotResolved = newNodeResolved;\r\n transaction.currentWriteId = repoGetNextWriteId(repo);\r\n // Mutates setsToIgnore in place\r\n setsToIgnore.splice(setsToIgnore.indexOf(oldWriteId), 1);\r\n events = events.concat(syncTreeApplyUserOverwrite(repo.serverSyncTree_, transaction.path, newNodeResolved, transaction.currentWriteId, transaction.applyLocally));\r\n events = events.concat(syncTreeAckUserWrite(repo.serverSyncTree_, oldWriteId, true));\r\n }\r\n else {\r\n abortTransaction = true;\r\n abortReason = 'nodata';\r\n events = events.concat(syncTreeAckUserWrite(repo.serverSyncTree_, transaction.currentWriteId, true));\r\n }\r\n }\r\n }\r\n eventQueueRaiseEventsForChangedPath(repo.eventQueue_, path, events);\r\n events = [];\r\n if (abortTransaction) {\r\n // Abort.\r\n queue[i].status = 2 /* TransactionStatus.COMPLETED */;\r\n // Removing a listener can trigger pruning which can muck with\r\n // mergedData/visibleData (as it prunes data). So defer the unwatcher\r\n // until we're done.\r\n (function (unwatcher) {\r\n setTimeout(unwatcher, Math.floor(0));\r\n })(queue[i].unwatcher);\r\n if (queue[i].onComplete) {\r\n if (abortReason === 'nodata') {\r\n callbacks.push(() => queue[i].onComplete(null, false, queue[i].currentInputSnapshot));\r\n }\r\n else {\r\n callbacks.push(() => queue[i].onComplete(new Error(abortReason), false, null));\r\n }\r\n }\r\n }\r\n }\r\n // Clean up completed transactions.\r\n repoPruneCompletedTransactionsBelowNode(repo, repo.transactionQueueTree_);\r\n // Now fire callbacks, now that we're in a good, known state.\r\n for (let i = 0; i < callbacks.length; i++) {\r\n exceptionGuard(callbacks[i]);\r\n }\r\n // Try to send the transaction result to the server.\r\n repoSendReadyTransactions(repo, repo.transactionQueueTree_);\r\n}\r\n/**\r\n * Returns the rootmost ancestor node of the specified path that has a pending\r\n * transaction on it, or just returns the node for the given path if there are\r\n * no pending transactions on any ancestor.\r\n *\r\n * @param path - The location to start at.\r\n * @returns The rootmost node with a transaction.\r\n */\r\nfunction repoGetAncestorTransactionNode(repo, path) {\r\n let front;\r\n // Start at the root and walk deeper into the tree towards path until we\r\n // find a node with pending transactions.\r\n let transactionNode = repo.transactionQueueTree_;\r\n front = pathGetFront(path);\r\n while (front !== null && treeGetValue(transactionNode) === undefined) {\r\n transactionNode = treeSubTree(transactionNode, front);\r\n path = pathPopFront(path);\r\n front = pathGetFront(path);\r\n }\r\n return transactionNode;\r\n}\r\n/**\r\n * Builds the queue of all transactions at or below the specified\r\n * transactionNode.\r\n *\r\n * @param transactionNode\r\n * @returns The generated queue.\r\n */\r\nfunction repoBuildTransactionQueue(repo, transactionNode) {\r\n // Walk any child transaction queues and aggregate them into a single queue.\r\n const transactionQueue = [];\r\n repoAggregateTransactionQueuesForNode(repo, transactionNode, transactionQueue);\r\n // Sort them by the order the transactions were created.\r\n transactionQueue.sort((a, b) => a.order - b.order);\r\n return transactionQueue;\r\n}\r\nfunction repoAggregateTransactionQueuesForNode(repo, node, queue) {\r\n const nodeQueue = treeGetValue(node);\r\n if (nodeQueue) {\r\n for (let i = 0; i < nodeQueue.length; i++) {\r\n queue.push(nodeQueue[i]);\r\n }\r\n }\r\n treeForEachChild(node, child => {\r\n repoAggregateTransactionQueuesForNode(repo, child, queue);\r\n });\r\n}\r\n/**\r\n * Remove COMPLETED transactions at or below this node in the transactionQueueTree_.\r\n */\r\nfunction repoPruneCompletedTransactionsBelowNode(repo, node) {\r\n const queue = treeGetValue(node);\r\n if (queue) {\r\n let to = 0;\r\n for (let from = 0; from < queue.length; from++) {\r\n if (queue[from].status !== 2 /* TransactionStatus.COMPLETED */) {\r\n queue[to] = queue[from];\r\n to++;\r\n }\r\n }\r\n queue.length = to;\r\n treeSetValue(node, queue.length > 0 ? queue : undefined);\r\n }\r\n treeForEachChild(node, childNode => {\r\n repoPruneCompletedTransactionsBelowNode(repo, childNode);\r\n });\r\n}\r\n/**\r\n * Aborts all transactions on ancestors or descendants of the specified path.\r\n * Called when doing a set() or update() since we consider them incompatible\r\n * with transactions.\r\n *\r\n * @param path - Path for which we want to abort related transactions.\r\n */\r\nfunction repoAbortTransactions(repo, path) {\r\n const affectedPath = treeGetPath(repoGetAncestorTransactionNode(repo, path));\r\n const transactionNode = treeSubTree(repo.transactionQueueTree_, path);\r\n treeForEachAncestor(transactionNode, (node) => {\r\n repoAbortTransactionsOnNode(repo, node);\r\n });\r\n repoAbortTransactionsOnNode(repo, transactionNode);\r\n treeForEachDescendant(transactionNode, (node) => {\r\n repoAbortTransactionsOnNode(repo, node);\r\n });\r\n return affectedPath;\r\n}\r\n/**\r\n * Abort transactions stored in this transaction queue node.\r\n *\r\n * @param node - Node to abort transactions for.\r\n */\r\nfunction repoAbortTransactionsOnNode(repo, node) {\r\n const queue = treeGetValue(node);\r\n if (queue) {\r\n // Queue up the callbacks and fire them after cleaning up all of our\r\n // transaction state, since the callback could trigger more transactions\r\n // or sets.\r\n const callbacks = [];\r\n // Go through queue. Any already-sent transactions must be marked for\r\n // abort, while the unsent ones can be immediately aborted and removed.\r\n let events = [];\r\n let lastSent = -1;\r\n for (let i = 0; i < queue.length; i++) {\r\n if (queue[i].status === 3 /* TransactionStatus.SENT_NEEDS_ABORT */) ;\r\n else if (queue[i].status === 1 /* TransactionStatus.SENT */) {\r\n assert(lastSent === i - 1, 'All SENT items should be at beginning of queue.');\r\n lastSent = i;\r\n // Mark transaction for abort when it comes back.\r\n queue[i].status = 3 /* TransactionStatus.SENT_NEEDS_ABORT */;\r\n queue[i].abortReason = 'set';\r\n }\r\n else {\r\n assert(queue[i].status === 0 /* TransactionStatus.RUN */, 'Unexpected transaction status in abort');\r\n // We can abort it immediately.\r\n queue[i].unwatcher();\r\n events = events.concat(syncTreeAckUserWrite(repo.serverSyncTree_, queue[i].currentWriteId, true));\r\n if (queue[i].onComplete) {\r\n callbacks.push(queue[i].onComplete.bind(null, new Error('set'), false, null));\r\n }\r\n }\r\n }\r\n if (lastSent === -1) {\r\n // We're not waiting for any sent transactions. We can clear the queue.\r\n treeSetValue(node, undefined);\r\n }\r\n else {\r\n // Remove the transactions we aborted.\r\n queue.length = lastSent + 1;\r\n }\r\n // Now fire the callbacks.\r\n eventQueueRaiseEventsForChangedPath(repo.eventQueue_, treeGetPath(node), events);\r\n for (let i = 0; i < callbacks.length; i++) {\r\n exceptionGuard(callbacks[i]);\r\n }\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nfunction decodePath(pathString) {\r\n let pathStringDecoded = '';\r\n const pieces = pathString.split('/');\r\n for (let i = 0; i < pieces.length; i++) {\r\n if (pieces[i].length > 0) {\r\n let piece = pieces[i];\r\n try {\r\n piece = decodeURIComponent(piece.replace(/\\+/g, ' '));\r\n }\r\n catch (e) { }\r\n pathStringDecoded += '/' + piece;\r\n }\r\n }\r\n return pathStringDecoded;\r\n}\r\n/**\r\n * @returns key value hash\r\n */\r\nfunction decodeQuery(queryString) {\r\n const results = {};\r\n if (queryString.charAt(0) === '?') {\r\n queryString = queryString.substring(1);\r\n }\r\n for (const segment of queryString.split('&')) {\r\n if (segment.length === 0) {\r\n continue;\r\n }\r\n const kv = segment.split('=');\r\n if (kv.length === 2) {\r\n results[decodeURIComponent(kv[0])] = decodeURIComponent(kv[1]);\r\n }\r\n else {\r\n warn(`Invalid query segment '${segment}' in query '${queryString}'`);\r\n }\r\n }\r\n return results;\r\n}\r\nconst parseRepoInfo = function (dataURL, nodeAdmin) {\r\n const parsedUrl = parseDatabaseURL(dataURL), namespace = parsedUrl.namespace;\r\n if (parsedUrl.domain === 'firebase.com') {\r\n fatal(parsedUrl.host +\r\n ' is no longer supported. ' +\r\n 'Please use .firebaseio.com instead');\r\n }\r\n // Catch common error of uninitialized namespace value.\r\n if ((!namespace || namespace === 'undefined') &&\r\n parsedUrl.domain !== 'localhost') {\r\n fatal('Cannot parse Firebase url. Please use https://.firebaseio.com');\r\n }\r\n if (!parsedUrl.secure) {\r\n warnIfPageIsSecure();\r\n }\r\n const webSocketOnly = parsedUrl.scheme === 'ws' || parsedUrl.scheme === 'wss';\r\n return {\r\n repoInfo: new RepoInfo(parsedUrl.host, parsedUrl.secure, namespace, webSocketOnly, nodeAdmin, \r\n /*persistenceKey=*/ '', \r\n /*includeNamespaceInQueryParams=*/ namespace !== parsedUrl.subdomain),\r\n path: new Path(parsedUrl.pathString)\r\n };\r\n};\r\nconst parseDatabaseURL = function (dataURL) {\r\n // Default to empty strings in the event of a malformed string.\r\n let host = '', domain = '', subdomain = '', pathString = '', namespace = '';\r\n // Always default to SSL, unless otherwise specified.\r\n let secure = true, scheme = 'https', port = 443;\r\n // Don't do any validation here. The caller is responsible for validating the result of parsing.\r\n if (typeof dataURL === 'string') {\r\n // Parse scheme.\r\n let colonInd = dataURL.indexOf('//');\r\n if (colonInd >= 0) {\r\n scheme = dataURL.substring(0, colonInd - 1);\r\n dataURL = dataURL.substring(colonInd + 2);\r\n }\r\n // Parse host, path, and query string.\r\n let slashInd = dataURL.indexOf('/');\r\n if (slashInd === -1) {\r\n slashInd = dataURL.length;\r\n }\r\n let questionMarkInd = dataURL.indexOf('?');\r\n if (questionMarkInd === -1) {\r\n questionMarkInd = dataURL.length;\r\n }\r\n host = dataURL.substring(0, Math.min(slashInd, questionMarkInd));\r\n if (slashInd < questionMarkInd) {\r\n // For pathString, questionMarkInd will always come after slashInd\r\n pathString = decodePath(dataURL.substring(slashInd, questionMarkInd));\r\n }\r\n const queryParams = decodeQuery(dataURL.substring(Math.min(dataURL.length, questionMarkInd)));\r\n // If we have a port, use scheme for determining if it's secure.\r\n colonInd = host.indexOf(':');\r\n if (colonInd >= 0) {\r\n secure = scheme === 'https' || scheme === 'wss';\r\n port = parseInt(host.substring(colonInd + 1), 10);\r\n }\r\n else {\r\n colonInd = host.length;\r\n }\r\n const hostWithoutPort = host.slice(0, colonInd);\r\n if (hostWithoutPort.toLowerCase() === 'localhost') {\r\n domain = 'localhost';\r\n }\r\n else if (hostWithoutPort.split('.').length <= 2) {\r\n domain = hostWithoutPort;\r\n }\r\n else {\r\n // Interpret the subdomain of a 3 or more component URL as the namespace name.\r\n const dotInd = host.indexOf('.');\r\n subdomain = host.substring(0, dotInd).toLowerCase();\r\n domain = host.substring(dotInd + 1);\r\n // Normalize namespaces to lowercase to share storage / connection.\r\n namespace = subdomain;\r\n }\r\n // Always treat the value of the `ns` as the namespace name if it is present.\r\n if ('ns' in queryParams) {\r\n namespace = queryParams['ns'];\r\n }\r\n }\r\n return {\r\n host,\r\n port,\r\n domain,\r\n subdomain,\r\n secure,\r\n scheme,\r\n pathString,\r\n namespace\r\n };\r\n};\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n// Modeled after base64 web-safe chars, but ordered by ASCII.\r\nconst PUSH_CHARS = '-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz';\r\n/**\r\n * Fancy ID generator that creates 20-character string identifiers with the\r\n * following properties:\r\n *\r\n * 1. They're based on timestamp so that they sort *after* any existing ids.\r\n * 2. They contain 72-bits of random data after the timestamp so that IDs won't\r\n * collide with other clients' IDs.\r\n * 3. They sort *lexicographically* (so the timestamp is converted to characters\r\n * that will sort properly).\r\n * 4. They're monotonically increasing. Even if you generate more than one in\r\n * the same timestamp, the latter ones will sort after the former ones. We do\r\n * this by using the previous random bits but \"incrementing\" them by 1 (only\r\n * in the case of a timestamp collision).\r\n */\r\nconst nextPushId = (function () {\r\n // Timestamp of last push, used to prevent local collisions if you push twice\r\n // in one ms.\r\n let lastPushTime = 0;\r\n // We generate 72-bits of randomness which get turned into 12 characters and\r\n // appended to the timestamp to prevent collisions with other clients. We\r\n // store the last characters we generated because in the event of a collision,\r\n // we'll use those same characters except \"incremented\" by one.\r\n const lastRandChars = [];\r\n return function (now) {\r\n const duplicateTime = now === lastPushTime;\r\n lastPushTime = now;\r\n let i;\r\n const timeStampChars = new Array(8);\r\n for (i = 7; i >= 0; i--) {\r\n timeStampChars[i] = PUSH_CHARS.charAt(now % 64);\r\n // NOTE: Can't use << here because javascript will convert to int and lose\r\n // the upper bits.\r\n now = Math.floor(now / 64);\r\n }\r\n assert(now === 0, 'Cannot push at time == 0');\r\n let id = timeStampChars.join('');\r\n if (!duplicateTime) {\r\n for (i = 0; i < 12; i++) {\r\n lastRandChars[i] = Math.floor(Math.random() * 64);\r\n }\r\n }\r\n else {\r\n // If the timestamp hasn't changed since last push, use the same random\r\n // number, except incremented by 1.\r\n for (i = 11; i >= 0 && lastRandChars[i] === 63; i--) {\r\n lastRandChars[i] = 0;\r\n }\r\n lastRandChars[i]++;\r\n }\r\n for (i = 0; i < 12; i++) {\r\n id += PUSH_CHARS.charAt(lastRandChars[i]);\r\n }\r\n assert(id.length === 20, 'nextPushId: Length should be 20.');\r\n return id;\r\n };\r\n})();\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * Encapsulates the data needed to raise an event\r\n */\r\nclass DataEvent {\r\n /**\r\n * @param eventType - One of: value, child_added, child_changed, child_moved, child_removed\r\n * @param eventRegistration - The function to call to with the event data. User provided\r\n * @param snapshot - The data backing the event\r\n * @param prevName - Optional, the name of the previous child for child_* events.\r\n */\r\n constructor(eventType, eventRegistration, snapshot, prevName) {\r\n this.eventType = eventType;\r\n this.eventRegistration = eventRegistration;\r\n this.snapshot = snapshot;\r\n this.prevName = prevName;\r\n }\r\n getPath() {\r\n const ref = this.snapshot.ref;\r\n if (this.eventType === 'value') {\r\n return ref._path;\r\n }\r\n else {\r\n return ref.parent._path;\r\n }\r\n }\r\n getEventType() {\r\n return this.eventType;\r\n }\r\n getEventRunner() {\r\n return this.eventRegistration.getEventRunner(this);\r\n }\r\n toString() {\r\n return (this.getPath().toString() +\r\n ':' +\r\n this.eventType +\r\n ':' +\r\n stringify(this.snapshot.exportVal()));\r\n }\r\n}\r\nclass CancelEvent {\r\n constructor(eventRegistration, error, path) {\r\n this.eventRegistration = eventRegistration;\r\n this.error = error;\r\n this.path = path;\r\n }\r\n getPath() {\r\n return this.path;\r\n }\r\n getEventType() {\r\n return 'cancel';\r\n }\r\n getEventRunner() {\r\n return this.eventRegistration.getEventRunner(this);\r\n }\r\n toString() {\r\n return this.path.toString() + ':cancel';\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * A wrapper class that converts events from the database@exp SDK to the legacy\r\n * Database SDK. Events are not converted directly as event registration relies\r\n * on reference comparison of the original user callback (see `matches()`) and\r\n * relies on equality of the legacy SDK's `context` object.\r\n */\r\nclass CallbackContext {\r\n constructor(snapshotCallback, cancelCallback) {\r\n this.snapshotCallback = snapshotCallback;\r\n this.cancelCallback = cancelCallback;\r\n }\r\n onValue(expDataSnapshot, previousChildName) {\r\n this.snapshotCallback.call(null, expDataSnapshot, previousChildName);\r\n }\r\n onCancel(error) {\r\n assert(this.hasCancelCallback, 'Raising a cancel event on a listener with no cancel callback');\r\n return this.cancelCallback.call(null, error);\r\n }\r\n get hasCancelCallback() {\r\n return !!this.cancelCallback;\r\n }\r\n matches(other) {\r\n return (this.snapshotCallback === other.snapshotCallback ||\r\n (this.snapshotCallback.userCallback !== undefined &&\r\n this.snapshotCallback.userCallback ===\r\n other.snapshotCallback.userCallback &&\r\n this.snapshotCallback.context === other.snapshotCallback.context));\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2021 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * The `onDisconnect` class allows you to write or clear data when your client\r\n * disconnects from the Database server. These updates occur whether your\r\n * client disconnects cleanly or not, so you can rely on them to clean up data\r\n * even if a connection is dropped or a client crashes.\r\n *\r\n * The `onDisconnect` class is most commonly used to manage presence in\r\n * applications where it is useful to detect how many clients are connected and\r\n * when other clients disconnect. See\r\n * {@link https://firebase.google.com/docs/database/web/offline-capabilities | Enabling Offline Capabilities in JavaScript}\r\n * for more information.\r\n *\r\n * To avoid problems when a connection is dropped before the requests can be\r\n * transferred to the Database server, these functions should be called before\r\n * writing any data.\r\n *\r\n * Note that `onDisconnect` operations are only triggered once. If you want an\r\n * operation to occur each time a disconnect occurs, you'll need to re-establish\r\n * the `onDisconnect` operations each time you reconnect.\r\n */\r\nclass OnDisconnect {\r\n /** @hideconstructor */\r\n constructor(_repo, _path) {\r\n this._repo = _repo;\r\n this._path = _path;\r\n }\r\n /**\r\n * Cancels all previously queued `onDisconnect()` set or update events for this\r\n * location and all children.\r\n *\r\n * If a write has been queued for this location via a `set()` or `update()` at a\r\n * parent location, the write at this location will be canceled, though writes\r\n * to sibling locations will still occur.\r\n *\r\n * @returns Resolves when synchronization to the server is complete.\r\n */\r\n cancel() {\r\n const deferred = new Deferred();\r\n repoOnDisconnectCancel(this._repo, this._path, deferred.wrapCallback(() => { }));\r\n return deferred.promise;\r\n }\r\n /**\r\n * Ensures the data at this location is deleted when the client is disconnected\r\n * (due to closing the browser, navigating to a new page, or network issues).\r\n *\r\n * @returns Resolves when synchronization to the server is complete.\r\n */\r\n remove() {\r\n validateWritablePath('OnDisconnect.remove', this._path);\r\n const deferred = new Deferred();\r\n repoOnDisconnectSet(this._repo, this._path, null, deferred.wrapCallback(() => { }));\r\n return deferred.promise;\r\n }\r\n /**\r\n * Ensures the data at this location is set to the specified value when the\r\n * client is disconnected (due to closing the browser, navigating to a new page,\r\n * or network issues).\r\n *\r\n * `set()` is especially useful for implementing \"presence\" systems, where a\r\n * value should be changed or cleared when a user disconnects so that they\r\n * appear \"offline\" to other users. See\r\n * {@link https://firebase.google.com/docs/database/web/offline-capabilities | Enabling Offline Capabilities in JavaScript}\r\n * for more information.\r\n *\r\n * Note that `onDisconnect` operations are only triggered once. If you want an\r\n * operation to occur each time a disconnect occurs, you'll need to re-establish\r\n * the `onDisconnect` operations each time.\r\n *\r\n * @param value - The value to be written to this location on disconnect (can\r\n * be an object, array, string, number, boolean, or null).\r\n * @returns Resolves when synchronization to the Database is complete.\r\n */\r\n set(value) {\r\n validateWritablePath('OnDisconnect.set', this._path);\r\n validateFirebaseDataArg('OnDisconnect.set', value, this._path, false);\r\n const deferred = new Deferred();\r\n repoOnDisconnectSet(this._repo, this._path, value, deferred.wrapCallback(() => { }));\r\n return deferred.promise;\r\n }\r\n /**\r\n * Ensures the data at this location is set to the specified value and priority\r\n * when the client is disconnected (due to closing the browser, navigating to a\r\n * new page, or network issues).\r\n *\r\n * @param value - The value to be written to this location on disconnect (can\r\n * be an object, array, string, number, boolean, or null).\r\n * @param priority - The priority to be written (string, number, or null).\r\n * @returns Resolves when synchronization to the Database is complete.\r\n */\r\n setWithPriority(value, priority) {\r\n validateWritablePath('OnDisconnect.setWithPriority', this._path);\r\n validateFirebaseDataArg('OnDisconnect.setWithPriority', value, this._path, false);\r\n validatePriority('OnDisconnect.setWithPriority', priority, false);\r\n const deferred = new Deferred();\r\n repoOnDisconnectSetWithPriority(this._repo, this._path, value, priority, deferred.wrapCallback(() => { }));\r\n return deferred.promise;\r\n }\r\n /**\r\n * Writes multiple values at this location when the client is disconnected (due\r\n * to closing the browser, navigating to a new page, or network issues).\r\n *\r\n * The `values` argument contains multiple property-value pairs that will be\r\n * written to the Database together. Each child property can either be a simple\r\n * property (for example, \"name\") or a relative path (for example, \"name/first\")\r\n * from the current location to the data to update.\r\n *\r\n * As opposed to the `set()` method, `update()` can be use to selectively update\r\n * only the referenced properties at the current location (instead of replacing\r\n * all the child properties at the current location).\r\n *\r\n * @param values - Object containing multiple values.\r\n * @returns Resolves when synchronization to the Database is complete.\r\n */\r\n update(values) {\r\n validateWritablePath('OnDisconnect.update', this._path);\r\n validateFirebaseMergeDataArg('OnDisconnect.update', values, this._path, false);\r\n const deferred = new Deferred();\r\n repoOnDisconnectUpdate(this._repo, this._path, values, deferred.wrapCallback(() => { }));\r\n return deferred.promise;\r\n }\r\n}\n\n/**\r\n * @license\r\n * Copyright 2020 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * @internal\r\n */\r\nclass QueryImpl {\r\n /**\r\n * @hideconstructor\r\n */\r\n constructor(_repo, _path, _queryParams, _orderByCalled) {\r\n this._repo = _repo;\r\n this._path = _path;\r\n this._queryParams = _queryParams;\r\n this._orderByCalled = _orderByCalled;\r\n }\r\n get key() {\r\n if (pathIsEmpty(this._path)) {\r\n return null;\r\n }\r\n else {\r\n return pathGetBack(this._path);\r\n }\r\n }\r\n get ref() {\r\n return new ReferenceImpl(this._repo, this._path);\r\n }\r\n get _queryIdentifier() {\r\n const obj = queryParamsGetQueryObject(this._queryParams);\r\n const id = ObjectToUniqueKey(obj);\r\n return id === '{}' ? 'default' : id;\r\n }\r\n /**\r\n * An object representation of the query parameters used by this Query.\r\n */\r\n get _queryObject() {\r\n return queryParamsGetQueryObject(this._queryParams);\r\n }\r\n isEqual(other) {\r\n other = getModularInstance(other);\r\n if (!(other instanceof QueryImpl)) {\r\n return false;\r\n }\r\n const sameRepo = this._repo === other._repo;\r\n const samePath = pathEquals(this._path, other._path);\r\n const sameQueryIdentifier = this._queryIdentifier === other._queryIdentifier;\r\n return sameRepo && samePath && sameQueryIdentifier;\r\n }\r\n toJSON() {\r\n return this.toString();\r\n }\r\n toString() {\r\n return this._repo.toString() + pathToUrlEncodedString(this._path);\r\n }\r\n}\r\n/**\r\n * Validates that no other order by call has been made\r\n */\r\nfunction validateNoPreviousOrderByCall(query, fnName) {\r\n if (query._orderByCalled === true) {\r\n throw new Error(fnName + \": You can't combine multiple orderBy calls.\");\r\n }\r\n}\r\n/**\r\n * Validates start/end values for queries.\r\n */\r\nfunction validateQueryEndpoints(params) {\r\n let startNode = null;\r\n let endNode = null;\r\n if (params.hasStart()) {\r\n startNode = params.getIndexStartValue();\r\n }\r\n if (params.hasEnd()) {\r\n endNode = params.getIndexEndValue();\r\n }\r\n if (params.getIndex() === KEY_INDEX) {\r\n const tooManyArgsError = 'Query: When ordering by key, you may only pass one argument to ' +\r\n 'startAt(), endAt(), or equalTo().';\r\n const wrongArgTypeError = 'Query: When ordering by key, the argument passed to startAt(), startAfter(), ' +\r\n 'endAt(), endBefore(), or equalTo() must be a string.';\r\n if (params.hasStart()) {\r\n const startName = params.getIndexStartName();\r\n if (startName !== MIN_NAME) {\r\n throw new Error(tooManyArgsError);\r\n }\r\n else if (typeof startNode !== 'string') {\r\n throw new Error(wrongArgTypeError);\r\n }\r\n }\r\n if (params.hasEnd()) {\r\n const endName = params.getIndexEndName();\r\n if (endName !== MAX_NAME) {\r\n throw new Error(tooManyArgsError);\r\n }\r\n else if (typeof endNode !== 'string') {\r\n throw new Error(wrongArgTypeError);\r\n }\r\n }\r\n }\r\n else if (params.getIndex() === PRIORITY_INDEX) {\r\n if ((startNode != null && !isValidPriority(startNode)) ||\r\n (endNode != null && !isValidPriority(endNode))) {\r\n throw new Error('Query: When ordering by priority, the first argument passed to startAt(), ' +\r\n 'startAfter() endAt(), endBefore(), or equalTo() must be a valid priority value ' +\r\n '(null, a number, or a string).');\r\n }\r\n }\r\n else {\r\n assert(params.getIndex() instanceof PathIndex ||\r\n params.getIndex() === VALUE_INDEX, 'unknown index type.');\r\n if ((startNode != null && typeof startNode === 'object') ||\r\n (endNode != null && typeof endNode === 'object')) {\r\n throw new Error('Query: First argument passed to startAt(), startAfter(), endAt(), endBefore(), or ' +\r\n 'equalTo() cannot be an object.');\r\n }\r\n }\r\n}\r\n/**\r\n * Validates that limit* has been called with the correct combination of parameters\r\n */\r\nfunction validateLimit(params) {\r\n if (params.hasStart() &&\r\n params.hasEnd() &&\r\n params.hasLimit() &&\r\n !params.hasAnchoredLimit()) {\r\n throw new Error(\"Query: Can't combine startAt(), startAfter(), endAt(), endBefore(), and limit(). Use \" +\r\n 'limitToFirst() or limitToLast() instead.');\r\n }\r\n}\r\n/**\r\n * @internal\r\n */\r\nclass ReferenceImpl extends QueryImpl {\r\n /** @hideconstructor */\r\n constructor(repo, path) {\r\n super(repo, path, new QueryParams(), false);\r\n }\r\n get parent() {\r\n const parentPath = pathParent(this._path);\r\n return parentPath === null\r\n ? null\r\n : new ReferenceImpl(this._repo, parentPath);\r\n }\r\n get root() {\r\n let ref = this;\r\n while (ref.parent !== null) {\r\n ref = ref.parent;\r\n }\r\n return ref;\r\n }\r\n}\r\n/**\r\n * A `DataSnapshot` contains data from a Database location.\r\n *\r\n * Any time you read data from the Database, you receive the data as a\r\n * `DataSnapshot`. A `DataSnapshot` is passed to the event callbacks you attach\r\n * with `on()` or `once()`. You can extract the contents of the snapshot as a\r\n * JavaScript object by calling the `val()` method. Alternatively, you can\r\n * traverse into the snapshot by calling `child()` to return child snapshots\r\n * (which you could then call `val()` on).\r\n *\r\n * A `DataSnapshot` is an efficiently generated, immutable copy of the data at\r\n * a Database location. It cannot be modified and will never change (to modify\r\n * data, you always call the `set()` method on a `Reference` directly).\r\n */\r\nclass DataSnapshot {\r\n /**\r\n * @param _node - A SnapshotNode to wrap.\r\n * @param ref - The location this snapshot came from.\r\n * @param _index - The iteration order for this snapshot\r\n * @hideconstructor\r\n */\r\n constructor(_node, \r\n /**\r\n * The location of this DataSnapshot.\r\n */\r\n ref, _index) {\r\n this._node = _node;\r\n this.ref = ref;\r\n this._index = _index;\r\n }\r\n /**\r\n * Gets the priority value of the data in this `DataSnapshot`.\r\n *\r\n * Applications need not use priority but can order collections by\r\n * ordinary properties (see\r\n * {@link https://firebase.google.com/docs/database/web/lists-of-data#sorting_and_filtering_data |Sorting and filtering data}\r\n * ).\r\n */\r\n get priority() {\r\n // typecast here because we never return deferred values or internal priorities (MAX_PRIORITY)\r\n return this._node.getPriority().val();\r\n }\r\n /**\r\n * The key (last part of the path) of the location of this `DataSnapshot`.\r\n *\r\n * The last token in a Database location is considered its key. For example,\r\n * \"ada\" is the key for the /users/ada/ node. Accessing the key on any\r\n * `DataSnapshot` will return the key for the location that generated it.\r\n * However, accessing the key on the root URL of a Database will return\r\n * `null`.\r\n */\r\n get key() {\r\n return this.ref.key;\r\n }\r\n /** Returns the number of child properties of this `DataSnapshot`. */\r\n get size() {\r\n return this._node.numChildren();\r\n }\r\n /**\r\n * Gets another `DataSnapshot` for the location at the specified relative path.\r\n *\r\n * Passing a relative path to the `child()` method of a DataSnapshot returns\r\n * another `DataSnapshot` for the location at the specified relative path. The\r\n * relative path can either be a simple child name (for example, \"ada\") or a\r\n * deeper, slash-separated path (for example, \"ada/name/first\"). If the child\r\n * location has no data, an empty `DataSnapshot` (that is, a `DataSnapshot`\r\n * whose value is `null`) is returned.\r\n *\r\n * @param path - A relative path to the location of child data.\r\n */\r\n child(path) {\r\n const childPath = new Path(path);\r\n const childRef = child(this.ref, path);\r\n return new DataSnapshot(this._node.getChild(childPath), childRef, PRIORITY_INDEX);\r\n }\r\n /**\r\n * Returns true if this `DataSnapshot` contains any data. It is slightly more\r\n * efficient than using `snapshot.val() !== null`.\r\n */\r\n exists() {\r\n return !this._node.isEmpty();\r\n }\r\n /**\r\n * Exports the entire contents of the DataSnapshot as a JavaScript object.\r\n *\r\n * The `exportVal()` method is similar to `val()`, except priority information\r\n * is included (if available), making it suitable for backing up your data.\r\n *\r\n * @returns The DataSnapshot's contents as a JavaScript value (Object,\r\n * Array, string, number, boolean, or `null`).\r\n */\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n exportVal() {\r\n return this._node.val(true);\r\n }\r\n /**\r\n * Enumerates the top-level children in the `IteratedDataSnapshot`.\r\n *\r\n * Because of the way JavaScript objects work, the ordering of data in the\r\n * JavaScript object returned by `val()` is not guaranteed to match the\r\n * ordering on the server nor the ordering of `onChildAdded()` events. That is\r\n * where `forEach()` comes in handy. It guarantees the children of a\r\n * `DataSnapshot` will be iterated in their query order.\r\n *\r\n * If no explicit `orderBy*()` method is used, results are returned\r\n * ordered by key (unless priorities are used, in which case, results are\r\n * returned by priority).\r\n *\r\n * @param action - A function that will be called for each child DataSnapshot.\r\n * The callback can return true to cancel further enumeration.\r\n * @returns true if enumeration was canceled due to your callback returning\r\n * true.\r\n */\r\n forEach(action) {\r\n if (this._node.isLeafNode()) {\r\n return false;\r\n }\r\n const childrenNode = this._node;\r\n // Sanitize the return value to a boolean. ChildrenNode.forEachChild has a weird return type...\r\n return !!childrenNode.forEachChild(this._index, (key, node) => {\r\n return action(new DataSnapshot(node, child(this.ref, key), PRIORITY_INDEX));\r\n });\r\n }\r\n /**\r\n * Returns true if the specified child path has (non-null) data.\r\n *\r\n * @param path - A relative path to the location of a potential child.\r\n * @returns `true` if data exists at the specified child path; else\r\n * `false`.\r\n */\r\n hasChild(path) {\r\n const childPath = new Path(path);\r\n return !this._node.getChild(childPath).isEmpty();\r\n }\r\n /**\r\n * Returns whether or not the `DataSnapshot` has any non-`null` child\r\n * properties.\r\n *\r\n * You can use `hasChildren()` to determine if a `DataSnapshot` has any\r\n * children. If it does, you can enumerate them using `forEach()`. If it\r\n * doesn't, then either this snapshot contains a primitive value (which can be\r\n * retrieved with `val()`) or it is empty (in which case, `val()` will return\r\n * `null`).\r\n *\r\n * @returns true if this snapshot has any children; else false.\r\n */\r\n hasChildren() {\r\n if (this._node.isLeafNode()) {\r\n return false;\r\n }\r\n else {\r\n return !this._node.isEmpty();\r\n }\r\n }\r\n /**\r\n * Returns a JSON-serializable representation of this object.\r\n */\r\n toJSON() {\r\n return this.exportVal();\r\n }\r\n /**\r\n * Extracts a JavaScript value from a `DataSnapshot`.\r\n *\r\n * Depending on the data in a `DataSnapshot`, the `val()` method may return a\r\n * scalar type (string, number, or boolean), an array, or an object. It may\r\n * also return null, indicating that the `DataSnapshot` is empty (contains no\r\n * data).\r\n *\r\n * @returns The DataSnapshot's contents as a JavaScript value (Object,\r\n * Array, string, number, boolean, or `null`).\r\n */\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n val() {\r\n return this._node.val();\r\n }\r\n}\r\n/**\r\n *\r\n * Returns a `Reference` representing the location in the Database\r\n * corresponding to the provided path. If no path is provided, the `Reference`\r\n * will point to the root of the Database.\r\n *\r\n * @param db - The database instance to obtain a reference for.\r\n * @param path - Optional path representing the location the returned\r\n * `Reference` will point. If not provided, the returned `Reference` will\r\n * point to the root of the Database.\r\n * @returns If a path is provided, a `Reference`\r\n * pointing to the provided path. Otherwise, a `Reference` pointing to the\r\n * root of the Database.\r\n */\r\nfunction ref(db, path) {\r\n db = getModularInstance(db);\r\n db._checkNotDeleted('ref');\r\n return path !== undefined ? child(db._root, path) : db._root;\r\n}\r\n/**\r\n * Returns a `Reference` representing the location in the Database\r\n * corresponding to the provided Firebase URL.\r\n *\r\n * An exception is thrown if the URL is not a valid Firebase Database URL or it\r\n * has a different domain than the current `Database` instance.\r\n *\r\n * Note that all query parameters (`orderBy`, `limitToLast`, etc.) are ignored\r\n * and are not applied to the returned `Reference`.\r\n *\r\n * @param db - The database instance to obtain a reference for.\r\n * @param url - The Firebase URL at which the returned `Reference` will\r\n * point.\r\n * @returns A `Reference` pointing to the provided\r\n * Firebase URL.\r\n */\r\nfunction refFromURL(db, url) {\r\n db = getModularInstance(db);\r\n db._checkNotDeleted('refFromURL');\r\n const parsedURL = parseRepoInfo(url, db._repo.repoInfo_.nodeAdmin);\r\n validateUrl('refFromURL', parsedURL);\r\n const repoInfo = parsedURL.repoInfo;\r\n if (!db._repo.repoInfo_.isCustomHost() &&\r\n repoInfo.host !== db._repo.repoInfo_.host) {\r\n fatal('refFromURL' +\r\n ': Host name does not match the current database: ' +\r\n '(found ' +\r\n repoInfo.host +\r\n ' but expected ' +\r\n db._repo.repoInfo_.host +\r\n ')');\r\n }\r\n return ref(db, parsedURL.path.toString());\r\n}\r\n/**\r\n * Gets a `Reference` for the location at the specified relative path.\r\n *\r\n * The relative path can either be a simple child name (for example, \"ada\") or\r\n * a deeper slash-separated path (for example, \"ada/name/first\").\r\n *\r\n * @param parent - The parent location.\r\n * @param path - A relative path from this location to the desired child\r\n * location.\r\n * @returns The specified child location.\r\n */\r\nfunction child(parent, path) {\r\n parent = getModularInstance(parent);\r\n if (pathGetFront(parent._path) === null) {\r\n validateRootPathString('child', 'path', path, false);\r\n }\r\n else {\r\n validatePathString('child', 'path', path, false);\r\n }\r\n return new ReferenceImpl(parent._repo, pathChild(parent._path, path));\r\n}\r\n/**\r\n * Returns an `OnDisconnect` object - see\r\n * {@link https://firebase.google.com/docs/database/web/offline-capabilities | Enabling Offline Capabilities in JavaScript}\r\n * for more information on how to use it.\r\n *\r\n * @param ref - The reference to add OnDisconnect triggers for.\r\n */\r\nfunction onDisconnect(ref) {\r\n ref = getModularInstance(ref);\r\n return new OnDisconnect(ref._repo, ref._path);\r\n}\r\n/**\r\n * Generates a new child location using a unique key and returns its\r\n * `Reference`.\r\n *\r\n * This is the most common pattern for adding data to a collection of items.\r\n *\r\n * If you provide a value to `push()`, the value is written to the\r\n * generated location. If you don't pass a value, nothing is written to the\r\n * database and the child remains empty (but you can use the `Reference`\r\n * elsewhere).\r\n *\r\n * The unique keys generated by `push()` are ordered by the current time, so the\r\n * resulting list of items is chronologically sorted. The keys are also\r\n * designed to be unguessable (they contain 72 random bits of entropy).\r\n *\r\n * See {@link https://firebase.google.com/docs/database/web/lists-of-data#append_to_a_list_of_data | Append to a list of data}.\r\n * See {@link https://firebase.googleblog.com/2015/02/the-2120-ways-to-ensure-unique_68.html | The 2^120 Ways to Ensure Unique Identifiers}.\r\n *\r\n * @param parent - The parent location.\r\n * @param value - Optional value to be written at the generated location.\r\n * @returns Combined `Promise` and `Reference`; resolves when write is complete,\r\n * but can be used immediately as the `Reference` to the child location.\r\n */\r\nfunction push(parent, value) {\r\n parent = getModularInstance(parent);\r\n validateWritablePath('push', parent._path);\r\n validateFirebaseDataArg('push', value, parent._path, true);\r\n const now = repoServerTime(parent._repo);\r\n const name = nextPushId(now);\r\n // push() returns a ThennableReference whose promise is fulfilled with a\r\n // regular Reference. We use child() to create handles to two different\r\n // references. The first is turned into a ThennableReference below by adding\r\n // then() and catch() methods and is used as the return value of push(). The\r\n // second remains a regular Reference and is used as the fulfilled value of\r\n // the first ThennableReference.\r\n const thennablePushRef = child(parent, name);\r\n const pushRef = child(parent, name);\r\n let promise;\r\n if (value != null) {\r\n promise = set(pushRef, value).then(() => pushRef);\r\n }\r\n else {\r\n promise = Promise.resolve(pushRef);\r\n }\r\n thennablePushRef.then = promise.then.bind(promise);\r\n thennablePushRef.catch = promise.then.bind(promise, undefined);\r\n return thennablePushRef;\r\n}\r\n/**\r\n * Removes the data at this Database location.\r\n *\r\n * Any data at child locations will also be deleted.\r\n *\r\n * The effect of the remove will be visible immediately and the corresponding\r\n * event 'value' will be triggered. Synchronization of the remove to the\r\n * Firebase servers will also be started, and the returned Promise will resolve\r\n * when complete. If provided, the onComplete callback will be called\r\n * asynchronously after synchronization has finished.\r\n *\r\n * @param ref - The location to remove.\r\n * @returns Resolves when remove on server is complete.\r\n */\r\nfunction remove(ref) {\r\n validateWritablePath('remove', ref._path);\r\n return set(ref, null);\r\n}\r\n/**\r\n * Writes data to this Database location.\r\n *\r\n * This will overwrite any data at this location and all child locations.\r\n *\r\n * The effect of the write will be visible immediately, and the corresponding\r\n * events (\"value\", \"child_added\", etc.) will be triggered. Synchronization of\r\n * the data to the Firebase servers will also be started, and the returned\r\n * Promise will resolve when complete. If provided, the `onComplete` callback\r\n * will be called asynchronously after synchronization has finished.\r\n *\r\n * Passing `null` for the new value is equivalent to calling `remove()`; namely,\r\n * all data at this location and all child locations will be deleted.\r\n *\r\n * `set()` will remove any priority stored at this location, so if priority is\r\n * meant to be preserved, you need to use `setWithPriority()` instead.\r\n *\r\n * Note that modifying data with `set()` will cancel any pending transactions\r\n * at that location, so extreme care should be taken if mixing `set()` and\r\n * `transaction()` to modify the same data.\r\n *\r\n * A single `set()` will generate a single \"value\" event at the location where\r\n * the `set()` was performed.\r\n *\r\n * @param ref - The location to write to.\r\n * @param value - The value to be written (string, number, boolean, object,\r\n * array, or null).\r\n * @returns Resolves when write to server is complete.\r\n */\r\nfunction set(ref, value) {\r\n ref = getModularInstance(ref);\r\n validateWritablePath('set', ref._path);\r\n validateFirebaseDataArg('set', value, ref._path, false);\r\n const deferred = new Deferred();\r\n repoSetWithPriority(ref._repo, ref._path, value, \r\n /*priority=*/ null, deferred.wrapCallback(() => { }));\r\n return deferred.promise;\r\n}\r\n/**\r\n * Sets a priority for the data at this Database location.\r\n *\r\n * Applications need not use priority but can order collections by\r\n * ordinary properties (see\r\n * {@link https://firebase.google.com/docs/database/web/lists-of-data#sorting_and_filtering_data | Sorting and filtering data}\r\n * ).\r\n *\r\n * @param ref - The location to write to.\r\n * @param priority - The priority to be written (string, number, or null).\r\n * @returns Resolves when write to server is complete.\r\n */\r\nfunction setPriority(ref, priority) {\r\n ref = getModularInstance(ref);\r\n validateWritablePath('setPriority', ref._path);\r\n validatePriority('setPriority', priority, false);\r\n const deferred = new Deferred();\r\n repoSetWithPriority(ref._repo, pathChild(ref._path, '.priority'), priority, null, deferred.wrapCallback(() => { }));\r\n return deferred.promise;\r\n}\r\n/**\r\n * Writes data the Database location. Like `set()` but also specifies the\r\n * priority for that data.\r\n *\r\n * Applications need not use priority but can order collections by\r\n * ordinary properties (see\r\n * {@link https://firebase.google.com/docs/database/web/lists-of-data#sorting_and_filtering_data | Sorting and filtering data}\r\n * ).\r\n *\r\n * @param ref - The location to write to.\r\n * @param value - The value to be written (string, number, boolean, object,\r\n * array, or null).\r\n * @param priority - The priority to be written (string, number, or null).\r\n * @returns Resolves when write to server is complete.\r\n */\r\nfunction setWithPriority(ref, value, priority) {\r\n validateWritablePath('setWithPriority', ref._path);\r\n validateFirebaseDataArg('setWithPriority', value, ref._path, false);\r\n validatePriority('setWithPriority', priority, false);\r\n if (ref.key === '.length' || ref.key === '.keys') {\r\n throw 'setWithPriority failed: ' + ref.key + ' is a read-only object.';\r\n }\r\n const deferred = new Deferred();\r\n repoSetWithPriority(ref._repo, ref._path, value, priority, deferred.wrapCallback(() => { }));\r\n return deferred.promise;\r\n}\r\n/**\r\n * Writes multiple values to the Database at once.\r\n *\r\n * The `values` argument contains multiple property-value pairs that will be\r\n * written to the Database together. Each child property can either be a simple\r\n * property (for example, \"name\") or a relative path (for example,\r\n * \"name/first\") from the current location to the data to update.\r\n *\r\n * As opposed to the `set()` method, `update()` can be use to selectively update\r\n * only the referenced properties at the current location (instead of replacing\r\n * all the child properties at the current location).\r\n *\r\n * The effect of the write will be visible immediately, and the corresponding\r\n * events ('value', 'child_added', etc.) will be triggered. Synchronization of\r\n * the data to the Firebase servers will also be started, and the returned\r\n * Promise will resolve when complete. If provided, the `onComplete` callback\r\n * will be called asynchronously after synchronization has finished.\r\n *\r\n * A single `update()` will generate a single \"value\" event at the location\r\n * where the `update()` was performed, regardless of how many children were\r\n * modified.\r\n *\r\n * Note that modifying data with `update()` will cancel any pending\r\n * transactions at that location, so extreme care should be taken if mixing\r\n * `update()` and `transaction()` to modify the same data.\r\n *\r\n * Passing `null` to `update()` will remove the data at this location.\r\n *\r\n * See\r\n * {@link https://firebase.googleblog.com/2015/09/introducing-multi-location-updates-and_86.html | Introducing multi-location updates and more}.\r\n *\r\n * @param ref - The location to write to.\r\n * @param values - Object containing multiple values.\r\n * @returns Resolves when update on server is complete.\r\n */\r\nfunction update(ref, values) {\r\n validateFirebaseMergeDataArg('update', values, ref._path, false);\r\n const deferred = new Deferred();\r\n repoUpdate(ref._repo, ref._path, values, deferred.wrapCallback(() => { }));\r\n return deferred.promise;\r\n}\r\n/**\r\n * Gets the most up-to-date result for this query.\r\n *\r\n * @param query - The query to run.\r\n * @returns A `Promise` which resolves to the resulting DataSnapshot if a value is\r\n * available, or rejects if the client is unable to return a value (e.g., if the\r\n * server is unreachable and there is nothing cached).\r\n */\r\nfunction get(query) {\r\n query = getModularInstance(query);\r\n const callbackContext = new CallbackContext(() => { });\r\n const container = new ValueEventRegistration(callbackContext);\r\n return repoGetValue(query._repo, query, container).then(node => {\r\n return new DataSnapshot(node, new ReferenceImpl(query._repo, query._path), query._queryParams.getIndex());\r\n });\r\n}\r\n/**\r\n * Represents registration for 'value' events.\r\n */\r\nclass ValueEventRegistration {\r\n constructor(callbackContext) {\r\n this.callbackContext = callbackContext;\r\n }\r\n respondsTo(eventType) {\r\n return eventType === 'value';\r\n }\r\n createEvent(change, query) {\r\n const index = query._queryParams.getIndex();\r\n return new DataEvent('value', this, new DataSnapshot(change.snapshotNode, new ReferenceImpl(query._repo, query._path), index));\r\n }\r\n getEventRunner(eventData) {\r\n if (eventData.getEventType() === 'cancel') {\r\n return () => this.callbackContext.onCancel(eventData.error);\r\n }\r\n else {\r\n return () => this.callbackContext.onValue(eventData.snapshot, null);\r\n }\r\n }\r\n createCancelEvent(error, path) {\r\n if (this.callbackContext.hasCancelCallback) {\r\n return new CancelEvent(this, error, path);\r\n }\r\n else {\r\n return null;\r\n }\r\n }\r\n matches(other) {\r\n if (!(other instanceof ValueEventRegistration)) {\r\n return false;\r\n }\r\n else if (!other.callbackContext || !this.callbackContext) {\r\n // If no callback specified, we consider it to match any callback.\r\n return true;\r\n }\r\n else {\r\n return other.callbackContext.matches(this.callbackContext);\r\n }\r\n }\r\n hasAnyCallback() {\r\n return this.callbackContext !== null;\r\n }\r\n}\r\n/**\r\n * Represents the registration of a child_x event.\r\n */\r\nclass ChildEventRegistration {\r\n constructor(eventType, callbackContext) {\r\n this.eventType = eventType;\r\n this.callbackContext = callbackContext;\r\n }\r\n respondsTo(eventType) {\r\n let eventToCheck = eventType === 'children_added' ? 'child_added' : eventType;\r\n eventToCheck =\r\n eventToCheck === 'children_removed' ? 'child_removed' : eventToCheck;\r\n return this.eventType === eventToCheck;\r\n }\r\n createCancelEvent(error, path) {\r\n if (this.callbackContext.hasCancelCallback) {\r\n return new CancelEvent(this, error, path);\r\n }\r\n else {\r\n return null;\r\n }\r\n }\r\n createEvent(change, query) {\r\n assert(change.childName != null, 'Child events should have a childName.');\r\n const childRef = child(new ReferenceImpl(query._repo, query._path), change.childName);\r\n const index = query._queryParams.getIndex();\r\n return new DataEvent(change.type, this, new DataSnapshot(change.snapshotNode, childRef, index), change.prevName);\r\n }\r\n getEventRunner(eventData) {\r\n if (eventData.getEventType() === 'cancel') {\r\n return () => this.callbackContext.onCancel(eventData.error);\r\n }\r\n else {\r\n return () => this.callbackContext.onValue(eventData.snapshot, eventData.prevName);\r\n }\r\n }\r\n matches(other) {\r\n if (other instanceof ChildEventRegistration) {\r\n return (this.eventType === other.eventType &&\r\n (!this.callbackContext ||\r\n !other.callbackContext ||\r\n this.callbackContext.matches(other.callbackContext)));\r\n }\r\n return false;\r\n }\r\n hasAnyCallback() {\r\n return !!this.callbackContext;\r\n }\r\n}\r\nfunction addEventListener(query, eventType, callback, cancelCallbackOrListenOptions, options) {\r\n let cancelCallback;\r\n if (typeof cancelCallbackOrListenOptions === 'object') {\r\n cancelCallback = undefined;\r\n options = cancelCallbackOrListenOptions;\r\n }\r\n if (typeof cancelCallbackOrListenOptions === 'function') {\r\n cancelCallback = cancelCallbackOrListenOptions;\r\n }\r\n if (options && options.onlyOnce) {\r\n const userCallback = callback;\r\n const onceCallback = (dataSnapshot, previousChildName) => {\r\n repoRemoveEventCallbackForQuery(query._repo, query, container);\r\n userCallback(dataSnapshot, previousChildName);\r\n };\r\n onceCallback.userCallback = callback.userCallback;\r\n onceCallback.context = callback.context;\r\n callback = onceCallback;\r\n }\r\n const callbackContext = new CallbackContext(callback, cancelCallback || undefined);\r\n const container = eventType === 'value'\r\n ? new ValueEventRegistration(callbackContext)\r\n : new ChildEventRegistration(eventType, callbackContext);\r\n repoAddEventCallbackForQuery(query._repo, query, container);\r\n return () => repoRemoveEventCallbackForQuery(query._repo, query, container);\r\n}\r\nfunction onValue(query, callback, cancelCallbackOrListenOptions, options) {\r\n return addEventListener(query, 'value', callback, cancelCallbackOrListenOptions, options);\r\n}\r\nfunction onChildAdded(query, callback, cancelCallbackOrListenOptions, options) {\r\n return addEventListener(query, 'child_added', callback, cancelCallbackOrListenOptions, options);\r\n}\r\nfunction onChildChanged(query, callback, cancelCallbackOrListenOptions, options) {\r\n return addEventListener(query, 'child_changed', callback, cancelCallbackOrListenOptions, options);\r\n}\r\nfunction onChildMoved(query, callback, cancelCallbackOrListenOptions, options) {\r\n return addEventListener(query, 'child_moved', callback, cancelCallbackOrListenOptions, options);\r\n}\r\nfunction onChildRemoved(query, callback, cancelCallbackOrListenOptions, options) {\r\n return addEventListener(query, 'child_removed', callback, cancelCallbackOrListenOptions, options);\r\n}\r\n/**\r\n * Detaches a callback previously attached with the corresponding `on*()` (`onValue`, `onChildAdded`) listener.\r\n * Note: This is not the recommended way to remove a listener. Instead, please use the returned callback function from\r\n * the respective `on*` callbacks.\r\n *\r\n * Detach a callback previously attached with `on*()`. Calling `off()` on a parent listener\r\n * will not automatically remove listeners registered on child nodes, `off()`\r\n * must also be called on any child listeners to remove the callback.\r\n *\r\n * If a callback is not specified, all callbacks for the specified eventType\r\n * will be removed. Similarly, if no eventType is specified, all callbacks\r\n * for the `Reference` will be removed.\r\n *\r\n * Individual listeners can also be removed by invoking their unsubscribe\r\n * callbacks.\r\n *\r\n * @param query - The query that the listener was registered with.\r\n * @param eventType - One of the following strings: \"value\", \"child_added\",\r\n * \"child_changed\", \"child_removed\", or \"child_moved.\" If omitted, all callbacks\r\n * for the `Reference` will be removed.\r\n * @param callback - The callback function that was passed to `on()` or\r\n * `undefined` to remove all callbacks.\r\n */\r\nfunction off(query, eventType, callback) {\r\n let container = null;\r\n const expCallback = callback ? new CallbackContext(callback) : null;\r\n if (eventType === 'value') {\r\n container = new ValueEventRegistration(expCallback);\r\n }\r\n else if (eventType) {\r\n container = new ChildEventRegistration(eventType, expCallback);\r\n }\r\n repoRemoveEventCallbackForQuery(query._repo, query, container);\r\n}\r\n/**\r\n * A `QueryConstraint` is used to narrow the set of documents returned by a\r\n * Database query. `QueryConstraint`s are created by invoking {@link endAt},\r\n * {@link endBefore}, {@link startAt}, {@link startAfter}, {@link\r\n * limitToFirst}, {@link limitToLast}, {@link orderByChild},\r\n * {@link orderByChild}, {@link orderByKey} , {@link orderByPriority} ,\r\n * {@link orderByValue} or {@link equalTo} and\r\n * can then be passed to {@link query} to create a new query instance that\r\n * also contains this `QueryConstraint`.\r\n */\r\nclass QueryConstraint {\r\n}\r\nclass QueryEndAtConstraint extends QueryConstraint {\r\n constructor(_value, _key) {\r\n super();\r\n this._value = _value;\r\n this._key = _key;\r\n }\r\n _apply(query) {\r\n validateFirebaseDataArg('endAt', this._value, query._path, true);\r\n const newParams = queryParamsEndAt(query._queryParams, this._value, this._key);\r\n validateLimit(newParams);\r\n validateQueryEndpoints(newParams);\r\n if (query._queryParams.hasEnd()) {\r\n throw new Error('endAt: Starting point was already set (by another call to endAt, ' +\r\n 'endBefore or equalTo).');\r\n }\r\n return new QueryImpl(query._repo, query._path, newParams, query._orderByCalled);\r\n }\r\n}\r\n/**\r\n * Creates a `QueryConstraint` with the specified ending point.\r\n *\r\n * Using `startAt()`, `startAfter()`, `endBefore()`, `endAt()` and `equalTo()`\r\n * allows you to choose arbitrary starting and ending points for your queries.\r\n *\r\n * The ending point is inclusive, so children with exactly the specified value\r\n * will be included in the query. The optional key argument can be used to\r\n * further limit the range of the query. If it is specified, then children that\r\n * have exactly the specified value must also have a key name less than or equal\r\n * to the specified key.\r\n *\r\n * You can read more about `endAt()` in\r\n * {@link https://firebase.google.com/docs/database/web/lists-of-data#filtering_data | Filtering data}.\r\n *\r\n * @param value - The value to end at. The argument type depends on which\r\n * `orderBy*()` function was used in this query. Specify a value that matches\r\n * the `orderBy*()` type. When used in combination with `orderByKey()`, the\r\n * value must be a string.\r\n * @param key - The child key to end at, among the children with the previously\r\n * specified priority. This argument is only allowed if ordering by child,\r\n * value, or priority.\r\n */\r\nfunction endAt(value, key) {\r\n validateKey('endAt', 'key', key, true);\r\n return new QueryEndAtConstraint(value, key);\r\n}\r\nclass QueryEndBeforeConstraint extends QueryConstraint {\r\n constructor(_value, _key) {\r\n super();\r\n this._value = _value;\r\n this._key = _key;\r\n }\r\n _apply(query) {\r\n validateFirebaseDataArg('endBefore', this._value, query._path, false);\r\n const newParams = queryParamsEndBefore(query._queryParams, this._value, this._key);\r\n validateLimit(newParams);\r\n validateQueryEndpoints(newParams);\r\n if (query._queryParams.hasEnd()) {\r\n throw new Error('endBefore: Starting point was already set (by another call to endAt, ' +\r\n 'endBefore or equalTo).');\r\n }\r\n return new QueryImpl(query._repo, query._path, newParams, query._orderByCalled);\r\n }\r\n}\r\n/**\r\n * Creates a `QueryConstraint` with the specified ending point (exclusive).\r\n *\r\n * Using `startAt()`, `startAfter()`, `endBefore()`, `endAt()` and `equalTo()`\r\n * allows you to choose arbitrary starting and ending points for your queries.\r\n *\r\n * The ending point is exclusive. If only a value is provided, children\r\n * with a value less than the specified value will be included in the query.\r\n * If a key is specified, then children must have a value less than or equal\r\n * to the specified value and a key name less than the specified key.\r\n *\r\n * @param value - The value to end before. The argument type depends on which\r\n * `orderBy*()` function was used in this query. Specify a value that matches\r\n * the `orderBy*()` type. When used in combination with `orderByKey()`, the\r\n * value must be a string.\r\n * @param key - The child key to end before, among the children with the\r\n * previously specified priority. This argument is only allowed if ordering by\r\n * child, value, or priority.\r\n */\r\nfunction endBefore(value, key) {\r\n validateKey('endBefore', 'key', key, true);\r\n return new QueryEndBeforeConstraint(value, key);\r\n}\r\nclass QueryStartAtConstraint extends QueryConstraint {\r\n constructor(_value, _key) {\r\n super();\r\n this._value = _value;\r\n this._key = _key;\r\n }\r\n _apply(query) {\r\n validateFirebaseDataArg('startAt', this._value, query._path, true);\r\n const newParams = queryParamsStartAt(query._queryParams, this._value, this._key);\r\n validateLimit(newParams);\r\n validateQueryEndpoints(newParams);\r\n if (query._queryParams.hasStart()) {\r\n throw new Error('startAt: Starting point was already set (by another call to startAt, ' +\r\n 'startBefore or equalTo).');\r\n }\r\n return new QueryImpl(query._repo, query._path, newParams, query._orderByCalled);\r\n }\r\n}\r\n/**\r\n * Creates a `QueryConstraint` with the specified starting point.\r\n *\r\n * Using `startAt()`, `startAfter()`, `endBefore()`, `endAt()` and `equalTo()`\r\n * allows you to choose arbitrary starting and ending points for your queries.\r\n *\r\n * The starting point is inclusive, so children with exactly the specified value\r\n * will be included in the query. The optional key argument can be used to\r\n * further limit the range of the query. If it is specified, then children that\r\n * have exactly the specified value must also have a key name greater than or\r\n * equal to the specified key.\r\n *\r\n * You can read more about `startAt()` in\r\n * {@link https://firebase.google.com/docs/database/web/lists-of-data#filtering_data | Filtering data}.\r\n *\r\n * @param value - The value to start at. The argument type depends on which\r\n * `orderBy*()` function was used in this query. Specify a value that matches\r\n * the `orderBy*()` type. When used in combination with `orderByKey()`, the\r\n * value must be a string.\r\n * @param key - The child key to start at. This argument is only allowed if\r\n * ordering by child, value, or priority.\r\n */\r\nfunction startAt(value = null, key) {\r\n validateKey('startAt', 'key', key, true);\r\n return new QueryStartAtConstraint(value, key);\r\n}\r\nclass QueryStartAfterConstraint extends QueryConstraint {\r\n constructor(_value, _key) {\r\n super();\r\n this._value = _value;\r\n this._key = _key;\r\n }\r\n _apply(query) {\r\n validateFirebaseDataArg('startAfter', this._value, query._path, false);\r\n const newParams = queryParamsStartAfter(query._queryParams, this._value, this._key);\r\n validateLimit(newParams);\r\n validateQueryEndpoints(newParams);\r\n if (query._queryParams.hasStart()) {\r\n throw new Error('startAfter: Starting point was already set (by another call to startAt, ' +\r\n 'startAfter, or equalTo).');\r\n }\r\n return new QueryImpl(query._repo, query._path, newParams, query._orderByCalled);\r\n }\r\n}\r\n/**\r\n * Creates a `QueryConstraint` with the specified starting point (exclusive).\r\n *\r\n * Using `startAt()`, `startAfter()`, `endBefore()`, `endAt()` and `equalTo()`\r\n * allows you to choose arbitrary starting and ending points for your queries.\r\n *\r\n * The starting point is exclusive. If only a value is provided, children\r\n * with a value greater than the specified value will be included in the query.\r\n * If a key is specified, then children must have a value greater than or equal\r\n * to the specified value and a a key name greater than the specified key.\r\n *\r\n * @param value - The value to start after. The argument type depends on which\r\n * `orderBy*()` function was used in this query. Specify a value that matches\r\n * the `orderBy*()` type. When used in combination with `orderByKey()`, the\r\n * value must be a string.\r\n * @param key - The child key to start after. This argument is only allowed if\r\n * ordering by child, value, or priority.\r\n */\r\nfunction startAfter(value, key) {\r\n validateKey('startAfter', 'key', key, true);\r\n return new QueryStartAfterConstraint(value, key);\r\n}\r\nclass QueryLimitToFirstConstraint extends QueryConstraint {\r\n constructor(_limit) {\r\n super();\r\n this._limit = _limit;\r\n }\r\n _apply(query) {\r\n if (query._queryParams.hasLimit()) {\r\n throw new Error('limitToFirst: Limit was already set (by another call to limitToFirst ' +\r\n 'or limitToLast).');\r\n }\r\n return new QueryImpl(query._repo, query._path, queryParamsLimitToFirst(query._queryParams, this._limit), query._orderByCalled);\r\n }\r\n}\r\n/**\r\n * Creates a new `QueryConstraint` that if limited to the first specific number\r\n * of children.\r\n *\r\n * The `limitToFirst()` method is used to set a maximum number of children to be\r\n * synced for a given callback. If we set a limit of 100, we will initially only\r\n * receive up to 100 `child_added` events. If we have fewer than 100 messages\r\n * stored in our Database, a `child_added` event will fire for each message.\r\n * However, if we have over 100 messages, we will only receive a `child_added`\r\n * event for the first 100 ordered messages. As items change, we will receive\r\n * `child_removed` events for each item that drops out of the active list so\r\n * that the total number stays at 100.\r\n *\r\n * You can read more about `limitToFirst()` in\r\n * {@link https://firebase.google.com/docs/database/web/lists-of-data#filtering_data | Filtering data}.\r\n *\r\n * @param limit - The maximum number of nodes to include in this query.\r\n */\r\nfunction limitToFirst(limit) {\r\n if (typeof limit !== 'number' || Math.floor(limit) !== limit || limit <= 0) {\r\n throw new Error('limitToFirst: First argument must be a positive integer.');\r\n }\r\n return new QueryLimitToFirstConstraint(limit);\r\n}\r\nclass QueryLimitToLastConstraint extends QueryConstraint {\r\n constructor(_limit) {\r\n super();\r\n this._limit = _limit;\r\n }\r\n _apply(query) {\r\n if (query._queryParams.hasLimit()) {\r\n throw new Error('limitToLast: Limit was already set (by another call to limitToFirst ' +\r\n 'or limitToLast).');\r\n }\r\n return new QueryImpl(query._repo, query._path, queryParamsLimitToLast(query._queryParams, this._limit), query._orderByCalled);\r\n }\r\n}\r\n/**\r\n * Creates a new `QueryConstraint` that is limited to return only the last\r\n * specified number of children.\r\n *\r\n * The `limitToLast()` method is used to set a maximum number of children to be\r\n * synced for a given callback. If we set a limit of 100, we will initially only\r\n * receive up to 100 `child_added` events. If we have fewer than 100 messages\r\n * stored in our Database, a `child_added` event will fire for each message.\r\n * However, if we have over 100 messages, we will only receive a `child_added`\r\n * event for the last 100 ordered messages. As items change, we will receive\r\n * `child_removed` events for each item that drops out of the active list so\r\n * that the total number stays at 100.\r\n *\r\n * You can read more about `limitToLast()` in\r\n * {@link https://firebase.google.com/docs/database/web/lists-of-data#filtering_data | Filtering data}.\r\n *\r\n * @param limit - The maximum number of nodes to include in this query.\r\n */\r\nfunction limitToLast(limit) {\r\n if (typeof limit !== 'number' || Math.floor(limit) !== limit || limit <= 0) {\r\n throw new Error('limitToLast: First argument must be a positive integer.');\r\n }\r\n return new QueryLimitToLastConstraint(limit);\r\n}\r\nclass QueryOrderByChildConstraint extends QueryConstraint {\r\n constructor(_path) {\r\n super();\r\n this._path = _path;\r\n }\r\n _apply(query) {\r\n validateNoPreviousOrderByCall(query, 'orderByChild');\r\n const parsedPath = new Path(this._path);\r\n if (pathIsEmpty(parsedPath)) {\r\n throw new Error('orderByChild: cannot pass in empty path. Use orderByValue() instead.');\r\n }\r\n const index = new PathIndex(parsedPath);\r\n const newParams = queryParamsOrderBy(query._queryParams, index);\r\n validateQueryEndpoints(newParams);\r\n return new QueryImpl(query._repo, query._path, newParams, \r\n /*orderByCalled=*/ true);\r\n }\r\n}\r\n/**\r\n * Creates a new `QueryConstraint` that orders by the specified child key.\r\n *\r\n * Queries can only order by one key at a time. Calling `orderByChild()`\r\n * multiple times on the same query is an error.\r\n *\r\n * Firebase queries allow you to order your data by any child key on the fly.\r\n * However, if you know in advance what your indexes will be, you can define\r\n * them via the .indexOn rule in your Security Rules for better performance. See\r\n * the{@link https://firebase.google.com/docs/database/security/indexing-data}\r\n * rule for more information.\r\n *\r\n * You can read more about `orderByChild()` in\r\n * {@link https://firebase.google.com/docs/database/web/lists-of-data#sort_data | Sort data}.\r\n *\r\n * @param path - The path to order by.\r\n */\r\nfunction orderByChild(path) {\r\n if (path === '$key') {\r\n throw new Error('orderByChild: \"$key\" is invalid. Use orderByKey() instead.');\r\n }\r\n else if (path === '$priority') {\r\n throw new Error('orderByChild: \"$priority\" is invalid. Use orderByPriority() instead.');\r\n }\r\n else if (path === '$value') {\r\n throw new Error('orderByChild: \"$value\" is invalid. Use orderByValue() instead.');\r\n }\r\n validatePathString('orderByChild', 'path', path, false);\r\n return new QueryOrderByChildConstraint(path);\r\n}\r\nclass QueryOrderByKeyConstraint extends QueryConstraint {\r\n _apply(query) {\r\n validateNoPreviousOrderByCall(query, 'orderByKey');\r\n const newParams = queryParamsOrderBy(query._queryParams, KEY_INDEX);\r\n validateQueryEndpoints(newParams);\r\n return new QueryImpl(query._repo, query._path, newParams, \r\n /*orderByCalled=*/ true);\r\n }\r\n}\r\n/**\r\n * Creates a new `QueryConstraint` that orders by the key.\r\n *\r\n * Sorts the results of a query by their (ascending) key values.\r\n *\r\n * You can read more about `orderByKey()` in\r\n * {@link https://firebase.google.com/docs/database/web/lists-of-data#sort_data | Sort data}.\r\n */\r\nfunction orderByKey() {\r\n return new QueryOrderByKeyConstraint();\r\n}\r\nclass QueryOrderByPriorityConstraint extends QueryConstraint {\r\n _apply(query) {\r\n validateNoPreviousOrderByCall(query, 'orderByPriority');\r\n const newParams = queryParamsOrderBy(query._queryParams, PRIORITY_INDEX);\r\n validateQueryEndpoints(newParams);\r\n return new QueryImpl(query._repo, query._path, newParams, \r\n /*orderByCalled=*/ true);\r\n }\r\n}\r\n/**\r\n * Creates a new `QueryConstraint` that orders by priority.\r\n *\r\n * Applications need not use priority but can order collections by\r\n * ordinary properties (see\r\n * {@link https://firebase.google.com/docs/database/web/lists-of-data#sort_data | Sort data}\r\n * for alternatives to priority.\r\n */\r\nfunction orderByPriority() {\r\n return new QueryOrderByPriorityConstraint();\r\n}\r\nclass QueryOrderByValueConstraint extends QueryConstraint {\r\n _apply(query) {\r\n validateNoPreviousOrderByCall(query, 'orderByValue');\r\n const newParams = queryParamsOrderBy(query._queryParams, VALUE_INDEX);\r\n validateQueryEndpoints(newParams);\r\n return new QueryImpl(query._repo, query._path, newParams, \r\n /*orderByCalled=*/ true);\r\n }\r\n}\r\n/**\r\n * Creates a new `QueryConstraint` that orders by value.\r\n *\r\n * If the children of a query are all scalar values (string, number, or\r\n * boolean), you can order the results by their (ascending) values.\r\n *\r\n * You can read more about `orderByValue()` in\r\n * {@link https://firebase.google.com/docs/database/web/lists-of-data#sort_data | Sort data}.\r\n */\r\nfunction orderByValue() {\r\n return new QueryOrderByValueConstraint();\r\n}\r\nclass QueryEqualToValueConstraint extends QueryConstraint {\r\n constructor(_value, _key) {\r\n super();\r\n this._value = _value;\r\n this._key = _key;\r\n }\r\n _apply(query) {\r\n validateFirebaseDataArg('equalTo', this._value, query._path, false);\r\n if (query._queryParams.hasStart()) {\r\n throw new Error('equalTo: Starting point was already set (by another call to startAt/startAfter or ' +\r\n 'equalTo).');\r\n }\r\n if (query._queryParams.hasEnd()) {\r\n throw new Error('equalTo: Ending point was already set (by another call to endAt/endBefore or ' +\r\n 'equalTo).');\r\n }\r\n return new QueryEndAtConstraint(this._value, this._key)._apply(new QueryStartAtConstraint(this._value, this._key)._apply(query));\r\n }\r\n}\r\n/**\r\n * Creates a `QueryConstraint` that includes children that match the specified\r\n * value.\r\n *\r\n * Using `startAt()`, `startAfter()`, `endBefore()`, `endAt()` and `equalTo()`\r\n * allows you to choose arbitrary starting and ending points for your queries.\r\n *\r\n * The optional key argument can be used to further limit the range of the\r\n * query. If it is specified, then children that have exactly the specified\r\n * value must also have exactly the specified key as their key name. This can be\r\n * used to filter result sets with many matches for the same value.\r\n *\r\n * You can read more about `equalTo()` in\r\n * {@link https://firebase.google.com/docs/database/web/lists-of-data#filtering_data | Filtering data}.\r\n *\r\n * @param value - The value to match for. The argument type depends on which\r\n * `orderBy*()` function was used in this query. Specify a value that matches\r\n * the `orderBy*()` type. When used in combination with `orderByKey()`, the\r\n * value must be a string.\r\n * @param key - The child key to start at, among the children with the\r\n * previously specified priority. This argument is only allowed if ordering by\r\n * child, value, or priority.\r\n */\r\nfunction equalTo(value, key) {\r\n validateKey('equalTo', 'key', key, true);\r\n return new QueryEqualToValueConstraint(value, key);\r\n}\r\n/**\r\n * Creates a new immutable instance of `Query` that is extended to also include\r\n * additional query constraints.\r\n *\r\n * @param query - The Query instance to use as a base for the new constraints.\r\n * @param queryConstraints - The list of `QueryConstraint`s to apply.\r\n * @throws if any of the provided query constraints cannot be combined with the\r\n * existing or new constraints.\r\n */\r\nfunction query(query, ...queryConstraints) {\r\n let queryImpl = getModularInstance(query);\r\n for (const constraint of queryConstraints) {\r\n queryImpl = constraint._apply(queryImpl);\r\n }\r\n return queryImpl;\r\n}\r\n/**\r\n * Define reference constructor in various modules\r\n *\r\n * We are doing this here to avoid several circular\r\n * dependency issues\r\n */\r\nsyncPointSetReferenceConstructor(ReferenceImpl);\r\nsyncTreeSetReferenceConstructor(ReferenceImpl);\n\n/**\r\n * @license\r\n * Copyright 2020 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * This variable is also defined in the firebase Node.js Admin SDK. Before\r\n * modifying this definition, consult the definition in:\r\n *\r\n * https://github.com/firebase/firebase-admin-node\r\n *\r\n * and make sure the two are consistent.\r\n */\r\nconst FIREBASE_DATABASE_EMULATOR_HOST_VAR = 'FIREBASE_DATABASE_EMULATOR_HOST';\r\n/**\r\n * Creates and caches `Repo` instances.\r\n */\r\nconst repos = {};\r\n/**\r\n * If true, any new `Repo` will be created to use `ReadonlyRestClient` (for testing purposes).\r\n */\r\nlet useRestClient = false;\r\n/**\r\n * Update an existing `Repo` in place to point to a new host/port.\r\n */\r\nfunction repoManagerApplyEmulatorSettings(repo, host, port, tokenProvider) {\r\n repo.repoInfo_ = new RepoInfo(`${host}:${port}`, \r\n /* secure= */ false, repo.repoInfo_.namespace, repo.repoInfo_.webSocketOnly, repo.repoInfo_.nodeAdmin, repo.repoInfo_.persistenceKey, repo.repoInfo_.includeNamespaceInQueryParams, \r\n /*isUsingEmulator=*/ true);\r\n if (tokenProvider) {\r\n repo.authTokenProvider_ = tokenProvider;\r\n }\r\n}\r\n/**\r\n * This function should only ever be called to CREATE a new database instance.\r\n * @internal\r\n */\r\nfunction repoManagerDatabaseFromApp(app, authProvider, appCheckProvider, url, nodeAdmin) {\r\n let dbUrl = url || app.options.databaseURL;\r\n if (dbUrl === undefined) {\r\n if (!app.options.projectId) {\r\n fatal(\"Can't determine Firebase Database URL. Be sure to include \" +\r\n ' a Project ID when calling firebase.initializeApp().');\r\n }\r\n log('Using default host for project ', app.options.projectId);\r\n dbUrl = `${app.options.projectId}-default-rtdb.firebaseio.com`;\r\n }\r\n let parsedUrl = parseRepoInfo(dbUrl, nodeAdmin);\r\n let repoInfo = parsedUrl.repoInfo;\r\n let isEmulator;\r\n let dbEmulatorHost = undefined;\r\n if (typeof process !== 'undefined' && process.env) {\r\n dbEmulatorHost = process.env[FIREBASE_DATABASE_EMULATOR_HOST_VAR];\r\n }\r\n if (dbEmulatorHost) {\r\n isEmulator = true;\r\n dbUrl = `http://${dbEmulatorHost}?ns=${repoInfo.namespace}`;\r\n parsedUrl = parseRepoInfo(dbUrl, nodeAdmin);\r\n repoInfo = parsedUrl.repoInfo;\r\n }\r\n else {\r\n isEmulator = !parsedUrl.repoInfo.secure;\r\n }\r\n const authTokenProvider = nodeAdmin && isEmulator\r\n ? new EmulatorTokenProvider(EmulatorTokenProvider.OWNER)\r\n : new FirebaseAuthTokenProvider(app.name, app.options, authProvider);\r\n validateUrl('Invalid Firebase Database URL', parsedUrl);\r\n if (!pathIsEmpty(parsedUrl.path)) {\r\n fatal('Database URL must point to the root of a Firebase Database ' +\r\n '(not including a child path).');\r\n }\r\n const repo = repoManagerCreateRepo(repoInfo, app, authTokenProvider, new AppCheckTokenProvider(app.name, appCheckProvider));\r\n return new Database(repo, app);\r\n}\r\n/**\r\n * Remove the repo and make sure it is disconnected.\r\n *\r\n */\r\nfunction repoManagerDeleteRepo(repo, appName) {\r\n const appRepos = repos[appName];\r\n // This should never happen...\r\n if (!appRepos || appRepos[repo.key] !== repo) {\r\n fatal(`Database ${appName}(${repo.repoInfo_}) has already been deleted.`);\r\n }\r\n repoInterrupt(repo);\r\n delete appRepos[repo.key];\r\n}\r\n/**\r\n * Ensures a repo doesn't already exist and then creates one using the\r\n * provided app.\r\n *\r\n * @param repoInfo - The metadata about the Repo\r\n * @returns The Repo object for the specified server / repoName.\r\n */\r\nfunction repoManagerCreateRepo(repoInfo, app, authTokenProvider, appCheckProvider) {\r\n let appRepos = repos[app.name];\r\n if (!appRepos) {\r\n appRepos = {};\r\n repos[app.name] = appRepos;\r\n }\r\n let repo = appRepos[repoInfo.toURLString()];\r\n if (repo) {\r\n fatal('Database initialized multiple times. Please make sure the format of the database URL matches with each database() call.');\r\n }\r\n repo = new Repo(repoInfo, useRestClient, authTokenProvider, appCheckProvider);\r\n appRepos[repoInfo.toURLString()] = repo;\r\n return repo;\r\n}\r\n/**\r\n * Forces us to use ReadonlyRestClient instead of PersistentConnection for new Repos.\r\n */\r\nfunction repoManagerForceRestClient(forceRestClient) {\r\n useRestClient = forceRestClient;\r\n}\r\n/**\r\n * Class representing a Firebase Realtime Database.\r\n */\r\nclass Database {\r\n /** @hideconstructor */\r\n constructor(_repoInternal, \r\n /** The {@link @firebase/app#FirebaseApp} associated with this Realtime Database instance. */\r\n app) {\r\n this._repoInternal = _repoInternal;\r\n this.app = app;\r\n /** Represents a `Database` instance. */\r\n this['type'] = 'database';\r\n /** Track if the instance has been used (root or repo accessed) */\r\n this._instanceStarted = false;\r\n }\r\n get _repo() {\r\n if (!this._instanceStarted) {\r\n repoStart(this._repoInternal, this.app.options.appId, this.app.options['databaseAuthVariableOverride']);\r\n this._instanceStarted = true;\r\n }\r\n return this._repoInternal;\r\n }\r\n get _root() {\r\n if (!this._rootInternal) {\r\n this._rootInternal = new ReferenceImpl(this._repo, newEmptyPath());\r\n }\r\n return this._rootInternal;\r\n }\r\n _delete() {\r\n if (this._rootInternal !== null) {\r\n repoManagerDeleteRepo(this._repo, this.app.name);\r\n this._repoInternal = null;\r\n this._rootInternal = null;\r\n }\r\n return Promise.resolve();\r\n }\r\n _checkNotDeleted(apiName) {\r\n if (this._rootInternal === null) {\r\n fatal('Cannot call ' + apiName + ' on a deleted database.');\r\n }\r\n }\r\n}\r\nfunction checkTransportInit() {\r\n if (TransportManager.IS_TRANSPORT_INITIALIZED) {\r\n warn('Transport has already been initialized. Please call this function before calling ref or setting up a listener');\r\n }\r\n}\r\n/**\r\n * Force the use of websockets instead of longPolling.\r\n */\r\nfunction forceWebSockets() {\r\n checkTransportInit();\r\n BrowserPollConnection.forceDisallow();\r\n}\r\n/**\r\n * Force the use of longPolling instead of websockets. This will be ignored if websocket protocol is used in databaseURL.\r\n */\r\nfunction forceLongPolling() {\r\n checkTransportInit();\r\n WebSocketConnection.forceDisallow();\r\n BrowserPollConnection.forceAllow();\r\n}\r\n/**\r\n * Returns the instance of the Realtime Database SDK that is associated\r\n * with the provided {@link @firebase/app#FirebaseApp}. Initializes a new instance with\r\n * with default settings if no instance exists or if the existing instance uses\r\n * a custom database URL.\r\n *\r\n * @param app - The {@link @firebase/app#FirebaseApp} instance that the returned Realtime\r\n * Database instance is associated with.\r\n * @param url - The URL of the Realtime Database instance to connect to. If not\r\n * provided, the SDK connects to the default instance of the Firebase App.\r\n * @returns The `Database` instance of the provided app.\r\n */\r\nfunction getDatabase(app = getApp(), url) {\r\n const db = _getProvider(app, 'database').getImmediate({\r\n identifier: url\r\n });\r\n if (!db._instanceStarted) {\r\n const emulator = getDefaultEmulatorHostnameAndPort('database');\r\n if (emulator) {\r\n connectDatabaseEmulator(db, ...emulator);\r\n }\r\n }\r\n return db;\r\n}\r\n/**\r\n * Modify the provided instance to communicate with the Realtime Database\r\n * emulator.\r\n *\r\n *

Note: This method must be called before performing any other operation.\r\n *\r\n * @param db - The instance to modify.\r\n * @param host - The emulator host (ex: localhost)\r\n * @param port - The emulator port (ex: 8080)\r\n * @param options.mockUserToken - the mock auth token to use for unit testing Security Rules\r\n */\r\nfunction connectDatabaseEmulator(db, host, port, options = {}) {\r\n db = getModularInstance(db);\r\n db._checkNotDeleted('useEmulator');\r\n if (db._instanceStarted) {\r\n fatal('Cannot call useEmulator() after instance has already been initialized.');\r\n }\r\n const repo = db._repoInternal;\r\n let tokenProvider = undefined;\r\n if (repo.repoInfo_.nodeAdmin) {\r\n if (options.mockUserToken) {\r\n fatal('mockUserToken is not supported by the Admin SDK. For client access with mock users, please use the \"firebase\" package instead of \"firebase-admin\".');\r\n }\r\n tokenProvider = new EmulatorTokenProvider(EmulatorTokenProvider.OWNER);\r\n }\r\n else if (options.mockUserToken) {\r\n const token = typeof options.mockUserToken === 'string'\r\n ? options.mockUserToken\r\n : createMockUserToken(options.mockUserToken, db.app.options.projectId);\r\n tokenProvider = new EmulatorTokenProvider(token);\r\n }\r\n // Modify the repo to apply emulator settings\r\n repoManagerApplyEmulatorSettings(repo, host, port, tokenProvider);\r\n}\r\n/**\r\n * Disconnects from the server (all Database operations will be completed\r\n * offline).\r\n *\r\n * The client automatically maintains a persistent connection to the Database\r\n * server, which will remain active indefinitely and reconnect when\r\n * disconnected. However, the `goOffline()` and `goOnline()` methods may be used\r\n * to control the client connection in cases where a persistent connection is\r\n * undesirable.\r\n *\r\n * While offline, the client will no longer receive data updates from the\r\n * Database. However, all Database operations performed locally will continue to\r\n * immediately fire events, allowing your application to continue behaving\r\n * normally. Additionally, each operation performed locally will automatically\r\n * be queued and retried upon reconnection to the Database server.\r\n *\r\n * To reconnect to the Database and begin receiving remote events, see\r\n * `goOnline()`.\r\n *\r\n * @param db - The instance to disconnect.\r\n */\r\nfunction goOffline(db) {\r\n db = getModularInstance(db);\r\n db._checkNotDeleted('goOffline');\r\n repoInterrupt(db._repo);\r\n}\r\n/**\r\n * Reconnects to the server and synchronizes the offline Database state\r\n * with the server state.\r\n *\r\n * This method should be used after disabling the active connection with\r\n * `goOffline()`. Once reconnected, the client will transmit the proper data\r\n * and fire the appropriate events so that your client \"catches up\"\r\n * automatically.\r\n *\r\n * @param db - The instance to reconnect.\r\n */\r\nfunction goOnline(db) {\r\n db = getModularInstance(db);\r\n db._checkNotDeleted('goOnline');\r\n repoResume(db._repo);\r\n}\r\nfunction enableLogging(logger, persistent) {\r\n enableLogging$1(logger, persistent);\r\n}\n\n/**\r\n * @license\r\n * Copyright 2021 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nfunction registerDatabase(variant) {\r\n setSDKVersion(SDK_VERSION$1);\r\n _registerComponent(new Component('database', (container, { instanceIdentifier: url }) => {\r\n const app = container.getProvider('app').getImmediate();\r\n const authProvider = container.getProvider('auth-internal');\r\n const appCheckProvider = container.getProvider('app-check-internal');\r\n return repoManagerDatabaseFromApp(app, authProvider, appCheckProvider, url);\r\n }, \"PUBLIC\" /* ComponentType.PUBLIC */).setMultipleInstances(true));\r\n registerVersion(name, version, variant);\r\n // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation\r\n registerVersion(name, version, 'esm2017');\r\n}\n\n/**\r\n * @license\r\n * Copyright 2020 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nconst SERVER_TIMESTAMP = {\r\n '.sv': 'timestamp'\r\n};\r\n/**\r\n * Returns a placeholder value for auto-populating the current timestamp (time\r\n * since the Unix epoch, in milliseconds) as determined by the Firebase\r\n * servers.\r\n */\r\nfunction serverTimestamp() {\r\n return SERVER_TIMESTAMP;\r\n}\r\n/**\r\n * Returns a placeholder value that can be used to atomically increment the\r\n * current database value by the provided delta.\r\n *\r\n * @param delta - the amount to modify the current value atomically.\r\n * @returns A placeholder value for modifying data atomically server-side.\r\n */\r\nfunction increment(delta) {\r\n return {\r\n '.sv': {\r\n 'increment': delta\r\n }\r\n };\r\n}\n\n/**\r\n * @license\r\n * Copyright 2020 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * A type for the resolve value of {@link runTransaction}.\r\n */\r\nclass TransactionResult {\r\n /** @hideconstructor */\r\n constructor(\r\n /** Whether the transaction was successfully committed. */\r\n committed, \r\n /** The resulting data snapshot. */\r\n snapshot) {\r\n this.committed = committed;\r\n this.snapshot = snapshot;\r\n }\r\n /** Returns a JSON-serializable representation of this object. */\r\n toJSON() {\r\n return { committed: this.committed, snapshot: this.snapshot.toJSON() };\r\n }\r\n}\r\n/**\r\n * Atomically modifies the data at this location.\r\n *\r\n * Atomically modify the data at this location. Unlike a normal `set()`, which\r\n * just overwrites the data regardless of its previous value, `runTransaction()` is\r\n * used to modify the existing value to a new value, ensuring there are no\r\n * conflicts with other clients writing to the same location at the same time.\r\n *\r\n * To accomplish this, you pass `runTransaction()` an update function which is\r\n * used to transform the current value into a new value. If another client\r\n * writes to the location before your new value is successfully written, your\r\n * update function will be called again with the new current value, and the\r\n * write will be retried. This will happen repeatedly until your write succeeds\r\n * without conflict or you abort the transaction by not returning a value from\r\n * your update function.\r\n *\r\n * Note: Modifying data with `set()` will cancel any pending transactions at\r\n * that location, so extreme care should be taken if mixing `set()` and\r\n * `runTransaction()` to update the same data.\r\n *\r\n * Note: When using transactions with Security and Firebase Rules in place, be\r\n * aware that a client needs `.read` access in addition to `.write` access in\r\n * order to perform a transaction. This is because the client-side nature of\r\n * transactions requires the client to read the data in order to transactionally\r\n * update it.\r\n *\r\n * @param ref - The location to atomically modify.\r\n * @param transactionUpdate - A developer-supplied function which will be passed\r\n * the current data stored at this location (as a JavaScript object). The\r\n * function should return the new value it would like written (as a JavaScript\r\n * object). If `undefined` is returned (i.e. you return with no arguments) the\r\n * transaction will be aborted and the data at this location will not be\r\n * modified.\r\n * @param options - An options object to configure transactions.\r\n * @returns A `Promise` that can optionally be used instead of the `onComplete`\r\n * callback to handle success and failure.\r\n */\r\nfunction runTransaction(ref, \r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\ntransactionUpdate, options) {\r\n var _a;\r\n ref = getModularInstance(ref);\r\n validateWritablePath('Reference.transaction', ref._path);\r\n if (ref.key === '.length' || ref.key === '.keys') {\r\n throw ('Reference.transaction failed: ' + ref.key + ' is a read-only object.');\r\n }\r\n const applyLocally = (_a = options === null || options === void 0 ? void 0 : options.applyLocally) !== null && _a !== void 0 ? _a : true;\r\n const deferred = new Deferred();\r\n const promiseComplete = (error, committed, node) => {\r\n let dataSnapshot = null;\r\n if (error) {\r\n deferred.reject(error);\r\n }\r\n else {\r\n dataSnapshot = new DataSnapshot(node, new ReferenceImpl(ref._repo, ref._path), PRIORITY_INDEX);\r\n deferred.resolve(new TransactionResult(committed, dataSnapshot));\r\n }\r\n };\r\n // Add a watch to make sure we get server updates.\r\n const unwatcher = onValue(ref, () => { });\r\n repoStartTransaction(ref._repo, ref._path, transactionUpdate, promiseComplete, unwatcher, applyLocally);\r\n return deferred.promise;\r\n}\n\n/**\r\n * @license\r\n * Copyright 2017 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\nPersistentConnection;\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\nPersistentConnection.prototype.simpleListen = function (pathString, onComplete) {\r\n this.sendRequest('q', { p: pathString }, onComplete);\r\n};\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\nPersistentConnection.prototype.echo = function (data, onEcho) {\r\n this.sendRequest('echo', { d: data }, onEcho);\r\n};\r\n// RealTimeConnection properties that we use in tests.\r\nConnection;\r\n/**\r\n * @internal\r\n */\r\nconst hijackHash = function (newHash) {\r\n const oldPut = PersistentConnection.prototype.put;\r\n PersistentConnection.prototype.put = function (pathString, data, onComplete, hash) {\r\n if (hash !== undefined) {\r\n hash = newHash();\r\n }\r\n oldPut.call(this, pathString, data, onComplete, hash);\r\n };\r\n return function () {\r\n PersistentConnection.prototype.put = oldPut;\r\n };\r\n};\r\nRepoInfo;\r\n/**\r\n * Forces the RepoManager to create Repos that use ReadonlyRestClient instead of PersistentConnection.\r\n * @internal\r\n */\r\nconst forceRestClient = function (forceRestClient) {\r\n repoManagerForceRestClient(forceRestClient);\r\n};\n\n/**\r\n * @license\r\n * Copyright 2023 Google LLC\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n/**\r\n * Used by console to create a database based on the app,\r\n * passed database URL and a custom auth implementation.\r\n * @internal\r\n * @param app - A valid FirebaseApp-like object\r\n * @param url - A valid Firebase databaseURL\r\n * @param version - custom version e.g. firebase-admin version\r\n * @param customAppCheckImpl - custom app check implementation\r\n * @param customAuthImpl - custom auth implementation\r\n */\r\nfunction _initStandalone({ app, url, version, customAuthImpl, customAppCheckImpl, nodeAdmin = false }) {\r\n setSDKVersion(version);\r\n /**\r\n * ComponentContainer('database-standalone') is just a placeholder that doesn't perform\r\n * any actual function.\r\n */\r\n const componentContainer = new ComponentContainer('database-standalone');\r\n const authProvider = new Provider('auth-internal', componentContainer);\r\n let appCheckProvider;\r\n if (customAppCheckImpl) {\r\n appCheckProvider = new Provider('app-check-internal', componentContainer);\r\n appCheckProvider.setComponent(new Component('app-check-internal', () => customAppCheckImpl, \"PRIVATE\" /* ComponentType.PRIVATE */));\r\n }\r\n authProvider.setComponent(new Component('auth-internal', () => customAuthImpl, \"PRIVATE\" /* ComponentType.PRIVATE */));\r\n return repoManagerDatabaseFromApp(app, authProvider, appCheckProvider, url, nodeAdmin);\r\n}\n\n/**\r\n * Firebase Realtime Database\r\n *\r\n * @packageDocumentation\r\n */\r\nregisterDatabase();\n\nexport { DataSnapshot, Database, OnDisconnect, QueryConstraint, TransactionResult, QueryImpl as _QueryImpl, QueryParams as _QueryParams, ReferenceImpl as _ReferenceImpl, forceRestClient as _TEST_ACCESS_forceRestClient, hijackHash as _TEST_ACCESS_hijackHash, _initStandalone, repoManagerDatabaseFromApp as _repoManagerDatabaseFromApp, setSDKVersion as _setSDKVersion, validatePathString as _validatePathString, validateWritablePath as _validateWritablePath, child, connectDatabaseEmulator, enableLogging, endAt, endBefore, equalTo, forceLongPolling, forceWebSockets, get, getDatabase, goOffline, goOnline, increment, limitToFirst, limitToLast, off, onChildAdded, onChildChanged, onChildMoved, onChildRemoved, onDisconnect, onValue, orderByChild, orderByKey, orderByPriority, orderByValue, push, query, ref, refFromURL, remove, runTransaction, serverTimestamp, set, setPriority, setWithPriority, startAfter, startAt, update };\n//# sourceMappingURL=index.esm2017.js.map\n"],"names":["name","version","SDK_VERSION","setSDKVersion","DOMStorageWrapper","constructor","domStorage_","this","prefix_","set","key","value","removeItem","prefixedName_","setItem","get","storedVal","getItem","remove","toString","MemoryStorage","cache_","isInMemoryStorage","createStoragefor","domStorageName","window","domStorage","e","PersistentStorage","SessionStorage","logClient","LUIDGenerator","id","sha1","str","utf8Bytes","update","sha1Bytes","digest","encodeByteArray","buildLogMessage_","varArgs","message","i","length","arg","Array","isArray","apply","logger","firstLog_","enableLogging$1","logger_","persistent","logLevel","VERBOSE","log","bind","logWrapper","prefix","error","fatal","Error","warn","isInvalidJSONNumber","data","Number","POSITIVE_INFINITY","NEGATIVE_INFINITY","MIN_NAME","MAX_NAME","nameCompare","a","b","aAsInt","tryParseInt","bAsInt","stringCompare","requireKey","obj","ObjectToUniqueKey","keys","k","push","sort","splitStringBySize","segsize","len","dataSegs","c","substring","each","fn","hasOwnProperty","doubleToIEEE754String","v","bias","s","f","ln","Infinity","Math","abs","pow","min","floor","LN2","round","bits","reverse","join","hexByteString","hexByte","parseInt","substr","toLowerCase","INTEGER_REGEXP_","RegExp","test","intVal","exceptionGuard","setTimeout","stack","setTimeoutNonBlocking","time","timeout","Deno","unrefTimer","AppCheckTokenProvider","appName_","appCheckProvider","appCheck","getImmediate","optional","then","getToken","forceRefresh","Promise","resolve","reject","addTokenChangeListener","listener","_a","addTokenListener","notifyForInvalidToken","FirebaseAuthTokenProvider","firebaseOptions_","authProvider_","auth_","onInit","auth","catch","code","addAuthTokenListener","removeTokenChangeListener","removeAuthTokenListener","errorMessage","EmulatorTokenProvider","accessToken","OWNER","PROTOCOL_VERSION","FORGE_DOMAIN_RE","APP_CHECK_TOKEN_PARAM","WEBSOCKET","LONG_POLLING","RepoInfo","host","secure","namespace","webSocketOnly","nodeAdmin","persistenceKey","includeNamespaceInQueryParams","isUsingEmulator","_host","_domain","indexOf","internalHost","isCacheableHost","isCustomHost","newHost","toURLString","protocol","query","repoInfoConnectionURL","repoInfo","type","params","connURL","repoInfoNeedsQueryParam","pairs","StatsCollection","counters_","incrementCounter","amount","collections","reporters","statsManagerGetCollection","hashString","PacketReceiver","onMessage_","pendingResponses","currentResponseNum","closeAfterResponse","onClose","closeAfter","responseNum","callback","handleResponse","requestNum","toProcess","FIREBASE_LONGPOLL_START_PARAM","BrowserPollConnection","connId","applicationId","appCheckToken","authToken","transportSessionId","lastSessionId","bytesSent","bytesReceived","everConnected_","log_","stats_","urlFn","open","onMessage","onDisconnect","curSegmentNum","onDisconnect_","myPacketOrderer","isClosed_","connectTimeoutTimer_","onClosed_","document","readyState","called","wrappedFn","body","addEventListener","attachEvent","executeWhenDOMReady","scriptTagHolder","FirebaseIFrameScriptHolder","args","command","arg1","arg2","arg3","arg4","incrementIncomingBytes_","clearTimeout","password","sendNewPolls","pN","urlParams","random","uniqueCallbackIdentifier","location","hostname","connectURL","addTag","start","startLongPoll","addDisconnectPingFrame","forceAllow","forceAllow_","forceDisallow","forceDisallow_","isAvailable","createElement","href","Windows","UI","markConnectionHealthy","shutdown_","close","myDisconnFrame","removeChild","send","dataStr","base64data","MAX_URL_DATA_SIZE","enqueueSegment","pw","src","style","display","appendChild","commandCB","onMessageCB","outstandingRequests","Set","pendingSegs","currentSerial","myIFrame","createIFrame_","script","domain","iframeContents","doc","write","iframe","contentWindow","contentDocument","alive","textContent","myID","myPW","newRequest_","size","theURL","curDataString","d","theSeg","shift","seg","ts","addLongPollTag_","segnum","totalsegs","url","serial","add","doNewRequest","delete","keepaliveTimeout","loadCB","doNodeLongPoll","newScript","async","onload","onreadystatechange","rstate","parentNode","onerror","WebSocketImpl","MozWebSocket","WebSocket","WebSocketConnection","keepaliveTimer","frames","totalFrames","connectionURL_","options","device","headers","process","platform","env","proxy","origin","mySock","onopen","onclose","onmessage","m","handleIncomingFrame","isOldAndroid","navigator","userAgent","oldAndroidRegex","oldAndroidMatch","match","parseFloat","previouslyFailed","appendFrame_","fullMess","jsonMess","handleNewFrameCount_","frameCount","extractFrameCount_","isNaN","mess","resetKeepAlive","remainingData","sendString_","String","clearInterval","setInterval","responsesRequiredToBeHealthy","healthyTimeout","TransportManager","initTransports_","ALL_TRANSPORTS","IS_TRANSPORT_INITIALIZED","globalTransportInitialized_","isWebSocketsAvailable","isSkipPollConnection","transports_","transports","transport","initialTransport","upgradeTransport","Connection","repoInfo_","applicationId_","appCheckToken_","authToken_","onReady_","onKill_","connectionCount","pendingDataMessages","state_","transportManager_","start_","conn","conn_","nextTransportId_","primaryResponsesRequired_","onMessageReceived","connReceiver_","onConnectionLost","disconnReceiver_","tx_","rx_","secondaryConn_","isHealthy_","healthyTimeoutMS","healthyTimeout_","everConnected","onConnectionLost_","onSecondaryConnectionLost_","onPrimaryMessageReceived_","onSecondaryMessageReceived_","sendRequest","dataMsg","msg","t","sendData_","tryCleanupConnection","onSecondaryControl_","controlData","cmd","upgradeIfSecondaryHealthy_","secondaryResponsesRequired_","parsedData","layer","proceedWithUpgrade_","onControl_","onDataMessage_","onPrimaryResponse_","payload","handshakePayload","Object","assign","h","onHandshake_","onConnectionShutdown_","onReset_","sendPingOnPrimaryIfNecessary_","handshake","timestamp","sessionId","onConnectionEstablished_","tryStartUpgrade_","startUpgrade_","closeConnections_","reason","ServerActions","put","pathString","onComplete","hash","merge","refreshAuthToken","token","refreshAppCheckToken","onDisconnectPut","onDisconnectMerge","onDisconnectCancel","reportStats","stats","EventEmitter","allowedEvents_","listeners_","trigger","eventType","listeners","context","on","validateEventType_","eventData","getInitialEvent","off","splice","find","et","OnlineMonitor","super","online_","getInstance","currentlyOnline","MAX_PATH_DEPTH","MAX_PATH_LENGTH_BYTES","Path","pathOrString","pieceNum","pieces_","split","copyTo","pieceNum_","newEmptyPath","pathGetFront","path","pathGetLength","pathPopFront","pathGetBack","pathSlice","begin","slice","pathParent","pieces","pathChild","childPathObj","childPieces","pathIsEmpty","newRelativePath","outerPath","innerPath","outer","inner","pathCompare","left","right","leftKeys","rightKeys","cmp","pathEquals","other","j","pathContains","ValidationPath","errorPrefix_","parts_","byteLength_","max","validationPathCheckValid","validationPath","validationPathToErrorString","VisibilityMonitor","hidden","visibilityChange","visible_","visible","RECONNECT_MIN_DELAY","PersistentConnection","onDataUpdate_","onConnectStatus_","onServerInfoUpdate_","authTokenProvider_","appCheckTokenProvider_","authOverride_","nextPersistentConnectionId_","interruptReasons_","listens","Map","outstandingPuts_","outstandingGets_","outstandingPutCount_","outstandingGetCount_","onDisconnectRequestQueue_","connected_","reconnectDelay_","maxReconnectDelay_","securityDebugCallback_","establishConnectionTimer_","requestCBHash_","requestNumber_","realtime_","forceTokenRefresh_","invalidAuthTokenCount_","invalidAppCheckTokenCount_","firstConnection_","lastConnectionAttemptTime_","lastConnectionEstablishedTime_","onVisible_","onOnline_","action","onResponse","curReqNum","r","initConnection_","deferred","outstandingGet","request","p","_path","q","_queryObject","index","sendGet_","promise","listen","currentHashFn","tag","queryId","_queryIdentifier","has","_queryParams","isDefault","loadsAllData","listenSpec","hashFn","sendListen_","req","status","warnOnListenWarnings_","removeListen_","warnings","indexSpec","getIndex","indexPath","tryAuth","reduceReconnectDelayIfAdminCredential_","credential","tryAppCheck","authMethod","requestData","cred","res","onAuthRevoked_","onAppCheckRevoked_","unlisten","sendUnlisten_","queryObj","sendOnDisconnect_","response","putInternal","undefined","sendPut_","queued","result","errorReason","reqNum","onDataPush_","onListenRevoked_","onSecurityDebugPacket_","Date","getTime","handleTimestamp_","sendConnectStats_","restoreState_","scheduleConnect_","establishConnection_","online","onRealtimeDisconnect_","cancelSentTransactions_","shouldReconnect_","timeSinceLastConnectAttempt","reconnectDelay","onDataMessage","onReady","nextConnectionId_","canceled","connection","closeFn","sendRequestFn","all","interrupt","resume","delta","serverTimeOffset","map","normalizedPathString","statusCode","explanation","console","replace","queries","values","clientName","NamedNode","node","Wrap","Index","getCompare","compare","indexedValueChanged","oldNode","newNode","oldWrapped","newWrapped","minPost","MIN","__EMPTY_NODE","KeyIndex","val","isDefinedOn","maxPost","makePost","indexValue","KEY_INDEX","SortedMapIterator","startKey","comparator","isReverse_","resultGenerator_","nodeStack_","isEmpty","getNext","pop","hasNext","peek","LLRBNode","color","RED","SortedMap","EMPTY_NODE","copy","count","inorderTraversal","reverseTraversal","min_","minKey","maxKey","insert","n","fixUp_","removeMin_","isRed_","moveRedLeft_","smallest","rotateRight_","moveRedRight_","rotateLeft_","colorFlip_","nl","nr","checkMaxDepth_","blackDepth","check_","BLACK","comparator_","root_","getPredecessorKey","rightParent","getIterator","resultGenerator","getIteratorFrom","getReverseIteratorFrom","getReverseIterator","NAME_ONLY_COMPARATOR","NAME_COMPARATOR","MAX_NODE$2","priorityHashText","priority","validatePriorityNode","priorityNode","isLeafNode","getPriority","__childrenNodeConstructor","nodeFromJSON$1","MAX_NODE$1","LeafNode","value_","priorityNode_","lazyHash_","updatePriority","newPriorityNode","getImmediateChild","childName","getChild","hasChild","getPredecessorChildName","childNode","updateImmediateChild","newChildNode","updateChild","front","numChildren","forEachChild","exportFormat","getValue","toHash","compareTo","compareToLeafNode_","otherLeaf","otherLeafType","thisLeafType","otherIndex","VALUE_TYPE_ORDER","thisIndex","withIndex","isIndexed","equals","PRIORITY_INDEX","aPriority","bPriority","indexCmp","LOG_2","Base12Num","num","current_","mask","bits_","nextBitIsOne","buildChildSet","childList","keyFn","mapSortFn","buildBalancedTree","low","high","namedNode","middle","root","base12","buildPennant","chunkSize","childTree","attachPennant","pennant","isOne","buildFrom12Array","_defaultIndexMap","fallbackObject","IndexMap","indexes_","indexSet_","Default","indexKey","sortedMap","hasIndex","indexDefinition","addIndex","existingChildren","sawIndexedValue","iter","newIndex","next","indexName","newIndexSet","newIndexes","addToIndexes","indexedChildren","existingSnap","newChildren","removeFromIndexes","ChildrenNode","children_","indexMap_","child","newIndexMap","newPriority","newImmediateChild","numKeys","allIntegerKeys","array","childHash","idx","resolveIndex_","predecessor","getFirstChildName","getFirstChild","getLastChildName","getLastChild","wrappedNode","startPost","iterator","endPost","MAX_NODE","otherChildrenNode","thisIter","otherIter","thisCurrent","otherCurrent","defineProperties","MAX","setMaxNode","USE_HINZE","nodeFromJSON","json","childData","children","childrenHavePriority","childSet","sortedChildSet","setNodeFromJSON","PathIndex","indexPath_","extractChild","snap","aChild","bChild","valueNode","VALUE_INDEX","changeValue","snapshotNode","changeChildAdded","changeChildRemoved","changeChildChanged","oldSnap","IndexedFilter","index_","newChild","affectedPath","source","optChangeAccumulator","oldChild","trackChildChange","updateFullNode","newSnap","filtersNodes","getIndexedFilter","RangedFilter","indexedFilter_","startPost_","getStartPost_","endPost_","getEndPost_","startIsInclusive_","startAfterSet_","endIsInclusive_","endBeforeSet_","getStartPost","getEndPost","matches","isWithinStart","isWithinEnd","filtered","self","hasStart","startName","getIndexStartName","getIndexStartValue","hasEnd","endName","getIndexEndName","getIndexEndValue","LimitedFilter","withinDirectionalStart","reverse_","withinEndPost","withinStartPost","withinDirectionalEnd","compareRes","rangedFilter_","limit_","getLimit","isViewFromLeft","fullLimitUpdateChild_","childKey","childSnap","changeAccumulator","oldEventCache","newChildNamedNode","windowBoundary","inRange","oldChildSnap","nextChild","getChildAfterChild","compareNext","newEventCache","QueryParams","limitSet_","startSet_","startNameSet_","endSet_","endNameSet_","viewFrom_","indexStartValue_","indexStartName_","indexEndValue_","indexEndName_","hasLimit","hasAnchoredLimit","queryParamsStartAt","queryParams","newParams","queryParamsEndAt","queryParamsOrderBy","queryParamsToRestQueryStringParameters","qs","orderBy","startParam","endParam","queryParamsGetQueryObject","viewFrom","ReadonlyRestClient","listens_","getListenId_","listenId","thisListen","queryStringParameters","restRequest_","xhr","XMLHttpRequest","responseText","SnapshotHolder","rootNode_","getNode","updateSnapshot","newSnapshotNode","newSparseSnapshotTree","sparseSnapshotTreeRemember","sparseSnapshotTree","clear","sparseSnapshotTreeForget","tree","sparseSnapshotTreeForEachTree","prefixPath","func","forEach","sparseSnapshotTreeForEachChild","StatsListener","collection_","last_","newStats","stat","StatsReporter","collection","server_","statsToReport_","statsListener_","reportStats_","reportedStats","haveStatsToReport","OperationType","newOperationSourceServerTaggedQuery","fromUser","fromServer","tagged","AckUserWrite","affectedTree","revert","ACK_USER_WRITE","operationForChild","subtree","ListenComplete","LISTEN_COMPLETE","Overwrite","OVERWRITE","Merge","MERGE","CacheNode","node_","fullyInitialized_","filtered_","isFullyInitialized","isFiltered","isCompleteForPath","isCompleteForChild","EventGenerator","query_","eventGeneratorGenerateEventsForType","eventGenerator","events","changes","registrations","eventCache","filteredChanges","filter","change","aWrapped","bWrapped","eventGeneratorCompareChanges","materializedChange","prevName","eventGeneratorMaterializeSingleChange","registration","respondsTo","createEvent","newViewCache","serverCache","viewCacheUpdateEventSnap","viewCache","eventSnap","complete","viewCacheUpdateServerSnap","serverSnap","viewCacheGetCompleteEventSnap","viewCacheGetCompleteServerSnap","emptyChildrenSingleton","ImmutableTree","EmptyChildren","fromObject","childPath","findRootMostMatchingPathAndValue","relativePath","predicate","childExistingPathAndValue","findRootMostValueAndPath","toSet","setTree","newTree","fold","fold_","pathSoFar","accum","findOnPath","findOnPath_","pathToFollow","foreachOnPath","foreachOnPath_","currentRelativePath","foreach","foreach_","foreachChild","CompoundWrite","writeTree_","empty","compoundWriteAddWrite","compoundWrite","rootmost","rootMostPath","newWriteTree","compoundWriteAddWrites","updates","newWrite","compoundWriteRemoveWrite","compoundWriteHasCompleteWrite","compoundWriteGetCompleteNode","compoundWriteGetCompleteChildren","compoundWriteChildCompoundWrite","shadowingNode","compoundWriteIsEmpty","compoundWriteApply","applySubtreeWrite","writeTree","priorityWrite","writeTreeChildWrites","newWriteTreeRef","writeTreeRemoveWrite","writeId","allWrites","findIndex","writeToRemove","removedWriteWasVisible","removedWriteOverlapsWithOtherWrites","currentWrite","writeTreeRecordContainsPath_","visibleWrites","writeTreeLayerTree_","writeTreeDefaultFilter_","lastWriteId","writeTreeResetTree_","writeRecord","writes","treeRoot","writePath","deepNode","writeTreeCalcCompleteEventCache","treePath","completeServerCache","writeIdsToExclude","includeHiddenWrites","subMerge","writeTreeRefCalcCompleteEventCache","writeTreeRef","writeTreeRefCalcCompleteEventChildren","completeServerChildren","completeChildren","topLevelSet","writeTreeCalcCompleteEventChildren","writeTreeRefCalcEventCacheAfterServerOverwrite","existingEventSnap","existingServerSnap","childMerge","writeTreeCalcEventCacheAfterServerOverwrite","writeTreeRefShadowingWrite","writeTreeShadowingWrite","writeTreeRefCalcIndexedSlice","completeServerData","toIterate","nodes","writeTreeCalcIndexedSlice","writeTreeRefCalcCompleteChild","existingServerCache","writeTreeCalcCompleteChild","writeTreeRefChild","ChildChangeAccumulator","changeMap","oldChange","oldType","getChanges","from","NO_COMPLETE_CHILD_SOURCE","getCompleteChild","WriteTreeCompleteChildSource","writes_","viewCache_","optCompleteServerCache_","serverNode","viewProcessorApplyOperation","viewProcessor","oldViewCache","operation","writesCache","completeCache","accumulator","filterServerNode","overwrite","viewProcessorApplyUserOverwrite","viewProcessorApplyServerOverwrite","changedChildren","curViewCache","viewProcessorCacheHasChild","viewProcessorApplyUserMerge","viewProcessorApplyServerMerge","ackUserWrite","serverChildren","viewProcessorRevertUserWrite","ackPath","mergePath","serverCachePath","viewProcessorAckUserWrite","oldServerNode","viewProcessorGenerateEventCacheAfterServerEvent","viewProcessorListenComplete","isLeafOrEmpty","oldCompleteSnap","viewProcessorMaybeAddValueEvent","changePath","oldEventSnap","completeEventChildren","completeNode","oldEventNode","updatedPriority","childChangePath","newEventChild","eventChildUpdate","changedSnap","oldServerSnap","newServerCache","serverFilter","newServerNode","viewProcessorApplyMerge","viewMergeTree","childMergeTree","isUnknownDeepMerge","View","initialViewCache","eventRegistrations_","indexFilter","processor_","newViewProcessor","initialServerCache","initialEventCache","eventGenerator_","viewGetCompleteServerCache","view","cache","viewIsEmpty","viewRemoveEventRegistration","eventRegistration","cancelError","cancelEvents","maybeEvent","createCancelEvent","remaining","existing","hasAnyCallback","concat","viewApplyOperation","viewGenerateEventsForChanges_","eventRegistrations","moves","eventGeneratorGenerateEventsForChanges","referenceConstructor$1","referenceConstructor","SyncPoint","views","syncPointApplyOperation","syncPoint","optCompleteServerCache","syncPointGetView","serverCacheComplete","eventCacheComplete","syncPointAddEventRegistration","viewAddEventRegistration","initialChanges","viewGetInitialEvents","syncPointRemoveEventRegistration","removed","hadCompleteView","syncPointHasCompleteView","viewQueryId","entries","_repo","syncPointGetQueryViews","syncPointGetCompleteServerCache","syncPointViewForQuery","syncPointGetCompleteView","syncPointViewExistsForQuery","syncTreeNextQueryTag_","SyncTree","listenProvider_","syncPointTree_","pendingWriteTree_","tagToQueryMap","queryToTagMap","syncTreeApplyUserOverwrite","syncTree","newData","writeTreeAddOverwrite","syncTreeApplyOperationToSyncPoints_","syncTreeApplyUserMerge","writeTreeAddMerge","changeTree","syncTreeAckUserWrite","record","writeTreeGetWrite","syncTreeApplyServerOverwrite","syncTreeRemoveEventRegistration","skipListenerDedup","maybeSyncPoint","removedAndEvents","removingDefault","covered","parentSyncPoint","newViews","maybeChildSyncPoint","childMap","_key","childViews","syncTreeCollectDistinctViewsForSubTree_","newQuery","syncTreeCreateListenerForView_","startListening","syncTreeQueryForListening_","syncTreeTagForQuery","defaultTag","stopListening","queryToRemove","tagToRemove","syncTreeMakeQueryKey_","removedQuery","removedQueryKey","removedQueryTag","syncTreeRemoveTags_","syncTreeApplyTaggedQueryOverwrite","queryKey","syncTreeQueryKeyForTag_","syncTreeParseQueryKey_","queryPath","syncTreeApplyTaggedOperation_","syncTreeAddEventRegistration","skipSetupListener","foundAncestorDefaultView","pathToSyncPoint","sp","childSyncPoint","viewAlreadyExists","queriesToStop","childQueries","queryToStop","syncTreeSetupListener_","syncTreeCalcCompleteEventCache","syncTreeGetServerValue","serverCacheNode","viewGetCompleteNode","syncTreeApplyOperationHelper_","syncPointTree","syncTreeApplyOperationDescendantsHelper_","childOperation","childServerCache","childWritesCache","viewGetServerCache","syncTreeApplyTaggedListenComplete","syncTreeApplyListenComplete","toUpperCase","errorForServerCode","splitIndex","ExistingValueProvider","DeferredValueProvider","syncTree_","path_","generateWithValues","resolveDeferredLeafValue","existingVal","serverValues","resolveScalarDeferredValue","resolveComplexDeferredValue","JSON","stringify","op","unused","existingNode","resolveDeferredValueTree","resolveDeferredValue","resolveDeferredValueSnapshot","rawPri","leafNode","childrenNode","Tree","parent","childCount","treeSubTree","pathObj","treeGetValue","treeSetValue","treeUpdateParents","treeHasChildren","treeForEachChild","treeForEachDescendant","includeSelf","childrenFirst","treeGetPath","childEmpty","treeIsEmpty","childExists","treeUpdateChild","INVALID_KEY_REGEX_","INVALID_PATH_REGEX_","MAX_LEAF_SIZE_","isValidKey","isValidPathString","isValidPriority","validateFirebaseDataArg","fnName","validateFirebaseData","errorPrefix","hasDotValue","hasActualChild","validationPathPush","last","validationPathPop","validateFirebaseMergeDataArg","errorPrefix$1","mergePaths","curPath","prevPath","validateFirebaseMergePaths","validatePriority","validateKey","argumentName","validatePathString","validateRootPathString","validateWritablePath","validateUrl","parsedUrl","isValidRootPathString","EventQueue","eventLists_","recursionDepth_","eventQueueQueueEvents","eventQueue","eventDataList","currList","getPath","eventQueueRaiseEventsAtPath","eventQueueRaiseQueuedEventsMatchingPredicate","eventPath","eventQueueRaiseEventsForChangedPath","changedPath","sentAll","eventList","eventListRaise","eventFn","getEventRunner","INTERRUPT_REASON","MAX_TRANSACTION_RETRIES","Repo","forceRestClient_","appCheckProvider_","dataUpdateCount","eventQueue_","nextWriteId_","interceptServerDataCallback_","transactionQueueTree_","persistentConnection_","repoStart","repo","appId","authOverride","search","isMerge","repoOnDataUpdate","repoOnConnectStatus","connectStatus","repoUpdateInfo","repoOnServerInfoUpdate","statsReporter_","creatorFunction","statsManagerGetOrCreateReporter","infoData_","infoSyncTree_","infoEvents","serverSyncTree_","repoServerTime","offset","repoGenerateServerValues","taggedChildren","raw","syncTreeApplyTaggedQueryMerge","taggedSnap","syncTreeApplyServerMerge","repoRerunTransactions","repoLog","resolvedOnDisconnectTree","resolved","repoAbortTransactions","repoRunOnDisconnectEvents","repoGetNextWriteId","repoSetWithPriority","newVal","newNodeUnresolved","success","clearEvents","repoCallOnCompleteCallback","repoOnDisconnectCancel","repoOnDisconnectSet","repoRemoveEventCallbackForQuery","repoInterrupt","repoGetLatestState","excludeSets","repoSendReadyTransactions","repoPruneCompletedTransactionsBelowNode","queue","repoBuildTransactionQueue","every","transaction","setsToIgnore","txn","currentWriteId","latestState","snapToSend","latestHash","retryCount","currentOutputSnapshotRaw","dataToSend","pathToSend","callbacks","currentOutputSnapshotResolved","unwatcher","abortReason","repoSendTransactionQueue","rootMostTransactionNode","repoGetAncestorTransactionNode","txnsToRerun","abortTransaction","currentNode","currentInputSnapshot","newDataNode","oldWriteId","newNodeResolved","applyLocally","repoRerunTransactionQueue","transactionNode","transactionQueue","repoAggregateTransactionQueuesForNode","order","nodeQueue","to","treeForEachAncestor","repoAbortTransactionsOnNode","lastSent","parseRepoInfo","dataURL","parseDatabaseURL","scheme","subdomain","port","colonInd","slashInd","questionMarkInd","pathStringDecoded","piece","decodeURIComponent","decodePath","queryString","results","charAt","segment","kv","decodeQuery","hostWithoutPort","dotInd","PUSH_CHARS","nextPushId","lastPushTime","lastRandChars","now","duplicateTime","timeStampChars","DataEvent","snapshot","ref","getEventType","exportVal","CancelEvent","CallbackContext","snapshotCallback","cancelCallback","onValue","expDataSnapshot","previousChildName","call","onCancel","hasCancelCallback","userCallback","OnDisconnect","cancel","wrapCallback","setWithPriority","repoOnDisconnectSetWithPriority","childrenToMerge","repoOnDisconnectUpdate","QueryImpl","_orderByCalled","ReferenceImpl","isEqual","sameRepo","samePath","sameQueryIdentifier","toJSON","encodeURIComponent","pathToUrlEncodedString","validateNoPreviousOrderByCall","validateQueryEndpoints","startNode","endNode","tooManyArgsError","wrongArgTypeError","validateLimit","parentPath","DataSnapshot","_node","_index","childRef","exists","hasChildren","db","_checkNotDeleted","_root","refFromURL","parsedURL","thennablePushRef","pushRef","setPriority","changedKey","changedValue","repoUpdate","callbackContext","container","ValueEventRegistration","cached","err","repoGetValue","ChildEventRegistration","eventToCheck","cancelCallbackOrListenOptions","onlyOnce","onceCallback","dataSnapshot","repoAddEventCallbackForQuery","onChildAdded","onChildChanged","onChildMoved","onChildRemoved","expCallback","QueryConstraint","QueryEndAtConstraint","_value","_apply","endAt","QueryEndBeforeConstraint","queryParamsEndBefore","endBefore","QueryStartAtConstraint","startAt","QueryStartAfterConstraint","queryParamsStartAfter","startAfter","QueryLimitToFirstConstraint","_limit","newLimit","queryParamsLimitToFirst","limitToFirst","limit","QueryLimitToLastConstraint","queryParamsLimitToLast","limitToLast","QueryOrderByChildConstraint","parsedPath","orderByChild","QueryOrderByKeyConstraint","orderByKey","QueryOrderByPriorityConstraint","orderByPriority","QueryOrderByValueConstraint","orderByValue","QueryEqualToValueConstraint","equalTo","queryConstraints","queryImpl","constraint","syncPointSetReferenceConstructor","syncTreeSetReferenceConstructor","FIREBASE_DATABASE_EMULATOR_HOST_VAR","repos","useRestClient","repoManagerDatabaseFromApp","app","authProvider","dbUrl","databaseURL","projectId","isEmulator","dbEmulatorHost","authTokenProvider","appRepos","repoManagerCreateRepo","Database","_repoInternal","_instanceStarted","_rootInternal","_delete","appName","repoManagerDeleteRepo","apiName","checkTransportInit","forceWebSockets","forceLongPolling","connectDatabaseEmulator","tokenProvider","mockUserToken","repoManagerApplyEmulatorSettings","goOffline","goOnline","enableLogging","SERVER_TIMESTAMP","serverTimestamp","increment","TransactionResult","committed","runTransaction","transactionUpdate","currentState","queueNode","priorityForNode","repoStartTransaction","prototype","simpleListen","echo","onEcho","variant","_registerComponent","instanceIdentifier","getProvider","setMultipleInstances","registerVersion"],"sourceRoot":""}