{"version":3,"file":"index.esm2017.js","sources":["../node_modules/google-closure-library/closure/goog/base.js","../node_modules/google-closure-library/closure/goog/disposable/disposable.js","../node_modules/google-closure-library/closure/goog/array/array.js","../node_modules/google-closure-library/closure/goog/events/event.js","../node_modules/google-closure-library/closure/goog/events/browserfeature.js","../node_modules/google-closure-library/closure/goog/string/internal.js","../node_modules/google-closure-library/closure/goog/labs/useragent/util.js","../node_modules/google-closure-library/closure/goog/reflect/reflect.js","../node_modules/google-closure-library/closure/goog/useragent/useragent.js","../node_modules/google-closure-library/closure/goog/net/xhrio.js","../node_modules/google-closure-library/closure/goog/labs/useragent/browser.js","../node_modules/google-closure-library/closure/goog/labs/useragent/engine.js","../node_modules/google-closure-library/closure/goog/events/browserevent.js","../node_modules/google-closure-library/closure/goog/events/eventtype.js","../node_modules/google-closure-library/closure/goog/events/listenable.js","../node_modules/google-closure-library/closure/goog/events/listenablekey.js","../node_modules/google-closure-library/closure/goog/events/listener.js","../node_modules/google-closure-library/closure/goog/events/listenermap.js","../node_modules/google-closure-library/closure/goog/object/object.js","../node_modules/google-closure-library/closure/goog/events/events.js","../node_modules/google-closure-library/closure/goog/events/eventtarget.js","../node_modules/google-closure-library/closure/goog/json/json.js","../node_modules/google-closure-library/closure/goog/async/workqueue.js","../node_modules/google-closure-library/closure/goog/async/run.js","../node_modules/google-closure-library/closure/goog/async/freelist.js","../node_modules/google-closure-library/closure/goog/async/throwexception.js","../node_modules/google-closure-library/closure/goog/timer/timer.js","../node_modules/google-closure-library/closure/goog/async/throttle.js","../node_modules/google-closure-library/closure/goog/events/eventhandler.js","../node_modules/google-closure-library/closure/goog/labs/net/webchannel/webchanneldebug.js","../node_modules/google-closure-library/closure/goog/labs/net/webchannel/requeststats.js","../node_modules/google-closure-library/closure/goog/net/errorcode.js","../node_modules/google-closure-library/closure/goog/net/eventtype.js","../node_modules/google-closure-library/closure/goog/net/xmlhttpfactory.js","../node_modules/google-closure-library/closure/goog/labs/net/webchannel.js","../node_modules/google-closure-library/closure/goog/net/xmlhttp.js","../node_modules/google-closure-library/closure/goog/labs/net/webchannel/channelrequest.js","../node_modules/google-closure-library/closure/goog/labs/net/webchannel/environment.js","../node_modules/google-closure-library/closure/goog/labs/net/webchannel/webchannelbase.js","../node_modules/google-closure-library/closure/goog/uri/uri.js","../node_modules/google-closure-library/closure/goog/string/string.js","../node_modules/google-closure-library/closure/goog/disposable/dispose.js","../node_modules/google-closure-library/closure/goog/labs/net/webchannel/wirev8.js","../node_modules/google-closure-library/closure/goog/labs/net/webchannel/forwardchannelrequestpool.js","../node_modules/google-closure-library/closure/goog/structs/structs.js","../node_modules/google-closure-library/closure/goog/uri/utils.js","../node_modules/google-closure-library/closure/goog/labs/net/webchannel/wire.js","../node_modules/google-closure-library/closure/goog/json/nativejsonprocessor.js","../node_modules/google-closure-library/closure/goog/labs/net/webchannel/netutils.js","../node_modules/google-closure-library/closure/goog/net/fetchxmlhttpfactory.js","../node_modules/google-closure-library/closure/goog/functions/functions.js","../node_modules/google-closure-library/closure/goog/json/hybrid.js","../node_modules/google-closure-library/closure/goog/net/httpstatus.js","../node_modules/google-closure-library/closure/goog/net/rpc/httpcors.js","../node_modules/google-closure-library/closure/goog/labs/net/webchanneltransport.js","../node_modules/google-closure-library/closure/goog/labs/net/webchannel/webchannelbasetransport.js","temp/src/index.js","../node_modules/google-closure-library/closure/goog/labs/net/webchanneltransportfactory.js"],"sourcesContent":["/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Bootstrap for the Google JS Library (Closure).\n *\n * In uncompiled mode base.js will attempt to load Closure's deps file, unless\n * the global <code>CLOSURE_NO_DEPS</code> is set to true.  This allows projects\n * to include their own deps file(s) from different locations.\n *\n * Avoid including base.js more than once. This is strictly discouraged and not\n * supported. goog.require(...) won't work properly in that case.\n *\n * @provideGoog\n */\n\n\n/**\n * @define {boolean} Overridden to true by the compiler.\n */\nvar COMPILED = false;\n\n\n/**\n * Base namespace for the Closure library.  Checks to see goog is already\n * defined in the current scope before assigning to prevent clobbering if\n * base.js is loaded more than once.\n *\n * @const\n */\nvar goog = goog || {};\n\n/**\n * Reference to the global object.\n * https://www.ecma-international.org/ecma-262/9.0/index.html#sec-global-object\n *\n * More info on this implementation here:\n * https://docs.google.com/document/d/1NAeW4Wk7I7FV0Y2tcUFvQdGMc89k2vdgSXInw8_nvCI/edit\n *\n * @const\n * @suppress {undefinedVars} self won't be referenced unless `this` is falsy.\n * @type {!Global}\n */\ngoog.global =\n    // Check `this` first for backwards compatibility.\n    // Valid unless running as an ES module or in a function wrapper called\n    //   without setting `this` properly.\n    // Note that base.js can't usefully be imported as an ES module, but it may\n    // be compiled into bundles that are loadable as ES modules.\n    this ||\n    // https://developer.mozilla.org/en-US/docs/Web/API/Window/self\n    // For in-page browser environments and workers.\n    self;\n\n\n/**\n * A hook for overriding the define values in uncompiled mode.\n *\n * In uncompiled mode, `CLOSURE_UNCOMPILED_DEFINES` may be defined before\n * loading base.js.  If a key is defined in `CLOSURE_UNCOMPILED_DEFINES`,\n * `goog.define` will use the value instead of the default value.  This\n * allows flags to be overwritten without compilation (this is normally\n * accomplished with the compiler's \"define\" flag).\n *\n * Example:\n * <pre>\n *   var CLOSURE_UNCOMPILED_DEFINES = {'goog.DEBUG': false};\n * </pre>\n *\n * @type {Object<string, (string|number|boolean)>|undefined}\n */\ngoog.global.CLOSURE_UNCOMPILED_DEFINES;\n\n\n/**\n * A hook for overriding the define values in uncompiled or compiled mode,\n * like CLOSURE_UNCOMPILED_DEFINES but effective in compiled code.  In\n * uncompiled code CLOSURE_UNCOMPILED_DEFINES takes precedence.\n *\n * Also unlike CLOSURE_UNCOMPILED_DEFINES the values must be number, boolean or\n * string literals or the compiler will emit an error.\n *\n * While any @define value may be set, only those set with goog.define will be\n * effective for uncompiled code.\n *\n * Example:\n * <pre>\n *   var CLOSURE_DEFINES = {'goog.DEBUG': false} ;\n * </pre>\n *\n * Currently the Closure Compiler will only recognize very simple definitions of\n * this value when looking for values to apply to compiled code and ignore all\n * other references.  Specifically, it looks the value defined at the variable\n * declaration, as with the example above.\n *\n * TODO(user): Improve the recognized definitions.\n *\n * @type {!Object<string, (string|number|boolean)>|null|undefined}\n */\ngoog.global.CLOSURE_DEFINES;\n\n\n/**\n * Builds an object structure for the provided namespace path, ensuring that\n * names that already exist are not overwritten. For example:\n * \"a.b.c\" -> a = {};a.b={};a.b.c={};\n * Used by goog.provide and goog.exportSymbol.\n * @param {string} name The name of the object that this file defines.\n * @param {*=} object The object to expose at the end of the path.\n * @param {boolean=} overwriteImplicit If object is set and a previous call\n *     implicitly constructed the namespace given by name, this parameter\n *     controls whether object should overwrite the implicitly constructed\n *     namespace or be merged into it. Defaults to false.\n * @param {?Object=} objectToExportTo The object to add the path to; if this\n *     field is not specified, its value defaults to `goog.global`.\n * @private\n */\ngoog.exportPath_ = function(name, object, overwriteImplicit, objectToExportTo) {\n  var parts = name.split('.');\n  var cur = objectToExportTo || goog.global;\n\n  // Internet Explorer exhibits strange behavior when throwing errors from\n  // methods externed in this manner.  See the testExportSymbolExceptions in\n  // base_test.html for an example.\n  if (!(parts[0] in cur) && typeof cur.execScript != 'undefined') {\n    cur.execScript('var ' + parts[0]);\n  }\n\n  for (var part; parts.length && (part = parts.shift());) {\n    if (!parts.length && object !== undefined) {\n      if (!overwriteImplicit && goog.isObject(object) &&\n          goog.isObject(cur[part])) {\n        // Merge properties on object (the input parameter) with the existing\n        // implicitly defined namespace, so as to not clobber previously\n        // defined child namespaces.\n        for (var prop in object) {\n          if (object.hasOwnProperty(prop)) {\n            cur[part][prop] = object[prop];\n          }\n        }\n      } else {\n        // Either there is no existing implicit namespace, or overwriteImplicit\n        // is set to true, so directly assign object (the input parameter) to\n        // the namespace.\n        cur[part] = object;\n      }\n    } else if (cur[part] && cur[part] !== Object.prototype[part]) {\n      cur = cur[part];\n    } else {\n      cur = cur[part] = {};\n    }\n  }\n};\n\n\n/**\n * Defines a named value. In uncompiled mode, the value is retrieved from\n * CLOSURE_DEFINES or CLOSURE_UNCOMPILED_DEFINES if the object is defined and\n * has the property specified, and otherwise used the defined defaultValue.\n * When compiled the default can be overridden using the compiler options or the\n * value set in the CLOSURE_DEFINES object. Returns the defined value so that it\n * can be used safely in modules. Note that the value type MUST be either\n * boolean, number, or string.\n *\n * @param {string} name The distinguished name to provide.\n * @param {T} defaultValue\n * @return {T} The defined value.\n * @template T\n */\ngoog.define = function(name, defaultValue) {\n  var value = defaultValue;\n  if (!COMPILED) {\n    var uncompiledDefines = goog.global.CLOSURE_UNCOMPILED_DEFINES;\n    var defines = goog.global.CLOSURE_DEFINES;\n    if (uncompiledDefines &&\n        // Anti DOM-clobbering runtime check (b/37736576).\n        /** @type {?} */ (uncompiledDefines).nodeType === undefined &&\n        Object.prototype.hasOwnProperty.call(uncompiledDefines, name)) {\n      value = uncompiledDefines[name];\n    } else if (\n        defines &&\n        // Anti DOM-clobbering runtime check (b/37736576).\n        /** @type {?} */ (defines).nodeType === undefined &&\n        Object.prototype.hasOwnProperty.call(defines, name)) {\n      value = defines[name];\n    }\n  }\n  return value;\n};\n\n\n/**\n * @define {number} Integer year indicating the set of browser features that are\n * guaranteed to be present.  This is defined to include exactly features that\n * work correctly on all \"modern\" browsers that are stable on January 1 of the\n * specified year.  For example,\n * ```js\n * if (goog.FEATURESET_YEAR >= 2019) {\n *   // use APIs known to be available on all major stable browsers Jan 1, 2019\n * } else {\n *   // polyfill for older browsers\n * }\n * ```\n * This is intended to be the primary define for removing\n * unnecessary browser compatibility code (such as ponyfills and workarounds),\n * and should inform the default value for most other defines:\n * ```js\n * const ASSUME_NATIVE_PROMISE =\n *     goog.define('ASSUME_NATIVE_PROMISE', goog.FEATURESET_YEAR >= 2016);\n * ```\n *\n * The default assumption is that IE9 is the lowest supported browser, which was\n * first available Jan 1, 2012.\n *\n * TODO(user): Reference more thorough documentation when it's available.\n */\ngoog.FEATURESET_YEAR = goog.define('goog.FEATURESET_YEAR', 2012);\n\n\n/**\n * @define {boolean} DEBUG is provided as a convenience so that debugging code\n * that should not be included in a production. It can be easily stripped\n * by specifying --define goog.DEBUG=false to the Closure Compiler aka\n * JSCompiler. For example, most toString() methods should be declared inside an\n * \"if (goog.DEBUG)\" conditional because they are generally used for debugging\n * purposes and it is difficult for the JSCompiler to statically determine\n * whether they are used.\n */\ngoog.DEBUG = goog.define('goog.DEBUG', true);\n\n\n/**\n * @define {string} LOCALE defines the locale being used for compilation. It is\n * used to select locale specific data to be compiled in js binary. BUILD rule\n * can specify this value by \"--define goog.LOCALE=<locale_name>\" as a compiler\n * option.\n *\n * Take into account that the locale code format is important. You should use\n * the canonical Unicode format with hyphen as a delimiter. Language must be\n * lowercase, Language Script - Capitalized, Region - UPPERCASE.\n * There are few examples: pt-BR, en, en-US, sr-Latin-BO, zh-Hans-CN.\n *\n * See more info about locale codes here:\n * http://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers\n *\n * For language codes you should use values defined by ISO 693-1. See it here\n * http://www.w3.org/WAI/ER/IG/ert/iso639.htm. There is only one exception from\n * this rule: the Hebrew language. For legacy reasons the old code (iw) should\n * be used instead of the new code (he).\n *\n */\ngoog.LOCALE = goog.define('goog.LOCALE', 'en');  // default to en\n\n\n/**\n * This method is intended to be used for bookkeeping purposes.  We would\n * like to distinguish uses of goog.LOCALE used for code stripping purposes\n * and uses of goog.LOCALE for other uses (such as URL parameters).\n *\n * This allows us to ban direct uses of goog.LOCALE and to ensure that all\n * code has been transformed to our new localization build scheme.\n *\n * @return {string}\n *\n */\ngoog.getLocale = function() {\n  return goog.LOCALE;\n};\n\n\n/**\n * @define {boolean} Whether this code is running on trusted sites.\n *\n * On untrusted sites, several native functions can be defined or overridden by\n * external libraries like Prototype, Datejs, and JQuery and setting this flag\n * to false forces closure to use its own implementations when possible.\n *\n * If your JavaScript can be loaded by a third party site and you are wary about\n * relying on non-standard implementations, specify\n * \"--define goog.TRUSTED_SITE=false\" to the compiler.\n */\ngoog.TRUSTED_SITE = goog.define('goog.TRUSTED_SITE', true);\n\n\n/**\n * @define {boolean} Whether code that calls {@link goog.setTestOnly} should\n *     be disallowed in the compilation unit.\n */\ngoog.DISALLOW_TEST_ONLY_CODE =\n    goog.define('goog.DISALLOW_TEST_ONLY_CODE', COMPILED && !goog.DEBUG);\n\n\n/**\n * @define {boolean} Whether to use a Chrome app CSP-compliant method for\n *     loading scripts via goog.require. @see appendScriptSrcNode_.\n */\ngoog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING =\n    goog.define('goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING', false);\n\n\n/**\n * Defines a namespace in Closure.\n *\n * A namespace may only be defined once in a codebase. It may be defined using\n * goog.provide() or goog.module().\n *\n * The presence of one or more goog.provide() calls in a file indicates\n * that the file defines the given objects/namespaces.\n * Provided symbols must not be null or undefined.\n *\n * In addition, goog.provide() creates the object stubs for a namespace\n * (for example, goog.provide(\"goog.foo.bar\") will create the object\n * goog.foo.bar if it does not already exist).\n *\n * Build tools also scan for provide/require/module statements\n * to discern dependencies, build dependency files (see deps.js), etc.\n *\n * @see goog.require\n * @see goog.module\n * @param {string} name Namespace provided by this file in the form\n *     \"goog.package.part\".\n * deprecated Use goog.module (see b/159289405)\n */\ngoog.provide = function(name) {\n  if (goog.isInModuleLoader_()) {\n    throw new Error('goog.provide cannot be used within a module.');\n  }\n  if (!COMPILED) {\n    // Ensure that the same namespace isn't provided twice.\n    // A goog.module/goog.provide maps a goog.require to a specific file\n    if (goog.isProvided_(name)) {\n      throw new Error('Namespace \"' + name + '\" already declared.');\n    }\n  }\n\n  goog.constructNamespace_(name);\n};\n\n\n/**\n * @param {string} name Namespace provided by this file in the form\n *     \"goog.package.part\".\n * @param {?Object=} object The object to embed in the namespace.\n * @param {boolean=} overwriteImplicit If object is set and a previous call\n *     implicitly constructed the namespace given by name, this parameter\n *     controls whether opt_obj should overwrite the implicitly constructed\n *     namespace or be merged into it. Defaults to false.\n * @private\n */\ngoog.constructNamespace_ = function(name, object, overwriteImplicit) {\n  if (!COMPILED) {\n    delete goog.implicitNamespaces_[name];\n\n    var namespace = name;\n    while ((namespace = namespace.substring(0, namespace.lastIndexOf('.')))) {\n      if (goog.getObjectByName(namespace)) {\n        break;\n      }\n      goog.implicitNamespaces_[namespace] = true;\n    }\n  }\n\n  goog.exportPath_(name, object, overwriteImplicit);\n};\n\n\n/**\n * According to the CSP3 spec a nonce must be a valid base64 string.\n * @see https://www.w3.org/TR/CSP3/#grammardef-base64-value\n * @private @const\n */\ngoog.NONCE_PATTERN_ = /^[\\w+/_-]+[=]{0,2}$/;\n\n\n/**\n * Returns CSP nonce, if set for any script tag.\n * @param {?Window=} opt_window The window context used to retrieve the nonce.\n *     Defaults to global context.\n * @return {string} CSP nonce or empty string if no nonce is present.\n * @private\n */\ngoog.getScriptNonce_ = function(opt_window) {\n  var doc = (opt_window || goog.global).document;\n  var script = doc.querySelector && doc.querySelector('script[nonce]');\n  if (script) {\n    // Try to get the nonce from the IDL property first, because browsers that\n    // implement additional nonce protection features (currently only Chrome) to\n    // prevent nonce stealing via CSS do not expose the nonce via attributes.\n    // See https://github.com/whatwg/html/issues/2369\n    var nonce = script['nonce'] || script.getAttribute('nonce');\n    if (nonce && goog.NONCE_PATTERN_.test(nonce)) {\n      return nonce;\n    }\n  }\n  return '';\n};\n\n\n/**\n * Module identifier validation regexp.\n * Note: This is a conservative check, it is very possible to be more lenient,\n *   the primary exclusion here is \"/\" and \"\\\" and a leading \".\", these\n *   restrictions are intended to leave the door open for using goog.require\n *   with relative file paths rather than module identifiers.\n * @private\n */\ngoog.VALID_MODULE_RE_ = /^[a-zA-Z_$][a-zA-Z0-9._$]*$/;\n\n\n/**\n * Defines a module in Closure.\n *\n * Marks that this file must be loaded as a module and claims the namespace.\n *\n * A namespace may only be defined once in a codebase. It may be defined using\n * goog.provide() or goog.module().\n *\n * goog.module() has three requirements:\n * - goog.module may not be used in the same file as goog.provide.\n * - goog.module must be the first statement in the file.\n * - only one goog.module is allowed per file.\n *\n * When a goog.module annotated file is loaded, it is enclosed in\n * a strict function closure. This means that:\n * - any variables declared in a goog.module file are private to the file\n * (not global), though the compiler is expected to inline the module.\n * - The code must obey all the rules of \"strict\" JavaScript.\n * - the file will be marked as \"use strict\"\n *\n * NOTE: unlike goog.provide, goog.module does not declare any symbols by\n * itself. If declared symbols are desired, use\n * goog.module.declareLegacyNamespace().\n *\n *\n * See the public goog.module proposal: http://goo.gl/Va1hin\n *\n * @param {string} name Namespace provided by this file in the form\n *     \"goog.package.part\", is expected but not required.\n * @return {void}\n */\ngoog.module = function(name) {\n  if (typeof name !== 'string' || !name ||\n      name.search(goog.VALID_MODULE_RE_) == -1) {\n    throw new Error('Invalid module identifier');\n  }\n  if (!goog.isInGoogModuleLoader_()) {\n    throw new Error(\n        'Module ' + name + ' has been loaded incorrectly. Note, ' +\n        'modules cannot be loaded as normal scripts. They require some kind of ' +\n        'pre-processing step. You\\'re likely trying to load a module via a ' +\n        'script tag or as a part of a concatenated bundle without rewriting the ' +\n        'module. For more info see: ' +\n        'https://github.com/google/closure-library/wiki/goog.module:-an-ES6-module-like-alternative-to-goog.provide.');\n  }\n  if (goog.moduleLoaderState_.moduleName) {\n    throw new Error('goog.module may only be called once per module.');\n  }\n\n  // Store the module name for the loader.\n  goog.moduleLoaderState_.moduleName = name;\n  if (!COMPILED) {\n    // Ensure that the same namespace isn't provided twice.\n    // A goog.module/goog.provide maps a goog.require to a specific file\n    if (goog.isProvided_(name)) {\n      throw new Error('Namespace \"' + name + '\" already declared.');\n    }\n    delete goog.implicitNamespaces_[name];\n  }\n};\n\n\n/**\n * @param {string} name The module identifier.\n * @return {?} The module exports for an already loaded module or null.\n *\n * Note: This is not an alternative to goog.require, it does not\n * indicate a hard dependency, instead it is used to indicate\n * an optional dependency or to access the exports of a module\n * that has already been loaded.\n * @suppress {missingProvide}\n */\ngoog.module.get = function(name) {\n  return goog.module.getInternal_(name);\n};\n\n\n/**\n * @param {string} name The module identifier.\n * @return {?} The module exports for an already loaded module or null.\n * @private\n */\ngoog.module.getInternal_ = function(name) {\n  if (!COMPILED) {\n    if (name in goog.loadedModules_) {\n      return goog.loadedModules_[name].exports;\n    } else if (!goog.implicitNamespaces_[name]) {\n      var ns = goog.getObjectByName(name);\n      return ns != null ? ns : null;\n    }\n  }\n  return null;\n};\n\n\n/**\n * Types of modules the debug loader can load.\n * @enum {string}\n */\ngoog.ModuleType = {\n  ES6: 'es6',\n  GOOG: 'goog'\n};\n\n\n/**\n * @private {?{\n *   moduleName: (string|undefined),\n *   declareLegacyNamespace:boolean,\n *   type: ?goog.ModuleType\n * }}\n */\ngoog.moduleLoaderState_ = null;\n\n\n/**\n * @private\n * @return {boolean} Whether a goog.module or an es6 module is currently being\n *     initialized.\n */\ngoog.isInModuleLoader_ = function() {\n  return goog.isInGoogModuleLoader_() || goog.isInEs6ModuleLoader_();\n};\n\n\n/**\n * @private\n * @return {boolean} Whether a goog.module is currently being initialized.\n */\ngoog.isInGoogModuleLoader_ = function() {\n  return !!goog.moduleLoaderState_ &&\n      goog.moduleLoaderState_.type == goog.ModuleType.GOOG;\n};\n\n\n/**\n * @private\n * @return {boolean} Whether an es6 module is currently being initialized.\n */\ngoog.isInEs6ModuleLoader_ = function() {\n  var inLoader = !!goog.moduleLoaderState_ &&\n      goog.moduleLoaderState_.type == goog.ModuleType.ES6;\n\n  if (inLoader) {\n    return true;\n  }\n\n  var jscomp = goog.global['$jscomp'];\n\n  if (jscomp) {\n    // jscomp may not have getCurrentModulePath if this is a compiled bundle\n    // that has some of the runtime, but not all of it. This can happen if\n    // optimizations are turned on so the unused runtime is removed but renaming\n    // and Closure pass are off (so $jscomp is still named $jscomp and the\n    // goog.provide/require calls still exist).\n    if (typeof jscomp.getCurrentModulePath != 'function') {\n      return false;\n    }\n\n    // Bundled ES6 module.\n    return !!jscomp.getCurrentModulePath();\n  }\n\n  return false;\n};\n\n\n/**\n * Provide the module's exports as a globally accessible object under the\n * module's declared name.  This is intended to ease migration to goog.module\n * for files that have existing usages.\n * @suppress {missingProvide}\n */\ngoog.module.declareLegacyNamespace = function() {\n  if (!COMPILED && !goog.isInGoogModuleLoader_()) {\n    throw new Error(\n        'goog.module.declareLegacyNamespace must be called from ' +\n        'within a goog.module');\n  }\n  if (!COMPILED && !goog.moduleLoaderState_.moduleName) {\n    throw new Error(\n        'goog.module must be called prior to ' +\n        'goog.module.declareLegacyNamespace.');\n  }\n  goog.moduleLoaderState_.declareLegacyNamespace = true;\n};\n\n\n/**\n * Associates an ES6 module with a Closure module ID so that is available via\n * goog.require. The associated ID  acts like a goog.module ID - it does not\n * create any global names, it is merely available via goog.require /\n * goog.module.get / goog.forwardDeclare / goog.requireType. goog.require and\n * goog.module.get will return the entire module as if it was import *'d. This\n * allows Closure files to reference ES6 modules for the sake of migration.\n *\n * @param {string} namespace\n * @suppress {missingProvide}\n */\ngoog.declareModuleId = function(namespace) {\n  if (!COMPILED) {\n    if (!goog.isInEs6ModuleLoader_()) {\n      throw new Error(\n          'goog.declareModuleId may only be called from ' +\n          'within an ES6 module');\n    }\n    if (goog.moduleLoaderState_ && goog.moduleLoaderState_.moduleName) {\n      throw new Error(\n          'goog.declareModuleId may only be called once per module.');\n    }\n    if (namespace in goog.loadedModules_) {\n      throw new Error(\n          'Module with namespace \"' + namespace + '\" already exists.');\n    }\n  }\n  if (goog.moduleLoaderState_) {\n    // Not bundled - debug loading.\n    goog.moduleLoaderState_.moduleName = namespace;\n  } else {\n    // Bundled - not debug loading, no module loader state.\n    var jscomp = goog.global['$jscomp'];\n    if (!jscomp || typeof jscomp.getCurrentModulePath != 'function') {\n      throw new Error(\n          'Module with namespace \"' + namespace +\n          '\" has been loaded incorrectly.');\n    }\n    var exports = jscomp.require(jscomp.getCurrentModulePath());\n    goog.loadedModules_[namespace] = {\n      exports: exports,\n      type: goog.ModuleType.ES6,\n      moduleId: namespace\n    };\n  }\n};\n\n\n/**\n * Marks that the current file should only be used for testing, and never for\n * live code in production.\n *\n * In the case of unit tests, the message may optionally be an exact namespace\n * for the test (e.g. 'goog.stringTest'). The linter will then ignore the extra\n * provide (if not explicitly defined in the code).\n *\n * @param {string=} opt_message Optional message to add to the error that's\n *     raised when used in production code.\n */\ngoog.setTestOnly = function(opt_message) {\n  if (goog.DISALLOW_TEST_ONLY_CODE) {\n    opt_message = opt_message || '';\n    throw new Error(\n        'Importing test-only code into non-debug environment' +\n        (opt_message ? ': ' + opt_message : '.'));\n  }\n};\n\n\n/**\n * Forward declares a symbol. This is an indication to the compiler that the\n * symbol may be used in the source yet is not required and may not be provided\n * in compilation.\n *\n * The most common usage of forward declaration is code that takes a type as a\n * function parameter but does not need to require it. By forward declaring\n * instead of requiring, no hard dependency is made, and (if not required\n * elsewhere) the namespace may never be required and thus, not be pulled\n * into the JavaScript binary. If it is required elsewhere, it will be type\n * checked as normal.\n *\n * Before using goog.forwardDeclare, please read the documentation at\n * https://github.com/google/closure-compiler/wiki/Bad-Type-Annotation to\n * understand the options and tradeoffs when working with forward declarations.\n *\n * @param {string} name The namespace to forward declare in the form of\n *     \"goog.package.part\".\n * @deprecated See go/noforwarddeclaration, Use `goog.requireType` instead.\n */\ngoog.forwardDeclare = function(name) {};\n\n\n/**\n * Forward declare type information. Used to assign types to goog.global\n * referenced object that would otherwise result in unknown type references\n * and thus block property disambiguation.\n */\ngoog.forwardDeclare('Document');\ngoog.forwardDeclare('HTMLScriptElement');\ngoog.forwardDeclare('XMLHttpRequest');\n\n\nif (!COMPILED) {\n  /**\n   * Check if the given name has been goog.provided. This will return false for\n   * names that are available only as implicit namespaces.\n   * @param {string} name name of the object to look for.\n   * @return {boolean} Whether the name has been provided.\n   * @private\n   */\n  goog.isProvided_ = function(name) {\n    return (name in goog.loadedModules_) ||\n        (!goog.implicitNamespaces_[name] && goog.getObjectByName(name) != null);\n  };\n\n  /**\n   * Namespaces implicitly defined by goog.provide. For example,\n   * goog.provide('goog.events.Event') implicitly declares that 'goog' and\n   * 'goog.events' must be namespaces.\n   *\n   * @type {!Object<string, (boolean|undefined)>}\n   * @private\n   */\n  goog.implicitNamespaces_ = {'goog.module': true};\n\n  // NOTE: We add goog.module as an implicit namespace as goog.module is defined\n  // here and because the existing module package has not been moved yet out of\n  // the goog.module namespace. This satisifies both the debug loader and\n  // ahead-of-time dependency management.\n}\n\n\n/**\n * Returns an object based on its fully qualified external name.  The object\n * is not found if null or undefined.  If you are using a compilation pass that\n * renames property names beware that using this function will not find renamed\n * properties.\n *\n * @param {string} name The fully qualified name.\n * @param {Object=} opt_obj The object within which to look; default is\n *     |goog.global|.\n * @return {?} The value (object or primitive) or, if not found, null.\n */\ngoog.getObjectByName = function(name, opt_obj) {\n  var parts = name.split('.');\n  var cur = opt_obj || goog.global;\n  for (var i = 0; i < parts.length; i++) {\n    cur = cur[parts[i]];\n    if (cur == null) {\n      return null;\n    }\n  }\n  return cur;\n};\n\n\n/**\n * Adds a dependency from a file to the files it requires.\n * @param {string} relPath The path to the js file.\n * @param {!Array<string>} provides An array of strings with\n *     the names of the objects this file provides.\n * @param {!Array<string>} requires An array of strings with\n *     the names of the objects this file requires.\n * @param {boolean|!Object<string>=} opt_loadFlags Parameters indicating\n *     how the file must be loaded.  The boolean 'true' is equivalent\n *     to {'module': 'goog'} for backwards-compatibility.  Valid properties\n *     and values include {'module': 'goog'} and {'lang': 'es6'}.\n */\ngoog.addDependency = function(relPath, provides, requires, opt_loadFlags) {\n  if (!COMPILED && goog.DEPENDENCIES_ENABLED) {\n    goog.debugLoader_.addDependency(relPath, provides, requires, opt_loadFlags);\n  }\n};\n\n\n// NOTE(nnaze): The debug DOM loader was included in base.js as an original way\n// to do \"debug-mode\" development.  The dependency system can sometimes be\n// confusing, as can the debug DOM loader's asynchronous nature.\n//\n// With the DOM loader, a call to goog.require() is not blocking -- the script\n// will not load until some point after the current script.  If a namespace is\n// needed at runtime, it needs to be defined in a previous script, or loaded via\n// require() with its registered dependencies.\n//\n// User-defined namespaces may need their own deps file. For a reference on\n// creating a deps file, see:\n// Externally: https://developers.google.com/closure/library/docs/depswriter\n//\n// Because of legacy clients, the DOM loader can't be easily removed from\n// base.js.  Work was done to make it disableable or replaceable for\n// different environments (DOM-less JavaScript interpreters like Rhino or V8,\n// for example). See bootstrap/ for more information.\n\n\n/**\n * @define {boolean} Whether to enable the debug loader.\n *\n * If enabled, a call to goog.require() will attempt to load the namespace by\n * appending a script tag to the DOM (if the namespace has been registered).\n *\n * If disabled, goog.require() will simply assert that the namespace has been\n * provided (and depend on the fact that some outside tool correctly ordered\n * the script).\n */\ngoog.ENABLE_DEBUG_LOADER = goog.define('goog.ENABLE_DEBUG_LOADER', true);\n\n\n/**\n * @param {string} msg\n * @private\n */\ngoog.logToConsole_ = function(msg) {\n  if (goog.global.console) {\n    goog.global.console['error'](msg);\n  }\n};\n\n\n/**\n * Implements a system for the dynamic resolution of dependencies that works in\n * parallel with the BUILD system.\n *\n * Note that all calls to goog.require will be stripped by the compiler.\n *\n * @see goog.provide\n * @param {string} namespace Namespace (as was given in goog.provide,\n *     goog.module, or goog.declareModuleId) in the form\n *     \"goog.package.part\".\n * @return {?} If called within a goog.module or ES6 module file, the associated\n *     namespace or module otherwise null.\n */\ngoog.require = function(namespace) {\n  if (!COMPILED) {\n    // Might need to lazy load on old IE.\n    if (goog.ENABLE_DEBUG_LOADER) {\n      goog.debugLoader_.requested(namespace);\n    }\n\n    // If the object already exists we do not need to do anything.\n    if (goog.isProvided_(namespace)) {\n      if (goog.isInModuleLoader_()) {\n        return goog.module.getInternal_(namespace);\n      }\n    } else if (goog.ENABLE_DEBUG_LOADER) {\n      var moduleLoaderState = goog.moduleLoaderState_;\n      goog.moduleLoaderState_ = null;\n      try {\n        goog.debugLoader_.load_(namespace);\n      } finally {\n        goog.moduleLoaderState_ = moduleLoaderState;\n      }\n    }\n\n    return null;\n  }\n};\n\n\n/**\n * Requires a symbol for its type information. This is an indication to the\n * compiler that the symbol may appear in type annotations, yet it is not\n * referenced at runtime.\n *\n * When called within a goog.module or ES6 module file, the return value may be\n * assigned to or destructured into a variable, but it may not be otherwise used\n * in code outside of a type annotation.\n *\n * Note that all calls to goog.requireType will be stripped by the compiler.\n *\n * @param {string} namespace Namespace (as was given in goog.provide,\n *     goog.module, or goog.declareModuleId) in the form\n *     \"goog.package.part\".\n * @return {?}\n */\ngoog.requireType = function(namespace) {\n  // Return an empty object so that single-level destructuring of the return\n  // value doesn't crash at runtime when using the debug loader. Multi-level\n  // destructuring isn't supported.\n  return {};\n};\n\n\n/**\n * Path for included scripts.\n * @type {string}\n */\ngoog.basePath = '';\n\n\n/**\n * A hook for overriding the base path.\n * @type {string|undefined}\n */\ngoog.global.CLOSURE_BASE_PATH;\n\n\n/**\n * Whether to attempt to load Closure's deps file. By default, when uncompiled,\n * deps files will attempt to be loaded.\n * @type {boolean|undefined}\n */\ngoog.global.CLOSURE_NO_DEPS;\n\n\n/**\n * A function to import a single script. This is meant to be overridden when\n * Closure is being run in non-HTML contexts, such as web workers. It's defined\n * in the global scope so that it can be set before base.js is loaded, which\n * allows deps.js to be imported properly.\n *\n * The first parameter the script source, which is a relative URI. The second,\n * optional parameter is the script contents, in the event the script needed\n * transformation. It should return true if the script was imported, false\n * otherwise.\n * @type {(function(string, string=): boolean)|undefined}\n */\ngoog.global.CLOSURE_IMPORT_SCRIPT;\n\n\n/**\n * Null function used for default values of callbacks, etc.\n * @return {void} Nothing.\n * @deprecated use '()=>{}' or 'function(){}' instead.\n */\ngoog.nullFunction = function() {};\n\n\n/**\n * When defining a class Foo with an abstract method bar(), you can do:\n * Foo.prototype.bar = goog.abstractMethod\n *\n * Now if a subclass of Foo fails to override bar(), an error will be thrown\n * when bar() is invoked.\n *\n * @type {!Function}\n * @throws {Error} when invoked to indicate the method should be overridden.\n * @deprecated Use \"@abstract\" annotation instead of goog.abstractMethod in new\n *     code. See\n *     https://github.com/google/closure-compiler/wiki/@abstract-classes-and-methods\n */\ngoog.abstractMethod = function() {\n  throw new Error('unimplemented abstract method');\n};\n\n\n/**\n * Adds a `getInstance` static method that always returns the same\n * instance object.\n * @param {!Function} ctor The constructor for the class to add the static\n *     method to.\n * @suppress {missingProperties} 'instance_' isn't a property on 'Function'\n *     but we don't have a better type to use here.\n */\ngoog.addSingletonGetter = function(ctor) {\n  // instance_ is immediately set to prevent issues with sealed constructors\n  // such as are encountered when a constructor is returned as the export object\n  // of a goog.module in unoptimized code.\n  // Delcare type to avoid conformance violations that ctor.instance_ is unknown\n  /** @type {undefined|!Object} @suppress {underscore} */\n  ctor.instance_ = undefined;\n  ctor.getInstance = function() {\n    if (ctor.instance_) {\n      return ctor.instance_;\n    }\n    if (goog.DEBUG) {\n      // NOTE: JSCompiler can't optimize away Array#push.\n      goog.instantiatedSingletons_[goog.instantiatedSingletons_.length] = ctor;\n    }\n    // Cast to avoid conformance violations that ctor.instance_ is unknown\n    return /** @type {!Object|undefined} */ (ctor.instance_) = new ctor;\n  };\n};\n\n\n/**\n * All singleton classes that have been instantiated, for testing. Don't read\n * it directly, use the `goog.testing.singleton` module. The compiler\n * removes this variable if unused.\n * @type {!Array<!Function>}\n * @private\n */\ngoog.instantiatedSingletons_ = [];\n\n\n/**\n * @define {boolean} Whether to load goog.modules using `eval` when using\n * the debug loader.  This provides a better debugging experience as the\n * source is unmodified and can be edited using Chrome Workspaces or similar.\n * However in some environments the use of `eval` is banned\n * so we provide an alternative.\n */\ngoog.LOAD_MODULE_USING_EVAL = goog.define('goog.LOAD_MODULE_USING_EVAL', true);\n\n\n/**\n * @define {boolean} Whether the exports of goog.modules should be sealed when\n * possible.\n */\ngoog.SEAL_MODULE_EXPORTS = goog.define('goog.SEAL_MODULE_EXPORTS', goog.DEBUG);\n\n\n/**\n * The registry of initialized modules:\n * The module identifier or path to module exports map.\n * @private @const {!Object<string, {exports:?,type:string,moduleId:string}>}\n */\ngoog.loadedModules_ = {};\n\n\n/**\n * True if the debug loader enabled and used.\n * @const {boolean}\n */\ngoog.DEPENDENCIES_ENABLED = !COMPILED && goog.ENABLE_DEBUG_LOADER;\n\n\n/**\n * @define {string} How to decide whether to transpile.  Valid values\n * are 'always', 'never', and 'detect'.  The default ('detect') is to\n * use feature detection to determine which language levels need\n * transpilation.\n */\n// NOTE(sdh): we could expand this to accept a language level to bypass\n// detection: e.g. goog.TRANSPILE == 'es5' would transpile ES6 files but\n// would leave ES3 and ES5 files alone.\ngoog.TRANSPILE = goog.define('goog.TRANSPILE', 'detect');\n\n/**\n * @define {boolean} If true assume that ES modules have already been\n * transpiled by the jscompiler (in the same way that transpile.js would\n * transpile them - to jscomp modules). Useful only for servers that wish to use\n * the debug loader and transpile server side. Thus this is only respected if\n * goog.TRANSPILE is \"never\".\n */\ngoog.ASSUME_ES_MODULES_TRANSPILED =\n    goog.define('goog.ASSUME_ES_MODULES_TRANSPILED', false);\n\n\n/**\n * @define {string} If a file needs to be transpiled what the output language\n * should be. By default this is the highest language level this file detects\n * the current environment supports. Generally this flag should not be set, but\n * it could be useful to override. Example: If the current environment supports\n * ES6 then by default ES7+ files will be transpiled to ES6, unless this is\n * overridden.\n *\n * Valid values include: es3, es5, es6, es7, and es8. Anything not recognized\n * is treated as es3.\n *\n * Note that setting this value does not force transpilation. Just if\n * transpilation occurs this will be the output. So this is most useful when\n * goog.TRANSPILE is set to 'always' and then forcing the language level to be\n * something lower than what the environment detects.\n */\ngoog.TRANSPILE_TO_LANGUAGE = goog.define('goog.TRANSPILE_TO_LANGUAGE', '');\n\n\n/**\n * @define {string} Path to the transpiler.  Executing the script at this\n * path (relative to base.js) should define a function $jscomp.transpile.\n */\ngoog.TRANSPILER = goog.define('goog.TRANSPILER', 'transpile.js');\n\n\n/**\n * @define {string} Trusted Types policy name. If non-empty then Closure will\n * use Trusted Types.\n */\ngoog.TRUSTED_TYPES_POLICY_NAME =\n    goog.define('goog.TRUSTED_TYPES_POLICY_NAME', 'goog');\n\n\n/**\n * @package {?boolean}\n * Visible for testing.\n */\ngoog.hasBadLetScoping = null;\n\n\n/**\n * @param {function(?):?|string} moduleDef The module definition.\n */\ngoog.loadModule = function(moduleDef) {\n  // NOTE: we allow function definitions to be either in the from\n  // of a string to eval (which keeps the original source intact) or\n  // in a eval forbidden environment (CSP) we allow a function definition\n  // which in its body must call `goog.module`, and return the exports\n  // of the module.\n  var previousState = goog.moduleLoaderState_;\n  try {\n    goog.moduleLoaderState_ = {\n      moduleName: '',\n      declareLegacyNamespace: false,\n      type: goog.ModuleType.GOOG\n    };\n    var origExports = {};\n    var exports = origExports;\n    if (typeof moduleDef === 'function') {\n      exports = moduleDef.call(undefined, exports);\n    } else if (typeof moduleDef === 'string') {\n      exports = goog.loadModuleFromSource_.call(undefined, exports, moduleDef);\n    } else {\n      throw new Error('Invalid module definition');\n    }\n\n    var moduleName = goog.moduleLoaderState_.moduleName;\n    if (typeof moduleName === 'string' && moduleName) {\n      // Don't seal legacy namespaces as they may be used as a parent of\n      // another namespace\n      if (goog.moduleLoaderState_.declareLegacyNamespace) {\n        // Whether exports was overwritten via default export assignment.\n        // This is important for legacy namespaces as it dictates whether\n        // previously a previously loaded implicit namespace should be clobbered\n        // or not.\n        var isDefaultExport = origExports !== exports;\n        goog.constructNamespace_(moduleName, exports, isDefaultExport);\n      } else if (\n          goog.SEAL_MODULE_EXPORTS && Object.seal &&\n          typeof exports == 'object' && exports != null) {\n        Object.seal(exports);\n      }\n\n      var data = {\n        exports: exports,\n        type: goog.ModuleType.GOOG,\n        moduleId: goog.moduleLoaderState_.moduleName\n      };\n      goog.loadedModules_[moduleName] = data;\n    } else {\n      throw new Error('Invalid module name \\\"' + moduleName + '\\\"');\n    }\n  } finally {\n    goog.moduleLoaderState_ = previousState;\n  }\n};\n\n\n/**\n * @private @const\n */\ngoog.loadModuleFromSource_ =\n    /** @type {function(!Object, string):?} */ (function(exports) {\n      // NOTE: we avoid declaring parameters or local variables here to avoid\n      // masking globals or leaking values into the module definition.\n      'use strict';\n      eval(goog.CLOSURE_EVAL_PREFILTER_.createScript(arguments[1]));\n      return exports;\n    });\n\n\n/**\n * Normalize a file path by removing redundant \"..\" and extraneous \".\" file\n * path components.\n * @param {string} path\n * @return {string}\n * @private\n */\ngoog.normalizePath_ = function(path) {\n  var components = path.split('/');\n  var i = 0;\n  while (i < components.length) {\n    if (components[i] == '.') {\n      components.splice(i, 1);\n    } else if (\n        i && components[i] == '..' && components[i - 1] &&\n        components[i - 1] != '..') {\n      components.splice(--i, 2);\n    } else {\n      i++;\n    }\n  }\n  return components.join('/');\n};\n\n\n/**\n * Provides a hook for loading a file when using Closure's goog.require() API\n * with goog.modules.  In particular this hook is provided to support Node.js.\n *\n * @type {(function(string):string)|undefined}\n */\ngoog.global.CLOSURE_LOAD_FILE_SYNC;\n\n\n/**\n * Loads file by synchronous XHR. Should not be used in production environments.\n * @param {string} src Source URL.\n * @return {?string} File contents, or null if load failed.\n * @private\n */\ngoog.loadFileSync_ = function(src) {\n  if (goog.global.CLOSURE_LOAD_FILE_SYNC) {\n    return goog.global.CLOSURE_LOAD_FILE_SYNC(src);\n  } else {\n    try {\n      /** @type {XMLHttpRequest} */\n      var xhr = new goog.global['XMLHttpRequest']();\n      xhr.open('get', src, false);\n      xhr.send();\n      // NOTE: Successful http: requests have a status of 200, but successful\n      // file: requests may have a status of zero.  Any other status, or a\n      // thrown exception (particularly in case of file: requests) indicates\n      // some sort of error, which we treat as a missing or unavailable file.\n      return xhr.status == 0 || xhr.status == 200 ? xhr.responseText : null;\n    } catch (err) {\n      // No need to rethrow or log, since errors should show up on their own.\n      return null;\n    }\n  }\n};\n\n\n/**\n * Lazily retrieves the transpiler and applies it to the source.\n * @param {string} code JS code.\n * @param {string} path Path to the code.\n * @param {string} target Language level output.\n * @return {string} The transpiled code.\n * @private\n */\ngoog.transpile_ = function(code, path, target) {\n  var jscomp = goog.global['$jscomp'];\n  if (!jscomp) {\n    goog.global['$jscomp'] = jscomp = {};\n  }\n  var transpile = jscomp.transpile;\n  if (!transpile) {\n    var transpilerPath = goog.basePath + goog.TRANSPILER;\n    var transpilerCode = goog.loadFileSync_(transpilerPath);\n    if (transpilerCode) {\n      // This must be executed synchronously, since by the time we know we\n      // need it, we're about to load and write the ES6 code synchronously,\n      // so a normal script-tag load will be too slow. Wrapped in a function\n      // so that code is eval'd in the global scope.\n      (function() {\n        (0, eval)(transpilerCode + '\\n//# sourceURL=' + transpilerPath);\n      }).call(goog.global);\n      // Even though the transpiler is optional, if $gwtExport is found, it's\n      // a sign the transpiler was loaded and the $jscomp.transpile *should*\n      // be there.\n      if (goog.global['$gwtExport'] && goog.global['$gwtExport']['$jscomp'] &&\n          !goog.global['$gwtExport']['$jscomp']['transpile']) {\n        throw new Error(\n            'The transpiler did not properly export the \"transpile\" ' +\n            'method. $gwtExport: ' + JSON.stringify(goog.global['$gwtExport']));\n      }\n      // transpile.js only exports a single $jscomp function, transpile. We\n      // grab just that and add it to the existing definition of $jscomp which\n      // contains the polyfills.\n      goog.global['$jscomp'].transpile =\n          goog.global['$gwtExport']['$jscomp']['transpile'];\n      jscomp = goog.global['$jscomp'];\n      transpile = jscomp.transpile;\n    }\n  }\n  if (!transpile) {\n    // The transpiler is an optional component.  If it's not available then\n    // replace it with a pass-through function that simply logs.\n    var suffix = ' requires transpilation but no transpiler was found.';\n    transpile = jscomp.transpile = function(code, path) {\n      // TODO(sdh): figure out some way to get this error to show up\n      // in test results, noting that the failure may occur in many\n      // different ways, including in loadModule() before the test\n      // runner even comes up.\n      goog.logToConsole_(path + suffix);\n      return code;\n    };\n  }\n  // Note: any transpilation errors/warnings will be logged to the console.\n  return transpile(code, path, target);\n};\n\n//==============================================================================\n// Language Enhancements\n//==============================================================================\n\n\n/**\n * This is a \"fixed\" version of the typeof operator.  It differs from the typeof\n * operator in such a way that null returns 'null' and arrays return 'array'.\n * @param {?} value The value to get the type of.\n * @return {string} The name of the type.\n */\ngoog.typeOf = function(value) {\n  var s = typeof value;\n\n  if (s != 'object') {\n    return s;\n  }\n\n  if (!value) {\n    return 'null';\n  }\n\n  if (Array.isArray(value)) {\n    return 'array';\n  }\n  return s;\n};\n\n\n/**\n * Returns true if the object looks like an array. To qualify as array like\n * the value needs to be either a NodeList or an object with a Number length\n * property. Note that for this function neither strings nor functions are\n * considered \"array-like\".\n *\n * @param {?} val Variable to test.\n * @return {boolean} Whether variable is an array.\n */\ngoog.isArrayLike = function(val) {\n  var type = goog.typeOf(val);\n  // We do not use goog.isObject here in order to exclude function values.\n  return type == 'array' || type == 'object' && typeof val.length == 'number';\n};\n\n\n/**\n * Returns true if the object looks like a Date. To qualify as Date-like the\n * value needs to be an object and have a getFullYear() function.\n * @param {?} val Variable to test.\n * @return {boolean} Whether variable is a like a Date.\n */\ngoog.isDateLike = function(val) {\n  return goog.isObject(val) && typeof val.getFullYear == 'function';\n};\n\n\n/**\n * Returns true if the specified value is an object.  This includes arrays and\n * functions.\n * @param {?} val Variable to test.\n * @return {boolean} Whether variable is an object.\n */\ngoog.isObject = function(val) {\n  var type = typeof val;\n  return type == 'object' && val != null || type == 'function';\n  // return Object(val) === val also works, but is slower, especially if val is\n  // not an object.\n};\n\n\n/**\n * Gets a unique ID for an object. This mutates the object so that further calls\n * with the same object as a parameter returns the same value. The unique ID is\n * guaranteed to be unique across the current session amongst objects that are\n * passed into `getUid`. There is no guarantee that the ID is unique or\n * consistent across sessions. It is unsafe to generate unique ID for function\n * prototypes.\n *\n * @param {Object} obj The object to get the unique ID for.\n * @return {number} The unique ID for the object.\n */\ngoog.getUid = function(obj) {\n  // TODO(arv): Make the type stricter, do not accept null.\n  return Object.prototype.hasOwnProperty.call(obj, goog.UID_PROPERTY_) &&\n      obj[goog.UID_PROPERTY_] ||\n      (obj[goog.UID_PROPERTY_] = ++goog.uidCounter_);\n};\n\n\n/**\n * Whether the given object is already assigned a unique ID.\n *\n * This does not modify the object.\n *\n * @param {!Object} obj The object to check.\n * @return {boolean} Whether there is an assigned unique id for the object.\n */\ngoog.hasUid = function(obj) {\n  return !!obj[goog.UID_PROPERTY_];\n};\n\n\n/**\n * Removes the unique ID from an object. This is useful if the object was\n * previously mutated using `goog.getUid` in which case the mutation is\n * undone.\n * @param {Object} obj The object to remove the unique ID field from.\n */\ngoog.removeUid = function(obj) {\n  // TODO(arv): Make the type stricter, do not accept null.\n\n  // In IE, DOM nodes are not instances of Object and throw an exception if we\n  // try to delete.  Instead we try to use removeAttribute.\n  if (obj !== null && 'removeAttribute' in obj) {\n    obj.removeAttribute(goog.UID_PROPERTY_);\n  }\n\n  try {\n    delete obj[goog.UID_PROPERTY_];\n  } catch (ex) {\n  }\n};\n\n\n/**\n * Name for unique ID property. Initialized in a way to help avoid collisions\n * with other closure JavaScript on the same page.\n * @type {string}\n * @private\n */\ngoog.UID_PROPERTY_ = 'closure_uid_' + ((Math.random() * 1e9) >>> 0);\n\n\n/**\n * Counter for UID.\n * @type {number}\n * @private\n */\ngoog.uidCounter_ = 0;\n\n\n/**\n * Clones a value. The input may be an Object, Array, or basic type. Objects and\n * arrays will be cloned recursively.\n *\n * WARNINGS:\n * <code>goog.cloneObject</code> does not detect reference loops. Objects that\n * refer to themselves will cause infinite recursion.\n *\n * <code>goog.cloneObject</code> is unaware of unique identifiers, and copies\n * UIDs created by <code>getUid</code> into cloned results.\n *\n * @param {*} obj The value to clone.\n * @return {*} A clone of the input value.\n * @deprecated goog.cloneObject is unsafe. Prefer the goog.object methods.\n */\ngoog.cloneObject = function(obj) {\n  var type = goog.typeOf(obj);\n  if (type == 'object' || type == 'array') {\n    if (typeof obj.clone === 'function') {\n      return obj.clone();\n    }\n    if (typeof Map !== 'undefined' && obj instanceof Map) {\n      return new Map(obj);\n    } else if (typeof Set !== 'undefined' && obj instanceof Set) {\n      return new Set(obj);\n    }\n    var clone = type == 'array' ? [] : {};\n    for (var key in obj) {\n      clone[key] = goog.cloneObject(obj[key]);\n    }\n    return clone;\n  }\n\n  return obj;\n};\n\n\n/**\n * A native implementation of goog.bind.\n * @param {?function(this:T, ...)} fn A function to partially apply.\n * @param {T} selfObj Specifies the object which this should point to when the\n *     function is run.\n * @param {...*} var_args Additional arguments that are partially applied to the\n *     function.\n * @return {!Function} A partially-applied form of the function goog.bind() was\n *     invoked as a method of.\n * @template T\n * @private\n */\ngoog.bindNative_ = function(fn, selfObj, var_args) {\n  return /** @type {!Function} */ (fn.call.apply(fn.bind, arguments));\n};\n\n\n/**\n * A pure-JS implementation of goog.bind.\n * @param {?function(this:T, ...)} fn A function to partially apply.\n * @param {T} selfObj Specifies the object which this should point to when the\n *     function is run.\n * @param {...*} var_args Additional arguments that are partially applied to the\n *     function.\n * @return {!Function} A partially-applied form of the function goog.bind() was\n *     invoked as a method of.\n * @template T\n * @private\n */\ngoog.bindJs_ = function(fn, selfObj, var_args) {\n  if (!fn) {\n    throw new Error();\n  }\n\n  if (arguments.length > 2) {\n    var boundArgs = Array.prototype.slice.call(arguments, 2);\n    return function() {\n      // Prepend the bound arguments to the current arguments.\n      var newArgs = Array.prototype.slice.call(arguments);\n      Array.prototype.unshift.apply(newArgs, boundArgs);\n      return fn.apply(selfObj, newArgs);\n    };\n\n  } else {\n    return function() {\n      return fn.apply(selfObj, arguments);\n    };\n  }\n};\n\n\n/**\n * Partially applies this function to a particular 'this object' and zero or\n * more arguments. The result is a new function with some arguments of the first\n * function pre-filled and the value of this 'pre-specified'.\n *\n * Remaining arguments specified at call-time are appended to the pre-specified\n * ones.\n *\n * Also see: {@link #partial}.\n *\n * Usage:\n * <pre>var barMethBound = goog.bind(myFunction, myObj, 'arg1', 'arg2');\n * barMethBound('arg3', 'arg4');</pre>\n *\n * @param {?function(this:T, ...)} fn A function to partially apply.\n * @param {T} selfObj Specifies the object which this should point to when the\n *     function is run.\n * @param {...*} var_args Additional arguments that are partially applied to the\n *     function.\n * @return {!Function} A partially-applied form of the function goog.bind() was\n *     invoked as a method of.\n * @template T\n * @suppress {deprecated} See above.\n * @deprecated use `=> {}` or Function.prototype.bind instead.\n */\ngoog.bind = function(fn, selfObj, var_args) {\n  // TODO(nicksantos): narrow the type signature.\n  if (Function.prototype.bind &&\n      // NOTE(nicksantos): Somebody pulled base.js into the default Chrome\n      // extension environment. This means that for Chrome extensions, they get\n      // the implementation of Function.prototype.bind that calls goog.bind\n      // instead of the native one. Even worse, we don't want to introduce a\n      // circular dependency between goog.bind and Function.prototype.bind, so\n      // we have to hack this to make sure it works correctly.\n      Function.prototype.bind.toString().indexOf('native code') != -1) {\n    goog.bind = goog.bindNative_;\n  } else {\n    goog.bind = goog.bindJs_;\n  }\n  return goog.bind.apply(null, arguments);\n};\n\n\n/**\n * Like goog.bind(), except that a 'this object' is not required. Useful when\n * the target function is already bound.\n *\n * Usage:\n * var g = goog.partial(f, arg1, arg2);\n * g(arg3, arg4);\n *\n * @param {Function} fn A function to partially apply.\n * @param {...*} var_args Additional arguments that are partially applied to fn.\n * @return {!Function} A partially-applied form of the function goog.partial()\n *     was invoked as a method of.\n */\ngoog.partial = function(fn, var_args) {\n  var args = Array.prototype.slice.call(arguments, 1);\n  return function() {\n    // Clone the array (with slice()) and append additional arguments\n    // to the existing arguments.\n    var newArgs = args.slice();\n    newArgs.push.apply(newArgs, arguments);\n    return fn.apply(/** @type {?} */ (this), newArgs);\n  };\n};\n\n\n/**\n * Copies all the members of a source object to a target object. This method\n * does not work on all browsers for all objects that contain keys such as\n * toString or hasOwnProperty. Use goog.object.extend for this purpose.\n *\n * NOTE: Some have advocated for the use of goog.mixin to setup classes\n * with multiple inheritence (traits, mixins, etc).  However, as it simply\n * uses \"for in\", this is not compatible with ES6 classes whose methods are\n * non-enumerable.  Changing this, would break cases where non-enumerable\n * properties are not expected.\n *\n * @param {Object} target Target.\n * @param {Object} source Source.\n * @deprecated Prefer Object.assign\n */\ngoog.mixin = function(target, source) {\n  for (var x in source) {\n    target[x] = source[x];\n  }\n\n  // For IE7 or lower, the for-in-loop does not contain any properties that are\n  // not enumerable on the prototype object (for example, isPrototypeOf from\n  // Object.prototype) but also it will not include 'replace' on objects that\n  // extend String and change 'replace' (not that it is common for anyone to\n  // extend anything except Object).\n};\n\n\n/**\n * @return {number} An integer value representing the number of milliseconds\n *     between midnight, January 1, 1970 and the current time.\n * @deprecated Use Date.now\n */\ngoog.now = function() {\n  return Date.now();\n};\n\n\n/**\n * Evals JavaScript in the global scope.\n *\n * Throws an exception if neither execScript or eval is defined.\n * @param {string|!TrustedScript} script JavaScript string.\n */\ngoog.globalEval = function(script) {\n  (0, eval)(script);\n};\n\n\n/**\n * Optional map of CSS class names to obfuscated names used with\n * goog.getCssName().\n * @private {!Object<string, string>|undefined}\n * @see goog.setCssNameMapping\n */\ngoog.cssNameMapping_;\n\n\n/**\n * Optional obfuscation style for CSS class names. Should be set to either\n * 'BY_WHOLE' or 'BY_PART' if defined.\n * @type {string|undefined}\n * @private\n * @see goog.setCssNameMapping\n */\ngoog.cssNameMappingStyle_;\n\n\n\n/**\n * A hook for modifying the default behavior goog.getCssName. The function\n * if present, will receive the standard output of the goog.getCssName as\n * its input.\n *\n * @type {(function(string):string)|undefined}\n */\ngoog.global.CLOSURE_CSS_NAME_MAP_FN;\n\n\n/**\n * Handles strings that are intended to be used as CSS class names.\n *\n * This function works in tandem with @see goog.setCssNameMapping.\n *\n * Without any mapping set, the arguments are simple joined with a hyphen and\n * passed through unaltered.\n *\n * When there is a mapping, there are two possible styles in which these\n * mappings are used. In the BY_PART style, each part (i.e. in between hyphens)\n * of the passed in css name is rewritten according to the map. In the BY_WHOLE\n * style, the full css name is looked up in the map directly. If a rewrite is\n * not specified by the map, the compiler will output a warning.\n *\n * When the mapping is passed to the compiler, it will replace calls to\n * goog.getCssName with the strings from the mapping, e.g.\n *     var x = goog.getCssName('foo');\n *     var y = goog.getCssName(this.baseClass, 'active');\n *  becomes:\n *     var x = 'foo';\n *     var y = this.baseClass + '-active';\n *\n * If one argument is passed it will be processed, if two are passed only the\n * modifier will be processed, as it is assumed the first argument was generated\n * as a result of calling goog.getCssName.\n *\n * @param {string} className The class name.\n * @param {string=} opt_modifier A modifier to be appended to the class name.\n * @return {string} The class name or the concatenation of the class name and\n *     the modifier.\n */\ngoog.getCssName = function(className, opt_modifier) {\n  // String() is used for compatibility with compiled soy where the passed\n  // className can be non-string objects.\n  if (String(className).charAt(0) == '.') {\n    throw new Error(\n        'className passed in goog.getCssName must not start with \".\".' +\n        ' You passed: ' + className);\n  }\n\n  var getMapping = function(cssName) {\n    return goog.cssNameMapping_[cssName] || cssName;\n  };\n\n  var renameByParts = function(cssName) {\n    // Remap all the parts individually.\n    var parts = cssName.split('-');\n    var mapped = [];\n    for (var i = 0; i < parts.length; i++) {\n      mapped.push(getMapping(parts[i]));\n    }\n    return mapped.join('-');\n  };\n\n  var rename;\n  if (goog.cssNameMapping_) {\n    rename =\n        goog.cssNameMappingStyle_ == 'BY_WHOLE' ? getMapping : renameByParts;\n  } else {\n    rename = function(a) {\n      return a;\n    };\n  }\n\n  var result =\n      opt_modifier ? className + '-' + rename(opt_modifier) : rename(className);\n\n  // The special CLOSURE_CSS_NAME_MAP_FN allows users to specify further\n  // processing of the class name.\n  if (goog.global.CLOSURE_CSS_NAME_MAP_FN) {\n    return goog.global.CLOSURE_CSS_NAME_MAP_FN(result);\n  }\n\n  return result;\n};\n\n\n/**\n * Sets the map to check when returning a value from goog.getCssName(). Example:\n * <pre>\n * goog.setCssNameMapping({\n *   \"goog\": \"a\",\n *   \"disabled\": \"b\",\n * });\n *\n * var x = goog.getCssName('goog');\n * // The following evaluates to: \"a a-b\".\n * goog.getCssName('goog') + ' ' + goog.getCssName(x, 'disabled')\n * </pre>\n * When declared as a map of string literals to string literals, the JSCompiler\n * will replace all calls to goog.getCssName() using the supplied map if the\n * --process_closure_primitives flag is set.\n *\n * @param {!Object} mapping A map of strings to strings where keys are possible\n *     arguments to goog.getCssName() and values are the corresponding values\n *     that should be returned.\n * @param {string=} opt_style The style of css name mapping. There are two valid\n *     options: 'BY_PART', and 'BY_WHOLE'.\n * @see goog.getCssName for a description.\n */\ngoog.setCssNameMapping = function(mapping, opt_style) {\n  goog.cssNameMapping_ = mapping;\n  goog.cssNameMappingStyle_ = opt_style;\n};\n\n\n/**\n * To use CSS renaming in compiled mode, one of the input files should have a\n * call to goog.setCssNameMapping() with an object literal that the JSCompiler\n * can extract and use to replace all calls to goog.getCssName(). In uncompiled\n * mode, JavaScript code should be loaded before this base.js file that declares\n * a global variable, CLOSURE_CSS_NAME_MAPPING, which is used below. This is\n * to ensure that the mapping is loaded before any calls to goog.getCssName()\n * are made in uncompiled mode.\n *\n * A hook for overriding the CSS name mapping.\n * @type {!Object<string, string>|undefined}\n */\ngoog.global.CLOSURE_CSS_NAME_MAPPING;\n\n\nif (!COMPILED && goog.global.CLOSURE_CSS_NAME_MAPPING) {\n  // This does not call goog.setCssNameMapping() because the JSCompiler\n  // requires that goog.setCssNameMapping() be called with an object literal.\n  goog.cssNameMapping_ = goog.global.CLOSURE_CSS_NAME_MAPPING;\n}\n\n\n/**\n * Gets a localized message.\n *\n * This function is a compiler primitive. If you give the compiler a localized\n * message bundle, it will replace the string at compile-time with a localized\n * version, and expand goog.getMsg call to a concatenated string.\n *\n * Messages must be initialized in the form:\n * <code>\n * var MSG_NAME = goog.getMsg('Hello {$placeholder}', {'placeholder': 'world'});\n * </code>\n *\n * This function produces a string which should be treated as plain text. Use\n * {@link goog.html.SafeHtmlFormatter} in conjunction with goog.getMsg to\n * produce SafeHtml.\n *\n * @param {string} str Translatable string, places holders in the form {$foo}.\n * @param {Object<string, string>=} opt_values Maps place holder name to value.\n * @param {{html: (boolean|undefined),\n *         unescapeHtmlEntities: (boolean|undefined)}=} opt_options Options:\n *     html: Escape '<' in str to '&lt;'. Used by Closure Templates where the\n *     generated code size and performance is critical which is why {@link\n *     goog.html.SafeHtmlFormatter} is not used. The value must be literal true\n *     or false.\n *     unescapeHtmlEntities: Unescape common html entities: &gt;, &lt;, &apos;,\n *     &quot; and &amp;. Used for messages not in HTML context, such as with\n *     `textContent` property.\n * @return {string} message with placeholders filled.\n */\ngoog.getMsg = function(str, opt_values, opt_options) {\n  if (opt_options && opt_options.html) {\n    // Note that '&' is not replaced because the translation can contain HTML\n    // entities.\n    str = str.replace(/</g, '&lt;');\n  }\n  if (opt_options && opt_options.unescapeHtmlEntities) {\n    // Note that \"&amp;\" must be the last to avoid \"creating\" new entities.\n    str = str.replace(/&lt;/g, '<')\n              .replace(/&gt;/g, '>')\n              .replace(/&apos;/g, '\\'')\n              .replace(/&quot;/g, '\"')\n              .replace(/&amp;/g, '&');\n  }\n  if (opt_values) {\n    str = str.replace(/\\{\\$([^}]+)}/g, function(match, key) {\n      return (opt_values != null && key in opt_values) ? opt_values[key] :\n                                                         match;\n    });\n  }\n  return str;\n};\n\n\n/**\n * Gets a localized message. If the message does not have a translation, gives a\n * fallback message.\n *\n * This is useful when introducing a new message that has not yet been\n * translated into all languages.\n *\n * This function is a compiler primitive. Must be used in the form:\n * <code>var x = goog.getMsgWithFallback(MSG_A, MSG_B);</code>\n * where MSG_A and MSG_B were initialized with goog.getMsg.\n *\n * @param {string} a The preferred message.\n * @param {string} b The fallback message.\n * @return {string} The best translated message.\n */\ngoog.getMsgWithFallback = function(a, b) {\n  return a;\n};\n\n\n/**\n * Exposes an unobfuscated global namespace path for the given object.\n * Note that fields of the exported object *will* be obfuscated, unless they are\n * exported in turn via this function or goog.exportProperty.\n *\n * Also handy for making public items that are defined in anonymous closures.\n *\n * ex. goog.exportSymbol('public.path.Foo', Foo);\n *\n * ex. goog.exportSymbol('public.path.Foo.staticFunction', Foo.staticFunction);\n *     public.path.Foo.staticFunction();\n *\n * ex. goog.exportSymbol('public.path.Foo.prototype.myMethod',\n *                       Foo.prototype.myMethod);\n *     new public.path.Foo().myMethod();\n *\n * @param {string} publicPath Unobfuscated name to export.\n * @param {*} object Object the name should point to.\n * @param {?Object=} objectToExportTo The object to add the path to; default\n *     is goog.global.\n */\ngoog.exportSymbol = function(publicPath, object, objectToExportTo) {\n  goog.exportPath_(\n      publicPath, object, /* overwriteImplicit= */ true, objectToExportTo);\n};\n\n\n/**\n * Exports a property unobfuscated into the object's namespace.\n * ex. goog.exportProperty(Foo, 'staticFunction', Foo.staticFunction);\n * ex. goog.exportProperty(Foo.prototype, 'myMethod', Foo.prototype.myMethod);\n * @param {Object} object Object whose static property is being exported.\n * @param {string} publicName Unobfuscated name to export.\n * @param {*} symbol Object the name should point to.\n */\ngoog.exportProperty = function(object, publicName, symbol) {\n  object[publicName] = symbol;\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * Usage:\n * <pre>\n * function ParentClass(a, b) { }\n * ParentClass.prototype.foo = function(a) { };\n *\n * function ChildClass(a, b, c) {\n *   ChildClass.base(this, 'constructor', a, b);\n * }\n * goog.inherits(ChildClass, ParentClass);\n *\n * var child = new ChildClass('a', 'b', 'see');\n * child.foo(); // This works.\n * </pre>\n *\n * @param {!Function} childCtor Child class.\n * @param {!Function} parentCtor Parent class.\n * @suppress {strictMissingProperties} superClass_ and base is not defined on\n *    Function.\n * @deprecated Use ECMAScript class syntax instead.\n */\ngoog.inherits = function(childCtor, parentCtor) {\n  /** @constructor */\n  function tempCtor() {}\n  tempCtor.prototype = parentCtor.prototype;\n  childCtor.superClass_ = parentCtor.prototype;\n  childCtor.prototype = new tempCtor();\n  /** @override */\n  childCtor.prototype.constructor = childCtor;\n\n  /**\n   * Calls superclass constructor/method.\n   *\n   * This function is only available if you use goog.inherits to\n   * express inheritance relationships between classes.\n   *\n   * NOTE: This is a replacement for goog.base and for superClass_\n   * property defined in childCtor.\n   *\n   * @param {!Object} me Should always be \"this\".\n   * @param {string} methodName The method name to call. Calling\n   *     superclass constructor can be done with the special string\n   *     'constructor'.\n   * @param {...*} var_args The arguments to pass to superclass\n   *     method/constructor.\n   * @return {*} The return value of the superclass method/constructor.\n   */\n  childCtor.base = function(me, methodName, var_args) {\n    // Copying using loop to avoid deop due to passing arguments object to\n    // function. This is faster in many JS engines as of late 2014.\n    var args = new Array(arguments.length - 2);\n    for (var i = 2; i < arguments.length; i++) {\n      args[i - 2] = arguments[i];\n    }\n    return parentCtor.prototype[methodName].apply(me, args);\n  };\n};\n\n\n/**\n * Allow for aliasing within scope functions.  This function exists for\n * uncompiled code - in compiled code the calls will be inlined and the aliases\n * applied.  In uncompiled code the function is simply run since the aliases as\n * written are valid JavaScript.\n *\n *\n * @param {function()} fn Function to call.  This function can contain aliases\n *     to namespaces (e.g. \"var dom = goog.dom\") or classes\n *     (e.g. \"var Timer = goog.Timer\").\n * @deprecated Use goog.module instead.\n */\ngoog.scope = function(fn) {\n  if (goog.isInModuleLoader_()) {\n    throw new Error('goog.scope is not supported within a module.');\n  }\n  fn.call(goog.global);\n};\n\n\n/*\n * To support uncompiled, strict mode bundles that use eval to divide source\n * like so:\n *    eval('someSource;//# sourceUrl sourcefile.js');\n * We need to export the globally defined symbols \"goog\" and \"COMPILED\".\n * Exporting \"goog\" breaks the compiler optimizations, so we required that\n * be defined externally.\n * NOTE: We don't use goog.exportSymbol here because we don't want to trigger\n * extern generation when that compiler option is enabled.\n */\nif (!COMPILED) {\n  goog.global['COMPILED'] = COMPILED;\n}\n\n\n//==============================================================================\n// goog.defineClass implementation\n//==============================================================================\n\n\n/**\n * Creates a restricted form of a Closure \"class\":\n *   - from the compiler's perspective, the instance returned from the\n *     constructor is sealed (no new properties may be added).  This enables\n *     better checks.\n *   - the compiler will rewrite this definition to a form that is optimal\n *     for type checking and optimization (initially this will be a more\n *     traditional form).\n *\n * @param {Function} superClass The superclass, Object or null.\n * @param {goog.defineClass.ClassDescriptor} def\n *     An object literal describing\n *     the class.  It may have the following properties:\n *     \"constructor\": the constructor function\n *     \"statics\": an object literal containing methods to add to the constructor\n *        as \"static\" methods or a function that will receive the constructor\n *        function as its only parameter to which static properties can\n *        be added.\n *     all other properties are added to the prototype.\n * @return {!Function} The class constructor.\n * @deprecated Use ECMAScript class syntax instead.\n */\ngoog.defineClass = function(superClass, def) {\n  // TODO(johnlenz): consider making the superClass an optional parameter.\n  var constructor = def.constructor;\n  var statics = def.statics;\n  // Wrap the constructor prior to setting up the prototype and static methods.\n  if (!constructor || constructor == Object.prototype.constructor) {\n    constructor = function() {\n      throw new Error(\n          'cannot instantiate an interface (no constructor defined).');\n    };\n  }\n\n  var cls = goog.defineClass.createSealingConstructor_(constructor, superClass);\n  if (superClass) {\n    goog.inherits(cls, superClass);\n  }\n\n  // Remove all the properties that should not be copied to the prototype.\n  delete def.constructor;\n  delete def.statics;\n\n  goog.defineClass.applyProperties_(cls.prototype, def);\n  if (statics != null) {\n    if (statics instanceof Function) {\n      statics(cls);\n    } else {\n      goog.defineClass.applyProperties_(cls, statics);\n    }\n  }\n\n  return cls;\n};\n\n\n/**\n * @typedef {{\n *   constructor: (!Function|undefined),\n *   statics: (Object|undefined|function(Function):void)\n * }}\n */\ngoog.defineClass.ClassDescriptor;\n\n\n/**\n * @define {boolean} Whether the instances returned by goog.defineClass should\n *     be sealed when possible.\n *\n * When sealing is disabled the constructor function will not be wrapped by\n * goog.defineClass, making it incompatible with ES6 class methods.\n */\ngoog.defineClass.SEAL_CLASS_INSTANCES =\n    goog.define('goog.defineClass.SEAL_CLASS_INSTANCES', goog.DEBUG);\n\n\n/**\n * If goog.defineClass.SEAL_CLASS_INSTANCES is enabled and Object.seal is\n * defined, this function will wrap the constructor in a function that seals the\n * results of the provided constructor function.\n *\n * @param {!Function} ctr The constructor whose results maybe be sealed.\n * @param {Function} superClass The superclass constructor.\n * @return {!Function} The replacement constructor.\n * @private\n */\ngoog.defineClass.createSealingConstructor_ = function(ctr, superClass) {\n  if (!goog.defineClass.SEAL_CLASS_INSTANCES) {\n    // Do now wrap the constructor when sealing is disabled. Angular code\n    // depends on this for injection to work properly.\n    return ctr;\n  }\n\n  // NOTE: The sealing behavior has been removed\n\n  /**\n   * @this {Object}\n   * @return {?}\n   */\n  var wrappedCtr = function() {\n    // Don't seal an instance of a subclass when it calls the constructor of\n    // its super class as there is most likely still setup to do.\n    var instance = ctr.apply(this, arguments) || this;\n    instance[goog.UID_PROPERTY_] = instance[goog.UID_PROPERTY_];\n\n    return instance;\n  };\n\n  return wrappedCtr;\n};\n\n\n\n// TODO(johnlenz): share these values with the goog.object\n/**\n * The names of the fields that are defined on Object.prototype.\n * @type {!Array<string>}\n * @private\n * @const\n */\ngoog.defineClass.OBJECT_PROTOTYPE_FIELDS_ = [\n  'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',\n  'toLocaleString', 'toString', 'valueOf'\n];\n\n\n// TODO(johnlenz): share this function with the goog.object\n/**\n * @param {!Object} target The object to add properties to.\n * @param {!Object} source The object to copy properties from.\n * @private\n */\ngoog.defineClass.applyProperties_ = function(target, source) {\n  // TODO(johnlenz): update this to support ES5 getters/setters\n\n  var key;\n  for (key in source) {\n    if (Object.prototype.hasOwnProperty.call(source, key)) {\n      target[key] = source[key];\n    }\n  }\n\n  // For IE the for-in-loop does not contain any properties that are not\n  // enumerable on the prototype object (for example isPrototypeOf from\n  // Object.prototype) and it will also not include 'replace' on objects that\n  // extend String and change 'replace' (not that it is common for anyone to\n  // extend anything except Object).\n  for (var i = 0; i < goog.defineClass.OBJECT_PROTOTYPE_FIELDS_.length; i++) {\n    key = goog.defineClass.OBJECT_PROTOTYPE_FIELDS_[i];\n    if (Object.prototype.hasOwnProperty.call(source, key)) {\n      target[key] = source[key];\n    }\n  }\n};\n\n/**\n * Returns the parameter.\n * @param {string} s\n * @return {string}\n * @private\n */\ngoog.identity_ = function(s) {\n  return s;\n};\n\n\n/**\n * Creates Trusted Types policy if Trusted Types are supported by the browser.\n * The policy just blesses any string as a Trusted Type. It is not visibility\n * restricted because anyone can also call trustedTypes.createPolicy directly.\n * However, the allowed names should be restricted by a HTTP header and the\n * reference to the created policy should be visibility restricted.\n * @param {string} name\n * @return {?TrustedTypePolicy}\n */\ngoog.createTrustedTypesPolicy = function(name) {\n  var policy = null;\n  var policyFactory = goog.global.trustedTypes;\n  if (!policyFactory || !policyFactory.createPolicy) {\n    return policy;\n  }\n  // trustedTypes.createPolicy throws if called with a name that is already\n  // registered, even in report-only mode. Until the API changes, catch the\n  // error not to break the applications functionally. In such case, the code\n  // will fall back to using regular Safe Types.\n  // TODO(koto): Remove catching once createPolicy API stops throwing.\n  try {\n    policy = policyFactory.createPolicy(name, {\n      createHTML: goog.identity_,\n      createScript: goog.identity_,\n      createScriptURL: goog.identity_\n    });\n  } catch (e) {\n    goog.logToConsole_(e.message);\n  }\n  return policy;\n};\n\n// There's a bug in the compiler where without collapse properties the\n// Closure namespace defines do not guard code correctly. To help reduce code\n// size also check for !COMPILED even though it redundant until this is fixed.\nif (!COMPILED && goog.DEPENDENCIES_ENABLED) {\n\n\n  /**\n   * Tries to detect whether the current browser is Edge, based on the user\n   * agent. This matches only pre-Chromium Edge.\n   * @see https://docs.microsoft.com/en-us/microsoft-edge/web-platform/user-agent-string\n   * @return {boolean} True if the current browser is Edge.\n   * @private\n   */\n  goog.isEdge_ = function() {\n    var userAgent = goog.global.navigator && goog.global.navigator.userAgent ?\n        goog.global.navigator.userAgent :\n        '';\n    var edgeRe = /Edge\\/(\\d+)(\\.\\d)*/i;\n    return !!userAgent.match(edgeRe);\n  };\n\n\n  /**\n   * Tries to detect whether is in the context of an HTML document.\n   * @return {boolean} True if it looks like HTML document.\n   * @private\n   */\n  goog.inHtmlDocument_ = function() {\n    /** @type {!Document} */\n    var doc = goog.global.document;\n    return doc != null && 'write' in doc;  // XULDocument misses write.\n  };\n\n\n  /**\n   * We'd like to check for if the document readyState is 'loading'; however\n   * there are bugs on IE 10 and below where the readyState being anything other\n   * than 'complete' is not reliable.\n   * @return {boolean}\n   * @private\n   */\n  goog.isDocumentLoading_ = function() {\n    // attachEvent is available on IE 6 thru 10 only, and thus can be used to\n    // detect those browsers.\n    /** @type {!HTMLDocument} */\n    var doc = goog.global.document;\n    return doc.attachEvent ? doc.readyState != 'complete' :\n                             doc.readyState == 'loading';\n  };\n\n\n  /**\n   * Tries to detect the base path of base.js script that bootstraps Closure.\n   * @private\n   */\n  goog.findBasePath_ = function() {\n    if (goog.global.CLOSURE_BASE_PATH != undefined &&\n        // Anti DOM-clobbering runtime check (b/37736576).\n        typeof goog.global.CLOSURE_BASE_PATH === 'string') {\n      goog.basePath = goog.global.CLOSURE_BASE_PATH;\n      return;\n    } else if (!goog.inHtmlDocument_()) {\n      return;\n    }\n    /** @type {!Document} */\n    var doc = goog.global.document;\n    // If we have a currentScript available, use it exclusively.\n    var currentScript = doc.currentScript;\n    if (currentScript) {\n      var scripts = [currentScript];\n    } else {\n      var scripts = doc.getElementsByTagName('SCRIPT');\n    }\n    // Search backwards since the current script is in almost all cases the one\n    // that has base.js.\n    for (var i = scripts.length - 1; i >= 0; --i) {\n      var script = /** @type {!HTMLScriptElement} */ (scripts[i]);\n      var src = script.src;\n      var qmark = src.lastIndexOf('?');\n      var l = qmark == -1 ? src.length : qmark;\n      if (src.substr(l - 7, 7) == 'base.js') {\n        goog.basePath = src.substr(0, l - 7);\n        return;\n      }\n    }\n  };\n\n  goog.findBasePath_();\n\n  /** @struct @constructor @final */\n  goog.Transpiler = function() {\n    /** @private {?Object<string, boolean>} */\n    this.requiresTranspilation_ = null;\n    /** @private {string} */\n    this.transpilationTarget_ = goog.TRANSPILE_TO_LANGUAGE;\n  };\n  /**\n   * Returns a newly created map from language mode string to a boolean\n   * indicating whether transpilation should be done for that mode as well as\n   * the highest level language that this environment supports.\n   *\n   * Guaranteed invariant:\n   * For any two modes, l1 and l2 where l2 is a newer mode than l1,\n   * `map[l1] == true` implies that `map[l2] == true`.\n   *\n   * Note this method is extracted and used elsewhere, so it cannot rely on\n   * anything external (it should easily be able to be transformed into a\n   * standalone, top level function).\n   *\n   * @private\n   * @return {{\n   *   target: string,\n   *   map: !Object<string, boolean>\n   * }}\n   */\n  goog.Transpiler.prototype.createRequiresTranspilation_ = function() {\n    var transpilationTarget = 'es3';\n    var /** !Object<string, boolean> */ requiresTranspilation = {'es3': false};\n    var transpilationRequiredForAllLaterModes = false;\n\n    /**\n     * Adds an entry to requiresTranspliation for the given language mode.\n     *\n     * IMPORTANT: Calls must be made in order from oldest to newest language\n     * mode.\n     * @param {string} modeName\n     * @param {function(): boolean} isSupported Returns true if the JS engine\n     *     supports the given mode.\n     */\n    function addNewerLanguageTranspilationCheck(modeName, isSupported) {\n      if (transpilationRequiredForAllLaterModes) {\n        requiresTranspilation[modeName] = true;\n      } else if (isSupported()) {\n        transpilationTarget = modeName;\n        requiresTranspilation[modeName] = false;\n      } else {\n        requiresTranspilation[modeName] = true;\n        transpilationRequiredForAllLaterModes = true;\n      }\n    }\n\n    /**\n     * Does the given code evaluate without syntax errors and return a truthy\n     * result?\n     */\n    function /** boolean */ evalCheck(/** string */ code) {\n      try {\n        return !!eval(goog.CLOSURE_EVAL_PREFILTER_.createScript(code));\n      } catch (ignored) {\n        return false;\n      }\n    }\n\n    // Identify ES3-only browsers by their incorrect treatment of commas.\n    addNewerLanguageTranspilationCheck('es5', function() {\n      return evalCheck('[1,].length==1');\n    });\n    addNewerLanguageTranspilationCheck('es6', function() {\n      // Edge has a non-deterministic (i.e., not reproducible) bug with ES6:\n      // https://github.com/Microsoft/ChakraCore/issues/1496.\n      if (goog.isEdge_()) {\n        // The Reflect.construct test below is flaky on Edge. It can sometimes\n        // pass or fail on 40 15.15063, so just exit early for Edge and treat\n        // it as ES5. Until we're on a more up to date version just always use\n        // ES5. See https://github.com/Microsoft/ChakraCore/issues/3217.\n        return false;\n      }\n      // Test es6: [FF50 (?), Edge 14 (?), Chrome 50]\n      //   (a) default params (specifically shadowing locals),\n      //   (b) destructuring, (c) block-scoped functions,\n      //   (d) for-of (const), (e) new.target/Reflect.construct\n      var es6fullTest =\n          'class X{constructor(){if(new.target!=String)throw 1;this.x=42}}' +\n          'let q=Reflect.construct(X,[],String);if(q.x!=42||!(q instanceof ' +\n          'String))throw 1;for(const a of[2,3]){if(a==2)continue;function ' +\n          'f(z={a}){let a=0;return z.a}{function f(){return 0;}}return f()' +\n          '==3}';\n\n      return evalCheck('(()=>{\"use strict\";' + es6fullTest + '})()');\n    });\n    // ** and **= are the only new features in 'es7'\n    addNewerLanguageTranspilationCheck('es7', function() {\n      return evalCheck('2**3==8');\n    });\n    // async functions are the only new features in 'es8'\n    addNewerLanguageTranspilationCheck('es8', function() {\n      return evalCheck('async()=>1,1');\n    });\n    addNewerLanguageTranspilationCheck('es9', function() {\n      return evalCheck('({...rest}={}),1');\n    });\n    // optional catch binding, unescaped unicode paragraph separator in strings\n    addNewerLanguageTranspilationCheck('es_2019', function() {\n      return evalCheck('let r;try{r=\"\\u2029\"}catch{};r');\n    });\n    // optional chaining, nullish coalescing\n    // untested/unsupported: bigint, import meta\n    addNewerLanguageTranspilationCheck('es_2020', function() {\n      return evalCheck('null?.x??1');\n    });\n    addNewerLanguageTranspilationCheck('es_next', function() {\n      return false;  // assume it always need to transpile\n    });\n    return {target: transpilationTarget, map: requiresTranspilation};\n  };\n\n\n  /**\n   * Determines whether the given language needs to be transpiled.\n   * @param {string} lang\n   * @param {string|undefined} module\n   * @return {boolean}\n   */\n  goog.Transpiler.prototype.needsTranspile = function(lang, module) {\n    if (goog.TRANSPILE == 'always') {\n      return true;\n    } else if (goog.TRANSPILE == 'never') {\n      return false;\n    } else if (!this.requiresTranspilation_) {\n      var obj = this.createRequiresTranspilation_();\n      this.requiresTranspilation_ = obj.map;\n      this.transpilationTarget_ = this.transpilationTarget_ || obj.target;\n    }\n    if (lang in this.requiresTranspilation_) {\n      if (this.requiresTranspilation_[lang]) {\n        return true;\n      } else if (\n          goog.inHtmlDocument_() && module == 'es6' &&\n          !('noModule' in goog.global.document.createElement('script'))) {\n        return true;\n      } else {\n        return false;\n      }\n    } else {\n      throw new Error('Unknown language mode: ' + lang);\n    }\n  };\n\n\n  /**\n   * Lazily retrieves the transpiler and applies it to the source.\n   * @param {string} code JS code.\n   * @param {string} path Path to the code.\n   * @return {string} The transpiled code.\n   */\n  goog.Transpiler.prototype.transpile = function(code, path) {\n    // TODO(johnplaisted): We should delete goog.transpile_ and just have this\n    // function. But there's some compile error atm where goog.global is being\n    // stripped incorrectly without this.\n    return goog.transpile_(code, path, this.transpilationTarget_);\n  };\n\n\n  /** @private @final {!goog.Transpiler} */\n  goog.transpiler_ = new goog.Transpiler();\n\n  /**\n   * Rewrites closing script tags in input to avoid ending an enclosing script\n   * tag.\n   *\n   * @param {string} str\n   * @return {string}\n   * @private\n   */\n  goog.protectScriptTag_ = function(str) {\n    return str.replace(/<\\/(SCRIPT)/ig, '\\\\x3c/$1');\n  };\n\n\n  /**\n   * A debug loader is responsible for downloading and executing javascript\n   * files in an unbundled, uncompiled environment.\n   *\n   * This can be custimized via the setDependencyFactory method, or by\n   * CLOSURE_IMPORT_SCRIPT/CLOSURE_LOAD_FILE_SYNC.\n   *\n   * @struct @constructor @final @private\n   */\n  goog.DebugLoader_ = function() {\n    /** @private @const {!Object<string, !goog.Dependency>} */\n    this.dependencies_ = {};\n    /** @private @const {!Object<string, string>} */\n    this.idToPath_ = {};\n    /** @private @const {!Object<string, boolean>} */\n    this.written_ = {};\n    /** @private @const {!Array<!goog.Dependency>} */\n    this.loadingDeps_ = [];\n    /** @private {!Array<!goog.Dependency>} */\n    this.depsToLoad_ = [];\n    /** @private {boolean} */\n    this.paused_ = false;\n    /** @private {!goog.DependencyFactory} */\n    this.factory_ = new goog.DependencyFactory(goog.transpiler_);\n    /** @private @const {!Object<string, !Function>} */\n    this.deferredCallbacks_ = {};\n    /** @private @const {!Array<string>} */\n    this.deferredQueue_ = [];\n  };\n\n  /**\n   * @param {!Array<string>} namespaces\n   * @param {function(): undefined} callback Function to call once all the\n   *     namespaces have loaded.\n   */\n  goog.DebugLoader_.prototype.bootstrap = function(namespaces, callback) {\n    var cb = callback;\n    function resolve() {\n      if (cb) {\n        goog.global.setTimeout(cb, 0);\n        cb = null;\n      }\n    }\n\n    if (!namespaces.length) {\n      resolve();\n      return;\n    }\n\n    var deps = [];\n    for (var i = 0; i < namespaces.length; i++) {\n      var path = this.getPathFromDeps_(namespaces[i]);\n      if (!path) {\n        throw new Error('Unregonized namespace: ' + namespaces[i]);\n      }\n      deps.push(this.dependencies_[path]);\n    }\n\n    var require = goog.require;\n    var loaded = 0;\n    for (var i = 0; i < namespaces.length; i++) {\n      require(namespaces[i]);\n      deps[i].onLoad(function() {\n        if (++loaded == namespaces.length) {\n          resolve();\n        }\n      });\n    }\n  };\n\n\n  /**\n   * Loads the Closure Dependency file.\n   *\n   * Exposed a public function so CLOSURE_NO_DEPS can be set to false, base\n   * loaded, setDependencyFactory called, and then this called. i.e. allows\n   * custom loading of the deps file.\n   */\n  goog.DebugLoader_.prototype.loadClosureDeps = function() {\n    // Circumvent addDependency, which would try to transpile deps.js if\n    // transpile is set to always.\n    var relPath = 'deps.js';\n    this.depsToLoad_.push(this.factory_.createDependency(\n        goog.normalizePath_(goog.basePath + relPath), relPath, [], [], {},\n        false));\n    this.loadDeps_();\n  };\n\n\n  /**\n   * Notifies the debug loader when a dependency has been requested.\n   *\n   * @param {string} absPathOrId Path of the dependency or goog id.\n   * @param {boolean=} opt_force\n   */\n  goog.DebugLoader_.prototype.requested = function(absPathOrId, opt_force) {\n    var path = this.getPathFromDeps_(absPathOrId);\n    if (path &&\n        (opt_force || this.areDepsLoaded_(this.dependencies_[path].requires))) {\n      var callback = this.deferredCallbacks_[path];\n      if (callback) {\n        delete this.deferredCallbacks_[path];\n        callback();\n      }\n    }\n  };\n\n\n  /**\n   * Sets the dependency factory, which can be used to create custom\n   * goog.Dependency implementations to control how dependencies are loaded.\n   *\n   * @param {!goog.DependencyFactory} factory\n   */\n  goog.DebugLoader_.prototype.setDependencyFactory = function(factory) {\n    this.factory_ = factory;\n  };\n\n\n  /**\n   * Travserses the dependency graph and queues the given dependency, and all of\n   * its transitive dependencies, for loading and then starts loading if not\n   * paused.\n   *\n   * @param {string} namespace\n   * @private\n   */\n  goog.DebugLoader_.prototype.load_ = function(namespace) {\n    if (!this.getPathFromDeps_(namespace)) {\n      var errorMessage = 'goog.require could not find: ' + namespace;\n      goog.logToConsole_(errorMessage);\n    } else {\n      var loader = this;\n\n      var deps = [];\n\n      /** @param {string} namespace */\n      var visit = function(namespace) {\n        var path = loader.getPathFromDeps_(namespace);\n\n        if (!path) {\n          throw new Error('Bad dependency path or symbol: ' + namespace);\n        }\n\n        if (loader.written_[path]) {\n          return;\n        }\n\n        loader.written_[path] = true;\n\n        var dep = loader.dependencies_[path];\n        for (var i = 0; i < dep.requires.length; i++) {\n          if (!goog.isProvided_(dep.requires[i])) {\n            visit(dep.requires[i]);\n          }\n        }\n\n        deps.push(dep);\n      };\n\n      visit(namespace);\n\n      var wasLoading = !!this.depsToLoad_.length;\n      this.depsToLoad_ = this.depsToLoad_.concat(deps);\n\n      if (!this.paused_ && !wasLoading) {\n        this.loadDeps_();\n      }\n    }\n  };\n\n\n  /**\n   * Loads any queued dependencies until they are all loaded or paused.\n   *\n   * @private\n   */\n  goog.DebugLoader_.prototype.loadDeps_ = function() {\n    var loader = this;\n    var paused = this.paused_;\n\n    while (this.depsToLoad_.length && !paused) {\n      (function() {\n        var loadCallDone = false;\n        var dep = loader.depsToLoad_.shift();\n\n        var loaded = false;\n        loader.loading_(dep);\n\n        var controller = {\n          pause: function() {\n            if (loadCallDone) {\n              throw new Error('Cannot call pause after the call to load.');\n            } else {\n              paused = true;\n            }\n          },\n          resume: function() {\n            if (loadCallDone) {\n              loader.resume_();\n            } else {\n              // Some dep called pause and then resume in the same load call.\n              // Just keep running this same loop.\n              paused = false;\n            }\n          },\n          loaded: function() {\n            if (loaded) {\n              throw new Error('Double call to loaded.');\n            }\n\n            loaded = true;\n            loader.loaded_(dep);\n          },\n          pending: function() {\n            // Defensive copy.\n            var pending = [];\n            for (var i = 0; i < loader.loadingDeps_.length; i++) {\n              pending.push(loader.loadingDeps_[i]);\n            }\n            return pending;\n          },\n          /**\n           * @param {goog.ModuleType} type\n           */\n          setModuleState: function(type) {\n            goog.moduleLoaderState_ = {\n              type: type,\n              moduleName: '',\n              declareLegacyNamespace: false\n            };\n          },\n          /** @type {function(string, string, string=)} */\n          registerEs6ModuleExports: function(\n              path, exports, opt_closureNamespace) {\n            if (opt_closureNamespace) {\n              goog.loadedModules_[opt_closureNamespace] = {\n                exports: exports,\n                type: goog.ModuleType.ES6,\n                moduleId: opt_closureNamespace || ''\n              };\n            }\n          },\n          /** @type {function(string, ?)} */\n          registerGoogModuleExports: function(moduleId, exports) {\n            goog.loadedModules_[moduleId] = {\n              exports: exports,\n              type: goog.ModuleType.GOOG,\n              moduleId: moduleId\n            };\n          },\n          clearModuleState: function() {\n            goog.moduleLoaderState_ = null;\n          },\n          defer: function(callback) {\n            if (loadCallDone) {\n              throw new Error(\n                  'Cannot register with defer after the call to load.');\n            }\n            loader.defer_(dep, callback);\n          },\n          areDepsLoaded: function() {\n            return loader.areDepsLoaded_(dep.requires);\n          }\n        };\n\n        try {\n          dep.load(controller);\n        } finally {\n          loadCallDone = true;\n        }\n      })();\n    }\n\n    if (paused) {\n      this.pause_();\n    }\n  };\n\n\n  /** @private */\n  goog.DebugLoader_.prototype.pause_ = function() {\n    this.paused_ = true;\n  };\n\n\n  /** @private */\n  goog.DebugLoader_.prototype.resume_ = function() {\n    if (this.paused_) {\n      this.paused_ = false;\n      this.loadDeps_();\n    }\n  };\n\n\n  /**\n   * Marks the given dependency as loading (load has been called but it has not\n   * yet marked itself as finished). Useful for dependencies that want to know\n   * what else is loading. Example: goog.modules cannot eval if there are\n   * loading dependencies.\n   *\n   * @param {!goog.Dependency} dep\n   * @private\n   */\n  goog.DebugLoader_.prototype.loading_ = function(dep) {\n    this.loadingDeps_.push(dep);\n  };\n\n\n  /**\n   * Marks the given dependency as having finished loading and being available\n   * for require.\n   *\n   * @param {!goog.Dependency} dep\n   * @private\n   */\n  goog.DebugLoader_.prototype.loaded_ = function(dep) {\n    for (var i = 0; i < this.loadingDeps_.length; i++) {\n      if (this.loadingDeps_[i] == dep) {\n        this.loadingDeps_.splice(i, 1);\n        break;\n      }\n    }\n\n    for (var i = 0; i < this.deferredQueue_.length; i++) {\n      if (this.deferredQueue_[i] == dep.path) {\n        this.deferredQueue_.splice(i, 1);\n        break;\n      }\n    }\n\n    if (this.loadingDeps_.length == this.deferredQueue_.length &&\n        !this.depsToLoad_.length) {\n      // Something has asked to load these, but they may not be directly\n      // required again later, so load them now that we know we're done loading\n      // everything else. e.g. a goog module entry point.\n      while (this.deferredQueue_.length) {\n        this.requested(this.deferredQueue_.shift(), true);\n      }\n    }\n\n    dep.loaded();\n  };\n\n\n  /**\n   * @param {!Array<string>} pathsOrIds\n   * @return {boolean}\n   * @private\n   */\n  goog.DebugLoader_.prototype.areDepsLoaded_ = function(pathsOrIds) {\n    for (var i = 0; i < pathsOrIds.length; i++) {\n      var path = this.getPathFromDeps_(pathsOrIds[i]);\n      if (!path ||\n          (!(path in this.deferredCallbacks_) &&\n           !goog.isProvided_(pathsOrIds[i]))) {\n        return false;\n      }\n    }\n\n    return true;\n  };\n\n\n  /**\n   * @param {string} absPathOrId\n   * @return {?string}\n   * @private\n   */\n  goog.DebugLoader_.prototype.getPathFromDeps_ = function(absPathOrId) {\n    if (absPathOrId in this.idToPath_) {\n      return this.idToPath_[absPathOrId];\n    } else if (absPathOrId in this.dependencies_) {\n      return absPathOrId;\n    } else {\n      return null;\n    }\n  };\n\n\n  /**\n   * @param {!goog.Dependency} dependency\n   * @param {!Function} callback\n   * @private\n   */\n  goog.DebugLoader_.prototype.defer_ = function(dependency, callback) {\n    this.deferredCallbacks_[dependency.path] = callback;\n    this.deferredQueue_.push(dependency.path);\n  };\n\n\n  /**\n   * Interface for goog.Dependency implementations to have some control over\n   * loading of dependencies.\n   *\n   * @record\n   */\n  goog.LoadController = function() {};\n\n\n  /**\n   * Tells the controller to halt loading of more dependencies.\n   */\n  goog.LoadController.prototype.pause = function() {};\n\n\n  /**\n   * Tells the controller to resume loading of more dependencies if paused.\n   */\n  goog.LoadController.prototype.resume = function() {};\n\n\n  /**\n   * Tells the controller that this dependency has finished loading.\n   *\n   * This causes this to be removed from pending() and any load callbacks to\n   * fire.\n   */\n  goog.LoadController.prototype.loaded = function() {};\n\n\n  /**\n   * List of dependencies on which load has been called but which have not\n   * called loaded on their controller. This includes the current dependency.\n   *\n   * @return {!Array<!goog.Dependency>}\n   */\n  goog.LoadController.prototype.pending = function() {};\n\n\n  /**\n   * Registers an object as an ES6 module's exports so that goog.modules may\n   * require it by path.\n   *\n   * @param {string} path Full path of the module.\n   * @param {?} exports\n   * @param {string=} opt_closureNamespace Closure namespace to associate with\n   *     this module.\n   */\n  goog.LoadController.prototype.registerEs6ModuleExports = function(\n      path, exports, opt_closureNamespace) {};\n\n\n  /**\n   * Sets the current module state.\n   *\n   * @param {goog.ModuleType} type Type of module.\n   */\n  goog.LoadController.prototype.setModuleState = function(type) {};\n\n\n  /**\n   * Clears the current module state.\n   */\n  goog.LoadController.prototype.clearModuleState = function() {};\n\n\n  /**\n   * Registers a callback to call once the dependency is actually requested\n   * via goog.require + all of the immediate dependencies have been loaded or\n   * all other files have been loaded. Allows for lazy loading until\n   * require'd without pausing dependency loading, which is needed on old IE.\n   *\n   * @param {!Function} callback\n   */\n  goog.LoadController.prototype.defer = function(callback) {};\n\n\n  /**\n   * @return {boolean}\n   */\n  goog.LoadController.prototype.areDepsLoaded = function() {};\n\n\n  /**\n   * Basic super class for all dependencies Closure Library can load.\n   *\n   * This default implementation is designed to load untranspiled, non-module\n   * scripts in a web broswer.\n   *\n   * For transpiled non-goog.module files {@see goog.TranspiledDependency}.\n   * For goog.modules see {@see goog.GoogModuleDependency}.\n   * For untranspiled ES6 modules {@see goog.Es6ModuleDependency}.\n   *\n   * @param {string} path Absolute path of this script.\n   * @param {string} relativePath Path of this script relative to goog.basePath.\n   * @param {!Array<string>} provides goog.provided or goog.module symbols\n   *     in this file.\n   * @param {!Array<string>} requires goog symbols or relative paths to Closure\n   *     this depends on.\n   * @param {!Object<string, string>} loadFlags\n   * @struct @constructor\n   */\n  goog.Dependency = function(\n      path, relativePath, provides, requires, loadFlags) {\n    /** @const */\n    this.path = path;\n    /** @const */\n    this.relativePath = relativePath;\n    /** @const */\n    this.provides = provides;\n    /** @const */\n    this.requires = requires;\n    /** @const */\n    this.loadFlags = loadFlags;\n    /** @private {boolean} */\n    this.loaded_ = false;\n    /** @private {!Array<function()>} */\n    this.loadCallbacks_ = [];\n  };\n\n\n  /**\n   * @return {string} The pathname part of this dependency's path if it is a\n   *     URI.\n   */\n  goog.Dependency.prototype.getPathName = function() {\n    var pathName = this.path;\n    var protocolIndex = pathName.indexOf('://');\n    if (protocolIndex >= 0) {\n      pathName = pathName.substring(protocolIndex + 3);\n      var slashIndex = pathName.indexOf('/');\n      if (slashIndex >= 0) {\n        pathName = pathName.substring(slashIndex + 1);\n      }\n    }\n    return pathName;\n  };\n\n\n  /**\n   * @param {function()} callback Callback to fire as soon as this has loaded.\n   * @final\n   */\n  goog.Dependency.prototype.onLoad = function(callback) {\n    if (this.loaded_) {\n      callback();\n    } else {\n      this.loadCallbacks_.push(callback);\n    }\n  };\n\n\n  /**\n   * Marks this dependency as loaded and fires any callbacks registered with\n   * onLoad.\n   * @final\n   */\n  goog.Dependency.prototype.loaded = function() {\n    this.loaded_ = true;\n    var callbacks = this.loadCallbacks_;\n    this.loadCallbacks_ = [];\n    for (var i = 0; i < callbacks.length; i++) {\n      callbacks[i]();\n    }\n  };\n\n\n  /**\n   * Whether or not document.written / appended script tags should be deferred.\n   *\n   * @private {boolean}\n   */\n  goog.Dependency.defer_ = false;\n\n\n  /**\n   * Map of script ready / state change callbacks. Old IE cannot handle putting\n   * these properties on goog.global.\n   *\n   * @private @const {!Object<string, function(?):undefined>}\n   */\n  goog.Dependency.callbackMap_ = {};\n\n\n  /**\n   * @param {function(...?):?} callback\n   * @return {string}\n   * @private\n   */\n  goog.Dependency.registerCallback_ = function(callback) {\n    var key = Math.random().toString(32);\n    goog.Dependency.callbackMap_[key] = callback;\n    return key;\n  };\n\n\n  /**\n   * @param {string} key\n   * @private\n   */\n  goog.Dependency.unregisterCallback_ = function(key) {\n    delete goog.Dependency.callbackMap_[key];\n  };\n\n\n  /**\n   * @param {string} key\n   * @param {...?} var_args\n   * @private\n   * @suppress {unusedPrivateMembers}\n   */\n  goog.Dependency.callback_ = function(key, var_args) {\n    if (key in goog.Dependency.callbackMap_) {\n      var callback = goog.Dependency.callbackMap_[key];\n      var args = [];\n      for (var i = 1; i < arguments.length; i++) {\n        args.push(arguments[i]);\n      }\n      callback.apply(undefined, args);\n    } else {\n      var errorMessage = 'Callback key ' + key +\n          ' does not exist (was base.js loaded more than once?).';\n      throw Error(errorMessage);\n    }\n  };\n\n\n  /**\n   * Starts loading this dependency. This dependency can pause loading if it\n   * needs to and resume it later via the controller interface.\n   *\n   * When this is loaded it should call controller.loaded(). Note that this will\n   * end up calling the loaded method of this dependency; there is no need to\n   * call it explicitly.\n   *\n   * @param {!goog.LoadController} controller\n   */\n  goog.Dependency.prototype.load = function(controller) {\n    if (goog.global.CLOSURE_IMPORT_SCRIPT) {\n      if (goog.global.CLOSURE_IMPORT_SCRIPT(this.path)) {\n        controller.loaded();\n      } else {\n        controller.pause();\n      }\n      return;\n    }\n\n    if (!goog.inHtmlDocument_()) {\n      goog.logToConsole_(\n          'Cannot use default debug loader outside of HTML documents.');\n      if (this.relativePath == 'deps.js') {\n        // Some old code is relying on base.js auto loading deps.js failing with\n        // no error before later setting CLOSURE_IMPORT_SCRIPT.\n        // CLOSURE_IMPORT_SCRIPT should be set *before* base.js is loaded, or\n        // CLOSURE_NO_DEPS set to true.\n        goog.logToConsole_(\n            'Consider setting CLOSURE_IMPORT_SCRIPT before loading base.js, ' +\n            'or setting CLOSURE_NO_DEPS to true.');\n        controller.loaded();\n      } else {\n        controller.pause();\n      }\n      return;\n    }\n\n    /** @type {!HTMLDocument} */\n    var doc = goog.global.document;\n\n    // If the user tries to require a new symbol after document load,\n    // something has gone terribly wrong. Doing a document.write would\n    // wipe out the page. This does not apply to the CSP-compliant method\n    // of writing script tags.\n    if (doc.readyState == 'complete' &&\n        !goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING) {\n      // Certain test frameworks load base.js multiple times, which tries\n      // to write deps.js each time. If that happens, just fail silently.\n      // These frameworks wipe the page between each load of base.js, so this\n      // is OK.\n      var isDeps = /\\bdeps.js$/.test(this.path);\n      if (isDeps) {\n        controller.loaded();\n        return;\n      } else {\n        throw Error('Cannot write \"' + this.path + '\" after document load');\n      }\n    }\n\n    var nonce = goog.getScriptNonce_();\n    if (!goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING &&\n        goog.isDocumentLoading_()) {\n      var key;\n      var callback = function(script) {\n        if (script.readyState && script.readyState != 'complete') {\n          script.onload = callback;\n          return;\n        }\n        goog.Dependency.unregisterCallback_(key);\n        controller.loaded();\n      };\n      key = goog.Dependency.registerCallback_(callback);\n\n      var defer = goog.Dependency.defer_ ? ' defer' : '';\n      var nonceAttr = nonce ? ' nonce=\"' + nonce + '\"' : '';\n      var script = '<script src=\"' + this.path + '\"' + nonceAttr + defer +\n          ' id=\"script-' + key + '\"><\\/script>';\n\n      script += '<script' + nonceAttr + '>';\n\n      if (goog.Dependency.defer_) {\n        script += 'document.getElementById(\\'script-' + key +\n            '\\').onload = function() {\\n' +\n            '  goog.Dependency.callback_(\\'' + key + '\\', this);\\n' +\n            '};\\n';\n      } else {\n        script += 'goog.Dependency.callback_(\\'' + key +\n            '\\', document.getElementById(\\'script-' + key + '\\'));';\n      }\n\n      script += '<\\/script>';\n\n      doc.write(\n          goog.TRUSTED_TYPES_POLICY_ ?\n              goog.TRUSTED_TYPES_POLICY_.createHTML(script) :\n              script);\n    } else {\n      var scriptEl =\n          /** @type {!HTMLScriptElement} */ (doc.createElement('script'));\n      scriptEl.defer = goog.Dependency.defer_;\n      scriptEl.async = false;\n\n      // If CSP nonces are used, propagate them to dynamically created scripts.\n      // This is necessary to allow nonce-based CSPs without 'strict-dynamic'.\n      if (nonce) {\n        scriptEl.nonce = nonce;\n      }\n\n      scriptEl.onload = function() {\n        scriptEl.onload = null;\n        controller.loaded();\n      };\n\n      scriptEl.src = goog.TRUSTED_TYPES_POLICY_ ?\n          goog.TRUSTED_TYPES_POLICY_.createScriptURL(this.path) :\n          this.path;\n      doc.head.appendChild(scriptEl);\n    }\n  };\n\n\n  /**\n   * @param {string} path Absolute path of this script.\n   * @param {string} relativePath Path of this script relative to goog.basePath.\n   * @param {!Array<string>} provides Should be an empty array.\n   *     TODO(johnplaisted) add support for adding closure namespaces to ES6\n   *     modules for interop purposes.\n   * @param {!Array<string>} requires goog symbols or relative paths to Closure\n   *     this depends on.\n   * @param {!Object<string, string>} loadFlags\n   * @struct @constructor\n   * @extends {goog.Dependency}\n   */\n  goog.Es6ModuleDependency = function(\n      path, relativePath, provides, requires, loadFlags) {\n    goog.Es6ModuleDependency.base(\n        this, 'constructor', path, relativePath, provides, requires, loadFlags);\n  };\n  goog.inherits(goog.Es6ModuleDependency, goog.Dependency);\n\n\n  /**\n   * @override\n   * @param {!goog.LoadController} controller\n   */\n  goog.Es6ModuleDependency.prototype.load = function(controller) {\n    if (goog.global.CLOSURE_IMPORT_SCRIPT) {\n      if (goog.global.CLOSURE_IMPORT_SCRIPT(this.path)) {\n        controller.loaded();\n      } else {\n        controller.pause();\n      }\n      return;\n    }\n\n    if (!goog.inHtmlDocument_()) {\n      goog.logToConsole_(\n          'Cannot use default debug loader outside of HTML documents.');\n      controller.pause();\n      return;\n    }\n\n    /** @type {!HTMLDocument} */\n    var doc = goog.global.document;\n\n    var dep = this;\n\n    // TODO(johnplaisted): Does document.writing really speed up anything? Any\n    // difference between this and just waiting for interactive mode and then\n    // appending?\n    function write(src, contents) {\n      var nonceAttr = '';\n      var nonce = goog.getScriptNonce_();\n      if (nonce) {\n        nonceAttr = ' nonce=\"' + nonce + '\"';\n      }\n\n      if (contents) {\n        var script = '<script type=\"module\" crossorigin' + nonceAttr + '>' +\n            contents + '</' +\n            'script>';\n        doc.write(\n            goog.TRUSTED_TYPES_POLICY_ ?\n                goog.TRUSTED_TYPES_POLICY_.createHTML(script) :\n                script);\n      } else {\n        var script = '<script type=\"module\" crossorigin src=\"' + src + '\"' +\n            nonceAttr + '></' +\n            'script>';\n        doc.write(\n            goog.TRUSTED_TYPES_POLICY_ ?\n                goog.TRUSTED_TYPES_POLICY_.createHTML(script) :\n                script);\n      }\n    }\n\n    function append(src, contents) {\n      var scriptEl =\n          /** @type {!HTMLScriptElement} */ (doc.createElement('script'));\n      scriptEl.defer = true;\n      scriptEl.async = false;\n      scriptEl.type = 'module';\n      scriptEl.setAttribute('crossorigin', true);\n\n      // If CSP nonces are used, propagate them to dynamically created scripts.\n      // This is necessary to allow nonce-based CSPs without 'strict-dynamic'.\n      var nonce = goog.getScriptNonce_();\n      if (nonce) {\n        scriptEl.nonce = nonce;\n      }\n\n      if (contents) {\n        scriptEl.text = goog.TRUSTED_TYPES_POLICY_ ?\n            goog.TRUSTED_TYPES_POLICY_.createScript(contents) :\n            contents;\n      } else {\n        scriptEl.src = goog.TRUSTED_TYPES_POLICY_ ?\n            goog.TRUSTED_TYPES_POLICY_.createScriptURL(src) :\n            src;\n      }\n\n      doc.head.appendChild(scriptEl);\n    }\n\n    var create;\n\n    if (goog.isDocumentLoading_()) {\n      create = write;\n      // We can ONLY call document.write if we are guaranteed that any\n      // non-module script tags document.written after this are deferred.\n      // Small optimization, in theory document.writing is faster.\n      goog.Dependency.defer_ = true;\n    } else {\n      create = append;\n    }\n\n    // Write 4 separate tags here:\n    // 1) Sets the module state at the correct time (just before execution).\n    // 2) A src node for this, which just hopefully lets the browser load it a\n    //    little early (no need to parse #3).\n    // 3) Import the module and register it.\n    // 4) Clear the module state at the correct time. Guaranteed to run even\n    //    if there is an error in the module (#3 will not run if there is an\n    //    error in the module).\n    var beforeKey = goog.Dependency.registerCallback_(function() {\n      goog.Dependency.unregisterCallback_(beforeKey);\n      controller.setModuleState(goog.ModuleType.ES6);\n    });\n    create(undefined, 'goog.Dependency.callback_(\"' + beforeKey + '\")');\n\n    // TODO(johnplaisted): Does this really speed up anything?\n    create(this.path, undefined);\n\n    var registerKey = goog.Dependency.registerCallback_(function(exports) {\n      goog.Dependency.unregisterCallback_(registerKey);\n      controller.registerEs6ModuleExports(\n          dep.path, exports, goog.moduleLoaderState_.moduleName);\n    });\n    create(\n        undefined,\n        'import * as m from \"' + this.path + '\"; goog.Dependency.callback_(\"' +\n            registerKey + '\", m)');\n\n    var afterKey = goog.Dependency.registerCallback_(function() {\n      goog.Dependency.unregisterCallback_(afterKey);\n      controller.clearModuleState();\n      controller.loaded();\n    });\n    create(undefined, 'goog.Dependency.callback_(\"' + afterKey + '\")');\n  };\n\n\n  /**\n   * Superclass of any dependency that needs to be loaded into memory,\n   * transformed, and then eval'd (goog.modules and transpiled files).\n   *\n   * @param {string} path Absolute path of this script.\n   * @param {string} relativePath Path of this script relative to goog.basePath.\n   * @param {!Array<string>} provides goog.provided or goog.module symbols\n   *     in this file.\n   * @param {!Array<string>} requires goog symbols or relative paths to Closure\n   *     this depends on.\n   * @param {!Object<string, string>} loadFlags\n   * @struct @constructor @abstract\n   * @extends {goog.Dependency}\n   */\n  goog.TransformedDependency = function(\n      path, relativePath, provides, requires, loadFlags) {\n    goog.TransformedDependency.base(\n        this, 'constructor', path, relativePath, provides, requires, loadFlags);\n    /** @private {?string} */\n    this.contents_ = null;\n\n    /**\n     * Whether to lazily make the synchronous XHR (when goog.require'd) or make\n     * the synchronous XHR when initially loading. On FireFox 61 there is a bug\n     * where an ES6 module cannot make a synchronous XHR (rather, it can, but if\n     * it does then no other ES6 modules will load after).\n     *\n     * tl;dr we lazy load due to bugs on older browsers and eager load due to\n     * bugs on newer ones.\n     *\n     * https://bugzilla.mozilla.org/show_bug.cgi?id=1477090\n     *\n     * @private @const {boolean}\n     */\n    this.lazyFetch_ = !goog.inHtmlDocument_() ||\n        !('noModule' in goog.global.document.createElement('script'));\n  };\n  goog.inherits(goog.TransformedDependency, goog.Dependency);\n\n\n  /**\n   * @override\n   * @param {!goog.LoadController} controller\n   */\n  goog.TransformedDependency.prototype.load = function(controller) {\n    var dep = this;\n\n    function fetch() {\n      dep.contents_ = goog.loadFileSync_(dep.path);\n\n      if (dep.contents_) {\n        dep.contents_ = dep.transform(dep.contents_);\n        if (dep.contents_) {\n          dep.contents_ += '\\n//# sourceURL=' + dep.path;\n        }\n      }\n    }\n\n    if (goog.global.CLOSURE_IMPORT_SCRIPT) {\n      fetch();\n      if (this.contents_ &&\n          goog.global.CLOSURE_IMPORT_SCRIPT('', this.contents_)) {\n        this.contents_ = null;\n        controller.loaded();\n      } else {\n        controller.pause();\n      }\n      return;\n    }\n\n\n    var isEs6 = this.loadFlags['module'] == goog.ModuleType.ES6;\n\n    if (!this.lazyFetch_) {\n      fetch();\n    }\n\n    function load() {\n      if (dep.lazyFetch_) {\n        fetch();\n      }\n\n      if (!dep.contents_) {\n        // loadFileSync_ or transform are responsible. Assume they logged an\n        // error.\n        return;\n      }\n\n      if (isEs6) {\n        controller.setModuleState(goog.ModuleType.ES6);\n      }\n\n      var namespace;\n\n      try {\n        var contents = dep.contents_;\n        dep.contents_ = null;\n        goog.globalEval(goog.CLOSURE_EVAL_PREFILTER_.createScript(contents));\n        if (isEs6) {\n          namespace = goog.moduleLoaderState_.moduleName;\n        }\n      } finally {\n        if (isEs6) {\n          controller.clearModuleState();\n        }\n      }\n\n      if (isEs6) {\n        // Due to circular dependencies this may not be available for require\n        // right now.\n        goog.global['$jscomp']['require']['ensure'](\n            [dep.getPathName()], function() {\n              controller.registerEs6ModuleExports(\n                  dep.path,\n                  goog.global['$jscomp']['require'](dep.getPathName()),\n                  namespace);\n            });\n      }\n\n      controller.loaded();\n    }\n\n    // Do not fetch now; in FireFox 47 the synchronous XHR doesn't block all\n    // events. If we fetched now and then document.write'd the contents the\n    // document.write would be an eval and would execute too soon! Instead write\n    // a script tag to fetch and eval synchronously at the correct time.\n    function fetchInOwnScriptThenLoad() {\n      /** @type {!HTMLDocument} */\n      var doc = goog.global.document;\n\n      var key = goog.Dependency.registerCallback_(function() {\n        goog.Dependency.unregisterCallback_(key);\n        load();\n      });\n\n      var nonce = goog.getScriptNonce_();\n      var nonceAttr = nonce ? ' nonce=\"' + nonce + '\"' : '';\n      var script = '<script' + nonceAttr + '>' +\n          goog.protectScriptTag_('goog.Dependency.callback_(\"' + key + '\");') +\n          '</' +\n          'script>';\n      doc.write(\n          goog.TRUSTED_TYPES_POLICY_ ?\n              goog.TRUSTED_TYPES_POLICY_.createHTML(script) :\n              script);\n    }\n\n    // If one thing is pending it is this.\n    var anythingElsePending = controller.pending().length > 1;\n\n    // Additionally if we are meant to defer scripts but the page is still\n    // loading (e.g. an ES6 module is loading) then also defer. Or if we are\n    // meant to defer and anything else is pending then defer (those may be\n    // scripts that did not need transformation and are just script tags with\n    // defer set to true, and we need to evaluate after that deferred script).\n    var needsAsyncLoading = goog.Dependency.defer_ &&\n        (anythingElsePending || goog.isDocumentLoading_());\n\n    if (needsAsyncLoading) {\n      // Note that we only defer when we have to rather than 100% of the time.\n      // Always defering would work, but then in theory the order of\n      // goog.require calls would then matter. We want to enforce that most of\n      // the time the order of the require calls does not matter.\n      controller.defer(function() {\n        load();\n      });\n      return;\n    }\n    // TODO(johnplaisted): Externs are missing onreadystatechange for\n    // HTMLDocument.\n    /** @type {?} */\n    var doc = goog.global.document;\n\n    var isInternetExplorerOrEdge = goog.inHtmlDocument_() &&\n        ('ActiveXObject' in goog.global || goog.isEdge_());\n\n    // Don't delay in any version of IE or pre-Chromium Edge. There's a bug\n    // around this that will cause out of order script execution. This means\n    // that on older IE ES6 modules will load too early (while the document is\n    // still loading + the dom is not available). The other option is to load\n    // too late (when the document is complete and the onload even will never\n    // fire). This seems to be the lesser of two evils as scripts already act\n    // like the former.\n    if (isEs6 && goog.inHtmlDocument_() && goog.isDocumentLoading_() &&\n        !isInternetExplorerOrEdge) {\n      goog.Dependency.defer_ = true;\n      // Transpiled ES6 modules still need to load like regular ES6 modules,\n      // aka only after the document is interactive.\n      controller.pause();\n      var oldCallback = doc.onreadystatechange;\n      doc.onreadystatechange = function() {\n        if (doc.readyState == 'interactive') {\n          doc.onreadystatechange = oldCallback;\n          load();\n          controller.resume();\n        }\n        if (typeof oldCallback === 'function') {\n          oldCallback.apply(undefined, arguments);\n        }\n      };\n    } else {\n      // Always eval on old IE.\n      if (!goog.inHtmlDocument_() || !goog.isDocumentLoading_()) {\n        load();\n      } else {\n        fetchInOwnScriptThenLoad();\n      }\n    }\n  };\n\n\n  /**\n   * @param {string} contents\n   * @return {string}\n   * @abstract\n   */\n  goog.TransformedDependency.prototype.transform = function(contents) {};\n\n\n  /**\n   * Any non-goog.module dependency which needs to be transpiled before eval.\n   *\n   * @param {string} path Absolute path of this script.\n   * @param {string} relativePath Path of this script relative to goog.basePath.\n   * @param {!Array<string>} provides goog.provided or goog.module symbols\n   *     in this file.\n   * @param {!Array<string>} requires goog symbols or relative paths to Closure\n   *     this depends on.\n   * @param {!Object<string, string>} loadFlags\n   * @param {!goog.Transpiler} transpiler\n   * @struct @constructor\n   * @extends {goog.TransformedDependency}\n   */\n  goog.TranspiledDependency = function(\n      path, relativePath, provides, requires, loadFlags, transpiler) {\n    goog.TranspiledDependency.base(\n        this, 'constructor', path, relativePath, provides, requires, loadFlags);\n    /** @protected @const*/\n    this.transpiler = transpiler;\n  };\n  goog.inherits(goog.TranspiledDependency, goog.TransformedDependency);\n\n\n  /**\n   * @override\n   * @param {string} contents\n   * @return {string}\n   */\n  goog.TranspiledDependency.prototype.transform = function(contents) {\n    // Transpile with the pathname so that ES6 modules are domain agnostic.\n    return this.transpiler.transpile(contents, this.getPathName());\n  };\n\n\n  /**\n   * An ES6 module dependency that was transpiled to a jscomp module outside\n   * of the debug loader, e.g. server side.\n   *\n   * @param {string} path Absolute path of this script.\n   * @param {string} relativePath Path of this script relative to goog.basePath.\n   * @param {!Array<string>} provides goog.provided or goog.module symbols\n   *     in this file.\n   * @param {!Array<string>} requires goog symbols or relative paths to Closure\n   *     this depends on.\n   * @param {!Object<string, string>} loadFlags\n   * @struct @constructor\n   * @extends {goog.TransformedDependency}\n   */\n  goog.PreTranspiledEs6ModuleDependency = function(\n      path, relativePath, provides, requires, loadFlags) {\n    goog.PreTranspiledEs6ModuleDependency.base(\n        this, 'constructor', path, relativePath, provides, requires, loadFlags);\n  };\n  goog.inherits(\n      goog.PreTranspiledEs6ModuleDependency, goog.TransformedDependency);\n\n\n  /**\n   * @override\n   * @param {string} contents\n   * @return {string}\n   */\n  goog.PreTranspiledEs6ModuleDependency.prototype.transform = function(\n      contents) {\n    return contents;\n  };\n\n\n  /**\n   * A goog.module, transpiled or not. Will always perform some minimal\n   * transformation even when not transpiled to wrap in a goog.loadModule\n   * statement.\n   *\n   * @param {string} path Absolute path of this script.\n   * @param {string} relativePath Path of this script relative to goog.basePath.\n   * @param {!Array<string>} provides goog.provided or goog.module symbols\n   *     in this file.\n   * @param {!Array<string>} requires goog symbols or relative paths to Closure\n   *     this depends on.\n   * @param {!Object<string, string>} loadFlags\n   * @param {boolean} needsTranspile\n   * @param {!goog.Transpiler} transpiler\n   * @struct @constructor\n   * @extends {goog.TransformedDependency}\n   */\n  goog.GoogModuleDependency = function(\n      path, relativePath, provides, requires, loadFlags, needsTranspile,\n      transpiler) {\n    goog.GoogModuleDependency.base(\n        this, 'constructor', path, relativePath, provides, requires, loadFlags);\n    /** @private @const */\n    this.needsTranspile_ = needsTranspile;\n    /** @private @const */\n    this.transpiler_ = transpiler;\n  };\n  goog.inherits(goog.GoogModuleDependency, goog.TransformedDependency);\n\n\n  /**\n   * @override\n   * @param {string} contents\n   * @return {string}\n   */\n  goog.GoogModuleDependency.prototype.transform = function(contents) {\n    if (this.needsTranspile_) {\n      contents = this.transpiler_.transpile(contents, this.getPathName());\n    }\n\n    if (!goog.LOAD_MODULE_USING_EVAL || goog.global.JSON === undefined) {\n      return '' +\n          'goog.loadModule(function(exports) {' +\n          '\"use strict\";' + contents +\n          '\\n' +  // terminate any trailing single line comment.\n          ';return exports' +\n          '});' +\n          '\\n//# sourceURL=' + this.path + '\\n';\n    } else {\n      return '' +\n          'goog.loadModule(' +\n          goog.global.JSON.stringify(\n              contents + '\\n//# sourceURL=' + this.path + '\\n') +\n          ');';\n    }\n  };\n\n\n  /**\n   * @param {string} relPath\n   * @param {!Array<string>|undefined} provides\n   * @param {!Array<string>} requires\n   * @param {boolean|!Object<string>=} opt_loadFlags\n   * @see goog.addDependency\n   */\n  goog.DebugLoader_.prototype.addDependency = function(\n      relPath, provides, requires, opt_loadFlags) {\n    provides = provides || [];\n    relPath = relPath.replace(/\\\\/g, '/');\n    var path = goog.normalizePath_(goog.basePath + relPath);\n    if (!opt_loadFlags || typeof opt_loadFlags === 'boolean') {\n      opt_loadFlags = opt_loadFlags ? {'module': goog.ModuleType.GOOG} : {};\n    }\n    var dep = this.factory_.createDependency(\n        path, relPath, provides, requires, opt_loadFlags,\n        goog.transpiler_.needsTranspile(\n            opt_loadFlags['lang'] || 'es3', opt_loadFlags['module']));\n    this.dependencies_[path] = dep;\n    for (var i = 0; i < provides.length; i++) {\n      this.idToPath_[provides[i]] = path;\n    }\n    this.idToPath_[relPath] = path;\n  };\n\n\n  /**\n   * Creates goog.Dependency instances for the debug loader to load.\n   *\n   * Should be overridden to have the debug loader use custom subclasses of\n   * goog.Dependency.\n   *\n   * @param {!goog.Transpiler} transpiler\n   * @struct @constructor\n   */\n  goog.DependencyFactory = function(transpiler) {\n    /** @protected @const */\n    this.transpiler = transpiler;\n  };\n\n\n  /**\n   * @param {string} path Absolute path of the file.\n   * @param {string} relativePath Path relative to closure’s base.js.\n   * @param {!Array<string>} provides Array of provided goog.provide/module ids.\n   * @param {!Array<string>} requires Array of required goog.provide/module /\n   *     relative ES6 module paths.\n   * @param {!Object<string, string>} loadFlags\n   * @param {boolean} needsTranspile True if the file needs to be transpiled\n   *     per the goog.Transpiler.\n   * @return {!goog.Dependency}\n   */\n  goog.DependencyFactory.prototype.createDependency = function(\n      path, relativePath, provides, requires, loadFlags, needsTranspile) {\n\n    if (loadFlags['module'] == goog.ModuleType.GOOG) {\n      return new goog.GoogModuleDependency(\n          path, relativePath, provides, requires, loadFlags, needsTranspile,\n          this.transpiler);\n    } else if (needsTranspile) {\n      return new goog.TranspiledDependency(\n          path, relativePath, provides, requires, loadFlags, this.transpiler);\n    } else {\n      if (loadFlags['module'] == goog.ModuleType.ES6) {\n        if (goog.TRANSPILE == 'never' && goog.ASSUME_ES_MODULES_TRANSPILED) {\n          return new goog.PreTranspiledEs6ModuleDependency(\n              path, relativePath, provides, requires, loadFlags);\n        } else {\n          return new goog.Es6ModuleDependency(\n              path, relativePath, provides, requires, loadFlags);\n        }\n      } else {\n        return new goog.Dependency(\n            path, relativePath, provides, requires, loadFlags);\n      }\n    }\n  };\n\n\n  /** @private @const */\n  goog.debugLoader_ = new goog.DebugLoader_();\n\n\n  /**\n   * Loads the Closure Dependency file.\n   *\n   * Exposed a public function so CLOSURE_NO_DEPS can be set to false, base\n   * loaded, setDependencyFactory called, and then this called. i.e. allows\n   * custom loading of the deps file.\n   */\n  goog.loadClosureDeps = function() {\n    goog.debugLoader_.loadClosureDeps();\n  };\n\n\n  /**\n   * Sets the dependency factory, which can be used to create custom\n   * goog.Dependency implementations to control how dependencies are loaded.\n   *\n   * Note: if you wish to call this function and provide your own implemnetation\n   * it is a wise idea to set CLOSURE_NO_DEPS to true, otherwise the dependency\n   * file and all of its goog.addDependency calls will use the default factory.\n   * You can call goog.loadClosureDeps to load the Closure dependency file\n   * later, after your factory is injected.\n   *\n   * @param {!goog.DependencyFactory} factory\n   */\n  goog.setDependencyFactory = function(factory) {\n    goog.debugLoader_.setDependencyFactory(factory);\n  };\n\n\n  /**\n   * Trusted Types policy for the debug loader.\n   * @private @const {?TrustedTypePolicy}\n   */\n  goog.TRUSTED_TYPES_POLICY_ = goog.TRUSTED_TYPES_POLICY_NAME ?\n      goog.createTrustedTypesPolicy(goog.TRUSTED_TYPES_POLICY_NAME + '#base') :\n      null;\n\n  if (!goog.global.CLOSURE_NO_DEPS) {\n    goog.debugLoader_.loadClosureDeps();\n  }\n\n\n  /**\n   * Bootstraps the given namespaces and calls the callback once they are\n   * available either via goog.require. This is a replacement for using\n   * `goog.require` to bootstrap Closure JavaScript. Previously a `goog.require`\n   * in an HTML file would guarantee that the require'd namespace was available\n   * in the next immediate script tag. With ES6 modules this no longer a\n   * guarantee.\n   *\n   * @param {!Array<string>} namespaces\n   * @param {function(): ?} callback Function to call once all the namespaces\n   *     have loaded. Always called asynchronously.\n   */\n  goog.bootstrap = function(namespaces, callback) {\n    goog.debugLoader_.bootstrap(namespaces, callback);\n  };\n}\n\n\nif (!COMPILED) {\n  var isChrome87 = false;\n  // Cannot run check for Chrome <87 bug in case of strict CSP environments.\n  // TODO(user): Remove once Chrome <87 bug is no longer a problem.\n  try {\n    isChrome87 = eval(goog.global.trustedTypes.emptyScript) !==\n        goog.global.trustedTypes.emptyScript;\n  } catch (err) {\n  }\n\n  /**\n   * Trusted Types for running dev servers.\n   *\n   * @private @const\n   */\n  goog.CLOSURE_EVAL_PREFILTER_ =\n      // Detect Chrome <87 bug with TT and eval.\n      goog.global.trustedTypes && isChrome87 &&\n          goog.createTrustedTypesPolicy('goog#base#devonly#eval') ||\n      {createScript: goog.identity_};\n}\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Implements the disposable interface.\n */\n\ngoog.provide('goog.Disposable');\n\ngoog.require('goog.disposable.IDisposable');\ngoog.require('goog.dispose');\n/**\n * TODO(user): Remove this require.\n * @suppress {extraRequire}\n */\ngoog.require('goog.disposeAll');\n\n/**\n * Class that provides the basic implementation for disposable objects. If your\n * class holds references or resources that can't be collected by standard GC,\n * it should extend this class or implement the disposable interface (defined\n * in goog.disposable.IDisposable). See description of\n * goog.disposable.IDisposable for examples of cleanup.\n * @constructor\n * @implements {goog.disposable.IDisposable}\n */\ngoog.Disposable = function() {\n  'use strict';\n  /**\n   * If monitoring the goog.Disposable instances is enabled, stores the creation\n   * stack trace of the Disposable instance.\n   * @type {string|undefined}\n   */\n  this.creationStack;\n\n  if (goog.Disposable.MONITORING_MODE != goog.Disposable.MonitoringMode.OFF) {\n    if (goog.Disposable.INCLUDE_STACK_ON_CREATION) {\n      this.creationStack = new Error().stack;\n    }\n    goog.Disposable.instances_[goog.getUid(this)] = this;\n  }\n  // Support sealing\n  this.disposed_ = this.disposed_;\n  this.onDisposeCallbacks_ = this.onDisposeCallbacks_;\n};\n\n\n/**\n * @enum {number} Different monitoring modes for Disposable.\n */\ngoog.Disposable.MonitoringMode = {\n  /**\n   * No monitoring.\n   */\n  OFF: 0,\n  /**\n   * Creating and disposing the goog.Disposable instances is monitored. All\n   * disposable objects need to call the `goog.Disposable` base\n   * constructor. The PERMANENT mode must be switched on before creating any\n   * goog.Disposable instances.\n   */\n  PERMANENT: 1,\n  /**\n   * INTERACTIVE mode can be switched on and off on the fly without producing\n   * errors. It also doesn't warn if the disposable objects don't call the\n   * `goog.Disposable` base constructor.\n   */\n  INTERACTIVE: 2\n};\n\n\n/**\n * @define {number} The monitoring mode of the goog.Disposable\n *     instances. Default is OFF. Switching on the monitoring is only\n *     recommended for debugging because it has a significant impact on\n *     performance and memory usage. If switched off, the monitoring code\n *     compiles down to 0 bytes.\n */\ngoog.Disposable.MONITORING_MODE =\n    goog.define('goog.Disposable.MONITORING_MODE', 0);\n\n\n/**\n * @define {boolean} Whether to attach creation stack to each created disposable\n *     instance; This is only relevant for when MonitoringMode != OFF.\n */\ngoog.Disposable.INCLUDE_STACK_ON_CREATION =\n    goog.define('goog.Disposable.INCLUDE_STACK_ON_CREATION', true);\n\n\n/**\n * Maps the unique ID of every undisposed `goog.Disposable` object to\n * the object itself.\n * @type {!Object<number, !goog.Disposable>}\n * @private\n */\ngoog.Disposable.instances_ = {};\n\n\n/**\n * @return {!Array<!goog.Disposable>} All `goog.Disposable` objects that\n *     haven't been disposed of.\n */\ngoog.Disposable.getUndisposedObjects = function() {\n  'use strict';\n  var ret = [];\n  for (var id in goog.Disposable.instances_) {\n    if (goog.Disposable.instances_.hasOwnProperty(id)) {\n      ret.push(goog.Disposable.instances_[Number(id)]);\n    }\n  }\n  return ret;\n};\n\n\n/**\n * Clears the registry of undisposed objects but doesn't dispose of them.\n */\ngoog.Disposable.clearUndisposedObjects = function() {\n  'use strict';\n  goog.Disposable.instances_ = {};\n};\n\n\n/**\n * Whether the object has been disposed of.\n * @type {boolean}\n * @private\n */\ngoog.Disposable.prototype.disposed_ = false;\n\n\n/**\n * Callbacks to invoke when this object is disposed.\n * @type {Array<!Function>}\n * @private\n */\ngoog.Disposable.prototype.onDisposeCallbacks_;\n\n\n/**\n * @return {boolean} Whether the object has been disposed of.\n * @override\n */\ngoog.Disposable.prototype.isDisposed = function() {\n  'use strict';\n  return this.disposed_;\n};\n\n\n/**\n * @return {boolean} Whether the object has been disposed of.\n * @deprecated Use {@link #isDisposed} instead.\n */\ngoog.Disposable.prototype.getDisposed = goog.Disposable.prototype.isDisposed;\n\n\n/**\n * Disposes of the object. If the object hasn't already been disposed of, calls\n * {@link #disposeInternal}. Classes that extend `goog.Disposable` should\n * override {@link #disposeInternal} in order to cleanup references, resources\n * and other disposable objects. Reentrant.\n *\n * @return {void} Nothing.\n * @override\n */\ngoog.Disposable.prototype.dispose = function() {\n  'use strict';\n  if (!this.disposed_) {\n    // Set disposed_ to true first, in case during the chain of disposal this\n    // gets disposed recursively.\n    this.disposed_ = true;\n    this.disposeInternal();\n    if (goog.Disposable.MONITORING_MODE != goog.Disposable.MonitoringMode.OFF) {\n      var uid = goog.getUid(this);\n      if (goog.Disposable.MONITORING_MODE ==\n              goog.Disposable.MonitoringMode.PERMANENT &&\n          !goog.Disposable.instances_.hasOwnProperty(uid)) {\n        throw new Error(\n            this + ' did not call the goog.Disposable base ' +\n            'constructor or was disposed of after a clearUndisposedObjects ' +\n            'call');\n      }\n      if (goog.Disposable.MONITORING_MODE !=\n              goog.Disposable.MonitoringMode.OFF &&\n          this.onDisposeCallbacks_ && this.onDisposeCallbacks_.length > 0) {\n        throw new Error(\n            this + ' did not empty its onDisposeCallbacks queue. This ' +\n            'probably means it overrode dispose() or disposeInternal() ' +\n            'without calling the superclass\\' method.');\n      }\n      delete goog.Disposable.instances_[uid];\n    }\n  }\n};\n\n\n/**\n * Associates a disposable object with this object so that they will be disposed\n * together.\n * @param {goog.disposable.IDisposable} disposable that will be disposed when\n *     this object is disposed.\n */\ngoog.Disposable.prototype.registerDisposable = function(disposable) {\n  'use strict';\n  this.addOnDisposeCallback(goog.partial(goog.dispose, disposable));\n};\n\n\n/**\n * Invokes a callback function when this object is disposed. Callbacks are\n * invoked in the order in which they were added. If a callback is added to\n * an already disposed Disposable, it will be called immediately.\n * @param {function(this:T):?} callback The callback function.\n * @param {T=} opt_scope An optional scope to call the callback in.\n * @template T\n */\ngoog.Disposable.prototype.addOnDisposeCallback = function(callback, opt_scope) {\n  'use strict';\n  if (this.disposed_) {\n    opt_scope !== undefined ? callback.call(opt_scope) : callback();\n    return;\n  }\n  if (!this.onDisposeCallbacks_) {\n    this.onDisposeCallbacks_ = [];\n  }\n\n  this.onDisposeCallbacks_.push(\n      opt_scope !== undefined ? goog.bind(callback, opt_scope) : callback);\n};\n\n\n/**\n * Performs appropriate cleanup. See description of goog.disposable.IDisposable\n * for examples. Classes that extend `goog.Disposable` should override this\n * method. Not reentrant. To avoid calling it twice, it must only be called from\n * the subclass' `disposeInternal` method. Everywhere else the public `dispose`\n * method must be used. For example:\n *\n * <pre>\n * mypackage.MyClass = function() {\n * mypackage.MyClass.base(this, 'constructor');\n *     // Constructor logic specific to MyClass.\n *     ...\n *   };\n *   goog.inherits(mypackage.MyClass, goog.Disposable);\n *\n *   mypackage.MyClass.prototype.disposeInternal = function() {\n *     // Dispose logic specific to MyClass.\n *     ...\n *     // Call superclass's disposeInternal at the end of the subclass's, like\n *     // in C++, to avoid hard-to-catch issues.\n *     mypackage.MyClass.base(this, 'disposeInternal');\n *   };\n * </pre>\n *\n * @protected\n */\ngoog.Disposable.prototype.disposeInternal = function() {\n  'use strict';\n  if (this.onDisposeCallbacks_) {\n    while (this.onDisposeCallbacks_.length) {\n      this.onDisposeCallbacks_.shift()();\n    }\n  }\n};\n\n\n/**\n * Returns True if we can verify the object is disposed.\n * Calls `isDisposed` on the argument if it supports it.  If obj\n * is not an object with an isDisposed() method, return false.\n * @param {*} obj The object to investigate.\n * @return {boolean} True if we can verify the object is disposed.\n */\ngoog.Disposable.isDisposed = function(obj) {\n  'use strict';\n  if (obj && typeof obj.isDisposed == 'function') {\n    return obj.isDisposed();\n  }\n  return false;\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Utilities for manipulating arrays.\n */\n\n\ngoog.module('goog.array');\ngoog.module.declareLegacyNamespace();\n\nconst asserts = goog.require('goog.asserts');\n\n\n/**\n * @define {boolean} NATIVE_ARRAY_PROTOTYPES indicates whether the code should\n * rely on Array.prototype functions, if available.\n *\n * The Array.prototype functions can be defined by external libraries like\n * Prototype and setting this flag to false forces closure to use its own\n * goog.array implementation.\n *\n * If your javascript can be loaded by a third party site and you are wary about\n * relying on the prototype functions, specify\n * \"--define goog.NATIVE_ARRAY_PROTOTYPES=false\" to the JSCompiler.\n *\n * Setting goog.TRUSTED_SITE to false will automatically set\n * NATIVE_ARRAY_PROTOTYPES to false.\n */\ngoog.NATIVE_ARRAY_PROTOTYPES =\n    goog.define('goog.NATIVE_ARRAY_PROTOTYPES', goog.TRUSTED_SITE);\n\n\n/**\n * @define {boolean} If true, JSCompiler will use the native implementation of\n * array functions where appropriate (e.g., `Array#filter`) and remove the\n * unused pure JS implementation.\n */\nconst ASSUME_NATIVE_FUNCTIONS = goog.define(\n    'goog.array.ASSUME_NATIVE_FUNCTIONS', goog.FEATURESET_YEAR > 2012);\nexports.ASSUME_NATIVE_FUNCTIONS = ASSUME_NATIVE_FUNCTIONS;\n\n\n/**\n * Returns the last element in an array without removing it.\n * Same as {@link goog.array.last}.\n * @param {IArrayLike<T>|string} array The array.\n * @return {T} Last item in array.\n * @template T\n */\nfunction peek(array) {\n  return array[array.length - 1];\n}\nexports.peek = peek;\n\n\n/**\n * Returns the last element in an array without removing it.\n * Same as {@link goog.array.peek}.\n * @param {IArrayLike<T>|string} array The array.\n * @return {T} Last item in array.\n * @template T\n */\nexports.last = peek;\n\n// NOTE(arv): Since most of the array functions are generic it allows you to\n// pass an array-like object. Strings have a length and are considered array-\n// like. However, the 'in' operator does not work on strings so we cannot just\n// use the array path even if the browser supports indexing into strings. We\n// therefore end up splitting the string.\n\n\n/**\n * Returns the index of the first element of an array with a specified value, or\n * -1 if the element is not present in the array.\n *\n * See {@link http://tinyurl.com/developer-mozilla-org-array-indexof}\n *\n * @param {IArrayLike<T>|string} arr The array to be searched.\n * @param {T} obj The object for which we are searching.\n * @param {number=} opt_fromIndex The index at which to start the search. If\n *     omitted the search starts at index 0.\n * @return {number} The index of the first matching array element.\n * @template T\n */\nconst indexOf = goog.NATIVE_ARRAY_PROTOTYPES &&\n        (ASSUME_NATIVE_FUNCTIONS || Array.prototype.indexOf) ?\n    function(arr, obj, opt_fromIndex) {\n      asserts.assert(arr.length != null);\n\n      return Array.prototype.indexOf.call(arr, obj, opt_fromIndex);\n    } :\n    function(arr, obj, opt_fromIndex) {\n      const fromIndex = opt_fromIndex == null ?\n          0 :\n          (opt_fromIndex < 0 ? Math.max(0, arr.length + opt_fromIndex) :\n                               opt_fromIndex);\n\n      if (typeof arr === 'string') {\n        // Array.prototype.indexOf uses === so only strings should be found.\n        if (typeof obj !== 'string' || obj.length != 1) {\n          return -1;\n        }\n        return arr.indexOf(obj, fromIndex);\n      }\n\n      for (let i = fromIndex; i < arr.length; i++) {\n        if (i in arr && arr[i] === obj) return i;\n      }\n      return -1;\n    };\nexports.indexOf = indexOf;\n\n\n/**\n * Returns the index of the last element of an array with a specified value, or\n * -1 if the element is not present in the array.\n *\n * See {@link http://tinyurl.com/developer-mozilla-org-array-lastindexof}\n *\n * @param {!IArrayLike<T>|string} arr The array to be searched.\n * @param {T} obj The object for which we are searching.\n * @param {?number=} opt_fromIndex The index at which to start the search. If\n *     omitted the search starts at the end of the array.\n * @return {number} The index of the last matching array element.\n * @template T\n */\nconst lastIndexOf = goog.NATIVE_ARRAY_PROTOTYPES &&\n        (ASSUME_NATIVE_FUNCTIONS || Array.prototype.lastIndexOf) ?\n    function(arr, obj, opt_fromIndex) {\n      asserts.assert(arr.length != null);\n\n      // Firefox treats undefined and null as 0 in the fromIndex argument which\n      // leads it to always return -1\n      const fromIndex = opt_fromIndex == null ? arr.length - 1 : opt_fromIndex;\n      return Array.prototype.lastIndexOf.call(arr, obj, fromIndex);\n    } :\n    function(arr, obj, opt_fromIndex) {\n      let fromIndex = opt_fromIndex == null ? arr.length - 1 : opt_fromIndex;\n\n      if (fromIndex < 0) {\n        fromIndex = Math.max(0, arr.length + fromIndex);\n      }\n\n      if (typeof arr === 'string') {\n        // Array.prototype.lastIndexOf uses === so only strings should be found.\n        if (typeof obj !== 'string' || obj.length != 1) {\n          return -1;\n        }\n        return arr.lastIndexOf(obj, fromIndex);\n      }\n\n      for (let i = fromIndex; i >= 0; i--) {\n        if (i in arr && arr[i] === obj) return i;\n      }\n      return -1;\n    };\nexports.lastIndexOf = lastIndexOf;\n\n\n/**\n * Calls a function for each element in an array. Skips holes in the array.\n * See {@link http://tinyurl.com/developer-mozilla-org-array-foreach}\n *\n * @param {IArrayLike<T>|string} arr Array or array like object over\n *     which to iterate.\n * @param {?function(this: S, T, number, ?): ?} f The function to call for every\n *     element. This function takes 3 arguments (the element, the index and the\n *     array). The return value is ignored.\n * @param {S=} opt_obj The object to be used as the value of 'this' within f.\n * @template T,S\n */\nconst forEach = goog.NATIVE_ARRAY_PROTOTYPES &&\n        (ASSUME_NATIVE_FUNCTIONS || Array.prototype.forEach) ?\n    function(arr, f, opt_obj) {\n      asserts.assert(arr.length != null);\n\n      Array.prototype.forEach.call(arr, f, opt_obj);\n    } :\n    function(arr, f, opt_obj) {\n      const l = arr.length;  // must be fixed during loop... see docs\n      const arr2 = (typeof arr === 'string') ? arr.split('') : arr;\n      for (let i = 0; i < l; i++) {\n        if (i in arr2) {\n          f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr);\n        }\n      }\n    };\nexports.forEach = forEach;\n\n\n/**\n * Calls a function for each element in an array, starting from the last\n * element rather than the first.\n *\n * @param {IArrayLike<T>|string} arr Array or array\n *     like object over which to iterate.\n * @param {?function(this: S, T, number, ?): ?} f The function to call for every\n *     element. This function\n *     takes 3 arguments (the element, the index and the array). The return\n *     value is ignored.\n * @param {S=} opt_obj The object to be used as the value of 'this'\n *     within f.\n * @template T,S\n */\nfunction forEachRight(arr, f, opt_obj) {\n  const l = arr.length;  // must be fixed during loop... see docs\n  const arr2 = (typeof arr === 'string') ? arr.split('') : arr;\n  for (let i = l - 1; i >= 0; --i) {\n    if (i in arr2) {\n      f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr);\n    }\n  }\n}\nexports.forEachRight = forEachRight;\n\n\n/**\n * Calls a function for each element in an array, and if the function returns\n * true adds the element to a new array.\n *\n * See {@link http://tinyurl.com/developer-mozilla-org-array-filter}\n *\n * @param {IArrayLike<T>|string} arr Array or array\n *     like object over which to iterate.\n * @param {?function(this:S, T, number, ?):boolean} f The function to call for\n *     every element. This function\n *     takes 3 arguments (the element, the index and the array) and must\n *     return a Boolean. If the return value is true the element is added to the\n *     result array. If it is false the element is not included.\n * @param {S=} opt_obj The object to be used as the value of 'this'\n *     within f.\n * @return {!Array<T>} a new array in which only elements that passed the test\n *     are present.\n * @template T,S\n */\nconst filter = goog.NATIVE_ARRAY_PROTOTYPES &&\n        (ASSUME_NATIVE_FUNCTIONS || Array.prototype.filter) ?\n    function(arr, f, opt_obj) {\n      asserts.assert(arr.length != null);\n\n      return Array.prototype.filter.call(arr, f, opt_obj);\n    } :\n    function(arr, f, opt_obj) {\n      const l = arr.length;  // must be fixed during loop... see docs\n      const res = [];\n      let resLength = 0;\n      const arr2 = (typeof arr === 'string') ? arr.split('') : arr;\n      for (let i = 0; i < l; i++) {\n        if (i in arr2) {\n          const val = arr2[i];  // in case f mutates arr2\n          if (f.call(/** @type {?} */ (opt_obj), val, i, arr)) {\n            res[resLength++] = val;\n          }\n        }\n      }\n      return res;\n    };\nexports.filter = filter;\n\n\n/**\n * Calls a function for each element in an array and inserts the result into a\n * new array.\n *\n * See {@link http://tinyurl.com/developer-mozilla-org-array-map}\n *\n * @param {IArrayLike<VALUE>|string} arr Array or array like object\n *     over which to iterate.\n * @param {function(this:THIS, VALUE, number, ?): RESULT} f The function to call\n *     for every element. This function takes 3 arguments (the element,\n *     the index and the array) and should return something. The result will be\n *     inserted into a new array.\n * @param {THIS=} opt_obj The object to be used as the value of 'this' within f.\n * @return {!Array<RESULT>} a new array with the results from f.\n * @template THIS, VALUE, RESULT\n */\nconst map = goog.NATIVE_ARRAY_PROTOTYPES &&\n        (ASSUME_NATIVE_FUNCTIONS || Array.prototype.map) ?\n    function(arr, f, opt_obj) {\n      asserts.assert(arr.length != null);\n\n      return Array.prototype.map.call(arr, f, opt_obj);\n    } :\n    function(arr, f, opt_obj) {\n      const l = arr.length;  // must be fixed during loop... see docs\n      const res = new Array(l);\n      const arr2 = (typeof arr === 'string') ? arr.split('') : arr;\n      for (let i = 0; i < l; i++) {\n        if (i in arr2) {\n          res[i] = f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr);\n        }\n      }\n      return res;\n    };\nexports.map = map;\n\n\n/**\n * Passes every element of an array into a function and accumulates the result.\n *\n * See {@link http://tinyurl.com/developer-mozilla-org-array-reduce}\n * Note that this implementation differs from the native Array.prototype.reduce\n * in that the initial value is assumed to be defined (the MDN docs linked above\n * recommend not omitting this parameter, although it is technically optional).\n *\n * For example:\n * var a = [1, 2, 3, 4];\n * reduce(a, function(r, v, i, arr) {return r + v;}, 0);\n * returns 10\n *\n * @param {IArrayLike<T>|string} arr Array or array\n *     like object over which to iterate.\n * @param {function(this:S, R, T, number, ?) : R} f The function to call for\n *     every element. This function\n *     takes 4 arguments (the function's previous result or the initial value,\n *     the value of the current array element, the current array index, and the\n *     array itself)\n *     function(previousValue, currentValue, index, array).\n * @param {?} val The initial value to pass into the function on the first call.\n * @param {S=} opt_obj  The object to be used as the value of 'this'\n *     within f.\n * @return {R} Result of evaluating f repeatedly across the values of the array.\n * @template T,S,R\n */\nconst reduce = goog.NATIVE_ARRAY_PROTOTYPES &&\n        (ASSUME_NATIVE_FUNCTIONS || Array.prototype.reduce) ?\n    function(arr, f, val, opt_obj) {\n      asserts.assert(arr.length != null);\n      if (opt_obj) {\n        f = goog.bind(f, opt_obj);\n      }\n      return Array.prototype.reduce.call(arr, f, val);\n    } :\n    function(arr, f, val, opt_obj) {\n      let rval = val;\n      forEach(arr, function(val, index) {\n        rval = f.call(/** @type {?} */ (opt_obj), rval, val, index, arr);\n      });\n      return rval;\n    };\nexports.reduce = reduce;\n\n\n/**\n * Passes every element of an array into a function and accumulates the result,\n * starting from the last element and working towards the first.\n *\n * See {@link http://tinyurl.com/developer-mozilla-org-array-reduceright}\n *\n * For example:\n * var a = ['a', 'b', 'c'];\n * reduceRight(a, function(r, v, i, arr) {return r + v;}, '');\n * returns 'cba'\n *\n * @param {IArrayLike<T>|string} arr Array or array\n *     like object over which to iterate.\n * @param {?function(this:S, R, T, number, ?) : R} f The function to call for\n *     every element. This function\n *     takes 4 arguments (the function's previous result or the initial value,\n *     the value of the current array element, the current array index, and the\n *     array itself)\n *     function(previousValue, currentValue, index, array).\n * @param {?} val The initial value to pass into the function on the first call.\n * @param {S=} opt_obj The object to be used as the value of 'this'\n *     within f.\n * @return {R} Object returned as a result of evaluating f repeatedly across the\n *     values of the array.\n * @template T,S,R\n */\nconst reduceRight = goog.NATIVE_ARRAY_PROTOTYPES &&\n        (ASSUME_NATIVE_FUNCTIONS || Array.prototype.reduceRight) ?\n    function(arr, f, val, opt_obj) {\n      asserts.assert(arr.length != null);\n      asserts.assert(f != null);\n      if (opt_obj) {\n        f = goog.bind(f, opt_obj);\n      }\n      return Array.prototype.reduceRight.call(arr, f, val);\n    } :\n    function(arr, f, val, opt_obj) {\n      let rval = val;\n      forEachRight(arr, function(val, index) {\n        rval = f.call(/** @type {?} */ (opt_obj), rval, val, index, arr);\n      });\n      return rval;\n    };\nexports.reduceRight = reduceRight;\n\n\n/**\n * Calls f for each element of an array. If any call returns true, some()\n * returns true (without checking the remaining elements). If all calls\n * return false, some() returns false.\n *\n * See {@link http://tinyurl.com/developer-mozilla-org-array-some}\n *\n * @param {IArrayLike<T>|string} arr Array or array\n *     like object over which to iterate.\n * @param {?function(this:S, T, number, ?) : boolean} f The function to call for\n *     for every element. This function takes 3 arguments (the element, the\n *     index and the array) and should return a boolean.\n * @param {S=} opt_obj  The object to be used as the value of 'this'\n *     within f.\n * @return {boolean} true if any element passes the test.\n * @template T,S\n */\nconst some = goog.NATIVE_ARRAY_PROTOTYPES &&\n        (ASSUME_NATIVE_FUNCTIONS || Array.prototype.some) ?\n    function(arr, f, opt_obj) {\n      asserts.assert(arr.length != null);\n\n      return Array.prototype.some.call(arr, f, opt_obj);\n    } :\n    function(arr, f, opt_obj) {\n      const l = arr.length;  // must be fixed during loop... see docs\n      const arr2 = (typeof arr === 'string') ? arr.split('') : arr;\n      for (let i = 0; i < l; i++) {\n        if (i in arr2 && f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr)) {\n          return true;\n        }\n      }\n      return false;\n    };\nexports.some = some;\n\n\n/**\n * Call f for each element of an array. If all calls return true, every()\n * returns true. If any call returns false, every() returns false and\n * does not continue to check the remaining elements.\n *\n * See {@link http://tinyurl.com/developer-mozilla-org-array-every}\n *\n * @param {IArrayLike<T>|string} arr Array or array\n *     like object over which to iterate.\n * @param {?function(this:S, T, number, ?) : boolean} f The function to call for\n *     for every element. This function takes 3 arguments (the element, the\n *     index and the array) and should return a boolean.\n * @param {S=} opt_obj The object to be used as the value of 'this'\n *     within f.\n * @return {boolean} false if any element fails the test.\n * @template T,S\n */\nconst every = goog.NATIVE_ARRAY_PROTOTYPES &&\n        (ASSUME_NATIVE_FUNCTIONS || Array.prototype.every) ?\n    function(arr, f, opt_obj) {\n      asserts.assert(arr.length != null);\n\n      return Array.prototype.every.call(arr, f, opt_obj);\n    } :\n    function(arr, f, opt_obj) {\n      const l = arr.length;  // must be fixed during loop... see docs\n      const arr2 = (typeof arr === 'string') ? arr.split('') : arr;\n      for (let i = 0; i < l; i++) {\n        if (i in arr2 && !f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr)) {\n          return false;\n        }\n      }\n      return true;\n    };\nexports.every = every;\n\n\n/**\n * Counts the array elements that fulfill the predicate, i.e. for which the\n * callback function returns true. Skips holes in the array.\n *\n * @param {!IArrayLike<T>|string} arr Array or array like object\n *     over which to iterate.\n * @param {function(this: S, T, number, ?): boolean} f The function to call for\n *     every element. Takes 3 arguments (the element, the index and the array).\n * @param {S=} opt_obj The object to be used as the value of 'this' within f.\n * @return {number} The number of the matching elements.\n * @template T,S\n */\nfunction count(arr, f, opt_obj) {\n  let count = 0;\n  forEach(arr, function(element, index, arr) {\n    if (f.call(/** @type {?} */ (opt_obj), element, index, arr)) {\n      ++count;\n    }\n  }, opt_obj);\n  return count;\n}\nexports.count = count;\n\n\n/**\n * Search an array for the first element that satisfies a given condition and\n * return that element.\n * @param {IArrayLike<T>|string} arr Array or array\n *     like object over which to iterate.\n * @param {?function(this:S, T, number, ?) : boolean} f The function to call\n *     for every element. This function takes 3 arguments (the element, the\n *     index and the array) and should return a boolean.\n * @param {S=} opt_obj An optional \"this\" context for the function.\n * @return {T|null} The first array element that passes the test, or null if no\n *     element is found.\n * @template T,S\n */\nfunction find(arr, f, opt_obj) {\n  const i = findIndex(arr, f, opt_obj);\n  return i < 0 ? null : typeof arr === 'string' ? arr.charAt(i) : arr[i];\n}\nexports.find = find;\n\n\n/**\n * Search an array for the first element that satisfies a given condition and\n * return its index.\n * @param {IArrayLike<T>|string} arr Array or array\n *     like object over which to iterate.\n * @param {?function(this:S, T, number, ?) : boolean} f The function to call for\n *     every element. This function\n *     takes 3 arguments (the element, the index and the array) and should\n *     return a boolean.\n * @param {S=} opt_obj An optional \"this\" context for the function.\n * @return {number} The index of the first array element that passes the test,\n *     or -1 if no element is found.\n * @template T,S\n */\nfunction findIndex(arr, f, opt_obj) {\n  const l = arr.length;  // must be fixed during loop... see docs\n  const arr2 = (typeof arr === 'string') ? arr.split('') : arr;\n  for (let i = 0; i < l; i++) {\n    if (i in arr2 && f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr)) {\n      return i;\n    }\n  }\n  return -1;\n}\nexports.findIndex = findIndex;\n\n\n/**\n * Search an array (in reverse order) for the last element that satisfies a\n * given condition and return that element.\n * @param {IArrayLike<T>|string} arr Array or array\n *     like object over which to iterate.\n * @param {?function(this:S, T, number, ?) : boolean} f The function to call\n *     for every element. This function\n *     takes 3 arguments (the element, the index and the array) and should\n *     return a boolean.\n * @param {S=} opt_obj An optional \"this\" context for the function.\n * @return {T|null} The last array element that passes the test, or null if no\n *     element is found.\n * @template T,S\n */\nfunction findRight(arr, f, opt_obj) {\n  const i = findIndexRight(arr, f, opt_obj);\n  return i < 0 ? null : typeof arr === 'string' ? arr.charAt(i) : arr[i];\n}\nexports.findRight = findRight;\n\n\n/**\n * Search an array (in reverse order) for the last element that satisfies a\n * given condition and return its index.\n * @param {IArrayLike<T>|string} arr Array or array\n *     like object over which to iterate.\n * @param {?function(this:S, T, number, ?) : boolean} f The function to call\n *     for every element. This function\n *     takes 3 arguments (the element, the index and the array) and should\n *     return a boolean.\n * @param {S=} opt_obj An optional \"this\" context for the function.\n * @return {number} The index of the last array element that passes the test,\n *     or -1 if no element is found.\n * @template T,S\n */\nfunction findIndexRight(arr, f, opt_obj) {\n  const l = arr.length;  // must be fixed during loop... see docs\n  const arr2 = (typeof arr === 'string') ? arr.split('') : arr;\n  for (let i = l - 1; i >= 0; i--) {\n    if (i in arr2 && f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr)) {\n      return i;\n    }\n  }\n  return -1;\n}\nexports.findIndexRight = findIndexRight;\n\n\n/**\n * Whether the array contains the given object.\n * @param {IArrayLike<?>|string} arr The array to test for the presence of the\n *     element.\n * @param {*} obj The object for which to test.\n * @return {boolean} true if obj is present.\n */\nfunction contains(arr, obj) {\n  return indexOf(arr, obj) >= 0;\n}\nexports.contains = contains;\n\n\n/**\n * Whether the array is empty.\n * @param {IArrayLike<?>|string} arr The array to test.\n * @return {boolean} true if empty.\n */\nfunction isEmpty(arr) {\n  return arr.length == 0;\n}\nexports.isEmpty = isEmpty;\n\n\n/**\n * Clears the array.\n * @param {IArrayLike<?>} arr Array or array like object to clear.\n */\nfunction clear(arr) {\n  // For non real arrays we don't have the magic length so we delete the\n  // indices.\n  if (!Array.isArray(arr)) {\n    for (let i = arr.length - 1; i >= 0; i--) {\n      delete arr[i];\n    }\n  }\n  arr.length = 0;\n}\nexports.clear = clear;\n\n\n/**\n * Pushes an item into an array, if it's not already in the array.\n * @param {Array<T>} arr Array into which to insert the item.\n * @param {T} obj Value to add.\n * @template T\n */\nfunction insert(arr, obj) {\n  if (!contains(arr, obj)) {\n    arr.push(obj);\n  }\n}\nexports.insert = insert;\n\n\n/**\n * Inserts an object at the given index of the array.\n * @param {IArrayLike<?>} arr The array to modify.\n * @param {*} obj The object to insert.\n * @param {number=} opt_i The index at which to insert the object. If omitted,\n *      treated as 0. A negative index is counted from the end of the array.\n */\nfunction insertAt(arr, obj, opt_i) {\n  splice(arr, opt_i, 0, obj);\n}\nexports.insertAt = insertAt;\n\n\n/**\n * Inserts at the given index of the array, all elements of another array.\n * @param {IArrayLike<?>} arr The array to modify.\n * @param {IArrayLike<?>} elementsToAdd The array of elements to add.\n * @param {number=} opt_i The index at which to insert the object. If omitted,\n *      treated as 0. A negative index is counted from the end of the array.\n */\nfunction insertArrayAt(arr, elementsToAdd, opt_i) {\n  goog.partial(splice, arr, opt_i, 0).apply(null, elementsToAdd);\n}\nexports.insertArrayAt = insertArrayAt;\n\n\n/**\n * Inserts an object into an array before a specified object.\n * @param {Array<T>} arr The array to modify.\n * @param {T} obj The object to insert.\n * @param {T=} opt_obj2 The object before which obj should be inserted. If obj2\n *     is omitted or not found, obj is inserted at the end of the array.\n * @template T\n */\nfunction insertBefore(arr, obj, opt_obj2) {\n  let i;\n  if (arguments.length == 2 || (i = indexOf(arr, opt_obj2)) < 0) {\n    arr.push(obj);\n  } else {\n    insertAt(arr, obj, i);\n  }\n}\nexports.insertBefore = insertBefore;\n\n\n/**\n * Removes the first occurrence of a particular value from an array.\n * @param {IArrayLike<T>} arr Array from which to remove\n *     value.\n * @param {T} obj Object to remove.\n * @return {boolean} True if an element was removed.\n * @template T\n */\nfunction remove(arr, obj) {\n  const i = indexOf(arr, obj);\n  let rv;\n  if ((rv = i >= 0)) {\n    removeAt(arr, i);\n  }\n  return rv;\n}\nexports.remove = remove;\n\n\n/**\n * Removes the last occurrence of a particular value from an array.\n * @param {!IArrayLike<T>} arr Array from which to remove value.\n * @param {T} obj Object to remove.\n * @return {boolean} True if an element was removed.\n * @template T\n */\nfunction removeLast(arr, obj) {\n  const i = lastIndexOf(arr, obj);\n  if (i >= 0) {\n    removeAt(arr, i);\n    return true;\n  }\n  return false;\n}\nexports.removeLast = removeLast;\n\n\n/**\n * Removes from an array the element at index i\n * @param {IArrayLike<?>} arr Array or array like object from which to\n *     remove value.\n * @param {number} i The index to remove.\n * @return {boolean} True if an element was removed.\n */\nfunction removeAt(arr, i) {\n  asserts.assert(arr.length != null);\n\n  // use generic form of splice\n  // splice returns the removed items and if successful the length of that\n  // will be 1\n  return Array.prototype.splice.call(arr, i, 1).length == 1;\n}\nexports.removeAt = removeAt;\n\n\n/**\n * Removes the first value that satisfies the given condition.\n * @param {IArrayLike<T>} arr Array or array\n *     like object over which to iterate.\n * @param {?function(this:S, T, number, ?) : boolean} f The function to call\n *     for every element. This function\n *     takes 3 arguments (the element, the index and the array) and should\n *     return a boolean.\n * @param {S=} opt_obj An optional \"this\" context for the function.\n * @return {boolean} True if an element was removed.\n * @template T,S\n */\nfunction removeIf(arr, f, opt_obj) {\n  const i = findIndex(arr, f, opt_obj);\n  if (i >= 0) {\n    removeAt(arr, i);\n    return true;\n  }\n  return false;\n}\nexports.removeIf = removeIf;\n\n\n/**\n * Removes all values that satisfy the given condition.\n * @param {IArrayLike<T>} arr Array or array\n *     like object over which to iterate.\n * @param {?function(this:S, T, number, ?) : boolean} f The function to call\n *     for every element. This function\n *     takes 3 arguments (the element, the index and the array) and should\n *     return a boolean.\n * @param {S=} opt_obj An optional \"this\" context for the function.\n * @return {number} The number of items removed\n * @template T,S\n */\nfunction removeAllIf(arr, f, opt_obj) {\n  let removedCount = 0;\n  forEachRight(arr, function(val, index) {\n    if (f.call(/** @type {?} */ (opt_obj), val, index, arr)) {\n      if (removeAt(arr, index)) {\n        removedCount++;\n      }\n    }\n  });\n  return removedCount;\n}\nexports.removeAllIf = removeAllIf;\n\n\n/**\n * Returns a new array that is the result of joining the arguments.  If arrays\n * are passed then their items are added, however, if non-arrays are passed they\n * will be added to the return array as is.\n *\n * Note that ArrayLike objects will be added as is, rather than having their\n * items added.\n *\n * concat([1, 2], [3, 4]) -> [1, 2, 3, 4]\n * concat(0, [1, 2]) -> [0, 1, 2]\n * concat([1, 2], null) -> [1, 2, null]\n *\n * There is bug in all current versions of IE (6, 7 and 8) where arrays created\n * in an iframe become corrupted soon (not immediately) after the iframe is\n * destroyed. This is common if loading data via goog.net.IframeIo, for example.\n * This corruption only affects the concat method which will start throwing\n * Catastrophic Errors (#-2147418113).\n *\n * See http://endoflow.com/scratch/corrupted-arrays.html for a test case.\n *\n * Internally goog.array should use this, so that all methods will continue to\n * work on these broken array objects.\n *\n * @param {...*} var_args Items to concatenate.  Arrays will have each item\n *     added, while primitives and objects will be added as is.\n * @return {!Array<?>} The new resultant array.\n */\nfunction concat(var_args) {\n  return Array.prototype.concat.apply([], arguments);\n}\nexports.concat = concat;\n\n\n/**\n * Returns a new array that contains the contents of all the arrays passed.\n * @param {...!Array<T>} var_args\n * @return {!Array<T>}\n * @template T\n */\nfunction join(var_args) {\n  return Array.prototype.concat.apply([], arguments);\n}\nexports.join = join;\n\n\n/**\n * Converts an object to an array.\n * @param {IArrayLike<T>|string} object  The object to convert to an\n *     array.\n * @return {!Array<T>} The object converted into an array. If object has a\n *     length property, every property indexed with a non-negative number\n *     less than length will be included in the result. If object does not\n *     have a length property, an empty array will be returned.\n * @template T\n */\nfunction toArray(object) {\n  const length = object.length;\n\n  // If length is not a number the following is false. This case is kept for\n  // backwards compatibility since there are callers that pass objects that are\n  // not array like.\n  if (length > 0) {\n    const rv = new Array(length);\n    for (let i = 0; i < length; i++) {\n      rv[i] = object[i];\n    }\n    return rv;\n  }\n  return [];\n}\nexports.toArray = toArray;\n\n\n/**\n * Does a shallow copy of an array.\n * @param {IArrayLike<T>|string} arr  Array or array-like object to\n *     clone.\n * @return {!Array<T>} Clone of the input array.\n * @template T\n */\nconst clone = toArray;\nexports.clone = clone;\n\n\n/**\n * Extends an array with another array, element, or \"array like\" object.\n * This function operates 'in-place', it does not create a new Array.\n *\n * Example:\n * var a = [];\n * extend(a, [0, 1]);\n * a; // [0, 1]\n * extend(a, 2);\n * a; // [0, 1, 2]\n *\n * @param {Array<VALUE>} arr1  The array to modify.\n * @param {...(IArrayLike<VALUE>|VALUE)} var_args The elements or arrays of\n *     elements to add to arr1.\n * @template VALUE\n */\nfunction extend(arr1, var_args) {\n  for (let i = 1; i < arguments.length; i++) {\n    const arr2 = arguments[i];\n    if (goog.isArrayLike(arr2)) {\n      const len1 = arr1.length || 0;\n      const len2 = arr2.length || 0;\n      arr1.length = len1 + len2;\n      for (let j = 0; j < len2; j++) {\n        arr1[len1 + j] = arr2[j];\n      }\n    } else {\n      arr1.push(arr2);\n    }\n  }\n}\nexports.extend = extend;\n\n\n/**\n * Adds or removes elements from an array. This is a generic version of Array\n * splice. This means that it might work on other objects similar to arrays,\n * such as the arguments object.\n *\n * @param {IArrayLike<T>} arr The array to modify.\n * @param {number|undefined} index The index at which to start changing the\n *     array. If not defined, treated as 0.\n * @param {number} howMany How many elements to remove (0 means no removal. A\n *     value below 0 is treated as zero and so is any other non number. Numbers\n *     are floored).\n * @param {...T} var_args Optional, additional elements to insert into the\n *     array.\n * @return {!Array<T>} the removed elements.\n * @template T\n */\nfunction splice(arr, index, howMany, var_args) {\n  asserts.assert(arr.length != null);\n\n  return Array.prototype.splice.apply(arr, slice(arguments, 1));\n}\nexports.splice = splice;\n\n\n/**\n * Returns a new array from a segment of an array. This is a generic version of\n * Array slice. This means that it might work on other objects similar to\n * arrays, such as the arguments object.\n *\n * @param {IArrayLike<T>|string} arr The array from\n * which to copy a segment.\n * @param {number} start The index of the first element to copy.\n * @param {number=} opt_end The index after the last element to copy.\n * @return {!Array<T>} A new array containing the specified segment of the\n *     original array.\n * @template T\n */\nfunction slice(arr, start, opt_end) {\n  asserts.assert(arr.length != null);\n\n  // passing 1 arg to slice is not the same as passing 2 where the second is\n  // null or undefined (in that case the second argument is treated as 0).\n  // we could use slice on the arguments object and then use apply instead of\n  // testing the length\n  if (arguments.length <= 2) {\n    return Array.prototype.slice.call(arr, start);\n  } else {\n    return Array.prototype.slice.call(arr, start, opt_end);\n  }\n}\nexports.slice = slice;\n\n\n/**\n * Removes all duplicates from an array (retaining only the first\n * occurrence of each array element).  This function modifies the\n * array in place and doesn't change the order of the non-duplicate items.\n *\n * For objects, duplicates are identified as having the same unique ID as\n * defined by {@link goog.getUid}.\n *\n * Alternatively you can specify a custom hash function that returns a unique\n * value for each item in the array it should consider unique.\n *\n * Runtime: N,\n * Worstcase space: 2N (no dupes)\n *\n * @param {IArrayLike<T>} arr The array from which to remove\n *     duplicates.\n * @param {Array=} opt_rv An optional array in which to return the results,\n *     instead of performing the removal inplace.  If specified, the original\n *     array will remain unchanged.\n * @param {function(T):string=} opt_hashFn An optional function to use to\n *     apply to every item in the array. This function should return a unique\n *     value for each item in the array it should consider unique.\n * @template T\n */\nfunction removeDuplicates(arr, opt_rv, opt_hashFn) {\n  const returnArray = opt_rv || arr;\n  const defaultHashFn = function(item) {\n    // Prefix each type with a single character representing the type to\n    // prevent conflicting keys (e.g. true and 'true').\n    return goog.isObject(item) ? 'o' + goog.getUid(item) :\n                                 (typeof item).charAt(0) + item;\n  };\n  const hashFn = opt_hashFn || defaultHashFn;\n\n  let cursorInsert = 0;\n  let cursorRead = 0;\n  const seen = {};\n\n  while (cursorRead < arr.length) {\n    const current = arr[cursorRead++];\n    const key = hashFn(current);\n    if (!Object.prototype.hasOwnProperty.call(seen, key)) {\n      seen[key] = true;\n      returnArray[cursorInsert++] = current;\n    }\n  }\n  returnArray.length = cursorInsert;\n}\nexports.removeDuplicates = removeDuplicates;\n\n\n/**\n * Searches the specified array for the specified target using the binary\n * search algorithm.  If no opt_compareFn is specified, elements are compared\n * using <code>defaultCompare</code>, which compares the elements\n * using the built in < and > operators.  This will produce the expected\n * behavior for homogeneous arrays of String(s) and Number(s). The array\n * specified <b>must</b> be sorted in ascending order (as defined by the\n * comparison function).  If the array is not sorted, results are undefined.\n * If the array contains multiple instances of the specified target value, the\n * left-most instance will be found.\n *\n * Runtime: O(log n)\n *\n * @param {IArrayLike<VALUE>} arr The array to be searched.\n * @param {TARGET} target The sought value.\n * @param {function(TARGET, VALUE): number=} opt_compareFn Optional comparison\n *     function by which the array is ordered. Should take 2 arguments to\n *     compare, the target value and an element from your array, and return a\n *     negative number, zero, or a positive number depending on whether the\n *     first argument is less than, equal to, or greater than the second.\n * @return {number} Lowest index of the target value if found, otherwise\n *     (-(insertion point) - 1). The insertion point is where the value should\n *     be inserted into arr to preserve the sorted property.  Return value >= 0\n *     iff target is found.\n * @template TARGET, VALUE\n */\nfunction binarySearch(arr, target, opt_compareFn) {\n  return binarySearch_(\n      arr, opt_compareFn || defaultCompare, false /* isEvaluator */, target);\n}\nexports.binarySearch = binarySearch;\n\n\n/**\n * Selects an index in the specified array using the binary search algorithm.\n * The evaluator receives an element and determines whether the desired index\n * is before, at, or after it.  The evaluator must be consistent (formally,\n * map(map(arr, evaluator, opt_obj), goog.math.sign)\n * must be monotonically non-increasing).\n *\n * Runtime: O(log n)\n *\n * @param {IArrayLike<VALUE>} arr The array to be searched.\n * @param {function(this:THIS, VALUE, number, ?): number} evaluator\n *     Evaluator function that receives 3 arguments (the element, the index and\n *     the array). Should return a negative number, zero, or a positive number\n *     depending on whether the desired index is before, at, or after the\n *     element passed to it.\n * @param {THIS=} opt_obj The object to be used as the value of 'this'\n *     within evaluator.\n * @return {number} Index of the leftmost element matched by the evaluator, if\n *     such exists; otherwise (-(insertion point) - 1). The insertion point is\n *     the index of the first element for which the evaluator returns negative,\n *     or arr.length if no such element exists. The return value is non-negative\n *     iff a match is found.\n * @template THIS, VALUE\n */\nfunction binarySelect(arr, evaluator, opt_obj) {\n  return binarySearch_(\n      arr, evaluator, true /* isEvaluator */, undefined /* opt_target */,\n      opt_obj);\n}\nexports.binarySelect = binarySelect;\n\n\n/**\n * Implementation of a binary search algorithm which knows how to use both\n * comparison functions and evaluators. If an evaluator is provided, will call\n * the evaluator with the given optional data object, conforming to the\n * interface defined in binarySelect. Otherwise, if a comparison function is\n * provided, will call the comparison function against the given data object.\n *\n * This implementation purposefully does not use goog.bind or goog.partial for\n * performance reasons.\n *\n * Runtime: O(log n)\n *\n * @param {IArrayLike<?>} arr The array to be searched.\n * @param {function(?, ?, ?): number | function(?, ?): number} compareFn\n *     Either an evaluator or a comparison function, as defined by binarySearch\n *     and binarySelect above.\n * @param {boolean} isEvaluator Whether the function is an evaluator or a\n *     comparison function.\n * @param {?=} opt_target If the function is a comparison function, then\n *     this is the target to binary search for.\n * @param {Object=} opt_selfObj If the function is an evaluator, this is an\n *     optional this object for the evaluator.\n * @return {number} Lowest index of the target value if found, otherwise\n *     (-(insertion point) - 1). The insertion point is where the value should\n *     be inserted into arr to preserve the sorted property.  Return value >= 0\n *     iff target is found.\n * @private\n */\nfunction binarySearch_(arr, compareFn, isEvaluator, opt_target, opt_selfObj) {\n  let left = 0;            // inclusive\n  let right = arr.length;  // exclusive\n  let found;\n  while (left < right) {\n    const middle = left + ((right - left) >>> 1);\n    let compareResult;\n    if (isEvaluator) {\n      compareResult = compareFn.call(opt_selfObj, arr[middle], middle, arr);\n    } else {\n      // NOTE(dimvar): To avoid this cast, we'd have to use function overloading\n      // for the type of binarySearch_, which the type system can't express yet.\n      compareResult = /** @type {function(?, ?): number} */ (compareFn)(\n          opt_target, arr[middle]);\n    }\n    if (compareResult > 0) {\n      left = middle + 1;\n    } else {\n      right = middle;\n      // We are looking for the lowest index so we can't return immediately.\n      found = !compareResult;\n    }\n  }\n  // left is the index if found, or the insertion point otherwise.\n  // Avoiding bitwise not operator, as that causes a loss in precision for array\n  // indexes outside the bounds of a 32-bit signed integer.  Array indexes have\n  // a maximum value of 2^32-2 https://tc39.es/ecma262/#array-index\n  return found ? left : -left - 1;\n}\n\n\n/**\n * Sorts the specified array into ascending order.  If no opt_compareFn is\n * specified, elements are compared using\n * <code>defaultCompare</code>, which compares the elements using\n * the built in < and > operators.  This will produce the expected behavior\n * for homogeneous arrays of String(s) and Number(s), unlike the native sort,\n * but will give unpredictable results for heterogeneous lists of strings and\n * numbers with different numbers of digits.\n *\n * This sort is not guaranteed to be stable.\n *\n * Runtime: Same as `Array.prototype.sort`\n *\n * @param {Array<T>} arr The array to be sorted.\n * @param {?function(T,T):number=} opt_compareFn Optional comparison\n *     function by which the\n *     array is to be ordered. Should take 2 arguments to compare, and return a\n *     negative number, zero, or a positive number depending on whether the\n *     first argument is less than, equal to, or greater than the second.\n * @template T\n */\nfunction sort(arr, opt_compareFn) {\n  // TODO(arv): Update type annotation since null is not accepted.\n  arr.sort(opt_compareFn || defaultCompare);\n}\nexports.sort = sort;\n\n\n/**\n * Sorts the specified array into ascending order in a stable way.  If no\n * opt_compareFn is specified, elements are compared using\n * <code>defaultCompare</code>, which compares the elements using\n * the built in < and > operators.  This will produce the expected behavior\n * for homogeneous arrays of String(s) and Number(s).\n *\n * Runtime: Same as `Array.prototype.sort`, plus an additional\n * O(n) overhead of copying the array twice.\n *\n * @param {Array<T>} arr The array to be sorted.\n * @param {?function(T, T): number=} opt_compareFn Optional comparison function\n *     by which the array is to be ordered. Should take 2 arguments to compare,\n *     and return a negative number, zero, or a positive number depending on\n *     whether the first argument is less than, equal to, or greater than the\n *     second.\n * @template T\n */\nfunction stableSort(arr, opt_compareFn) {\n  const compArr = new Array(arr.length);\n  for (let i = 0; i < arr.length; i++) {\n    compArr[i] = {index: i, value: arr[i]};\n  }\n  const valueCompareFn = opt_compareFn || defaultCompare;\n  function stableCompareFn(obj1, obj2) {\n    return valueCompareFn(obj1.value, obj2.value) || obj1.index - obj2.index;\n  }\n  sort(compArr, stableCompareFn);\n  for (let i = 0; i < arr.length; i++) {\n    arr[i] = compArr[i].value;\n  }\n}\nexports.stableSort = stableSort;\n\n\n/**\n * Sort the specified array into ascending order based on item keys\n * returned by the specified key function.\n * If no opt_compareFn is specified, the keys are compared in ascending order\n * using <code>defaultCompare</code>.\n *\n * Runtime: O(S(f(n)), where S is runtime of <code>sort</code>\n * and f(n) is runtime of the key function.\n *\n * @param {Array<T>} arr The array to be sorted.\n * @param {function(T): K} keyFn Function taking array element and returning\n *     a key used for sorting this element.\n * @param {?function(K, K): number=} opt_compareFn Optional comparison function\n *     by which the keys are to be ordered. Should take 2 arguments to compare,\n *     and return a negative number, zero, or a positive number depending on\n *     whether the first argument is less than, equal to, or greater than the\n *     second.\n * @template T,K\n */\nfunction sortByKey(arr, keyFn, opt_compareFn) {\n  const keyCompareFn = opt_compareFn || defaultCompare;\n  sort(arr, function(a, b) {\n    return keyCompareFn(keyFn(a), keyFn(b));\n  });\n}\nexports.sortByKey = sortByKey;\n\n\n/**\n * Sorts an array of objects by the specified object key and compare\n * function. If no compare function is provided, the key values are\n * compared in ascending order using <code>defaultCompare</code>.\n * This won't work for keys that get renamed by the compiler. So use\n * {'foo': 1, 'bar': 2} rather than {foo: 1, bar: 2}.\n * @param {Array<Object>} arr An array of objects to sort.\n * @param {string} key The object key to sort by.\n * @param {Function=} opt_compareFn The function to use to compare key\n *     values.\n */\nfunction sortObjectsByKey(arr, key, opt_compareFn) {\n  sortByKey(arr, function(obj) {\n    return obj[key];\n  }, opt_compareFn);\n}\nexports.sortObjectsByKey = sortObjectsByKey;\n\n\n/**\n * Tells if the array is sorted.\n * @param {!IArrayLike<T>} arr The array.\n * @param {?function(T,T):number=} opt_compareFn Function to compare the\n *     array elements.\n *     Should take 2 arguments to compare, and return a negative number, zero,\n *     or a positive number depending on whether the first argument is less\n *     than, equal to, or greater than the second.\n * @param {boolean=} opt_strict If true no equal elements are allowed.\n * @return {boolean} Whether the array is sorted.\n * @template T\n */\nfunction isSorted(arr, opt_compareFn, opt_strict) {\n  const compare = opt_compareFn || defaultCompare;\n  for (let i = 1; i < arr.length; i++) {\n    const compareResult = compare(arr[i - 1], arr[i]);\n    if (compareResult > 0 || compareResult == 0 && opt_strict) {\n      return false;\n    }\n  }\n  return true;\n}\nexports.isSorted = isSorted;\n\n\n/**\n * Compares two arrays for equality. Two arrays are considered equal if they\n * have the same length and their corresponding elements are equal according to\n * the comparison function.\n *\n * @param {IArrayLike<A>} arr1 The first array to compare.\n * @param {IArrayLike<B>} arr2 The second array to compare.\n * @param {?function(A,B):boolean=} opt_equalsFn Optional comparison function.\n *     Should take 2 arguments to compare, and return true if the arguments\n *     are equal. Defaults to {@link goog.array.defaultCompareEquality} which\n *     compares the elements using the built-in '===' operator.\n * @return {boolean} Whether the two arrays are equal.\n * @template A\n * @template B\n */\nfunction equals(arr1, arr2, opt_equalsFn) {\n  if (!goog.isArrayLike(arr1) || !goog.isArrayLike(arr2) ||\n      arr1.length != arr2.length) {\n    return false;\n  }\n  const l = arr1.length;\n  const equalsFn = opt_equalsFn || defaultCompareEquality;\n  for (let i = 0; i < l; i++) {\n    if (!equalsFn(arr1[i], arr2[i])) {\n      return false;\n    }\n  }\n  return true;\n}\nexports.equals = equals;\n\n\n/**\n * 3-way array compare function.\n * @param {!IArrayLike<VALUE>} arr1 The first array to\n *     compare.\n * @param {!IArrayLike<VALUE>} arr2 The second array to\n *     compare.\n * @param {function(VALUE, VALUE): number=} opt_compareFn Optional comparison\n *     function by which the array is to be ordered. Should take 2 arguments to\n *     compare, and return a negative number, zero, or a positive number\n *     depending on whether the first argument is less than, equal to, or\n *     greater than the second.\n * @return {number} Negative number, zero, or a positive number depending on\n *     whether the first argument is less than, equal to, or greater than the\n *     second.\n * @template VALUE\n */\nfunction compare3(arr1, arr2, opt_compareFn) {\n  const compare = opt_compareFn || defaultCompare;\n  const l = Math.min(arr1.length, arr2.length);\n  for (let i = 0; i < l; i++) {\n    const result = compare(arr1[i], arr2[i]);\n    if (result != 0) {\n      return result;\n    }\n  }\n  return defaultCompare(arr1.length, arr2.length);\n}\nexports.compare3 = compare3;\n\n\n/**\n * Compares its two arguments for order, using the built in < and >\n * operators.\n * @param {VALUE} a The first object to be compared.\n * @param {VALUE} b The second object to be compared.\n * @return {number} A negative number, zero, or a positive number as the first\n *     argument is less than, equal to, or greater than the second,\n *     respectively.\n * @template VALUE\n */\nfunction defaultCompare(a, b) {\n  return a > b ? 1 : a < b ? -1 : 0;\n}\nexports.defaultCompare = defaultCompare;\n\n\n/**\n * Compares its two arguments for inverse order, using the built in < and >\n * operators.\n * @param {VALUE} a The first object to be compared.\n * @param {VALUE} b The second object to be compared.\n * @return {number} A negative number, zero, or a positive number as the first\n *     argument is greater than, equal to, or less than the second,\n *     respectively.\n * @template VALUE\n */\nfunction inverseDefaultCompare(a, b) {\n  return -defaultCompare(a, b);\n}\nexports.inverseDefaultCompare = inverseDefaultCompare;\n\n\n/**\n * Compares its two arguments for equality, using the built in === operator.\n * @param {*} a The first object to compare.\n * @param {*} b The second object to compare.\n * @return {boolean} True if the two arguments are equal, false otherwise.\n */\nfunction defaultCompareEquality(a, b) {\n  return a === b;\n}\nexports.defaultCompareEquality = defaultCompareEquality;\n\n\n/**\n * Inserts a value into a sorted array. The array is not modified if the\n * value is already present.\n * @param {IArrayLike<VALUE>} array The array to modify.\n * @param {VALUE} value The object to insert.\n * @param {function(VALUE, VALUE): number=} opt_compareFn Optional comparison\n *     function by which the array is ordered. Should take 2 arguments to\n *     compare, and return a negative number, zero, or a positive number\n *     depending on whether the first argument is less than, equal to, or\n *     greater than the second.\n * @return {boolean} True if an element was inserted.\n * @template VALUE\n */\nfunction binaryInsert(array, value, opt_compareFn) {\n  const index = binarySearch(array, value, opt_compareFn);\n  if (index < 0) {\n    insertAt(array, value, -(index + 1));\n    return true;\n  }\n  return false;\n}\nexports.binaryInsert = binaryInsert;\n\n\n/**\n * Removes a value from a sorted array.\n * @param {!IArrayLike<VALUE>} array The array to modify.\n * @param {VALUE} value The object to remove.\n * @param {function(VALUE, VALUE): number=} opt_compareFn Optional comparison\n *     function by which the array is ordered. Should take 2 arguments to\n *     compare, and return a negative number, zero, or a positive number\n *     depending on whether the first argument is less than, equal to, or\n *     greater than the second.\n * @return {boolean} True if an element was removed.\n * @template VALUE\n */\nfunction binaryRemove(array, value, opt_compareFn) {\n  const index = binarySearch(array, value, opt_compareFn);\n  return (index >= 0) ? removeAt(array, index) : false;\n}\nexports.binaryRemove = binaryRemove;\n\n\n/**\n * Splits an array into disjoint buckets according to a splitting function.\n * @param {IArrayLike<T>} array The array.\n * @param {function(this:S, T, number, !IArrayLike<T>):?} sorter Function to\n *     call for every element.  This takes 3 arguments (the element, the index\n *     and the array) and must return a valid object key (a string, number,\n *     etc), or undefined, if that object should not be placed in a bucket.\n * @param {S=} opt_obj The object to be used as the value of 'this' within\n *     sorter.\n * @return {!Object<!Array<T>>} An object, with keys being all of the unique\n *     return values of sorter, and values being arrays containing the items for\n *     which the splitter returned that key.\n * @template T,S\n */\nfunction bucket(array, sorter, opt_obj) {\n  const buckets = {};\n\n  for (let i = 0; i < array.length; i++) {\n    const value = array[i];\n    const key = sorter.call(/** @type {?} */ (opt_obj), value, i, array);\n    if (key !== undefined) {\n      // Push the value to the right bucket, creating it if necessary.\n      const bucket = buckets[key] || (buckets[key] = []);\n      bucket.push(value);\n    }\n  }\n\n  return buckets;\n}\nexports.bucket = bucket;\n\n\n/**\n * Splits an array into disjoint buckets according to a splitting function.\n * @param {!IArrayLike<V>} array The array.\n * @param {function(V, number, !IArrayLike<V>):(K|undefined)} sorter Function to\n *     call for every element.  This takes 3 arguments (the element, the index,\n *     and the array) and must return a value to use as a key, or undefined, if\n *     that object should not be placed in a bucket.\n * @return {!Map<K, !Array<V>>} A map, with keys being all of the unique\n *     return values of sorter, and values being arrays containing the items for\n *     which the splitter returned that key.\n * @template K,V\n */\nfunction bucketToMap(array, sorter) {\n  const /** !Map<K, !Array<V>> */ buckets = new Map();\n\n  for (let i = 0; i < array.length; i++) {\n    const value = array[i];\n    const key = sorter(value, i, array);\n    if (key !== undefined) {\n      // Push the value to the right bucket, creating it if necessary.\n      let bucket = buckets.get(key);\n      if (!bucket) {\n        bucket = [];\n        buckets.set(key, bucket);\n      }\n      bucket.push(value);\n    }\n  }\n\n  return buckets;\n}\nexports.bucketToMap = bucketToMap;\n\n\n/**\n * Creates a new object built from the provided array and the key-generation\n * function.\n * @param {IArrayLike<T>} arr Array or array like object over\n *     which to iterate whose elements will be the values in the new object.\n * @param {?function(this:S, T, number, ?) : string} keyFunc The function to\n *     call for every element. This function takes 3 arguments (the element, the\n *     index and the array) and should return a string that will be used as the\n *     key for the element in the new object. If the function returns the same\n *     key for more than one element, the value for that key is\n *     implementation-defined.\n * @param {S=} opt_obj The object to be used as the value of 'this'\n *     within keyFunc.\n * @return {!Object<T>} The new object.\n * @template T,S\n */\nfunction toObject(arr, keyFunc, opt_obj) {\n  const ret = {};\n  forEach(arr, function(element, index) {\n    ret[keyFunc.call(/** @type {?} */ (opt_obj), element, index, arr)] =\n        element;\n  });\n  return ret;\n}\nexports.toObject = toObject;\n\n\n/**\n * Creates a new ES6 Map built from the provided array and the key-generation\n * function.\n * @param {!IArrayLike<V>} arr Array or array like object over which to iterate\n *     whose elements will be the values in the new object.\n * @param {?function(V, number, ?) : K} keyFunc The function to call for every\n *     element. This function takes 3 arguments (the element, the index, and the\n *     array) and should return a value that will be used as the key for the\n *     element in the new object. If the function returns the same key for more\n *     than one element, the value for that key is implementation-defined.\n * @return {!Map<K, V>} The new map.\n * @template K,V\n */\nfunction toMap(arr, keyFunc) {\n  const /** !Map<K, V> */ map = new Map();\n\n  for (let i = 0; i < arr.length; i++) {\n    const element = arr[i];\n    map.set(keyFunc(element, i, arr), element);\n  }\n\n  return map;\n}\nexports.toMap = toMap;\n\n\n/**\n * Creates a range of numbers in an arithmetic progression.\n *\n * Range takes 1, 2, or 3 arguments:\n * <pre>\n * range(5) is the same as range(0, 5, 1) and produces [0, 1, 2, 3, 4]\n * range(2, 5) is the same as range(2, 5, 1) and produces [2, 3, 4]\n * range(-2, -5, -1) produces [-2, -3, -4]\n * range(-2, -5, 1) produces [], since stepping by 1 wouldn't ever reach -5.\n * </pre>\n *\n * @param {number} startOrEnd The starting value of the range if an end argument\n *     is provided. Otherwise, the start value is 0, and this is the end value.\n * @param {number=} opt_end The optional end value of the range.\n * @param {number=} opt_step The step size between range values. Defaults to 1\n *     if opt_step is undefined or 0.\n * @return {!Array<number>} An array of numbers for the requested range. May be\n *     an empty array if adding the step would not converge toward the end\n *     value.\n */\nfunction range(startOrEnd, opt_end, opt_step) {\n  const array = [];\n  let start = 0;\n  let end = startOrEnd;\n  const step = opt_step || 1;\n  if (opt_end !== undefined) {\n    start = startOrEnd;\n    end = opt_end;\n  }\n\n  if (step * (end - start) < 0) {\n    // Sign mismatch: start + step will never reach the end value.\n    return [];\n  }\n\n  if (step > 0) {\n    for (let i = start; i < end; i += step) {\n      array.push(i);\n    }\n  } else {\n    for (let i = start; i > end; i += step) {\n      array.push(i);\n    }\n  }\n  return array;\n}\nexports.range = range;\n\n\n/**\n * Returns an array consisting of the given value repeated N times.\n *\n * @param {VALUE} value The value to repeat.\n * @param {number} n The repeat count.\n * @return {!Array<VALUE>} An array with the repeated value.\n * @template VALUE\n */\nfunction repeat(value, n) {\n  const array = [];\n  for (let i = 0; i < n; i++) {\n    array[i] = value;\n  }\n  return array;\n}\nexports.repeat = repeat;\n\n\n/**\n * Returns an array consisting of every argument with all arrays\n * expanded in-place recursively.\n *\n * @param {...*} var_args The values to flatten.\n * @return {!Array<?>} An array containing the flattened values.\n */\nfunction flatten(var_args) {\n  const CHUNK_SIZE = 8192;\n\n  const result = [];\n  for (let i = 0; i < arguments.length; i++) {\n    const element = arguments[i];\n    if (Array.isArray(element)) {\n      for (let c = 0; c < element.length; c += CHUNK_SIZE) {\n        const chunk = slice(element, c, c + CHUNK_SIZE);\n        const recurseResult = flatten.apply(null, chunk);\n        for (let r = 0; r < recurseResult.length; r++) {\n          result.push(recurseResult[r]);\n        }\n      }\n    } else {\n      result.push(element);\n    }\n  }\n  return result;\n}\nexports.flatten = flatten;\n\n\n/**\n * Rotates an array in-place. After calling this method, the element at\n * index i will be the element previously at index (i - n) %\n * array.length, for all values of i between 0 and array.length - 1,\n * inclusive.\n *\n * For example, suppose list comprises [t, a, n, k, s]. After invoking\n * rotate(array, 1) (or rotate(array, -4)), array will comprise [s, t, a, n, k].\n *\n * @param {!Array<T>} array The array to rotate.\n * @param {number} n The amount to rotate.\n * @return {!Array<T>} The array.\n * @template T\n */\nfunction rotate(array, n) {\n  asserts.assert(array.length != null);\n\n  if (array.length) {\n    n %= array.length;\n    if (n > 0) {\n      Array.prototype.unshift.apply(array, array.splice(-n, n));\n    } else if (n < 0) {\n      Array.prototype.push.apply(array, array.splice(0, -n));\n    }\n  }\n  return array;\n}\nexports.rotate = rotate;\n\n\n/**\n * Moves one item of an array to a new position keeping the order of the rest\n * of the items. Example use case: keeping a list of JavaScript objects\n * synchronized with the corresponding list of DOM elements after one of the\n * elements has been dragged to a new position.\n * @param {!IArrayLike<?>} arr The array to modify.\n * @param {number} fromIndex Index of the item to move between 0 and\n *     `arr.length - 1`.\n * @param {number} toIndex Target index between 0 and `arr.length - 1`.\n */\nfunction moveItem(arr, fromIndex, toIndex) {\n  asserts.assert(fromIndex >= 0 && fromIndex < arr.length);\n  asserts.assert(toIndex >= 0 && toIndex < arr.length);\n  // Remove 1 item at fromIndex.\n  const removedItems = Array.prototype.splice.call(arr, fromIndex, 1);\n  // Insert the removed item at toIndex.\n  Array.prototype.splice.call(arr, toIndex, 0, removedItems[0]);\n  // We don't use goog.array.insertAt and goog.array.removeAt, because they're\n  // significantly slower than splice.\n}\nexports.moveItem = moveItem;\n\n\n/**\n * Creates a new array for which the element at position i is an array of the\n * ith element of the provided arrays.  The returned array will only be as long\n * as the shortest array provided; additional values are ignored.  For example,\n * the result of zipping [1, 2] and [3, 4, 5] is [[1,3], [2, 4]].\n *\n * This is similar to the zip() function in Python.  See {@link\n * http://docs.python.org/library/functions.html#zip}\n *\n * @param {...!IArrayLike<?>} var_args Arrays to be combined.\n * @return {!Array<!Array<?>>} A new array of arrays created from\n *     provided arrays.\n */\nfunction zip(var_args) {\n  if (!arguments.length) {\n    return [];\n  }\n  const result = [];\n  let minLen = arguments[0].length;\n  for (let i = 1; i < arguments.length; i++) {\n    if (arguments[i].length < minLen) {\n      minLen = arguments[i].length;\n    }\n  }\n  for (let i = 0; i < minLen; i++) {\n    const value = [];\n    for (let j = 0; j < arguments.length; j++) {\n      value.push(arguments[j][i]);\n    }\n    result.push(value);\n  }\n  return result;\n}\nexports.zip = zip;\n\n\n/**\n * Shuffles the values in the specified array using the Fisher-Yates in-place\n * shuffle (also known as the Knuth Shuffle). By default, calls Math.random()\n * and so resets the state of that random number generator. Similarly, may reset\n * the state of any other specified random number generator.\n *\n * Runtime: O(n)\n *\n * @param {!Array<?>} arr The array to be shuffled.\n * @param {function():number=} opt_randFn Optional random function to use for\n *     shuffling.\n *     Takes no arguments, and returns a random number on the interval [0, 1).\n *     Defaults to Math.random() using JavaScript's built-in Math library.\n */\nfunction shuffle(arr, opt_randFn) {\n  const randFn = opt_randFn || Math.random;\n\n  for (let i = arr.length - 1; i > 0; i--) {\n    // Choose a random array index in [0, i] (inclusive with i).\n    const j = Math.floor(randFn() * (i + 1));\n\n    const tmp = arr[i];\n    arr[i] = arr[j];\n    arr[j] = tmp;\n  }\n}\nexports.shuffle = shuffle;\n\n\n/**\n * Returns a new array of elements from arr, based on the indexes of elements\n * provided by index_arr. For example, the result of index copying\n * ['a', 'b', 'c'] with index_arr [1,0,0,2] is ['b', 'a', 'a', 'c'].\n *\n * @param {!IArrayLike<T>} arr The array to get a indexed copy from.\n * @param {!IArrayLike<number>} index_arr An array of indexes to get from arr.\n * @return {!Array<T>} A new array of elements from arr in index_arr order.\n * @template T\n */\nfunction copyByIndex(arr, index_arr) {\n  const result = [];\n  forEach(index_arr, function(index) {\n    result.push(arr[index]);\n  });\n  return result;\n}\nexports.copyByIndex = copyByIndex;\n\n\n/**\n * Maps each element of the input array into zero or more elements of the output\n * array.\n *\n * @param {!IArrayLike<VALUE>|string} arr Array or array like object\n *     over which to iterate.\n * @param {function(this:THIS, VALUE, number, ?): !Array<RESULT>} f The function\n *     to call for every element. This function takes 3 arguments (the element,\n *     the index and the array) and should return an array. The result will be\n *     used to extend a new array.\n * @param {THIS=} opt_obj The object to be used as the value of 'this' within f.\n * @return {!Array<RESULT>} a new array with the concatenation of all arrays\n *     returned from f.\n * @template THIS, VALUE, RESULT\n */\nfunction concatMap(arr, f, opt_obj) {\n  return concat.apply([], map(arr, f, opt_obj));\n}\nexports.concatMap = concatMap;\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview A base class for event objects.\n */\n\n\ngoog.provide('goog.events.Event');\n\n/**\n * goog.events.Event no longer depends on goog.Disposable. Keep requiring\n * goog.Disposable here to not break projects which assume this dependency.\n * @suppress {extraRequire}\n */\ngoog.require('goog.Disposable');\ngoog.require('goog.events.EventId');\n\n\n/**\n * A base class for event objects, so that they can support preventDefault and\n * stopPropagation.\n *\n * @param {string|!goog.events.EventId} type Event Type.\n * @param {Object=} opt_target Reference to the object that is the target of\n *     this event. It has to implement the `EventTarget` interface\n *     declared at {@link http://developer.mozilla.org/en/DOM/EventTarget}.\n * @constructor\n */\ngoog.events.Event = function(type, opt_target) {\n  'use strict';\n  /**\n   * Event type.\n   * @type {string}\n   */\n  this.type = type instanceof goog.events.EventId ? String(type) : type;\n\n  /**\n   * TODO(tbreisacher): The type should probably be\n   * EventTarget|goog.events.EventTarget.\n   *\n   * Target of the event.\n   * @type {Object|undefined}\n   */\n  this.target = opt_target;\n\n  /**\n   * Object that had the listener attached.\n   * @type {Object|undefined}\n   */\n  this.currentTarget = this.target;\n\n  /**\n   * Whether to cancel the event in internal capture/bubble processing for IE.\n   * @type {boolean}\n   * @private\n   */\n  this.propagationStopped_ = false;\n\n  /**\n   * Whether the default action has been prevented.\n   * This is a property to match the W3C specification at\n   * {@link http://www.w3.org/TR/DOM-Level-3-Events/\n   * #events-event-type-defaultPrevented}.\n   * Must be treated as read-only outside the class.\n   * @type {boolean}\n   */\n  this.defaultPrevented = false;\n};\n\n/**\n * @return {boolean} true iff internal propagation has been stopped.\n */\ngoog.events.Event.prototype.hasPropagationStopped = function() {\n  'use strict';\n  return this.propagationStopped_;\n};\n\n/**\n * Stops event propagation.\n * @return {void}\n */\ngoog.events.Event.prototype.stopPropagation = function() {\n  'use strict';\n  this.propagationStopped_ = true;\n};\n\n\n/**\n * Prevents the default action, for example a link redirecting to a url.\n * @return {void}\n */\ngoog.events.Event.prototype.preventDefault = function() {\n  'use strict';\n  this.defaultPrevented = true;\n};\n\n\n/**\n * Stops the propagation of the event. It is equivalent to\n * `e.stopPropagation()`, but can be used as the callback argument of\n * {@link goog.events.listen} without declaring another function.\n * @param {!goog.events.Event} e An event.\n * @return {void}\n */\ngoog.events.Event.stopPropagation = function(e) {\n  'use strict';\n  e.stopPropagation();\n};\n\n\n/**\n * Prevents the default action. It is equivalent to\n * `e.preventDefault()`, but can be used as the callback argument of\n * {@link goog.events.listen} without declaring another function.\n * @param {!goog.events.Event} e An event.\n * @return {void}\n */\ngoog.events.Event.preventDefault = function(e) {\n  'use strict';\n  e.preventDefault();\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Browser capability checks for the events package.\n */\n\ngoog.module('goog.events.BrowserFeature');\ngoog.module.declareLegacyNamespace();\n\n\n/**\n * Tricks Closure Compiler into believing that a function is pure.  The compiler\n * assumes that any `valueOf` function is pure, without analyzing its contents.\n *\n * @param {function(): T} fn\n * @return {T}\n * @template T\n */\nconst purify = (fn) => {\n  return ({valueOf: fn}).valueOf();\n};\n\n\n/**\n * Enum of browser capabilities.\n * @enum {boolean}\n */\nexports = {\n  /**\n   * Whether touch is enabled in the browser.\n   */\n  TOUCH_ENABLED:\n      ('ontouchstart' in goog.global ||\n       !!(goog.global['document'] && document.documentElement &&\n          'ontouchstart' in document.documentElement) ||\n       // IE10 uses non-standard touch events, so it has a different check.\n       !!(goog.global['navigator'] &&\n          (goog.global['navigator']['maxTouchPoints'] ||\n           goog.global['navigator']['msMaxTouchPoints']))),\n\n  /**\n   * Whether addEventListener supports W3C standard pointer events.\n   * http://www.w3.org/TR/pointerevents/\n   */\n  POINTER_EVENTS: ('PointerEvent' in goog.global),\n\n  /**\n   * Whether addEventListener supports MSPointer events (only used in IE10).\n   * http://msdn.microsoft.com/en-us/library/ie/hh772103(v=vs.85).aspx\n   * http://msdn.microsoft.com/library/hh673557(v=vs.85).aspx\n   */\n  MSPOINTER_EVENTS:\n      ('MSPointerEvent' in goog.global &&\n       !!(goog.global['navigator'] &&\n          goog.global['navigator']['msPointerEnabled'])),\n\n  /**\n   * Whether addEventListener supports {passive: true}.\n   * https://developers.google.com/web/updates/2016/06/passive-event-listeners\n   */\n  PASSIVE_EVENTS: purify(function() {\n    // If we're in a web worker or other custom environment, we can't tell.\n    if (!goog.global.addEventListener || !Object.defineProperty) {  // IE 8\n      return false;\n    }\n\n    var passive = false;\n    var options = Object.defineProperty({}, 'passive', {\n      get: function() {\n        passive = true;\n      }\n    });\n    try {\n      goog.global.addEventListener('test', goog.nullFunction, options);\n      goog.global.removeEventListener('test', goog.nullFunction, options);\n    } catch (e) {\n    }\n\n    return passive;\n  })\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview String functions called from Closure packages that couldn't\n * depend on each other. Outside Closure, use goog.string function which\n * delegate to these.\n */\n\n\ngoog.provide('goog.string.internal');\n\n\n/**\n * Fast prefix-checker.\n * @param {string} str The string to check.\n * @param {string} prefix A string to look for at the start of `str`.\n * @return {boolean} True if `str` begins with `prefix`.\n * @see goog.string.startsWith\n */\ngoog.string.internal.startsWith = function(str, prefix) {\n  'use strict';\n  return str.lastIndexOf(prefix, 0) == 0;\n};\n\n\n/**\n * Fast suffix-checker.\n * @param {string} str The string to check.\n * @param {string} suffix A string to look for at the end of `str`.\n * @return {boolean} True if `str` ends with `suffix`.\n * @see goog.string.endsWith\n */\ngoog.string.internal.endsWith = function(str, suffix) {\n  'use strict';\n  const l = str.length - suffix.length;\n  return l >= 0 && str.indexOf(suffix, l) == l;\n};\n\n\n/**\n * Case-insensitive prefix-checker.\n * @param {string} str The string to check.\n * @param {string} prefix  A string to look for at the end of `str`.\n * @return {boolean} True if `str` begins with `prefix` (ignoring\n *     case).\n * @see goog.string.caseInsensitiveStartsWith\n */\ngoog.string.internal.caseInsensitiveStartsWith = function(str, prefix) {\n  'use strict';\n  return goog.string.internal.caseInsensitiveCompare(\n             prefix, str.substr(0, prefix.length)) == 0;\n};\n\n\n/**\n * Case-insensitive suffix-checker.\n * @param {string} str The string to check.\n * @param {string} suffix A string to look for at the end of `str`.\n * @return {boolean} True if `str` ends with `suffix` (ignoring\n *     case).\n * @see goog.string.caseInsensitiveEndsWith\n */\ngoog.string.internal.caseInsensitiveEndsWith = function(str, suffix) {\n  'use strict';\n  return (\n      goog.string.internal.caseInsensitiveCompare(\n          suffix, str.substr(str.length - suffix.length, suffix.length)) == 0);\n};\n\n\n/**\n * Case-insensitive equality checker.\n * @param {string} str1 First string to check.\n * @param {string} str2 Second string to check.\n * @return {boolean} True if `str1` and `str2` are the same string,\n *     ignoring case.\n * @see goog.string.caseInsensitiveEquals\n */\ngoog.string.internal.caseInsensitiveEquals = function(str1, str2) {\n  'use strict';\n  return str1.toLowerCase() == str2.toLowerCase();\n};\n\n\n/**\n * Checks if a string is empty or contains only whitespaces.\n * @param {string} str The string to check.\n * @return {boolean} Whether `str` is empty or whitespace only.\n * @see goog.string.isEmptyOrWhitespace\n */\ngoog.string.internal.isEmptyOrWhitespace = function(str) {\n  'use strict';\n  // testing length == 0 first is actually slower in all browsers (about the\n  // same in Opera).\n  // Since IE doesn't include non-breaking-space (0xa0) in their \\s character\n  // class (as required by section 7.2 of the ECMAScript spec), we explicitly\n  // include it in the regexp to enforce consistent cross-browser behavior.\n  return /^[\\s\\xa0]*$/.test(str);\n};\n\n\n/**\n * Trims white spaces to the left and right of a string.\n * @param {string} str The string to trim.\n * @return {string} A trimmed copy of `str`.\n */\ngoog.string.internal.trim =\n    (goog.TRUSTED_SITE && String.prototype.trim) ? function(str) {\n      'use strict';\n      return str.trim();\n    } : function(str) {\n      'use strict';\n      // Since IE doesn't include non-breaking-space (0xa0) in their \\s\n      // character class (as required by section 7.2 of the ECMAScript spec),\n      // we explicitly include it in the regexp to enforce consistent\n      // cross-browser behavior.\n      // NOTE: We don't use String#replace because it might have side effects\n      // causing this function to not compile to 0 bytes.\n      return /^[\\s\\xa0]*([\\s\\S]*?)[\\s\\xa0]*$/.exec(str)[1];\n    };\n\n\n/**\n * A string comparator that ignores case.\n * -1 = str1 less than str2\n *  0 = str1 equals str2\n *  1 = str1 greater than str2\n *\n * @param {string} str1 The string to compare.\n * @param {string} str2 The string to compare `str1` to.\n * @return {number} The comparator result, as described above.\n * @see goog.string.caseInsensitiveCompare\n */\ngoog.string.internal.caseInsensitiveCompare = function(str1, str2) {\n  'use strict';\n  const test1 = String(str1).toLowerCase();\n  const test2 = String(str2).toLowerCase();\n\n  if (test1 < test2) {\n    return -1;\n  } else if (test1 == test2) {\n    return 0;\n  } else {\n    return 1;\n  }\n};\n\n\n/**\n * Converts \\n to <br>s or <br />s.\n * @param {string} str The string in which to convert newlines.\n * @param {boolean=} opt_xml Whether to use XML compatible tags.\n * @return {string} A copy of `str` with converted newlines.\n * @see goog.string.newLineToBr\n */\ngoog.string.internal.newLineToBr = function(str, opt_xml) {\n  'use strict';\n  return str.replace(/(\\r\\n|\\r|\\n)/g, opt_xml ? '<br />' : '<br>');\n};\n\n\n/**\n * Escapes double quote '\"' and single quote '\\'' characters in addition to\n * '&', '<', and '>' so that a string can be included in an HTML tag attribute\n * value within double or single quotes.\n * @param {string} str string to be escaped.\n * @param {boolean=} opt_isLikelyToContainHtmlChars\n * @return {string} An escaped copy of `str`.\n * @see goog.string.htmlEscape\n */\ngoog.string.internal.htmlEscape = function(\n    str, opt_isLikelyToContainHtmlChars) {\n  'use strict';\n  if (opt_isLikelyToContainHtmlChars) {\n    str = str.replace(goog.string.internal.AMP_RE_, '&amp;')\n              .replace(goog.string.internal.LT_RE_, '&lt;')\n              .replace(goog.string.internal.GT_RE_, '&gt;')\n              .replace(goog.string.internal.QUOT_RE_, '&quot;')\n              .replace(goog.string.internal.SINGLE_QUOTE_RE_, '&#39;')\n              .replace(goog.string.internal.NULL_RE_, '&#0;');\n    return str;\n\n  } else {\n    // quick test helps in the case when there are no chars to replace, in\n    // worst case this makes barely a difference to the time taken\n    if (!goog.string.internal.ALL_RE_.test(str)) return str;\n\n    // str.indexOf is faster than regex.test in this case\n    if (str.indexOf('&') != -1) {\n      str = str.replace(goog.string.internal.AMP_RE_, '&amp;');\n    }\n    if (str.indexOf('<') != -1) {\n      str = str.replace(goog.string.internal.LT_RE_, '&lt;');\n    }\n    if (str.indexOf('>') != -1) {\n      str = str.replace(goog.string.internal.GT_RE_, '&gt;');\n    }\n    if (str.indexOf('\"') != -1) {\n      str = str.replace(goog.string.internal.QUOT_RE_, '&quot;');\n    }\n    if (str.indexOf('\\'') != -1) {\n      str = str.replace(goog.string.internal.SINGLE_QUOTE_RE_, '&#39;');\n    }\n    if (str.indexOf('\\x00') != -1) {\n      str = str.replace(goog.string.internal.NULL_RE_, '&#0;');\n    }\n    return str;\n  }\n};\n\n\n/**\n * Regular expression that matches an ampersand, for use in escaping.\n * @const {!RegExp}\n * @private\n */\ngoog.string.internal.AMP_RE_ = /&/g;\n\n\n/**\n * Regular expression that matches a less than sign, for use in escaping.\n * @const {!RegExp}\n * @private\n */\ngoog.string.internal.LT_RE_ = /</g;\n\n\n/**\n * Regular expression that matches a greater than sign, for use in escaping.\n * @const {!RegExp}\n * @private\n */\ngoog.string.internal.GT_RE_ = />/g;\n\n\n/**\n * Regular expression that matches a double quote, for use in escaping.\n * @const {!RegExp}\n * @private\n */\ngoog.string.internal.QUOT_RE_ = /\"/g;\n\n\n/**\n * Regular expression that matches a single quote, for use in escaping.\n * @const {!RegExp}\n * @private\n */\ngoog.string.internal.SINGLE_QUOTE_RE_ = /'/g;\n\n\n/**\n * Regular expression that matches null character, for use in escaping.\n * @const {!RegExp}\n * @private\n */\ngoog.string.internal.NULL_RE_ = /\\x00/g;\n\n\n/**\n * Regular expression that matches any character that needs to be escaped.\n * @const {!RegExp}\n * @private\n */\ngoog.string.internal.ALL_RE_ = /[\\x00&<>\"']/;\n\n\n/**\n * Do escaping of whitespace to preserve spatial formatting. We use character\n * entity #160 to make it safer for xml.\n * @param {string} str The string in which to escape whitespace.\n * @param {boolean=} opt_xml Whether to use XML compatible tags.\n * @return {string} An escaped copy of `str`.\n * @see goog.string.whitespaceEscape\n */\ngoog.string.internal.whitespaceEscape = function(str, opt_xml) {\n  'use strict';\n  // This doesn't use goog.string.preserveSpaces for backwards compatibility.\n  return goog.string.internal.newLineToBr(\n      str.replace(/  /g, ' &#160;'), opt_xml);\n};\n\n\n/**\n * Determines whether a string contains a substring.\n * @param {string} str The string to search.\n * @param {string} subString The substring to search for.\n * @return {boolean} Whether `str` contains `subString`.\n * @see goog.string.contains\n */\ngoog.string.internal.contains = function(str, subString) {\n  'use strict';\n  return str.indexOf(subString) != -1;\n};\n\n\n/**\n * Determines whether a string contains a substring, ignoring case.\n * @param {string} str The string to search.\n * @param {string} subString The substring to search for.\n * @return {boolean} Whether `str` contains `subString`.\n * @see goog.string.caseInsensitiveContains\n */\ngoog.string.internal.caseInsensitiveContains = function(str, subString) {\n  'use strict';\n  return goog.string.internal.contains(\n      str.toLowerCase(), subString.toLowerCase());\n};\n\n\n/**\n * Compares two version numbers.\n *\n * @param {string|number} version1 Version of first item.\n * @param {string|number} version2 Version of second item.\n *\n * @return {number}  1 if `version1` is higher.\n *                   0 if arguments are equal.\n *                  -1 if `version2` is higher.\n * @see goog.string.compareVersions\n */\ngoog.string.internal.compareVersions = function(version1, version2) {\n  'use strict';\n  let order = 0;\n  // Trim leading and trailing whitespace and split the versions into\n  // subversions.\n  const v1Subs = goog.string.internal.trim(String(version1)).split('.');\n  const v2Subs = goog.string.internal.trim(String(version2)).split('.');\n  const subCount = Math.max(v1Subs.length, v2Subs.length);\n\n  // Iterate over the subversions, as long as they appear to be equivalent.\n  for (let subIdx = 0; order == 0 && subIdx < subCount; subIdx++) {\n    let v1Sub = v1Subs[subIdx] || '';\n    let v2Sub = v2Subs[subIdx] || '';\n\n    do {\n      // Split the subversions into pairs of numbers and qualifiers (like 'b').\n      // Two different RegExp objects are use to make it clear the code\n      // is side-effect free\n      const v1Comp = /(\\d*)(\\D*)(.*)/.exec(v1Sub) || ['', '', '', ''];\n      const v2Comp = /(\\d*)(\\D*)(.*)/.exec(v2Sub) || ['', '', '', ''];\n      // Break if there are no more matches.\n      if (v1Comp[0].length == 0 && v2Comp[0].length == 0) {\n        break;\n      }\n\n      // Parse the numeric part of the subversion. A missing number is\n      // equivalent to 0.\n      const v1CompNum = v1Comp[1].length == 0 ? 0 : parseInt(v1Comp[1], 10);\n      const v2CompNum = v2Comp[1].length == 0 ? 0 : parseInt(v2Comp[1], 10);\n\n      // Compare the subversion components. The number has the highest\n      // precedence. Next, if the numbers are equal, a subversion without any\n      // qualifier is always higher than a subversion with any qualifier. Next,\n      // the qualifiers are compared as strings.\n      order = goog.string.internal.compareElements_(v1CompNum, v2CompNum) ||\n          goog.string.internal.compareElements_(\n              v1Comp[2].length == 0, v2Comp[2].length == 0) ||\n          goog.string.internal.compareElements_(v1Comp[2], v2Comp[2]);\n      // Stop as soon as an inequality is discovered.\n\n      v1Sub = v1Comp[3];\n      v2Sub = v2Comp[3];\n    } while (order == 0);\n  }\n\n  return order;\n};\n\n\n/**\n * Compares elements of a version number.\n *\n * @param {string|number|boolean} left An element from a version number.\n * @param {string|number|boolean} right An element from a version number.\n *\n * @return {number}  1 if `left` is higher.\n *                   0 if arguments are equal.\n *                  -1 if `right` is higher.\n * @private\n */\ngoog.string.internal.compareElements_ = function(left, right) {\n  'use strict';\n  if (left < right) {\n    return -1;\n  } else if (left > right) {\n    return 1;\n  }\n  return 0;\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Utilities used by goog.labs.userAgent tools. These functions\n * should not be used outside of goog.labs.userAgent.*.\n *\n */\n\ngoog.module('goog.labs.userAgent.util');\ngoog.module.declareLegacyNamespace();\n\nconst {USE_CLIENT_HINTS} = goog.require('goog.labs.userAgent');\nconst {caseInsensitiveContains, contains} = goog.require('goog.string.internal');\n\n/**\n * @const {boolean} If true, use navigator.userAgentData without check.\n * TODO(user): FEATURESET_YEAR >= 2023 if it supports mobile and all the\n * brands we need.  See https://caniuse.com/mdn-api_navigator_useragentdata.\n */\nconst ASSUME_CLIENT_HINTS_SUPPORT = false;\n\n/**\n * Gets the native userAgent string from navigator if it exists.\n * If navigator or navigator.userAgent string is missing, returns an empty\n * string.\n * @return {string}\n */\nfunction getNativeUserAgentString() {\n  const navigator = getNavigator();\n  if (navigator) {\n    const userAgent = navigator.userAgent;\n    if (userAgent) {\n      return userAgent;\n    }\n  }\n  return '';\n}\n\n/**\n * Gets the native userAgentData object from navigator if it exists.\n * If navigator.userAgentData object is missing or USE_CLIENT_HINTS is set to\n * false, returns null.\n * @return {?NavigatorUAData}\n */\nfunction getNativeUserAgentData() {\n  if (!USE_CLIENT_HINTS) {\n    return null;\n  }\n  const navigator = getNavigator();\n  // TODO(user): Use navigator?.userAgent ?? null once it's supported.\n  if (navigator) {\n    return navigator.userAgentData || null;\n  }\n  return null;\n}\n\n/**\n * Getter for the native navigator.\n * @return {!Navigator}\n */\nfunction getNavigator() {\n  return goog.global.navigator;\n}\n\n/**\n * A possible override for applications which wish to not check\n * navigator.userAgent but use a specified value for detection instead.\n * @type {?string}\n */\nlet userAgentInternal = null;\n\n/**\n * A possible override for applications which wish to not check\n * navigator.userAgentData but use a specified value for detection instead.\n * @type {?NavigatorUAData}\n */\nlet userAgentDataInternal = getNativeUserAgentData();\n\n/**\n * Override the user agent string with the given value.\n * This should only be used for testing within the goog.labs.userAgent\n * namespace.\n * Pass `null` to use the native browser object instead.\n * @param {?string=} userAgent The userAgent override.\n * @return {void}\n */\nfunction setUserAgent(userAgent = undefined) {\n  userAgentInternal =\n      typeof userAgent === 'string' ? userAgent : getNativeUserAgentString();\n}\n\n/** @return {string} The user agent string. */\nfunction getUserAgent() {\n  return userAgentInternal == null ? getNativeUserAgentString() :\n                                     userAgentInternal;\n}\n\n/**\n * Override the user agent data object with the given value.\n * This should only be used for testing within the goog.labs.userAgent\n * namespace.\n * Pass `null` to specify the absence of userAgentData. Note that this behavior\n * is different from setUserAgent.\n * @param {?NavigatorUAData} userAgentData The userAgentData override.\n */\nfunction setUserAgentData(userAgentData) {\n  userAgentDataInternal = userAgentData;\n}\n\n/**\n * If the user agent data object was overridden using setUserAgentData,\n * reset it so that it uses the native browser object instead, if it exists.\n */\nfunction resetUserAgentData() {\n  userAgentDataInternal = getNativeUserAgentData();\n}\n\n/** @return {?NavigatorUAData} Navigator.userAgentData if exist */\nfunction getUserAgentData() {\n  return userAgentDataInternal;\n}\n\n/**\n * Checks if any string in userAgentData.brands matches str.\n * Returns false if userAgentData is not supported.\n * @param {string} str\n * @return {boolean} Whether any brand string from userAgentData contains the\n *     given string.\n */\nfunction matchUserAgentDataBrand(str) {\n  const data = getUserAgentData();\n  if (!data) return false;\n  return data.brands.some(({brand}) => brand && contains(brand, str));\n}\n\n/**\n * @param {string} str\n * @return {boolean} Whether the user agent contains the given string.\n */\nfunction matchUserAgent(str) {\n  const userAgent = getUserAgent();\n  return contains(userAgent, str);\n}\n\n/**\n * @param {string} str\n * @return {boolean} Whether the user agent contains the given string, ignoring\n *     case.\n */\nfunction matchUserAgentIgnoreCase(str) {\n  const userAgent = getUserAgent();\n  return caseInsensitiveContains(userAgent, str);\n}\n\n/**\n * Parses the user agent into tuples for each section.\n * @param {string} userAgent\n * @return {!Array<!Array<string>>} Tuples of key, version, and the contents of\n *     the parenthetical.\n */\nfunction extractVersionTuples(userAgent) {\n  // Matches each section of a user agent string.\n  // Example UA:\n  // Mozilla/5.0 (iPad; U; CPU OS 3_2_1 like Mac OS X; en-us)\n  // AppleWebKit/531.21.10 (KHTML, like Gecko) Mobile/7B405\n  // This has three version tuples: Mozilla, AppleWebKit, and Mobile.\n\n  const versionRegExp = new RegExp(\n      // Key. Note that a key may have a space.\n      // (i.e. 'Mobile Safari' in 'Mobile Safari/5.0')\n      '([A-Z][\\\\w ]+)' +\n\n          '/' +                // slash\n          '([^\\\\s]+)' +        // version (i.e. '5.0b')\n          '\\\\s*' +             // whitespace\n          '(?:\\\\((.*?)\\\\))?',  // parenthetical info. parentheses not matched.\n      'g');\n\n  const data = [];\n  let match;\n\n  // Iterate and collect the version tuples.  Each iteration will be the\n  // next regex match.\n  while (match = versionRegExp.exec(userAgent)) {\n    data.push([\n      match[1],  // key\n      match[2],  // value\n      // || undefined as this is not undefined in IE7 and IE8\n      match[3] || undefined  // info\n    ]);\n  }\n\n  return data;\n}\n\nexports = {\n  ASSUME_CLIENT_HINTS_SUPPORT,\n  extractVersionTuples,\n  getNativeUserAgentString,\n  getUserAgent,\n  getUserAgentData,\n  matchUserAgent,\n  matchUserAgentDataBrand,\n  matchUserAgentIgnoreCase,\n  resetUserAgentData,\n  setUserAgent,\n  setUserAgentData,\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Useful compiler idioms.\n */\n\ngoog.provide('goog.reflect');\n\n\n/**\n * Syntax for object literal casts.\n * @see http://go/jscompiler-renaming\n * @see https://goo.gl/CRs09P\n *\n * Use this if you have an object literal whose keys need to have the same names\n * as the properties of some class even after they are renamed by the compiler.\n *\n * @param {!Function} type Type to cast to.\n * @param {Object} object Object literal to cast.\n * @return {Object} The object literal.\n */\ngoog.reflect.object = function(type, object) {\n  'use strict';\n  return object;\n};\n\n/**\n * Syntax for renaming property strings.\n * @see http://go/jscompiler-renaming\n * @see https://goo.gl/CRs09P\n *\n * Use this if you have an need to access a property as a string, but want\n * to also have the property renamed by the compiler. In contrast to\n * goog.reflect.object, this method takes an instance of an object.\n *\n * Properties must be simple names (not qualified names).\n *\n * @param {string} prop Name of the property\n * @param {!Object} object Instance of the object whose type will be used\n *     for renaming\n * @return {string} The renamed property.\n */\ngoog.reflect.objectProperty = function(prop, object) {\n  'use strict';\n  return prop;\n};\n\n/**\n * To assert to the compiler that an operation is needed when it would\n * otherwise be stripped. For example:\n * <code>\n *     // Force a layout\n *     goog.reflect.sinkValue(dialog.offsetHeight);\n * </code>\n * @param {T} x\n * @return {T}\n * @template T\n */\ngoog.reflect.sinkValue = function(x) {\n  'use strict';\n  goog.reflect.sinkValue[' '](x);\n  return x;\n};\n\n\n/**\n * The compiler should optimize this function away iff no one ever uses\n * goog.reflect.sinkValue.\n */\ngoog.reflect.sinkValue[' '] = goog.nullFunction;\n\n\n/**\n * Check if a property can be accessed without throwing an exception.\n * @param {Object} obj The owner of the property.\n * @param {string} prop The property name.\n * @return {boolean} Whether the property is accessible. Will also return true\n *     if obj is null.\n */\ngoog.reflect.canAccessProperty = function(obj, prop) {\n  'use strict';\n  try {\n    goog.reflect.sinkValue(obj[prop]);\n    return true;\n  } catch (e) {\n  }\n  return false;\n};\n\n\n/**\n * Retrieves a value from a cache given a key. The compiler provides special\n * consideration for this call such that it is generally considered side-effect\n * free. However, if the `opt_keyFn` or `valueFn` have side-effects\n * then the entire call is considered to have side-effects.\n *\n * Conventionally storing the value on the cache would be considered a\n * side-effect and preclude unused calls from being pruned, ie. even if\n * the value was never used, it would still always be stored in the cache.\n *\n * Providing a side-effect free `valueFn` and `opt_keyFn`\n * allows unused calls to `goog.reflect.cache` to be pruned.\n *\n * @param {!Object<K, V>} cacheObj The object that contains the cached values.\n * @param {?} key The key to lookup in the cache. If it is not string or number\n *     then a `opt_keyFn` should be provided. The key is also used as the\n *     parameter to the `valueFn`.\n * @param {function(?):V} valueFn The value provider to use to calculate the\n *     value to store in the cache. This function should be side-effect free\n *     to take advantage of the optimization.\n * @param {function(?):K=} opt_keyFn The key provider to determine the cache\n *     map key. This should be used if the given key is not a string or number.\n *     If not provided then the given key is used. This function should be\n *     side-effect free to take advantage of the optimization.\n * @return {V} The cached or calculated value.\n * @template K\n * @template V\n */\ngoog.reflect.cache = function(cacheObj, key, valueFn, opt_keyFn) {\n  'use strict';\n  const storedKey = opt_keyFn ? opt_keyFn(key) : key;\n\n  if (Object.prototype.hasOwnProperty.call(cacheObj, storedKey)) {\n    return cacheObj[storedKey];\n  }\n\n  return (cacheObj[storedKey] = valueFn(key));\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Rendering engine detection.\n * @see <a href=\"http://www.useragentstring.com/\">User agent strings</a>\n * For information on the browser brand (such as Safari versus Chrome), see\n * goog.userAgent.product.\n * @see ../demos/useragent.html\n */\n\ngoog.provide('goog.userAgent');\n\ngoog.require('goog.labs.userAgent.browser');\ngoog.require('goog.labs.userAgent.engine');\ngoog.require('goog.labs.userAgent.platform');\ngoog.require('goog.labs.userAgent.util');\ngoog.require('goog.reflect');\ngoog.require('goog.string.internal');\n\n\n/**\n * @define {boolean} Whether we know at compile-time that the browser is IE.\n */\ngoog.userAgent.ASSUME_IE = goog.define('goog.userAgent.ASSUME_IE', false);\n\n\n/**\n * @define {boolean} Whether we know at compile-time that the browser is EDGE,\n * referring to EdgeHTML based Edge.\n */\ngoog.userAgent.ASSUME_EDGE = goog.define('goog.userAgent.ASSUME_EDGE', false);\n\n\n/**\n * @define {boolean} Whether we know at compile-time that the browser is GECKO.\n */\ngoog.userAgent.ASSUME_GECKO = goog.define('goog.userAgent.ASSUME_GECKO', false);\n\n\n/**\n * @define {boolean} Whether we know at compile-time that the browser is WEBKIT.\n */\ngoog.userAgent.ASSUME_WEBKIT =\n    goog.define('goog.userAgent.ASSUME_WEBKIT', false);\n\n\n/**\n * @define {boolean} Whether we know at compile-time that the browser is a\n *     mobile device running WebKit e.g. iPhone or Android.\n */\ngoog.userAgent.ASSUME_MOBILE_WEBKIT =\n    goog.define('goog.userAgent.ASSUME_MOBILE_WEBKIT', false);\n\n\n/**\n * @define {boolean} Whether we know at compile-time that the browser is OPERA,\n * referring to Presto-based Opera.\n */\ngoog.userAgent.ASSUME_OPERA = goog.define('goog.userAgent.ASSUME_OPERA', false);\n\n\n/**\n * @define {boolean} Whether the\n *     `goog.userAgent.isVersionOrHigher`\n *     function will return true for any version.\n */\ngoog.userAgent.ASSUME_ANY_VERSION =\n    goog.define('goog.userAgent.ASSUME_ANY_VERSION', false);\n\n\n/**\n * Whether we know the browser engine at compile-time.\n * @type {boolean}\n * @private\n */\ngoog.userAgent.BROWSER_KNOWN_ = goog.userAgent.ASSUME_IE ||\n    goog.userAgent.ASSUME_EDGE || goog.userAgent.ASSUME_GECKO ||\n    goog.userAgent.ASSUME_MOBILE_WEBKIT || goog.userAgent.ASSUME_WEBKIT ||\n    goog.userAgent.ASSUME_OPERA;\n\n\n/**\n * Returns the userAgent string for the current browser.\n *\n * @return {string} The userAgent string.\n */\ngoog.userAgent.getUserAgentString = function() {\n  'use strict';\n  return goog.labs.userAgent.util.getUserAgent();\n};\n\n\n/**\n * @return {?Navigator} The native navigator object.\n */\ngoog.userAgent.getNavigatorTyped = function() {\n  'use strict';\n  // Need a local navigator reference instead of using the global one,\n  // to avoid the rare case where they reference different objects.\n  // (in a WorkerPool, for example).\n  return goog.global['navigator'] || null;\n};\n\n\n/**\n * TODO(nnaze): Change type to \"Navigator\" and update compilation targets.\n * @return {?Object} The native navigator object.\n */\ngoog.userAgent.getNavigator = function() {\n  'use strict';\n  return goog.userAgent.getNavigatorTyped();\n};\n\n\n/**\n * Whether the user agent is Presto-based Opera.\n * @type {boolean}\n */\ngoog.userAgent.OPERA = goog.userAgent.BROWSER_KNOWN_ ?\n    goog.userAgent.ASSUME_OPERA :\n    goog.labs.userAgent.browser.isOpera();\n\n\n/**\n * Whether the user agent is Internet Explorer.\n * @type {boolean}\n */\ngoog.userAgent.IE = goog.userAgent.BROWSER_KNOWN_ ?\n    goog.userAgent.ASSUME_IE :\n    goog.labs.userAgent.browser.isIE();\n\n\n/**\n * Whether the user agent is Microsoft Edge (EdgeHTML based).\n * @type {boolean}\n */\ngoog.userAgent.EDGE = goog.userAgent.BROWSER_KNOWN_ ?\n    goog.userAgent.ASSUME_EDGE :\n    goog.labs.userAgent.engine.isEdge();\n\n\n/**\n * Whether the user agent is MS Internet Explorer or MS Edge (EdgeHTML based).\n * @type {boolean}\n */\ngoog.userAgent.EDGE_OR_IE = goog.userAgent.EDGE || goog.userAgent.IE;\n\n\n/**\n * Whether the user agent is Gecko. Gecko is the rendering engine used by\n * Mozilla, Firefox, and others.\n * @type {boolean}\n */\ngoog.userAgent.GECKO = goog.userAgent.BROWSER_KNOWN_ ?\n    goog.userAgent.ASSUME_GECKO :\n    goog.labs.userAgent.engine.isGecko();\n\n\n/**\n * Whether the user agent is WebKit. WebKit is the rendering engine that\n * Safari, Edge Chromium, Opera Chromium, Android and others use.\n * @type {boolean}\n */\ngoog.userAgent.WEBKIT = goog.userAgent.BROWSER_KNOWN_ ?\n    goog.userAgent.ASSUME_WEBKIT || goog.userAgent.ASSUME_MOBILE_WEBKIT :\n    goog.labs.userAgent.engine.isWebKit();\n\n\n/**\n * Whether the user agent is running on a mobile device.\n *\n * This is a separate function so that the logic can be tested.\n *\n * TODO(nnaze): Investigate swapping in goog.labs.userAgent.device.isMobile().\n *\n * @return {boolean} Whether the user agent is running on a mobile device.\n * @private\n */\ngoog.userAgent.isMobile_ = function() {\n  'use strict';\n  return goog.userAgent.WEBKIT &&\n      goog.labs.userAgent.util.matchUserAgent('Mobile');\n};\n\n\n/**\n * Whether the user agent is running on a mobile device.\n *\n * TODO(nnaze): Consider deprecating MOBILE when labs.userAgent\n *   is promoted as the gecko/webkit logic is likely inaccurate.\n *\n * @type {boolean}\n */\ngoog.userAgent.MOBILE =\n    goog.userAgent.ASSUME_MOBILE_WEBKIT || goog.userAgent.isMobile_();\n\n\n/**\n * Used while transitioning code to use WEBKIT instead.\n * @type {boolean}\n * @deprecated Use {@link goog.userAgent.product.SAFARI} instead.\n * TODO(nicksantos): Delete this from goog.userAgent.\n */\ngoog.userAgent.SAFARI = goog.userAgent.WEBKIT;\n\n\n/**\n * @return {string} the platform (operating system) the user agent is running\n *     on. Default to empty string because navigator.platform may not be defined\n *     (on Rhino, for example).\n * @private\n */\ngoog.userAgent.determinePlatform_ = function() {\n  'use strict';\n  var navigator = goog.userAgent.getNavigatorTyped();\n  return navigator && navigator.platform || '';\n};\n\n\n/**\n * The platform (operating system) the user agent is running on. Default to\n * empty string because navigator.platform may not be defined (on Rhino, for\n * example).\n * @type {string}\n */\ngoog.userAgent.PLATFORM = goog.userAgent.determinePlatform_();\n\n\n/**\n * @define {boolean} Whether the user agent is running on a Macintosh operating\n *     system.\n */\ngoog.userAgent.ASSUME_MAC = goog.define('goog.userAgent.ASSUME_MAC', false);\n\n\n/**\n * @define {boolean} Whether the user agent is running on a Windows operating\n *     system.\n */\ngoog.userAgent.ASSUME_WINDOWS =\n    goog.define('goog.userAgent.ASSUME_WINDOWS', false);\n\n\n/**\n * @define {boolean} Whether the user agent is running on a Linux operating\n *     system.\n */\ngoog.userAgent.ASSUME_LINUX = goog.define('goog.userAgent.ASSUME_LINUX', false);\n\n\n/**\n * @define {boolean} Whether the user agent is running on a X11 windowing\n *     system.\n */\ngoog.userAgent.ASSUME_X11 = goog.define('goog.userAgent.ASSUME_X11', false);\n\n\n/**\n * @define {boolean} Whether the user agent is running on Android.\n */\ngoog.userAgent.ASSUME_ANDROID =\n    goog.define('goog.userAgent.ASSUME_ANDROID', false);\n\n\n/**\n * @define {boolean} Whether the user agent is running on an iPhone.\n */\ngoog.userAgent.ASSUME_IPHONE =\n    goog.define('goog.userAgent.ASSUME_IPHONE', false);\n\n\n/**\n * @define {boolean} Whether the user agent is running on an iPad.\n */\ngoog.userAgent.ASSUME_IPAD = goog.define('goog.userAgent.ASSUME_IPAD', false);\n\n\n/**\n * @define {boolean} Whether the user agent is running on an iPod.\n */\ngoog.userAgent.ASSUME_IPOD = goog.define('goog.userAgent.ASSUME_IPOD', false);\n\n\n/**\n * @define {boolean} Whether the user agent is running on KaiOS.\n */\ngoog.userAgent.ASSUME_KAIOS = goog.define('goog.userAgent.ASSUME_KAIOS', false);\n\n\n/**\n * @type {boolean}\n * @private\n */\ngoog.userAgent.PLATFORM_KNOWN_ = goog.userAgent.ASSUME_MAC ||\n    goog.userAgent.ASSUME_WINDOWS || goog.userAgent.ASSUME_LINUX ||\n    goog.userAgent.ASSUME_X11 || goog.userAgent.ASSUME_ANDROID ||\n    goog.userAgent.ASSUME_IPHONE || goog.userAgent.ASSUME_IPAD ||\n    goog.userAgent.ASSUME_IPOD;\n\n\n/**\n * Whether the user agent is running on a Macintosh operating system.\n * @type {boolean}\n */\ngoog.userAgent.MAC = goog.userAgent.PLATFORM_KNOWN_ ?\n    goog.userAgent.ASSUME_MAC :\n    goog.labs.userAgent.platform.isMacintosh();\n\n\n/**\n * Whether the user agent is running on a Windows operating system.\n * @type {boolean}\n */\ngoog.userAgent.WINDOWS = goog.userAgent.PLATFORM_KNOWN_ ?\n    goog.userAgent.ASSUME_WINDOWS :\n    goog.labs.userAgent.platform.isWindows();\n\n\n/**\n * Whether the user agent is Linux per the legacy behavior of\n * goog.userAgent.LINUX, which considered ChromeOS to also be\n * Linux.\n * @return {boolean}\n * @private\n */\ngoog.userAgent.isLegacyLinux_ = function() {\n  'use strict';\n  return goog.labs.userAgent.platform.isLinux() ||\n      goog.labs.userAgent.platform.isChromeOS();\n};\n\n\n/**\n * Whether the user agent is running on a Linux operating system.\n *\n * Note that goog.userAgent.LINUX considers ChromeOS to be Linux,\n * while goog.labs.userAgent.platform considers ChromeOS and\n * Linux to be different OSes.\n *\n * @type {boolean}\n */\ngoog.userAgent.LINUX = goog.userAgent.PLATFORM_KNOWN_ ?\n    goog.userAgent.ASSUME_LINUX :\n    goog.userAgent.isLegacyLinux_();\n\n\n/**\n * @return {boolean} Whether the user agent is an X11 windowing system.\n * @private\n */\ngoog.userAgent.isX11_ = function() {\n  'use strict';\n  var navigator = goog.userAgent.getNavigatorTyped();\n  return !!navigator &&\n      goog.string.internal.contains(navigator['appVersion'] || '', 'X11');\n};\n\n\n/**\n * Whether the user agent is running on a X11 windowing system.\n * @type {boolean}\n */\ngoog.userAgent.X11 = goog.userAgent.PLATFORM_KNOWN_ ?\n    goog.userAgent.ASSUME_X11 :\n    goog.userAgent.isX11_();\n\n\n/**\n * Whether the user agent is running on Android.\n * @type {boolean}\n */\ngoog.userAgent.ANDROID = goog.userAgent.PLATFORM_KNOWN_ ?\n    goog.userAgent.ASSUME_ANDROID :\n    goog.labs.userAgent.platform.isAndroid();\n\n\n/**\n * Whether the user agent is running on an iPhone.\n * @type {boolean}\n */\ngoog.userAgent.IPHONE = goog.userAgent.PLATFORM_KNOWN_ ?\n    goog.userAgent.ASSUME_IPHONE :\n    goog.labs.userAgent.platform.isIphone();\n\n\n/**\n * Whether the user agent is running on an iPad.\n * @type {boolean}\n */\ngoog.userAgent.IPAD = goog.userAgent.PLATFORM_KNOWN_ ?\n    goog.userAgent.ASSUME_IPAD :\n    goog.labs.userAgent.platform.isIpad();\n\n\n/**\n * Whether the user agent is running on an iPod.\n * @type {boolean}\n */\ngoog.userAgent.IPOD = goog.userAgent.PLATFORM_KNOWN_ ?\n    goog.userAgent.ASSUME_IPOD :\n    goog.labs.userAgent.platform.isIpod();\n\n\n/**\n * Whether the user agent is running on iOS.\n * @type {boolean}\n */\ngoog.userAgent.IOS = goog.userAgent.PLATFORM_KNOWN_ ?\n    (goog.userAgent.ASSUME_IPHONE || goog.userAgent.ASSUME_IPAD ||\n     goog.userAgent.ASSUME_IPOD) :\n    goog.labs.userAgent.platform.isIos();\n\n/**\n * Whether the user agent is running on KaiOS.\n * @type {boolean}\n */\ngoog.userAgent.KAIOS = goog.userAgent.PLATFORM_KNOWN_ ?\n    goog.userAgent.ASSUME_KAIOS :\n    goog.labs.userAgent.platform.isKaiOS();\n\n\n/**\n * @return {string} The string that describes the version number of the user\n *     agent.\n * @private\n */\ngoog.userAgent.determineVersion_ = function() {\n  'use strict';\n  // All browsers have different ways to detect the version and they all have\n  // different naming schemes.\n  // version is a string rather than a number because it may contain 'b', 'a',\n  // and so on.\n  var version = '';\n  var arr = goog.userAgent.getVersionRegexResult_();\n  if (arr) {\n    version = arr ? arr[1] : '';\n  }\n\n  if (goog.userAgent.IE) {\n    // IE9 can be in document mode 9 but be reporting an inconsistent user agent\n    // version.  If it is identifying as a version lower than 9 we take the\n    // documentMode as the version instead.  IE8 has similar behavior.\n    // It is recommended to set the X-UA-Compatible header to ensure that IE9\n    // uses documentMode 9.\n    var docMode = goog.userAgent.getDocumentMode_();\n    if (docMode != null && docMode > parseFloat(version)) {\n      return String(docMode);\n    }\n  }\n\n  return version;\n};\n\n\n/**\n * @return {?IArrayLike<string>|undefined} The version regex matches from\n *     parsing the user\n *     agent string. These regex statements must be executed inline so they can\n *     be compiled out by the closure compiler with the rest of the useragent\n *     detection logic when ASSUME_* is specified.\n * @private\n */\ngoog.userAgent.getVersionRegexResult_ = function() {\n  'use strict';\n  var userAgent = goog.userAgent.getUserAgentString();\n  if (goog.userAgent.GECKO) {\n    return /rv\\:([^\\);]+)(\\)|;)/.exec(userAgent);\n  }\n  if (goog.userAgent.EDGE) {\n    return /Edge\\/([\\d\\.]+)/.exec(userAgent);\n  }\n  if (goog.userAgent.IE) {\n    return /\\b(?:MSIE|rv)[: ]([^\\);]+)(\\)|;)/.exec(userAgent);\n  }\n  if (goog.userAgent.WEBKIT) {\n    // WebKit/125.4\n    return /WebKit\\/(\\S+)/.exec(userAgent);\n  }\n  if (goog.userAgent.OPERA) {\n    // If none of the above browsers were detected but the browser is Opera, the\n    // only string that is of interest is 'Version/<number>'.\n    return /(?:Version)[ \\/]?(\\S+)/.exec(userAgent);\n  }\n  return undefined;\n};\n\n\n/**\n * @return {number|undefined} Returns the document mode (for testing).\n * @private\n */\ngoog.userAgent.getDocumentMode_ = function() {\n  'use strict';\n  // NOTE(user): goog.userAgent may be used in context where there is no DOM.\n  var doc = goog.global['document'];\n  return doc ? doc['documentMode'] : undefined;\n};\n\n\n/**\n * The version of the user agent. This is a string because it might contain\n * 'b' (as in beta) as well as multiple dots.\n * @type {string}\n */\ngoog.userAgent.VERSION = goog.userAgent.determineVersion_();\n\n\n/**\n * Compares two version numbers.\n *\n * @param {string} v1 Version of first item.\n * @param {string} v2 Version of second item.\n *\n * @return {number}  1 if first argument is higher\n *                   0 if arguments are equal\n *                  -1 if second argument is higher.\n * @deprecated Use goog.string.compareVersions.\n */\ngoog.userAgent.compare = function(v1, v2) {\n  'use strict';\n  return goog.string.internal.compareVersions(v1, v2);\n};\n\n\n/**\n * Cache for {@link goog.userAgent.isVersionOrHigher}.\n * Calls to compareVersions are surprisingly expensive and, as a browser's\n * version number is unlikely to change during a session, we cache the results.\n * @const\n * @private\n */\ngoog.userAgent.isVersionOrHigherCache_ = {};\n\n\n/**\n * Whether the user agent version is higher or the same as the given version.\n * NOTE: When checking the version numbers for Firefox and Safari, be sure to\n * use the engine's version, not the browser's version number.  For example,\n * Firefox 3.0 corresponds to Gecko 1.9 and Safari 3.0 to Webkit 522.11.\n * Opera and Internet Explorer versions match the product release number.<br>\n * @see <a href=\"http://en.wikipedia.org/wiki/Safari_version_history\">\n *     Webkit</a>\n * @see <a href=\"http://en.wikipedia.org/wiki/Gecko_engine\">Gecko</a>\n *\n * @param {string|number} version The version to check.\n * @return {boolean} Whether the user agent version is higher or the same as\n *     the given version.\n */\ngoog.userAgent.isVersionOrHigher = function(version) {\n  'use strict';\n  return goog.userAgent.ASSUME_ANY_VERSION ||\n      goog.reflect.cache(\n          goog.userAgent.isVersionOrHigherCache_, version, function() {\n            'use strict';\n            return goog.string.internal.compareVersions(\n                       goog.userAgent.VERSION, version) >= 0;\n          });\n};\n\n\n/**\n * Whether the IE effective document mode is higher or the same as the given\n * document mode version.\n * NOTE: Only for IE, return false for another browser.\n *\n * @param {number} documentMode The document mode version to check.\n * @return {boolean} Whether the IE effective document mode is higher or the\n *     same as the given version.\n */\ngoog.userAgent.isDocumentModeOrHigher = function(documentMode) {\n  'use strict';\n  return Number(goog.userAgent.DOCUMENT_MODE) >= documentMode;\n};\n\n\n/**\n * Deprecated alias to `goog.userAgent.isDocumentModeOrHigher`.\n * @param {number} version The version to check.\n * @return {boolean} Whether the IE effective document mode is higher or the\n *      same as the given version.\n * @deprecated Use goog.userAgent.isDocumentModeOrHigher().\n */\ngoog.userAgent.isDocumentMode = goog.userAgent.isDocumentModeOrHigher;\n\n\n/**\n * For IE version < 7, documentMode is undefined, so attempt to use the\n * CSS1Compat property to see if we are in standards mode. If we are in\n * standards mode, treat the browser version as the document mode. Otherwise,\n * IE is emulating version 5.\n *\n * NOTE(user): Support for IE < 7 is long gone, so this is now simplified.\n * It returns document.documentMode for IE and undefined for everything else.\n *\n * @type {number|undefined}\n * @const\n */\ngoog.userAgent.DOCUMENT_MODE = (function() {\n  'use strict';\n  var doc = goog.global['document'];\n  if (!doc || !goog.userAgent.IE) return undefined;\n  // This must be an IE user agent.\n  var documentMode = goog.userAgent.getDocumentMode_();\n  if (documentMode) return documentMode;\n  // The user agent version string begins with the major version.\n  // Parse the major version and truncate anything following.\n  var ieVersion = parseInt(goog.userAgent.VERSION, 10);\n  return ieVersion || undefined;\n})();\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Wrapper class for handling XmlHttpRequests.\n *\n * One off requests can be sent through goog.net.XhrIo.send() or an\n * instance can be created to send multiple requests.  Each request uses its\n * own XmlHttpRequest object and handles clearing of the event callback to\n * ensure no leaks.\n *\n * XhrIo is event based, it dispatches events on success, failure, finishing,\n * ready-state change, or progress (download and upload).\n *\n * The ready-state or timeout event fires first, followed by\n * a generic completed event. Then the abort, error, or success event\n * is fired as appropriate. Progress events are fired as they are\n * received. Lastly, the ready event will fire to indicate that the\n * object may be used to make another request.\n *\n * The error event may also be called before completed and\n * ready-state-change if the XmlHttpRequest.open() or .send() methods throw.\n *\n * This class does not support multiple requests, queuing, or prioritization.\n *\n * When progress events are supported by the browser, and progress is\n * enabled via .setProgressEventsEnabled(true), the\n * goog.net.EventType.PROGRESS event will be the re-dispatched browser\n * progress event. Additionally, a DOWNLOAD_PROGRESS or UPLOAD_PROGRESS event\n * will be fired for download and upload progress respectively.\n */\n\n\ngoog.provide('goog.net.XhrIo');\ngoog.provide('goog.net.XhrIo.ResponseType');\n\ngoog.require('goog.Timer');\ngoog.require('goog.array');\ngoog.require('goog.asserts');\ngoog.require('goog.collections.maps');\ngoog.require('goog.debug.entryPointRegistry');\ngoog.require('goog.events.EventTarget');\ngoog.require('goog.json.hybrid');\ngoog.require('goog.log');\ngoog.require('goog.net.ErrorCode');\ngoog.require('goog.net.EventType');\ngoog.require('goog.net.HttpStatus');\ngoog.require('goog.net.XmlHttp');\ngoog.require('goog.object');\ngoog.require('goog.string');\ngoog.require('goog.uri.utils');\ngoog.require('goog.userAgent');\ngoog.requireType('goog.Uri');\ngoog.requireType('goog.debug.ErrorHandler');\ngoog.requireType('goog.net.XhrLike');\ngoog.requireType('goog.net.XmlHttpFactory');\n\ngoog.scope(function() {\n\n'use strict';\n/**\n * Basic class for handling XMLHttpRequests.\n * @param {goog.net.XmlHttpFactory=} opt_xmlHttpFactory Factory to use when\n *     creating XMLHttpRequest objects.\n * @constructor\n * @extends {goog.events.EventTarget}\n */\ngoog.net.XhrIo = function(opt_xmlHttpFactory) {\n  'use strict';\n  XhrIo.base(this, 'constructor');\n\n  /**\n   * Map of default headers to add to every request, use:\n   * XhrIo.headers.set(name, value)\n   * @type {!Map<string,string>}\n   */\n  this.headers = new Map();\n\n  /**\n   * Optional XmlHttpFactory\n   * @private {goog.net.XmlHttpFactory}\n   */\n  this.xmlHttpFactory_ = opt_xmlHttpFactory || null;\n\n  /**\n   * Whether XMLHttpRequest is active.  A request is active from the time send()\n   * is called until onReadyStateChange() is complete, or error() or abort()\n   * is called.\n   * @private {boolean}\n   */\n  this.active_ = false;\n\n  /**\n   * The XMLHttpRequest object that is being used for the transfer.\n   * @private {?goog.net.XhrLike.OrNative}\n   */\n  this.xhr_ = null;\n\n  /**\n   * The options to use with the current XMLHttpRequest object.\n   * @private {?Object}\n   */\n  this.xhrOptions_ = null;\n\n  /**\n   * Last URL that was requested.\n   * @private {string|goog.Uri}\n   */\n  this.lastUri_ = '';\n\n  /**\n   * Method for the last request.\n   * @private {string}\n   */\n  this.lastMethod_ = '';\n\n  /**\n   * Last error code.\n   * @private {!goog.net.ErrorCode}\n   */\n  this.lastErrorCode_ = goog.net.ErrorCode.NO_ERROR;\n\n  /**\n   * Last error message.\n   * @private {Error|string}\n   */\n  this.lastError_ = '';\n\n  /**\n   * Used to ensure that we don't dispatch an multiple ERROR events. This can\n   * happen in IE when it does a synchronous load and one error is handled in\n   * the ready state change and one is handled due to send() throwing an\n   * exception.\n   * @private {boolean}\n   */\n  this.errorDispatched_ = false;\n\n  /**\n   * Used to make sure we don't fire the complete event from inside a send call.\n   * @private {boolean}\n   */\n  this.inSend_ = false;\n\n  /**\n   * Used in determining if a call to {@link #onReadyStateChange_} is from\n   * within a call to this.xhr_.open.\n   * @private {boolean}\n   */\n  this.inOpen_ = false;\n\n  /**\n   * Used in determining if a call to {@link #onReadyStateChange_} is from\n   * within a call to this.xhr_.abort.\n   * @private {boolean}\n   */\n  this.inAbort_ = false;\n\n  /**\n   * Number of milliseconds after which an incomplete request will be aborted\n   * and a {@link goog.net.EventType.TIMEOUT} event raised; 0 means no timeout\n   * is set.\n   * @private {number}\n   */\n  this.timeoutInterval_ = 0;\n\n  /**\n   * Timer to track request timeout.\n   * @private {?number}\n   */\n  this.timeoutId_ = null;\n\n  /**\n   * The requested type for the response. The empty string means use the default\n   * XHR behavior.\n   * @private {goog.net.XhrIo.ResponseType}\n   */\n  this.responseType_ = ResponseType.DEFAULT;\n\n  /**\n   * Whether a \"credentialed\" request is to be sent (one that is aware of\n   * cookies and authentication). This is applicable only for cross-domain\n   * requests and more recent browsers that support this part of the HTTP Access\n   * Control standard.\n   *\n   * @see http://www.w3.org/TR/XMLHttpRequest/#the-withcredentials-attribute\n   *\n   * @private {boolean}\n   */\n  this.withCredentials_ = false;\n\n  /**\n   * Whether progress events are enabled for this request. This is\n   * disabled by default because setting a progress event handler\n   * causes pre-flight OPTIONS requests to be sent for CORS requests,\n   * even in cases where a pre-flight request would not otherwise be\n   * sent.\n   *\n   * @see http://xhr.spec.whatwg.org/#security-considerations\n   *\n   * Note that this can cause problems for Firefox 22 and below, as an\n   * older \"LSProgressEvent\" will be dispatched by the browser. That\n   * progress event is no longer supported, and can lead to failures,\n   * including throwing exceptions.\n   *\n   * @see http://bugzilla.mozilla.org/show_bug.cgi?id=845631\n   * @see b/23469793\n   *\n   * @private {boolean}\n   */\n  this.progressEventsEnabled_ = false;\n\n  /**\n   * True if we can use XMLHttpRequest's timeout directly.\n   * @private {boolean}\n   */\n  this.useXhr2Timeout_ = false;\n\n  /**\n   * Specification for Trust Token operations (issuance, signing, and\n   * redemption).\n   * @private {?TrustTokenAttributeType}\n   */\n  this.trustToken_ = null;\n};\ngoog.inherits(goog.net.XhrIo, goog.events.EventTarget);\n\nconst XhrIo = goog.net.XhrIo;\n\n/**\n * Response types that may be requested for XMLHttpRequests.\n * @enum {string}\n * @see http://www.w3.org/TR/XMLHttpRequest/#the-responsetype-attribute\n */\ngoog.net.XhrIo.ResponseType = {\n  DEFAULT: '',\n  TEXT: 'text',\n  DOCUMENT: 'document',\n  // Not supported as of Chrome 10.0.612.1 dev\n  BLOB: 'blob',\n  ARRAY_BUFFER: 'arraybuffer',\n};\n\nconst ResponseType = goog.net.XhrIo.ResponseType;\n\n\n/**\n * A reference to the XhrIo logger\n * @private {?goog.log.Logger}\n * @const\n */\ngoog.net.XhrIo.prototype.logger_ = goog.log.getLogger('goog.net.XhrIo');\n\n\n/**\n * The Content-Type HTTP header name\n * @type {string}\n */\ngoog.net.XhrIo.CONTENT_TYPE_HEADER = 'Content-Type';\n\n\n/**\n * The Content-Transfer-Encoding HTTP header name\n * @type {string}\n */\ngoog.net.XhrIo.CONTENT_TRANSFER_ENCODING = 'Content-Transfer-Encoding';\n\n\n/**\n * The pattern matching the 'http' and 'https' URI schemes\n * @type {!RegExp}\n */\ngoog.net.XhrIo.HTTP_SCHEME_PATTERN = /^https?$/i;\n\nconst HTTP_SCHEME_PATTERN = goog.net.XhrIo.HTTP_SCHEME_PATTERN;\n\n\n/**\n * The methods that typically come along with form data.  We set different\n * headers depending on whether the HTTP action is one of these.\n * @type {!Array<string>}\n */\ngoog.net.XhrIo.METHODS_WITH_FORM_DATA = ['POST', 'PUT'];\n\n\n/**\n * The Content-Type HTTP header value for a url-encoded form\n * @type {string}\n */\ngoog.net.XhrIo.FORM_CONTENT_TYPE =\n    'application/x-www-form-urlencoded;charset=utf-8';\n\n\n/**\n * The XMLHttpRequest Level two timeout delay ms property name.\n *\n * @see http://www.w3.org/TR/XMLHttpRequest/#the-timeout-attribute\n *\n * @private {string}\n * @const\n */\ngoog.net.XhrIo.XHR2_TIMEOUT_ = 'timeout';\n\n\n/**\n * The XMLHttpRequest Level two ontimeout handler property name.\n *\n * @see http://www.w3.org/TR/XMLHttpRequest/#the-timeout-attribute\n *\n * @private {string}\n * @const\n */\ngoog.net.XhrIo.XHR2_ON_TIMEOUT_ = 'ontimeout';\n\n\n/**\n * All non-disposed instances of goog.net.XhrIo created\n * by {@link goog.net.XhrIo.send} are in this Array.\n * @see goog.net.XhrIo.cleanup\n * @private {!Array<!goog.net.XhrIo>}\n */\ngoog.net.XhrIo.sendInstances_ = [];\n\n\n/**\n * Static send that creates a short lived instance of XhrIo to send the\n * request.\n * @see goog.net.XhrIo.cleanup\n * @param {string|goog.Uri} url Uri to make request to.\n * @param {?function(this:goog.net.XhrIo, ?)=} opt_callback Callback function\n *     for when request is complete.\n * @param {string=} opt_method Send method, default: GET.\n * @param {ArrayBuffer|ArrayBufferView|Blob|Document|FormData|string=}\n *     opt_content Body data.\n * @param {(?Object|?goog.collections.maps.MapLike<string, string>)=}\n *     opt_headers Map of headers to add to the request.\n * @param {number=} opt_timeoutInterval Number of milliseconds after which an\n *     incomplete request will be aborted; 0 means no timeout is set.\n * @param {boolean=} opt_withCredentials Whether to send credentials with the\n *     request. Default to false. See {@link goog.net.XhrIo#setWithCredentials}.\n * @return {!goog.net.XhrIo} The sent XhrIo.\n */\ngoog.net.XhrIo.send = function(\n    url, opt_callback, opt_method, opt_content, opt_headers,\n    opt_timeoutInterval, opt_withCredentials) {\n  'use strict';\n  const x = new goog.net.XhrIo();\n  goog.net.XhrIo.sendInstances_.push(x);\n  if (opt_callback) {\n    x.listen(goog.net.EventType.COMPLETE, opt_callback);\n  }\n  x.listenOnce(goog.net.EventType.READY, x.cleanupSend_);\n  if (opt_timeoutInterval) {\n    x.setTimeoutInterval(opt_timeoutInterval);\n  }\n  if (opt_withCredentials) {\n    x.setWithCredentials(opt_withCredentials);\n  }\n  x.send(url, opt_method, opt_content, opt_headers);\n  return x;\n};\n\n\n/**\n * Disposes all non-disposed instances of goog.net.XhrIo created by\n * {@link goog.net.XhrIo.send}.\n * {@link goog.net.XhrIo.send} cleans up the goog.net.XhrIo instance\n * it creates when the request completes or fails.  However, if\n * the request never completes, then the goog.net.XhrIo is not disposed.\n * This can occur if the window is unloaded before the request completes.\n * We could have {@link goog.net.XhrIo.send} return the goog.net.XhrIo\n * it creates and make the client of {@link goog.net.XhrIo.send} be\n * responsible for disposing it in this case.  However, this makes things\n * significantly more complicated for the client, and the whole point\n * of {@link goog.net.XhrIo.send} is that it's simple and easy to use.\n * Clients of {@link goog.net.XhrIo.send} should call\n * {@link goog.net.XhrIo.cleanup} when doing final\n * cleanup on window unload.\n */\ngoog.net.XhrIo.cleanup = function() {\n  'use strict';\n  const instances = goog.net.XhrIo.sendInstances_;\n  while (instances.length) {\n    instances.pop().dispose();\n  }\n};\n\n\n/**\n * Installs exception protection for all entry point introduced by\n * goog.net.XhrIo instances which are not protected by\n * {@link goog.debug.ErrorHandler#protectWindowSetTimeout},\n * {@link goog.debug.ErrorHandler#protectWindowSetInterval}, or\n * {@link goog.events.protectBrowserEventEntryPoint}.\n *\n * @param {goog.debug.ErrorHandler} errorHandler Error handler with which to\n *     protect the entry point(s).\n */\ngoog.net.XhrIo.protectEntryPoints = function(errorHandler) {\n  'use strict';\n  goog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_ =\n      errorHandler.protectEntryPoint(\n          goog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_);\n};\n\n\n/**\n * Disposes of the specified goog.net.XhrIo created by\n * {@link goog.net.XhrIo.send} and removes it from\n * {@link goog.net.XhrIo.pendingStaticSendInstances_}.\n * @private\n */\ngoog.net.XhrIo.prototype.cleanupSend_ = function() {\n  'use strict';\n  this.dispose();\n  goog.array.remove(goog.net.XhrIo.sendInstances_, this);\n};\n\n\n/**\n * Returns the number of milliseconds after which an incomplete request will be\n * aborted, or 0 if no timeout is set.\n * @return {number} Timeout interval in milliseconds.\n */\ngoog.net.XhrIo.prototype.getTimeoutInterval = function() {\n  'use strict';\n  return this.timeoutInterval_;\n};\n\n\n/**\n * Sets the number of milliseconds after which an incomplete request will be\n * aborted and a {@link goog.net.EventType.TIMEOUT} event raised; 0 means no\n * timeout is set.\n * @param {number} ms Timeout interval in milliseconds; 0 means none.\n */\ngoog.net.XhrIo.prototype.setTimeoutInterval = function(ms) {\n  'use strict';\n  this.timeoutInterval_ = Math.max(0, ms);\n};\n\n\n/**\n * Sets the desired type for the response. At time of writing, this is only\n * supported in very recent versions of WebKit (10.0.612.1 dev and later).\n *\n * If this is used, the response may only be accessed via {@link #getResponse}.\n *\n * @param {goog.net.XhrIo.ResponseType} type The desired type for the response.\n */\ngoog.net.XhrIo.prototype.setResponseType = function(type) {\n  'use strict';\n  this.responseType_ = type;\n};\n\n\n/**\n * Gets the desired type for the response.\n * @return {goog.net.XhrIo.ResponseType} The desired type for the response.\n */\ngoog.net.XhrIo.prototype.getResponseType = function() {\n  'use strict';\n  return this.responseType_;\n};\n\n\n/**\n * Sets whether a \"credentialed\" request that is aware of cookie and\n * authentication information should be made. This option is only supported by\n * browsers that support HTTP Access Control. As of this writing, this option\n * is not supported in IE.\n *\n * @param {boolean} withCredentials Whether this should be a \"credentialed\"\n *     request.\n */\ngoog.net.XhrIo.prototype.setWithCredentials = function(withCredentials) {\n  'use strict';\n  this.withCredentials_ = withCredentials;\n};\n\n\n/**\n * Gets whether a \"credentialed\" request is to be sent.\n * @return {boolean} The desired type for the response.\n */\ngoog.net.XhrIo.prototype.getWithCredentials = function() {\n  'use strict';\n  return this.withCredentials_;\n};\n\n\n/**\n * Sets whether progress events are enabled for this request. Note\n * that progress events require pre-flight OPTIONS request handling\n * for CORS requests, and may cause trouble with older browsers. See\n * progressEventsEnabled_ for details.\n * @param {boolean} enabled Whether progress events should be enabled.\n */\ngoog.net.XhrIo.prototype.setProgressEventsEnabled = function(enabled) {\n  'use strict';\n  this.progressEventsEnabled_ = enabled;\n};\n\n\n/**\n * Gets whether progress events are enabled.\n * @return {boolean} Whether progress events are enabled for this request.\n */\ngoog.net.XhrIo.prototype.getProgressEventsEnabled = function() {\n  'use strict';\n  return this.progressEventsEnabled_;\n};\n\n/**\n * Specify a Trust Tokens operation to execute alongside the request.\n * @param {!TrustTokenAttributeType} trustToken a Trust Tokens operation to\n *     execute.\n */\ngoog.net.XhrIo.prototype.setTrustToken = function(trustToken) {\n  'use strict';\n  this.trustToken_ = trustToken;\n};\n\n/**\n * Instance send that actually uses XMLHttpRequest to make a server call.\n * @param {string|goog.Uri} url Uri to make request to.\n * @param {string=} opt_method Send method, default: GET.\n * @param {ArrayBuffer|ArrayBufferView|Blob|Document|FormData|string=}\n *     opt_content Body data.\n * @param {(?Object|?goog.collections.maps.MapLike<string, string>)=}\n *     opt_headers Map of headers to add to the request.\n * @suppress {deprecated} Use deprecated goog.structs.forEach to allow different\n * types of parameters for opt_headers.\n */\ngoog.net.XhrIo.prototype.send = function(\n    url, opt_method, opt_content, opt_headers) {\n  'use strict';\n  if (this.xhr_) {\n    throw new Error(\n        '[goog.net.XhrIo] Object is active with another request=' +\n        this.lastUri_ + '; newUri=' + url);\n  }\n\n  const method = opt_method ? opt_method.toUpperCase() : 'GET';\n\n  this.lastUri_ = url;\n  this.lastError_ = '';\n  this.lastErrorCode_ = goog.net.ErrorCode.NO_ERROR;\n  this.lastMethod_ = method;\n  this.errorDispatched_ = false;\n  this.active_ = true;\n\n  // Use the factory to create the XHR object and options\n  this.xhr_ = this.createXhr();\n  this.xhrOptions_ = this.xmlHttpFactory_ ? this.xmlHttpFactory_.getOptions() :\n                                            goog.net.XmlHttp.getOptions();\n\n  // Set up the onreadystatechange callback\n  this.xhr_.onreadystatechange = goog.bind(this.onReadyStateChange_, this);\n\n  // Set up upload/download progress events, if progress events are supported.\n  if (this.getProgressEventsEnabled() && 'onprogress' in this.xhr_) {\n    this.xhr_.onprogress = goog.bind(function(e) {\n      'use strict';\n      this.onProgressHandler_(e, true);\n    }, this);\n    if (this.xhr_.upload) {\n      this.xhr_.upload.onprogress = goog.bind(this.onProgressHandler_, this);\n    }\n  }\n\n  /**\n   * Try to open the XMLHttpRequest (always async), if an error occurs here it\n   * is generally permission denied\n   */\n  try {\n    goog.log.fine(this.logger_, this.formatMsg_('Opening Xhr'));\n    this.inOpen_ = true;\n    this.xhr_.open(method, String(url), true);  // Always async!\n    this.inOpen_ = false;\n  } catch (err) {\n    goog.log.fine(\n        this.logger_, this.formatMsg_('Error opening Xhr: ' + err.message));\n    this.error_(goog.net.ErrorCode.EXCEPTION, err);\n    return;\n  }\n\n  // We can't use null since this won't allow requests with form data to have a\n  // content length specified which will cause some proxies to return a 411\n  // error.\n  const content = opt_content || '';\n\n  const headers = new Map(this.headers);\n\n  // Add headers specific to this request\n  if (opt_headers) {\n    if (Object.getPrototypeOf(opt_headers) === Object.prototype) {\n      for (let key in opt_headers) {\n        headers.set(key, opt_headers[key]);\n      }\n    } else if (\n        typeof opt_headers.keys === 'function' &&\n        typeof opt_headers.get === 'function') {\n      for (const key of opt_headers.keys()) {\n        headers.set(key, opt_headers.get(key));\n      }\n    } else {\n      throw new Error(\n          'Unknown input type for opt_headers: ' + String(opt_headers));\n    }\n  }\n\n  // Find whether a content type header is set, ignoring case.\n  // HTTP header names are case-insensitive.  See:\n  // http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2\n  const contentTypeKey =\n      Array.from(headers.keys())\n          .find(\n              header => goog.string.caseInsensitiveEquals(\n                  goog.net.XhrIo.CONTENT_TYPE_HEADER, header));\n\n  const contentIsFormData =\n      (goog.global['FormData'] && (content instanceof goog.global['FormData']));\n  if (goog.array.contains(goog.net.XhrIo.METHODS_WITH_FORM_DATA, method) &&\n      !contentTypeKey && !contentIsFormData) {\n    // For requests typically with form data, default to the url-encoded form\n    // content type unless this is a FormData request.  For FormData,\n    // the browser will automatically add a multipart/form-data content type\n    // with an appropriate multipart boundary.\n    headers.set(\n        goog.net.XhrIo.CONTENT_TYPE_HEADER, goog.net.XhrIo.FORM_CONTENT_TYPE);\n  }\n\n  // Add the headers to the Xhr object\n  for (const [key, value] of headers) {\n    this.xhr_.setRequestHeader(key, value);\n  }\n\n  if (this.responseType_) {\n    this.xhr_.responseType = this.responseType_;\n  }\n  // Set xhr_.withCredentials only when the value is different, or else in\n  // synchronous XMLHtppRequest.open Firefox will throw an exception.\n  // https://bugzilla.mozilla.org/show_bug.cgi?id=736340\n  if ('withCredentials' in this.xhr_ &&\n      this.xhr_.withCredentials !== this.withCredentials_) {\n    this.xhr_.withCredentials = this.withCredentials_;\n  }\n\n  if ('setTrustToken' in this.xhr_ && this.trustToken_) {\n    try {\n      this.xhr_.setTrustToken(this.trustToken_);\n    } catch (err) {\n      goog.log.fine(\n          this.logger_, this.formatMsg_('Error SetTrustToken: ' + err.message));\n    }\n  }\n  /**\n   * Try to send the request, or other wise report an error (404 not found).\n   */\n  try {\n    this.cleanUpTimeoutTimer_();  // Paranoid, should never be running.\n    if (this.timeoutInterval_ > 0) {\n      this.useXhr2Timeout_ = goog.net.XhrIo.shouldUseXhr2Timeout_(this.xhr_);\n      goog.log.fine(\n          this.logger_,\n          this.formatMsg_(\n              'Will abort after ' + this.timeoutInterval_ +\n              'ms if incomplete, xhr2 ' + this.useXhr2Timeout_));\n      if (this.useXhr2Timeout_) {\n        this.xhr_[goog.net.XhrIo.XHR2_TIMEOUT_] = this.timeoutInterval_;\n        this.xhr_[goog.net.XhrIo.XHR2_ON_TIMEOUT_] =\n            goog.bind(this.timeout_, this);\n      } else {\n        this.timeoutId_ =\n            goog.Timer.callOnce(this.timeout_, this.timeoutInterval_, this);\n      }\n    }\n    goog.log.fine(this.logger_, this.formatMsg_('Sending request'));\n    this.inSend_ = true;\n    this.xhr_.send(content);\n    this.inSend_ = false;\n\n  } catch (err) {\n    goog.log.fine(this.logger_, this.formatMsg_('Send error: ' + err.message));\n    this.error_(goog.net.ErrorCode.EXCEPTION, err);\n  }\n};\n\n\n/**\n * Determines if the argument is an XMLHttpRequest that supports the level 2\n * timeout value and event.\n *\n * Currently, FF 21.0 OS X has the fields but won't actually call the timeout\n * handler.  Perhaps the confusion in the bug referenced below hasn't\n * entirely been resolved.\n *\n * @see http://www.w3.org/TR/XMLHttpRequest/#the-timeout-attribute\n * @see https://bugzilla.mozilla.org/show_bug.cgi?id=525816\n *\n * @param {!goog.net.XhrLike.OrNative} xhr The request.\n * @return {boolean} True if the request supports level 2 timeout.\n * @private\n */\ngoog.net.XhrIo.shouldUseXhr2Timeout_ = function(xhr) {\n  'use strict';\n  return goog.userAgent.IE && goog.userAgent.isVersionOrHigher(9) &&\n      typeof xhr[goog.net.XhrIo.XHR2_TIMEOUT_] === 'number' &&\n      xhr[goog.net.XhrIo.XHR2_ON_TIMEOUT_] !== undefined;\n};\n\n\n/**\n * Creates a new XHR object.\n * @return {!goog.net.XhrLike.OrNative} The newly created XHR object.\n * @protected\n */\ngoog.net.XhrIo.prototype.createXhr = function() {\n  'use strict';\n  return this.xmlHttpFactory_ ? this.xmlHttpFactory_.createInstance() :\n                                goog.net.XmlHttp();\n};\n\n\n/**\n * The request didn't complete after {@link goog.net.XhrIo#timeoutInterval_}\n * milliseconds; raises a {@link goog.net.EventType.TIMEOUT} event and aborts\n * the request.\n * @private\n */\ngoog.net.XhrIo.prototype.timeout_ = function() {\n  'use strict';\n  if (typeof goog == 'undefined') {\n    // If goog is undefined then the callback has occurred as the application\n    // is unloading and will error.  Thus we let it silently fail.\n  } else if (this.xhr_) {\n    this.lastError_ =\n        'Timed out after ' + this.timeoutInterval_ + 'ms, aborting';\n    this.lastErrorCode_ = goog.net.ErrorCode.TIMEOUT;\n    goog.log.fine(this.logger_, this.formatMsg_(this.lastError_));\n    this.dispatchEvent(goog.net.EventType.TIMEOUT);\n    this.abort(goog.net.ErrorCode.TIMEOUT);\n  }\n};\n\n\n/**\n * Something errorred, so inactivate, fire error callback and clean up\n * @param {goog.net.ErrorCode} errorCode The error code.\n * @param {Error} err The error object.\n * @private\n */\ngoog.net.XhrIo.prototype.error_ = function(errorCode, err) {\n  'use strict';\n  this.active_ = false;\n  if (this.xhr_) {\n    this.inAbort_ = true;\n    this.xhr_.abort();  // Ensures XHR isn't hung (FF)\n    this.inAbort_ = false;\n  }\n  this.lastError_ = err;\n  this.lastErrorCode_ = errorCode;\n  this.dispatchErrors_();\n  this.cleanUpXhr_();\n};\n\n\n/**\n * Dispatches COMPLETE and ERROR in case of an error. This ensures that we do\n * not dispatch multiple error events.\n * @private\n */\ngoog.net.XhrIo.prototype.dispatchErrors_ = function() {\n  'use strict';\n  if (!this.errorDispatched_) {\n    this.errorDispatched_ = true;\n    this.dispatchEvent(goog.net.EventType.COMPLETE);\n    this.dispatchEvent(goog.net.EventType.ERROR);\n  }\n};\n\n\n/**\n * Abort the current XMLHttpRequest\n * @param {goog.net.ErrorCode=} opt_failureCode Optional error code to use -\n *     defaults to ABORT.\n */\ngoog.net.XhrIo.prototype.abort = function(opt_failureCode) {\n  'use strict';\n  if (this.xhr_ && this.active_) {\n    goog.log.fine(this.logger_, this.formatMsg_('Aborting'));\n    this.active_ = false;\n    this.inAbort_ = true;\n    this.xhr_.abort();\n    this.inAbort_ = false;\n    this.lastErrorCode_ = opt_failureCode || goog.net.ErrorCode.ABORT;\n    this.dispatchEvent(goog.net.EventType.COMPLETE);\n    this.dispatchEvent(goog.net.EventType.ABORT);\n    this.cleanUpXhr_();\n  }\n};\n\n\n/**\n * Nullifies all callbacks to reduce risks of leaks.\n * @override\n * @protected\n */\ngoog.net.XhrIo.prototype.disposeInternal = function() {\n  'use strict';\n  if (this.xhr_) {\n    // We explicitly do not call xhr_.abort() unless active_ is still true.\n    // This is to avoid unnecessarily aborting a successful request when\n    // dispose() is called in a callback triggered by a complete response, but\n    // in which browser cleanup has not yet finished.\n    // (See http://b/issue?id=1684217.)\n    if (this.active_) {\n      this.active_ = false;\n      this.inAbort_ = true;\n      this.xhr_.abort();\n      this.inAbort_ = false;\n    }\n    this.cleanUpXhr_(true);\n  }\n\n  XhrIo.base(this, 'disposeInternal');\n};\n\n\n/**\n * Internal handler for the XHR object's readystatechange event.  This method\n * checks the status and the readystate and fires the correct callbacks.\n * If the request has ended, the handlers are cleaned up and the XHR object is\n * nullified.\n * @private\n */\ngoog.net.XhrIo.prototype.onReadyStateChange_ = function() {\n  'use strict';\n  if (this.isDisposed()) {\n    // This method is the target of an untracked goog.Timer.callOnce().\n    return;\n  }\n  if (!this.inOpen_ && !this.inSend_ && !this.inAbort_) {\n    // Were not being called from within a call to this.xhr_.send\n    // this.xhr_.abort, or this.xhr_.open, so this is an entry point\n    this.onReadyStateChangeEntryPoint_();\n  } else {\n    this.onReadyStateChangeHelper_();\n  }\n};\n\n\n/**\n * Used to protect the onreadystatechange handler entry point.  Necessary\n * as {#onReadyStateChange_} maybe called from within send or abort, this\n * method is only called when {#onReadyStateChange_} is called as an\n * entry point.\n * {@see #protectEntryPoints}\n * @private\n */\ngoog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_ = function() {\n  'use strict';\n  this.onReadyStateChangeHelper_();\n};\n\n\n/**\n * Helper for {@link #onReadyStateChange_}.  This is used so that\n * entry point calls to {@link #onReadyStateChange_} can be routed through\n * {@link #onReadyStateChangeEntryPoint_}.\n * @private\n */\ngoog.net.XhrIo.prototype.onReadyStateChangeHelper_ = function() {\n  'use strict';\n  if (!this.active_) {\n    // can get called inside abort call\n    return;\n  }\n\n  if (typeof goog == 'undefined') {\n    // NOTE(user): If goog is undefined then the callback has occurred as the\n    // application is unloading and will error.  Thus we let it silently fail.\n\n  } else if (\n      this.xhrOptions_[goog.net.XmlHttp.OptionType.LOCAL_REQUEST_ERROR] &&\n      this.getReadyState() == goog.net.XmlHttp.ReadyState.COMPLETE &&\n      this.getStatus() == 2) {\n    // NOTE(user): In IE if send() errors on a *local* request the readystate\n    // is still changed to COMPLETE.  We need to ignore it and allow the\n    // try/catch around send() to pick up the error.\n    goog.log.fine(\n        this.logger_,\n        this.formatMsg_('Local request error detected and ignored'));\n\n  } else {\n    // In IE when the response has been cached we sometimes get the callback\n    // from inside the send call and this usually breaks code that assumes that\n    // XhrIo is asynchronous.  If that is the case we delay the callback\n    // using a timer.\n    if (this.inSend_ &&\n        this.getReadyState() == goog.net.XmlHttp.ReadyState.COMPLETE) {\n      goog.Timer.callOnce(this.onReadyStateChange_, 0, this);\n      return;\n    }\n\n    this.dispatchEvent(goog.net.EventType.READY_STATE_CHANGE);\n\n    // readyState indicates the transfer has finished\n    if (this.isComplete()) {\n      goog.log.fine(this.logger_, this.formatMsg_('Request complete'));\n\n      this.active_ = false;\n\n      try {\n        // Call the specific callbacks for success or failure. Only call the\n        // success if the status is 200 (HTTP_OK) or 304 (HTTP_CACHED)\n        if (this.isSuccess()) {\n          this.dispatchEvent(goog.net.EventType.COMPLETE);\n          this.dispatchEvent(goog.net.EventType.SUCCESS);\n        } else {\n          this.lastErrorCode_ = goog.net.ErrorCode.HTTP_ERROR;\n          this.lastError_ =\n              this.getStatusText() + ' [' + this.getStatus() + ']';\n          this.dispatchErrors_();\n        }\n      } finally {\n        this.cleanUpXhr_();\n      }\n    }\n  }\n};\n\n\n/**\n * Internal handler for the XHR object's onprogress event. Fires both a generic\n * PROGRESS event and either a DOWNLOAD_PROGRESS or UPLOAD_PROGRESS event to\n * allow specific binding for each XHR progress event.\n * @param {!ProgressEvent} e XHR progress event.\n * @param {boolean=} opt_isDownload Whether the current progress event is from a\n *     download. Used to determine whether DOWNLOAD_PROGRESS or UPLOAD_PROGRESS\n *     event should be dispatched.\n * @private\n */\ngoog.net.XhrIo.prototype.onProgressHandler_ = function(e, opt_isDownload) {\n  'use strict';\n  goog.asserts.assert(\n      e.type === goog.net.EventType.PROGRESS,\n      'goog.net.EventType.PROGRESS is of the same type as raw XHR progress.');\n  this.dispatchEvent(\n      goog.net.XhrIo.buildProgressEvent_(e, goog.net.EventType.PROGRESS));\n  this.dispatchEvent(goog.net.XhrIo.buildProgressEvent_(\n      e,\n      opt_isDownload ? goog.net.EventType.DOWNLOAD_PROGRESS :\n                       goog.net.EventType.UPLOAD_PROGRESS));\n};\n\n\n/**\n * Creates a representation of the native ProgressEvent. IE doesn't support\n * constructing ProgressEvent via \"new\", and the alternatives (e.g.,\n * ProgressEvent.initProgressEvent) are non-standard or deprecated.\n * @param {!ProgressEvent} e XHR progress event.\n * @param {!goog.net.EventType} eventType The type of the event.\n * @return {!ProgressEvent} The progress event.\n * @private\n */\ngoog.net.XhrIo.buildProgressEvent_ = function(e, eventType) {\n  'use strict';\n  return /** @type {!ProgressEvent} */ ({\n    type: eventType,\n    lengthComputable: e.lengthComputable,\n    loaded: e.loaded,\n    total: e.total,\n  });\n};\n\n\n/**\n * Remove the listener to protect against leaks, and nullify the XMLHttpRequest\n * object.\n * @param {boolean=} opt_fromDispose If this is from the dispose (don't want to\n *     fire any events).\n * @private\n */\ngoog.net.XhrIo.prototype.cleanUpXhr_ = function(opt_fromDispose) {\n  'use strict';\n  if (this.xhr_) {\n    // Cancel any pending timeout event handler.\n    this.cleanUpTimeoutTimer_();\n\n    // Save reference so we can mark it as closed after the READY event.  The\n    // READY event may trigger another request, thus we must nullify this.xhr_\n    const xhr = this.xhr_;\n    const clearedOnReadyStateChange =\n        this.xhrOptions_[goog.net.XmlHttp.OptionType.USE_NULL_FUNCTION] ?\n        goog.nullFunction :\n        null;\n    this.xhr_ = null;\n    this.xhrOptions_ = null;\n\n    if (!opt_fromDispose) {\n      this.dispatchEvent(goog.net.EventType.READY);\n    }\n\n    try {\n      // NOTE(user): Not nullifying in FireFox can still leak if the callbacks\n      // are defined in the same scope as the instance of XhrIo. But, IE doesn't\n      // allow you to set the onreadystatechange to NULL so nullFunction is\n      // used.\n      xhr.onreadystatechange = clearedOnReadyStateChange;\n    } catch (e) {\n      // This seems to occur with a Gears HTTP request. Delayed the setting of\n      // this onreadystatechange until after READY is sent out and catching the\n      // error to see if we can track down the problem.\n      goog.log.error(\n          this.logger_,\n          'Problem encountered resetting onreadystatechange: ' + e.message);\n    }\n  }\n};\n\n\n/**\n * Make sure the timeout timer isn't running.\n * @private\n */\ngoog.net.XhrIo.prototype.cleanUpTimeoutTimer_ = function() {\n  'use strict';\n  if (this.xhr_ && this.useXhr2Timeout_) {\n    this.xhr_[goog.net.XhrIo.XHR2_ON_TIMEOUT_] = null;\n  }\n  if (this.timeoutId_) {\n    goog.Timer.clear(this.timeoutId_);\n    this.timeoutId_ = null;\n  }\n};\n\n\n/**\n * @return {boolean} Whether there is an active request.\n */\ngoog.net.XhrIo.prototype.isActive = function() {\n  'use strict';\n  return !!this.xhr_;\n};\n\n\n/**\n * @return {boolean} Whether the request has completed.\n */\ngoog.net.XhrIo.prototype.isComplete = function() {\n  'use strict';\n  return this.getReadyState() == goog.net.XmlHttp.ReadyState.COMPLETE;\n};\n\n\n/**\n * @return {boolean} Whether the request completed with a success.\n */\ngoog.net.XhrIo.prototype.isSuccess = function() {\n  'use strict';\n  const status = this.getStatus();\n  // A zero status code is considered successful for local files.\n  return goog.net.HttpStatus.isSuccess(status) ||\n      status === 0 && !this.isLastUriEffectiveSchemeHttp_();\n};\n\n\n/**\n * @return {boolean} whether the effective scheme of the last URI that was\n *     fetched was 'http' or 'https'.\n * @private\n */\ngoog.net.XhrIo.prototype.isLastUriEffectiveSchemeHttp_ = function() {\n  'use strict';\n  const scheme = goog.uri.utils.getEffectiveScheme(String(this.lastUri_));\n  return HTTP_SCHEME_PATTERN.test(scheme);\n};\n\n\n/**\n * Get the readystate from the Xhr object\n * Will only return correct result when called from the context of a callback\n * @return {goog.net.XmlHttp.ReadyState} goog.net.XmlHttp.ReadyState.*.\n */\ngoog.net.XhrIo.prototype.getReadyState = function() {\n  'use strict';\n  return this.xhr_ ?\n      /** @type {goog.net.XmlHttp.ReadyState} */ (this.xhr_.readyState) :\n      goog.net.XmlHttp.ReadyState.UNINITIALIZED;\n};\n\n\n/**\n * Get the status from the Xhr object\n * Will only return correct result when called from the context of a callback\n * @return {number} Http status.\n */\ngoog.net.XhrIo.prototype.getStatus = function() {\n  'use strict';\n  /**\n   * IE doesn't like you checking status until the readystate is greater than 2\n   * (i.e. it is receiving or complete).  The try/catch is used for when the\n   * page is unloading and an ERROR_NOT_AVAILABLE may occur when accessing xhr_.\n   */\n  try {\n    return this.getReadyState() > goog.net.XmlHttp.ReadyState.LOADED ?\n        this.xhr_.status :\n        -1;\n  } catch (e) {\n    return -1;\n  }\n};\n\n\n/**\n * Get the status text from the Xhr object\n * Will only return correct result when called from the context of a callback\n * @return {string} Status text.\n */\ngoog.net.XhrIo.prototype.getStatusText = function() {\n  'use strict';\n  /**\n   * IE doesn't like you checking status until the readystate is greater than 2\n   * (i.e. it is receiving or complete).  The try/catch is used for when the\n   * page is unloading and an ERROR_NOT_AVAILABLE may occur when accessing xhr_.\n   */\n  try {\n    return this.getReadyState() > goog.net.XmlHttp.ReadyState.LOADED ?\n        this.xhr_.statusText :\n        '';\n  } catch (e) {\n    goog.log.fine(this.logger_, 'Can not get status: ' + e.message);\n    return '';\n  }\n};\n\n\n/**\n * Get the last Uri that was requested\n * @return {string} Last Uri.\n */\ngoog.net.XhrIo.prototype.getLastUri = function() {\n  'use strict';\n  return String(this.lastUri_);\n};\n\n\n/**\n * Get the response text from the Xhr object\n * Will only return correct result when called from the context of a callback.\n * @return {string} Result from the server, or '' if no result available.\n */\ngoog.net.XhrIo.prototype.getResponseText = function() {\n  'use strict';\n  try {\n    return this.xhr_ ? this.xhr_.responseText : '';\n  } catch (e) {\n    // http://www.w3.org/TR/XMLHttpRequest/#the-responsetext-attribute\n    // states that responseText should return '' (and responseXML null)\n    // when the state is not LOADING or DONE. Instead, IE can\n    // throw unexpected exceptions, for example when a request is aborted\n    // or no data is available yet.\n    goog.log.fine(this.logger_, 'Can not get responseText: ' + e.message);\n    return '';\n  }\n};\n\n\n/**\n * Get the response body from the Xhr object. This property is only available\n * in IE since version 7 according to MSDN:\n * http://msdn.microsoft.com/en-us/library/ie/ms534368(v=vs.85).aspx\n * Will only return correct result when called from the context of a callback.\n *\n * One option is to construct a VBArray from the returned object and convert\n * it to a JavaScript array using the toArray method:\n * `(new window['VBArray'](xhrIo.getResponseBody())).toArray()`\n * This will result in an array of numbers in the range of [0..255]\n *\n * Another option is to use the VBScript CStr method to convert it into a\n * string as outlined in http://stackoverflow.com/questions/1919972\n *\n * @return {Object} Binary result from the server or null if not available.\n */\ngoog.net.XhrIo.prototype.getResponseBody = function() {\n  'use strict';\n  try {\n    if (this.xhr_ && 'responseBody' in this.xhr_) {\n      return this.xhr_['responseBody'];\n    }\n  } catch (e) {\n    // IE can throw unexpected exceptions, for example when a request is aborted\n    // or no data is yet available.\n    goog.log.fine(this.logger_, 'Can not get responseBody: ' + e.message);\n  }\n  return null;\n};\n\n\n/**\n * Get the response XML from the Xhr object\n * Will only return correct result when called from the context of a callback.\n * @return {Document} The DOM Document representing the XML file, or null\n * if no result available.\n */\ngoog.net.XhrIo.prototype.getResponseXml = function() {\n  'use strict';\n  try {\n    return this.xhr_ ? this.xhr_.responseXML : null;\n  } catch (e) {\n    goog.log.fine(this.logger_, 'Can not get responseXML: ' + e.message);\n    return null;\n  }\n};\n\n\n/**\n * Get the response and evaluates it as JSON from the Xhr object\n * Will only return correct result when called from the context of a callback\n * @param {string=} opt_xssiPrefix Optional XSSI prefix string to use for\n *     stripping of the response before parsing. This needs to be set only if\n *     your backend server prepends the same prefix string to the JSON response.\n * @throws Error if the response text is invalid JSON.\n * @return {Object|undefined} JavaScript object.\n */\ngoog.net.XhrIo.prototype.getResponseJson = function(opt_xssiPrefix) {\n  'use strict';\n  if (!this.xhr_) {\n    return undefined;\n  }\n\n  let responseText = this.xhr_.responseText;\n  if (opt_xssiPrefix && responseText.indexOf(opt_xssiPrefix) == 0) {\n    responseText = responseText.substring(opt_xssiPrefix.length);\n  }\n\n  return goog.json.hybrid.parse(responseText);\n};\n\n\n/**\n * Get the response as the type specificed by {@link #setResponseType}. At time\n * of writing, this is only directly supported in very recent versions of WebKit\n * (10.0.612.1 dev and later). If the field is not supported directly, we will\n * try to emulate it.\n *\n * Emulating the response means following the rules laid out at\n * http://www.w3.org/TR/XMLHttpRequest/#the-response-attribute\n *\n * On browsers with no support for this (Chrome < 10, Firefox < 4, etc), only\n * response types of DEFAULT or TEXT may be used, and the response returned will\n * be the text response.\n *\n * On browsers with Mozilla's draft support for array buffers (Firefox 4, 5),\n * only response types of DEFAULT, TEXT, and ARRAY_BUFFER may be used, and the\n * response returned will be either the text response or the Mozilla\n * implementation of the array buffer response.\n *\n * On browsers will full support, any valid response type supported by the\n * browser may be used, and the response provided by the browser will be\n * returned.\n *\n * @return {*} The response.\n */\ngoog.net.XhrIo.prototype.getResponse = function() {\n  'use strict';\n  try {\n    if (!this.xhr_) {\n      return null;\n    }\n    if ('response' in this.xhr_) {\n      return this.xhr_.response;\n    }\n    switch (this.responseType_) {\n      case ResponseType.DEFAULT:\n      case ResponseType.TEXT:\n        return this.xhr_.responseText;\n      // DOCUMENT and BLOB don't need to be handled here because they are\n      // introduced in the same spec that adds the .response field, and would\n      // have been caught above.\n      // ARRAY_BUFFER needs an implementation for Firefox 4, where it was\n      // implemented using a draft spec rather than the final spec.\n      case ResponseType.ARRAY_BUFFER:\n        if ('mozResponseArrayBuffer' in this.xhr_) {\n          return this.xhr_.mozResponseArrayBuffer;\n        }\n    }\n    // Fell through to a response type that is not supported on this browser.\n    goog.log.error(\n        this.logger_,\n        'Response type ' + this.responseType_ + ' is not ' +\n            'supported on this browser');\n    return null;\n  } catch (e) {\n    goog.log.fine(this.logger_, 'Can not get response: ' + e.message);\n    return null;\n  }\n};\n\n\n/**\n * Get the value of the response-header with the given name from the Xhr object\n * Will only return correct result when called from the context of a callback\n * and the request has completed\n * @param {string} key The name of the response-header to retrieve.\n * @return {string|undefined} The value of the response-header named key.\n */\ngoog.net.XhrIo.prototype.getResponseHeader = function(key) {\n  'use strict';\n  if (!this.xhr_ || !this.isComplete()) {\n    return undefined;\n  }\n\n  const value = this.xhr_.getResponseHeader(key);\n  return value === null ? undefined : value;\n};\n\n\n/**\n * Gets the text of all the headers in the response.\n * Will only return correct result when called from the context of a callback\n * and the request has completed.\n * @return {string} The value of the response headers or empty string.\n */\ngoog.net.XhrIo.prototype.getAllResponseHeaders = function() {\n  'use strict';\n  // getAllResponseHeaders can return null if no response has been received,\n  // ensure we always return an empty string.\n  return this.xhr_ && this.isComplete() ?\n      (this.xhr_.getAllResponseHeaders() || '') :\n      '';\n};\n\n\n/**\n * Returns all response headers as a key-value map.\n * Multiple values for the same header key can be combined into one,\n * separated by a comma and a space.\n * Note that the native getResponseHeader method for retrieving a single header\n * does a case insensitive match on the header name. This method does not\n * include any case normalization logic, it will just return a key-value\n * representation of the headers.\n * See: http://www.w3.org/TR/XMLHttpRequest/#the-getresponseheader()-method\n * @return {!Object<string, string>} An object with the header keys as keys\n *     and header values as values.\n */\ngoog.net.XhrIo.prototype.getResponseHeaders = function() {\n  'use strict';\n  // TODO(user): Make this function parse headers as per the spec\n  // (https://tools.ietf.org/html/rfc2616#section-4.2).\n\n  const headersObject = {};\n  const headersArray = this.getAllResponseHeaders().split('\\r\\n');\n  for (let i = 0; i < headersArray.length; i++) {\n    if (goog.string.isEmptyOrWhitespace(headersArray[i])) {\n      continue;\n    }\n    const keyValue =\n        goog.string.splitLimit(headersArray[i], ':', /* maxSplitCount= */ 1);\n    const key = keyValue[0];\n    let value = keyValue[1];\n\n    if (typeof value !== 'string') {\n      // There must be a value but it can be the empty string.\n      continue;\n    }\n\n    // Whitespace at the start and end of the value is meaningless.\n    value = value.trim();\n    // The key should not contain whitespace but we currently ignore that.\n\n    const values = headersObject[key] || [];\n    headersObject[key] = values;\n    values.push(value);\n  }\n\n  return goog.object.map(headersObject, function(values) {\n    'use strict';\n    return values.join(', ');\n  });\n};\n\n\n/**\n * Get the value of the response-header with the given name from the Xhr object.\n * As opposed to {@link #getResponseHeader}, this method does not require that\n * the request has completed.\n * @param {string} key The name of the response-header to retrieve.\n * @return {?string} The value of the response-header, or null if it is\n *     unavailable.\n */\ngoog.net.XhrIo.prototype.getStreamingResponseHeader = function(key) {\n  'use strict';\n  return this.xhr_ ? this.xhr_.getResponseHeader(key) : null;\n};\n\n\n/**\n * Gets the text of all the headers in the response. As opposed to\n * {@link #getAllResponseHeaders}, this method does not require that the request\n * has completed.\n * @return {string} The value of the response headers or empty string.\n */\ngoog.net.XhrIo.prototype.getAllStreamingResponseHeaders = function() {\n  'use strict';\n  return this.xhr_ ? this.xhr_.getAllResponseHeaders() : '';\n};\n\n\n/**\n * Get the last error message\n * @return {!goog.net.ErrorCode} Last error code.\n */\ngoog.net.XhrIo.prototype.getLastErrorCode = function() {\n  'use strict';\n  return this.lastErrorCode_;\n};\n\n\n/**\n * Get the last error message\n * @return {string} Last error message.\n */\ngoog.net.XhrIo.prototype.getLastError = function() {\n  'use strict';\n  return typeof this.lastError_ === 'string' ? this.lastError_ :\n                                               String(this.lastError_);\n};\n\n\n/**\n * Adds the last method, status and URI to the message.  This is used to add\n * this information to the logging calls.\n * @param {string} msg The message text that we want to add the extra text to.\n * @return {string} The message with the extra text appended.\n * @private\n */\ngoog.net.XhrIo.prototype.formatMsg_ = function(msg) {\n  'use strict';\n  return msg + ' [' + this.lastMethod_ + ' ' + this.lastUri_ + ' ' +\n      this.getStatus() + ']';\n};\n\n\n// Register the xhr handler as an entry point, so that\n// it can be monitored for exception handling, etc.\ngoog.debug.entryPointRegistry.register(\n    /**\n     * @param {function(!Function): !Function} transformer The transforming\n     *     function.\n     */\n    function(transformer) {\n      'use strict';\n      goog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_ =\n          transformer(goog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_);\n    });\n});  // goog.scope\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Closure user agent detection (Browser).\n * @see <a href=\"http://www.useragentstring.com/\">User agent strings</a>\n * For more information on rendering engine, platform, or device see the other\n * sub-namespaces in goog.labs.userAgent, goog.labs.userAgent.platform,\n * goog.labs.userAgent.device respectively.)\n */\n\ngoog.module('goog.labs.userAgent.browser');\ngoog.module.declareLegacyNamespace();\n\nconst googAsserts = goog.require('goog.asserts');\nconst util = goog.require('goog.labs.userAgent.util');\nconst {AsyncValue, Version} = goog.require('goog.labs.userAgent.highEntropy.highEntropyValue');\nconst {compareVersions} = goog.require('goog.string.internal');\nconst {fullVersionList, hasFullVersionList} = goog.require('goog.labs.userAgent.highEntropy.highEntropyData');\n\n// TODO(nnaze): Refactor to remove excessive exclusion logic in matching\n// functions.\n\n/**\n * A browser brand represents an opaque string that is used for making\n * brand-specific version checks in userAgentData.\n * @enum {string}\n */\nconst Brand = {\n  /**\n   * The browser brand for Android Browser.\n   * Do not depend on the value of this string. Because Android Browser has not\n   * implemented userAgentData yet, the value of this string is not guaranteed\n   * to stay the same in future revisions.\n   */\n  ANDROID_BROWSER: 'Android Browser',\n  /**\n   * The browser brand for Chromium, including Chromium-based Edge and Opera.\n   */\n  CHROMIUM: 'Chromium',\n  /**\n   * The browser brand for Edge.\n   * This brand can be used to get the version of both EdgeHTML and\n   * Chromium-based Edge.\n   */\n  EDGE: 'Microsoft Edge',\n  /**\n   * The browser brand for Firefox.\n   * Do not depend on the value of this string. Because Firefox has not\n   * implemented userAgentData yet, the value of this string is not guaranteed\n   * to stay the same in future revisions.\n   */\n  FIREFOX: 'Firefox',\n  /**\n   * The browser brand for Internet Explorer.\n   * Do not depend on the value of this string. Because IE will never support\n   * userAgentData, the value of this string should be treated as opaque (it's\n   * used internally for legacy-userAgent fallback).\n   */\n  IE: 'Internet Explorer',\n  /**\n   * The browser brand for Opera.\n   * This brand can be used to get the version of both Presto- and\n   * Chromium-based Opera.\n   */\n  OPERA: 'Opera',\n  /**\n   * The browser brand for Safari.\n   * Do not depend on the value of this string. Because Safari has not\n   * implemented userAgentData yet, the value of this string is not guaranteed\n   * to stay the same in future revisions.\n   */\n  SAFARI: 'Safari',\n  /**\n   * The browser brand for Silk.\n   * See\n   * https://docs.aws.amazon.com/silk/latest/developerguide/what-is-silk.html\n   * Do not depend on the value of this string. Because Silk does not\n   * identify itself in userAgentData yet, the value of this string is not\n   * guaranteed to stay the same in future revisions.\n   */\n  SILK: 'Silk',\n};\nexports.Brand = Brand;\n\n/**\n * @return {boolean} Whether to use navigator.userAgentData to determine\n * browser's brand.\n */\nfunction useUserAgentDataBrand() {\n  if (util.ASSUME_CLIENT_HINTS_SUPPORT) return true;\n  const userAgentData = util.getUserAgentData();\n  return !!userAgentData && userAgentData.brands.length > 0;\n}\n\n/**\n * @return {boolean} Whether the user's browser is Opera. Note: Chromium based\n *     Opera (Opera 15+) is detected as Chrome to avoid unnecessary special\n *     casing.\n */\nfunction matchOpera() {\n  if (useUserAgentDataBrand()) {\n    // Pre-Chromium Edge doesn't support navigator.userAgentData.\n    return false;\n  }\n  return util.matchUserAgent('Opera');\n}\n\n/** @return {boolean} Whether the user's browser is IE. */\nfunction matchIE() {\n  if (useUserAgentDataBrand()) {\n    // IE doesn't support navigator.userAgentData.\n    return false;\n  }\n  return util.matchUserAgent('Trident') || util.matchUserAgent('MSIE');\n}\n\n/**\n * @return {boolean} Whether the user's browser is Edge. This refers to\n *     EdgeHTML based Edge.\n */\nfunction matchEdgeHtml() {\n  if (useUserAgentDataBrand()) {\n    // Pre-Chromium Edge doesn't support navigator.userAgentData.\n    return false;\n  }\n  return util.matchUserAgent('Edge');\n}\n\n/** @return {boolean} Whether the user's browser is Chromium based Edge. */\nfunction matchEdgeChromium() {\n  if (useUserAgentDataBrand()) {\n    return util.matchUserAgentDataBrand(Brand.EDGE);\n  }\n  return util.matchUserAgent('Edg/');\n}\n\n/** @return {boolean} Whether the user's browser is Chromium based Opera. */\nfunction matchOperaChromium() {\n  if (useUserAgentDataBrand()) {\n    return util.matchUserAgentDataBrand(Brand.OPERA);\n  }\n  return util.matchUserAgent('OPR');\n}\n\n/** @return {boolean} Whether the user's browser is Firefox. */\nfunction matchFirefox() {\n  // Firefox doesn't support navigator.userAgentData yet, so use\n  // navigator.userAgent.\n  return util.matchUserAgent('Firefox') || util.matchUserAgent('FxiOS');\n}\n\n/** @return {boolean} Whether the user's browser is Safari. */\nfunction matchSafari() {\n  // Apple-based browsers don't support navigator.userAgentData yet, so use\n  // navigator.userAgent.\n  return util.matchUserAgent('Safari') &&\n      !(matchChrome() || matchCoast() || matchOpera() || matchEdgeHtml() ||\n        matchEdgeChromium() || matchOperaChromium() || matchFirefox() ||\n        isSilk() || util.matchUserAgent('Android'));\n}\n\n/**\n * @return {boolean} Whether the user's browser is Coast (Opera's Webkit-based\n *     iOS browser).\n */\nfunction matchCoast() {\n  if (useUserAgentDataBrand()) {\n    // Coast doesn't support navigator.userAgentData.\n    return false;\n  }\n  return util.matchUserAgent('Coast');\n}\n\n/** @return {boolean} Whether the user's browser is iOS Webview. */\nfunction matchIosWebview() {\n  // Apple-based browsers don't support navigator.userAgentData yet, so use\n  // navigator.userAgent.\n  // iOS Webview does not show up as Chrome or Safari.\n  return (util.matchUserAgent('iPad') || util.matchUserAgent('iPhone')) &&\n      !matchSafari() && !matchChrome() && !matchCoast() && !matchFirefox() &&\n      util.matchUserAgent('AppleWebKit');\n}\n\n/**\n * @return {boolean} Whether the user's browser is any Chromium browser. This\n *     returns true for Chrome, Opera 15+, and Edge Chromium.\n */\nfunction matchChrome() {\n  if (useUserAgentDataBrand()) {\n    return util.matchUserAgentDataBrand(Brand.CHROMIUM);\n  }\n  return ((util.matchUserAgent('Chrome') || util.matchUserAgent('CriOS')) &&\n          !matchEdgeHtml()) ||\n      isSilk();\n}\n\n/** @return {boolean} Whether the user's browser is the Android browser. */\nfunction matchAndroidBrowser() {\n  // Android can appear in the user agent string for Chrome on Android.\n  // This is not the Android standalone browser if it does.\n  return util.matchUserAgent('Android') &&\n      !(isChrome() || isFirefox() || isOpera() || isSilk());\n}\n\n/** @return {boolean} Whether the user's browser is Opera. */\nconst isOpera = matchOpera;\nexports.isOpera = isOpera;\n\n/** @return {boolean} Whether the user's browser is IE. */\nconst isIE = matchIE;\nexports.isIE = isIE;\n\n/** @return {boolean} Whether the user's browser is EdgeHTML based Edge. */\nconst isEdge = matchEdgeHtml;\nexports.isEdge = isEdge;\n\n/** @return {boolean} Whether the user's browser is Chromium based Edge. */\nconst isEdgeChromium = matchEdgeChromium;\nexports.isEdgeChromium = isEdgeChromium;\n\n/** @return {boolean} Whether the user's browser is Chromium based Opera. */\nconst isOperaChromium = matchOperaChromium;\nexports.isOperaChromium = isOperaChromium;\n\n/** @return {boolean} Whether the user's browser is Firefox. */\nconst isFirefox = matchFirefox;\nexports.isFirefox = isFirefox;\n\n/** @return {boolean} Whether the user's browser is Safari. */\nconst isSafari = matchSafari;\nexports.isSafari = isSafari;\n\n/**\n * @return {boolean} Whether the user's browser is Coast (Opera's Webkit-based\n *     iOS browser).\n */\nconst isCoast = matchCoast;\nexports.isCoast = isCoast;\n\n/** @return {boolean} Whether the user's browser is iOS Webview. */\nconst isIosWebview = matchIosWebview;\nexports.isIosWebview = isIosWebview;\n\n/**\n * @return {boolean} Whether the user's browser is any Chromium based browser (\n *     Chrome, Blink-based Opera (15+) and Edge Chromium).\n */\nconst isChrome = matchChrome;\nexports.isChrome = isChrome;\n\n/** @return {boolean} Whether the user's browser is the Android browser. */\nconst isAndroidBrowser = matchAndroidBrowser;\nexports.isAndroidBrowser = isAndroidBrowser;\n\n/**\n * For more information, see:\n * http://docs.aws.amazon.com/silk/latest/developerguide/user-agent.html\n * @return {boolean} Whether the user's browser is Silk.\n */\nfunction isSilk() {\n  // As of Silk 93, Silk does not identify itself in userAgentData.brands.\n  // When Silk changes this behavior, update this method to call\n  // matchUserAgentDataBrand (akin to isChrome, etc.)\n  return util.matchUserAgent('Silk');\n}\nexports.isSilk = isSilk;\n\n/**\n * A helper function that returns a function mapping a list of candidate\n * version tuple keys to the first version string present under a key.\n * Ex:\n * <code>\n * // Arg extracted from \"Foo/1.2.3 Bar/0.2021\"\n * const mapVersion = createVersionMap([[\"Foo\", \"1.2.3\"], [\"Bar\", \"0.2021\"]]);\n * mapVersion([\"Bar\", \"Foo\"]); // returns \"0.2021\"\n * mapVersion([\"Baz\", \"Foo\"]); // returns \"1.2.3\"\n * mapVersion([\"Baz\", \"???\"]); // returns \"\"\n * </code>\n * @param {!Array<!Array<string>>} versionTuples Version tuples pre-extracted\n *     from a user agent string.\n * @return {function(!Array<string>): string} The version string, or empty\n * string if it doesn't exist under the given key.\n */\nfunction createVersionMap(versionTuples) {\n  // Construct a map for easy lookup.\n  const versionMap = {};\n  versionTuples.forEach((tuple) => {\n    // Note that the tuple is of length three, but we only care about the\n    // first two.\n    const key = tuple[0];\n    const value = tuple[1];\n    versionMap[key] = value;\n  });\n\n  // Gives the value with the first key it finds, otherwise empty string.\n  return (keys) => versionMap[keys.find((key) => key in versionMap)] || '';\n}\n\n/**\n * Returns the browser version.\n *\n * Note that for browsers with multiple brands, this function assumes a primary\n * brand and returns the version for that brand.\n *\n * Additionally, this function is not userAgentData-aware and will return\n * incorrect values when the User Agent string is frozen. The current status of\n * User Agent string freezing is available here:\n * https://www.chromestatus.com/feature/5704553745874944\n *\n * To mitigate both of these potential issues, use\n * getVersionStringForLogging() or fullVersionOf() instead.\n *\n * @return {string} The browser version or empty string if version cannot be\n *     determined. Note that for Internet Explorer, this returns the version of\n *     the browser, not the version of the rendering engine. (IE 8 in\n *     compatibility mode will return 8.0 rather than 7.0. To determine the\n *     rendering engine version, look at document.documentMode instead. See\n *     http://msdn.microsoft.com/en-us/library/cc196988(v=vs.85).aspx for more\n *     details.)\n */\nfunction getVersion() {\n  const userAgentString = util.getUserAgent();\n\n  // Special case IE since IE's version is inside the parenthesis and\n  // without the '/'.\n  if (isIE()) {\n    return getIEVersion(userAgentString);\n  }\n\n  const versionTuples = util.extractVersionTuples(userAgentString);\n  const lookUpValueWithKeys = createVersionMap(versionTuples);\n\n  // Check Opera before Chrome since Opera 15+ has \"Chrome\" in the string.\n  // See\n  // http://my.opera.com/ODIN/blog/2013/07/15/opera-user-agent-strings-opera-15-and-beyond\n  if (isOpera()) {\n    // Opera 10 has Version/10.0 but Opera/9.8, so look for \"Version\" first.\n    // Opera uses 'OPR' for more recent UAs.\n    return lookUpValueWithKeys(['Version', 'Opera']);\n  }\n\n  // Check Edge before Chrome since it has Chrome in the string.\n  if (isEdge()) {\n    return lookUpValueWithKeys(['Edge']);\n  }\n\n  // Check Chromium Edge before Chrome since it has Chrome in the string.\n  if (isEdgeChromium()) {\n    return lookUpValueWithKeys(['Edg']);\n  }\n\n  // Check Silk before Chrome since it may have Chrome in its string and be\n  // treated as Chrome.\n  if (isSilk()) {\n    return lookUpValueWithKeys(['Silk']);\n  }\n\n  if (isChrome()) {\n    return lookUpValueWithKeys(['Chrome', 'CriOS', 'HeadlessChrome']);\n  }\n\n  // Usually products browser versions are in the third tuple after \"Mozilla\"\n  // and the engine.\n  const tuple = versionTuples[2];\n  return tuple && tuple[1] || '';\n}\nexports.getVersion = getVersion;\n\n/**\n * Returns whether the current browser's version is at least as high as the\n * given one.\n *\n * Note that for browsers with multiple brands, this function assumes a primary\n * brand and checks the version for that brand.\n *\n * Additionally, this function is not userAgentData-aware and will return\n * incorrect values when the User Agent string is frozen. The current status of\n * User Agent string freezing is available here:\n * https://www.chromestatus.com/feature/5704553745874944\n *\n * To mitigate both of these potential issues, use isAtLeast()/isAtMost() or\n * fullVersionOf() instead.\n *\n * @param {string|number} version The version to check.\n * @return {boolean} Whether the browser version is higher or the same as the\n *     given version.\n * @deprecated Use isAtLeast()/isAtMost() instead.\n */\nfunction isVersionOrHigher(version) {\n  return compareVersions(getVersion(), version) >= 0;\n}\nexports.isVersionOrHigher = isVersionOrHigher;\n\n/**\n * A helper function to determine IE version. More information:\n * http://msdn.microsoft.com/en-us/library/ie/bg182625(v=vs.85).aspx#uaString\n * http://msdn.microsoft.com/en-us/library/hh869301(v=vs.85).aspx\n * http://blogs.msdn.com/b/ie/archive/2010/03/23/introducing-ie9-s-user-agent-string.aspx\n * http://blogs.msdn.com/b/ie/archive/2009/01/09/the-internet-explorer-8-user-agent-string-updated-edition.aspx\n * @param {string} userAgent the User-Agent.\n * @return {string}\n */\nfunction getIEVersion(userAgent) {\n  // IE11 may identify itself as MSIE 9.0 or MSIE 10.0 due to an IE 11 upgrade\n  // bug. Example UA:\n  // Mozilla/5.0 (MSIE 9.0; Windows NT 6.1; WOW64; Trident/7.0; rv:11.0)\n  // like Gecko.\n  // See http://www.whatismybrowser.com/developers/unknown-user-agent-fragments.\n  const rv = /rv: *([\\d\\.]*)/.exec(userAgent);\n  if (rv && rv[1]) {\n    return rv[1];\n  }\n\n  let version = '';\n  const msie = /MSIE +([\\d\\.]+)/.exec(userAgent);\n  if (msie && msie[1]) {\n    // IE in compatibility mode usually identifies itself as MSIE 7.0; in this\n    // case, use the Trident version to determine the version of IE. For more\n    // details, see the links above.\n    const tridentVersion = /Trident\\/(\\d.\\d)/.exec(userAgent);\n    if (msie[1] == '7.0') {\n      if (tridentVersion && tridentVersion[1]) {\n        switch (tridentVersion[1]) {\n          case '4.0':\n            version = '8.0';\n            break;\n          case '5.0':\n            version = '9.0';\n            break;\n          case '6.0':\n            version = '10.0';\n            break;\n          case '7.0':\n            version = '11.0';\n            break;\n        }\n      } else {\n        version = '7.0';\n      }\n    } else {\n      version = msie[1];\n    }\n  }\n  return version;\n}\n\n/**\n * A helper function to return the navigator.userAgent-supplied full version\n * number of the current browser or an empty string, based on whether the\n * current browser is the one specified.\n * @param {string} browser The brand whose version should be returned.\n * @return {string}\n */\nfunction getFullVersionFromUserAgentString(browser) {\n  const userAgentString = util.getUserAgent();\n  // Special case IE since IE's version is inside the parenthesis and\n  // without the '/'.\n  if (browser === Brand.IE) {\n    return isIE() ? getIEVersion(userAgentString) : '';\n  }\n\n  const versionTuples = util.extractVersionTuples(userAgentString);\n  const lookUpValueWithKeys = createVersionMap(versionTuples);\n  switch (browser) {\n    case Brand.OPERA:\n      // Opera 10 has Version/10.0 but Opera/9.8, so look for \"Version\"\n      // first. Opera uses 'OPR' for more recent UAs.\n      if (isOpera()) {\n        return lookUpValueWithKeys(['Version', 'Opera']);\n      } else if (isOperaChromium()) {\n        return lookUpValueWithKeys(['OPR']);\n      }\n      break;\n    case Brand.EDGE:\n      if (isEdge()) {\n        return lookUpValueWithKeys(['Edge']);\n      } else if (isEdgeChromium()) {\n        return lookUpValueWithKeys(['Edg']);\n      }\n      break;\n    case Brand.CHROMIUM:\n      if (isChrome()) {\n        return lookUpValueWithKeys(['Chrome', 'CriOS', 'HeadlessChrome']);\n      }\n      break;\n  }\n\n  // For the following browsers, the browser version is in the third tuple after\n  // \"Mozilla\" and the engine.\n  if ((browser === Brand.FIREFOX && isFirefox()) ||\n      (browser === Brand.SAFARI && isSafari()) ||\n      (browser === Brand.ANDROID_BROWSER && isAndroidBrowser()) ||\n      (browser === Brand.SILK && isSilk())) {\n    const tuple = versionTuples[2];\n    return tuple && tuple[1] || '';\n  }\n\n  return '';\n}\n\n/**\n * Returns the major version of the given browser brand, or NaN if the current\n * browser is not the given brand.\n * Note that the major version number may be different depending on which\n * browser is specified. The returned value can be used to make browser version\n * comparisons using comparison operators.\n * @deprecated Use isAtLeast or isAtMost instead.\n * @param {!Brand} browser The brand whose version should be returned.\n * @return {number} The major version number associated with the current\n * browser under the given brand, or NaN if the current browser doesn't match\n * the given brand.\n */\nfunction versionOf(browser) {\n  let versionParts;\n  // Silk currently does not identify itself in its userAgentData.brands array,\n  // so if checking its version, always fall back to the user agent string.\n  if (useUserAgentDataBrand() && browser !== Brand.SILK) {\n    const data = util.getUserAgentData();\n    const matchingBrand = data.brands.find(({brand}) => brand === browser);\n    if (!matchingBrand || !matchingBrand.version) {\n      return NaN;\n    }\n    versionParts = matchingBrand.version.split('.');\n  } else {\n    const fullVersion = getFullVersionFromUserAgentString(browser);\n    if (fullVersion === '') {\n      return NaN;\n    }\n    versionParts = fullVersion.split('.');\n  }\n  if (versionParts.length === 0) {\n    return NaN;\n  }\n  const majorVersion = versionParts[0];\n  return Number(majorVersion);  // Returns NaN if it is not parseable.\n}\nexports.versionOf = versionOf;\n\n/**\n * Returns true if the current browser matches the given brand and is at least\n * the given major version. The major version must be a whole number (i.e.\n * decimals should not be used to represent a minor version).\n * @param {!Brand} brand The brand whose version should be returned.\n * @param {number} majorVersion The major version number to compare against.\n *     This must be a whole number.\n * @return {boolean} Whether the current browser both matches the given brand\n *     and is at least the given version.\n */\nfunction isAtLeast(brand, majorVersion) {\n  googAsserts.assert(\n      Math.floor(majorVersion) === majorVersion,\n      'Major version must be an integer');\n  return versionOf(brand) >= majorVersion;\n}\nexports.isAtLeast = isAtLeast;\n\n/**\n * Returns true if the current browser matches the given brand and is at most\n * the given version. The major version must be a whole number (i.e. decimals\n * should not be used to represent a minor version).\n * @param {!Brand} brand The brand whose version should be returned.\n * @param {number} majorVersion The major version number to compare against.\n *     This must be a whole number.\n * @return {boolean} Whether the current browser both matches the given brand\n *     and is at most the given version.\n */\nfunction isAtMost(brand, majorVersion) {\n  googAsserts.assert(\n      Math.floor(majorVersion) === majorVersion,\n      'Major version must be an integer');\n  return versionOf(brand) <= majorVersion;\n}\nexports.isAtMost = isAtMost;\n\n/**\n * Loads the high-entropy browser brand/version data and wraps the correct\n * version string in a Version object.\n * @implements {AsyncValue<!Version>}\n */\nclass HighEntropyBrandVersion {\n  /**\n   * @param {string} brand The brand whose version is retrieved in this\n   *     container.\n   */\n  constructor(brand) {\n    /**\n     * @const {string}\n     * @private\n     */\n    this.brand_ = brand;\n  }\n\n  /**\n   * @return {!Version|undefined}\n   * @override\n   */\n  getIfLoaded() {\n    const loadedVersionList = fullVersionList.getIfLoaded();\n    if (loadedVersionList !== undefined) {\n      const matchingBrand =\n          loadedVersionList.find(({brand}) => this.brand_ === brand);\n      googAsserts.assertExists(matchingBrand);\n      return new Version(matchingBrand.version);\n    }\n    return;\n  }\n\n  /**\n   * @return {!Promise<!Version>}\n   * @override\n   */\n  async load() {\n    const loadedVersionList = await fullVersionList.load();\n    const matchingBrand =\n        loadedVersionList.find(({brand}) => this.brand_ === brand);\n    googAsserts.assertExists(matchingBrand);\n    return new Version(matchingBrand.version);\n  }\n}\n\n/**\n * Wraps a version string in a Version object.\n * @implements {AsyncValue<!Version>}\n */\nclass UserAgentStringFallbackBrandVersion {\n  /**\n   * @param {string} versionString\n   */\n  constructor(versionString) {\n    /**\n     * @const {!Version}\n     * @private\n     */\n    this.version_ = new Version(versionString);\n  }\n\n  /**\n   * @return {!Version|undefined}\n   * @override\n   */\n  getIfLoaded() {\n    return this.version_;\n  }\n\n  /**\n   * @return {!Promise<!Version>}\n   * @override\n   */\n  async load() {\n    return this.version_;\n  }\n}\n\n/**\n * Requests all full browser versions to be cached.  When the returned promise\n * resolves, subsequent calls to `fullVersionOf(...).getIfLoaded()` will return\n * a value.\n *\n * This method should be avoided in favor of directly awaiting\n * `fullVersionOf(...).load()` where it is used.\n *\n * @return {!Promise<void>}\n */\nasync function loadFullVersions() {\n  if (useUserAgentDataBrand() && hasFullVersionList()) {\n    await fullVersionList.load();\n  }\n}\nexports.loadFullVersions = loadFullVersions;\n\n/**\n * Returns an object that provides access to the full version string of the\n * current browser -- or undefined, based on whether the current browser matches\n * the requested browser brand. Note that the full version string is a\n * high-entropy value, and must be asynchronously loaded before it can be\n * accessed synchronously.\n * @param {!Brand} browser The brand whose version should be returned.\n * @return {!AsyncValue<!Version>|undefined} An object that can be used\n *     to get or load the full version string as a high-entropy value, or\n * undefined if the current browser doesn't match the given brand.\n */\nfunction fullVersionOf(browser) {\n  // Silk currently does not identify itself in its userAgentData.brands array,\n  // so if checking its version, always fall back to the user agent string.\n  if (useUserAgentDataBrand() && hasFullVersionList()) {\n    const data = util.getUserAgentData();\n    // Operate under the assumption that the low-entropy and high-entropy lists\n    // of brand/version pairs contain an identical set of brands. Therefore, if\n    // the low-entropy list doesn't contain the given brand, return undefined.\n    if (!data.brands.find(({brand}) => brand === browser)) {\n      return undefined;\n    }\n    return new HighEntropyBrandVersion(browser);\n  } else {\n    const fullVersionFromUserAgentString =\n        getFullVersionFromUserAgentString(browser);\n    if (fullVersionFromUserAgentString === '') {\n      return undefined;\n    }\n    return new UserAgentStringFallbackBrandVersion(\n        fullVersionFromUserAgentString);\n  }\n}\nexports.fullVersionOf = fullVersionOf;\n\n/**\n * Returns a version string for the current browser or undefined, based on\n * whether the current browser is the one specified.\n * This value should ONLY be used for logging/debugging purposes. Do not use it\n * to branch code paths. For comparing versions, use isAtLeast()/isAtMost() or\n * fullVersionOf() instead.\n * @param {!Brand} browser The brand whose version should be returned.\n * @return {string} The version as a string.\n */\nfunction getVersionStringForLogging(browser) {\n  if (useUserAgentDataBrand()) {\n    const fullVersionObj = fullVersionOf(browser);\n    if (fullVersionObj) {\n      const fullVersion = fullVersionObj.getIfLoaded();\n      if (fullVersion) {\n        return fullVersion.toVersionStringForLogging();\n      }\n      // No full version, return the major version instead.\n      const data = util.getUserAgentData();\n      const matchingBrand = data.brands.find(({brand}) => brand === browser);\n      // Checking for the existence of matchingBrand is not necessary because\n      // the existence of fullVersionObj implies that there is already a\n      // matching brand.\n      googAsserts.assertExists(matchingBrand);\n      return matchingBrand.version;\n    }\n    // If fullVersionObj is undefined, this doesn't mean that the full version\n    // is unavailable, but rather that the current browser doesn't match the\n    // input `browser` argument.\n    return '';\n  } else {\n    return getFullVersionFromUserAgentString(browser);\n  }\n}\nexports.getVersionStringForLogging = getVersionStringForLogging;\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Closure user agent detection.\n * @see http://en.wikipedia.org/wiki/User_agent\n * For more information on browser brand, platform, or device see the other\n * sub-namespaces in goog.labs.userAgent (browser, platform, and device).\n */\n\ngoog.module('goog.labs.userAgent.engine');\ngoog.module.declareLegacyNamespace();\n\nconst googArray = goog.require('goog.array');\nconst googString = goog.require('goog.string.internal');\nconst util = goog.require('goog.labs.userAgent.util');\n\n/**\n * @return {boolean} Whether the rendering engine is Presto.\n */\nfunction isPresto() {\n  return util.matchUserAgent('Presto');\n}\n\n/**\n * @return {boolean} Whether the rendering engine is Trident.\n */\nfunction isTrident() {\n  // IE only started including the Trident token in IE8.\n  return util.matchUserAgent('Trident') || util.matchUserAgent('MSIE');\n}\n\n/**\n * @return {boolean} Whether the rendering engine is EdgeHTML.\n */\nfunction isEdge() {\n  return util.matchUserAgent('Edge');\n}\n\n/**\n * @return {boolean} Whether the rendering engine is WebKit. This will return\n * true for Chrome, Blink-based Opera (15+), Edge Chromium and Safari.\n */\nfunction isWebKit() {\n  return util.matchUserAgentIgnoreCase('WebKit') && !isEdge();\n}\n\n/**\n * @return {boolean} Whether the rendering engine is Gecko.\n */\nfunction isGecko() {\n  return util.matchUserAgent('Gecko') && !isWebKit() && !isTrident() &&\n      !isEdge();\n}\n\n/**\n * @return {string} The rendering engine's version or empty string if version\n *     can't be determined.\n */\nfunction getVersion() {\n  const userAgentString = util.getUserAgent();\n  if (userAgentString) {\n    const tuples = util.extractVersionTuples(userAgentString);\n\n    const engineTuple = getEngineTuple(tuples);\n    if (engineTuple) {\n      // In Gecko, the version string is either in the browser info or the\n      // Firefox version.  See Gecko user agent string reference:\n      // http://goo.gl/mULqa\n      if (engineTuple[0] == 'Gecko') {\n        return getVersionForKey(tuples, 'Firefox');\n      }\n\n      return engineTuple[1];\n    }\n\n    // MSIE has only one version identifier, and the Trident version is\n    // specified in the parenthetical. IE Edge is covered in the engine tuple\n    // detection.\n    const browserTuple = tuples[0];\n    let info;\n    if (browserTuple && (info = browserTuple[2])) {\n      const match = /Trident\\/([^\\s;]+)/.exec(info);\n      if (match) {\n        return match[1];\n      }\n    }\n  }\n  return '';\n}\n\n/**\n * @param {!Array<!Array<string>>} tuples Extracted version tuples.\n * @return {!Array<string>|undefined} The engine tuple or undefined if not\n *     found.\n */\nfunction getEngineTuple(tuples) {\n  if (!isEdge()) {\n    return tuples[1];\n  }\n  for (let i = 0; i < tuples.length; i++) {\n    const tuple = tuples[i];\n    if (tuple[0] == 'Edge') {\n      return tuple;\n    }\n  }\n}\n\n/**\n * @param {string|number} version The version to check.\n * @return {boolean} Whether the rendering engine version is higher or the same\n *     as the given version.\n */\nfunction isVersionOrHigher(version) {\n  return googString.compareVersions(getVersion(), version) >= 0;\n}\n\n/**\n * @param {!Array<!Array<string>>} tuples Version tuples.\n * @param {string} key The key to look for.\n * @return {string} The version string of the given key, if present.\n *     Otherwise, the empty string.\n */\nfunction getVersionForKey(tuples, key) {\n  // TODO(nnaze): Move to util if useful elsewhere.\n\n  const pair = googArray.find(tuples, function(pair) {\n    return key == pair[0];\n  });\n\n  return pair && pair[1] || '';\n}\n\nexports = {\n  getVersion,\n  isEdge,\n  isGecko,\n  isPresto,\n  isTrident,\n  isVersionOrHigher,\n  isWebKit,\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview A patched, standardized event object for browser events.\n *\n * <pre>\n * The patched event object contains the following members:\n * - type           {string}    Event type, e.g. 'click'\n * - target         {Object}    The element that actually triggered the event\n * - currentTarget  {Object}    The element the listener is attached to\n * - relatedTarget  {Object}    For mouseover and mouseout, the previous object\n * - offsetX        {number}    X-coordinate relative to target\n * - offsetY        {number}    Y-coordinate relative to target\n * - clientX        {number}    X-coordinate relative to viewport\n * - clientY        {number}    Y-coordinate relative to viewport\n * - screenX        {number}    X-coordinate relative to the edge of the screen\n * - screenY        {number}    Y-coordinate relative to the edge of the screen\n * - button         {number}    Mouse button. Use isButton() to test.\n * - keyCode        {number}    Key-code\n * - ctrlKey        {boolean}   Was ctrl key depressed\n * - altKey         {boolean}   Was alt key depressed\n * - shiftKey       {boolean}   Was shift key depressed\n * - metaKey        {boolean}   Was meta key depressed\n * - pointerId      {number}    Pointer ID\n * - pointerType    {string}    Pointer type, e.g. 'mouse', 'pen', or 'touch'\n * - defaultPrevented {boolean} Whether the default action has been prevented\n * - state          {Object}    History state object\n *\n * NOTE: The keyCode member contains the raw browser keyCode. For normalized\n * key and character code use {@link goog.events.KeyHandler}.\n * </pre>\n */\n\ngoog.provide('goog.events.BrowserEvent');\ngoog.provide('goog.events.BrowserEvent.MouseButton');\ngoog.provide('goog.events.BrowserEvent.PointerType');\n\ngoog.require('goog.debug');\ngoog.require('goog.events.Event');\ngoog.require('goog.events.EventType');\ngoog.require('goog.reflect');\ngoog.require('goog.userAgent');\n\n/**\n * Accepts a browser event object and creates a patched, cross browser event\n * object.\n * The content of this object will not be initialized if no event object is\n * provided. If this is the case, init() needs to be invoked separately.\n * @param {Event=} opt_e Browser event object.\n * @param {EventTarget=} opt_currentTarget Current target for event.\n * @constructor\n * @extends {goog.events.Event}\n */\ngoog.events.BrowserEvent = function(opt_e, opt_currentTarget) {\n  'use strict';\n  goog.events.BrowserEvent.base(this, 'constructor', opt_e ? opt_e.type : '');\n\n  /**\n   * Target that fired the event.\n   * @override\n   * @type {?Node}\n   */\n  this.target = null;\n\n  /**\n   * Node that had the listener attached.\n   * @override\n   * @type {?Node|undefined}\n   */\n  this.currentTarget = null;\n\n  /**\n   * For mouseover and mouseout events, the related object for the event.\n   * @type {?Node}\n   */\n  this.relatedTarget = null;\n\n  /**\n   * X-coordinate relative to target.\n   * @type {number}\n   */\n  this.offsetX = 0;\n\n  /**\n   * Y-coordinate relative to target.\n   * @type {number}\n   */\n  this.offsetY = 0;\n\n  /**\n   * X-coordinate relative to the window.\n   * @type {number}\n   */\n  this.clientX = 0;\n\n  /**\n   * Y-coordinate relative to the window.\n   * @type {number}\n   */\n  this.clientY = 0;\n\n  /**\n   * X-coordinate relative to the monitor.\n   * @type {number}\n   */\n  this.screenX = 0;\n\n  /**\n   * Y-coordinate relative to the monitor.\n   * @type {number}\n   */\n  this.screenY = 0;\n\n  /**\n   * Which mouse button was pressed.\n   * @type {number}\n   */\n  this.button = 0;\n\n  /**\n   * Key of key press.\n   * @type {string}\n   */\n  this.key = '';\n\n  /**\n   * Keycode of key press.\n   * @type {number}\n   */\n  this.keyCode = 0;\n\n  /**\n   * Keycode of key press.\n   * @type {number}\n   */\n  this.charCode = 0;\n\n  /**\n   * Whether control was pressed at time of event.\n   * @type {boolean}\n   */\n  this.ctrlKey = false;\n\n  /**\n   * Whether alt was pressed at time of event.\n   * @type {boolean}\n   */\n  this.altKey = false;\n\n  /**\n   * Whether shift was pressed at time of event.\n   * @type {boolean}\n   */\n  this.shiftKey = false;\n\n  /**\n   * Whether the meta key was pressed at time of event.\n   * @type {boolean}\n   */\n  this.metaKey = false;\n\n  /**\n   * History state object, only set for PopState events where it's a copy of the\n   * state object provided to pushState or replaceState.\n   * @type {?Object}\n   */\n  this.state = null;\n\n  /**\n   * Whether the default platform modifier key was pressed at time of event.\n   * (This is control for all platforms except Mac, where it's Meta.)\n   * @type {boolean}\n   */\n  this.platformModifierKey = false;\n\n  /**\n   * @type {number}\n   */\n  this.pointerId = 0;\n\n  /**\n   * @type {string}\n   */\n  this.pointerType = '';\n\n  /**\n   * The browser event object.\n   * @private {?Event}\n   */\n  this.event_ = null;\n\n  if (opt_e) {\n    this.init(opt_e, opt_currentTarget);\n  }\n};\ngoog.inherits(goog.events.BrowserEvent, goog.events.Event);\n\n/**\n * @define {boolean} If true, use the layerX and layerY properties of a native\n * browser event over the offsetX and offsetY properties, which cause expensive\n * reflow. If layerX or layerY is not defined, offsetX and offsetY will be used\n * as usual.\n */\ngoog.events.BrowserEvent.USE_LAYER_XY_AS_OFFSET_XY =\n    goog.define('goog.events.BrowserEvent.USE_LAYER_XY_AS_OFFSET_XY', false);\n\n\n/**\n * Normalized button constants for the mouse.\n * @enum {number}\n */\ngoog.events.BrowserEvent.MouseButton = {\n  LEFT: 0,\n  MIDDLE: 1,\n  RIGHT: 2\n};\n\n\n/**\n * Normalized pointer type constants for pointer events.\n * @enum {string}\n */\ngoog.events.BrowserEvent.PointerType = {\n  MOUSE: 'mouse',\n  PEN: 'pen',\n  TOUCH: 'touch'\n};\n\n\n/**\n * Static data for mapping mouse buttons.\n * @type {!Array<number>}\n * @deprecated Use `goog.events.BrowserEvent.IE_BUTTON_MAP` instead.\n */\ngoog.events.BrowserEvent.IEButtonMap = goog.debug.freeze([\n  1,  // LEFT\n  4,  // MIDDLE\n  2   // RIGHT\n]);\n\n\n/**\n * Static data for mapping mouse buttons.\n * @const {!Array<number>}\n */\ngoog.events.BrowserEvent.IE_BUTTON_MAP = goog.events.BrowserEvent.IEButtonMap;\n\n\n/**\n * Static data for mapping MSPointerEvent types to PointerEvent types.\n * @const {!Object<number, goog.events.BrowserEvent.PointerType>}\n */\ngoog.events.BrowserEvent.IE_POINTER_TYPE_MAP = goog.debug.freeze({\n  2: goog.events.BrowserEvent.PointerType.TOUCH,\n  3: goog.events.BrowserEvent.PointerType.PEN,\n  4: goog.events.BrowserEvent.PointerType.MOUSE\n});\n\n\n/**\n * Accepts a browser event object and creates a patched, cross browser event\n * object.\n * @param {Event} e Browser event object.\n * @param {EventTarget=} opt_currentTarget Current target for event.\n */\ngoog.events.BrowserEvent.prototype.init = function(e, opt_currentTarget) {\n  'use strict';\n  var type = this.type = e.type;\n\n  /**\n   * On touch devices use the first \"changed touch\" as the relevant touch.\n   * @type {?Touch}\n   */\n  var relevantTouch =\n      e.changedTouches && e.changedTouches.length ? e.changedTouches[0] : null;\n\n  // TODO(nicksantos): Change this.target to type EventTarget.\n  this.target = /** @type {Node} */ (e.target) || e.srcElement;\n\n  // TODO(nicksantos): Change this.currentTarget to type EventTarget.\n  this.currentTarget = /** @type {Node} */ (opt_currentTarget);\n\n  var relatedTarget = /** @type {Node} */ (e.relatedTarget);\n  if (relatedTarget) {\n    // There's a bug in FireFox where sometimes, relatedTarget will be a\n    // chrome element, and accessing any property of it will get a permission\n    // denied exception. See:\n    // https://bugzilla.mozilla.org/show_bug.cgi?id=497780\n    if (goog.userAgent.GECKO) {\n      if (!goog.reflect.canAccessProperty(relatedTarget, 'nodeName')) {\n        relatedTarget = null;\n      }\n    }\n  } else if (type == goog.events.EventType.MOUSEOVER) {\n    relatedTarget = e.fromElement;\n  } else if (type == goog.events.EventType.MOUSEOUT) {\n    relatedTarget = e.toElement;\n  }\n\n  this.relatedTarget = relatedTarget;\n\n  if (relevantTouch) {\n    this.clientX = relevantTouch.clientX !== undefined ? relevantTouch.clientX :\n                                                         relevantTouch.pageX;\n    this.clientY = relevantTouch.clientY !== undefined ? relevantTouch.clientY :\n                                                         relevantTouch.pageY;\n    this.screenX = relevantTouch.screenX || 0;\n    this.screenY = relevantTouch.screenY || 0;\n  } else {\n    if (goog.events.BrowserEvent.USE_LAYER_XY_AS_OFFSET_XY) {\n      this.offsetX = (e.layerX !== undefined) ? e.layerX : e.offsetX;\n      this.offsetY = (e.layerY !== undefined) ? e.layerY : e.offsetY;\n    } else {\n      // Webkit emits a lame warning whenever layerX/layerY is accessed.\n      // http://code.google.com/p/chromium/issues/detail?id=101733\n      this.offsetX = (goog.userAgent.WEBKIT || e.offsetX !== undefined) ?\n          e.offsetX :\n          e.layerX;\n      this.offsetY = (goog.userAgent.WEBKIT || e.offsetY !== undefined) ?\n          e.offsetY :\n          e.layerY;\n    }\n    this.clientX = e.clientX !== undefined ? e.clientX : e.pageX;\n    this.clientY = e.clientY !== undefined ? e.clientY : e.pageY;\n    this.screenX = e.screenX || 0;\n    this.screenY = e.screenY || 0;\n  }\n\n  this.button = e.button;\n\n  this.keyCode = e.keyCode || 0;\n  this.key = e.key || '';\n  this.charCode = e.charCode || (type == 'keypress' ? e.keyCode : 0);\n  this.ctrlKey = e.ctrlKey;\n  this.altKey = e.altKey;\n  this.shiftKey = e.shiftKey;\n  this.metaKey = e.metaKey;\n  this.platformModifierKey = goog.userAgent.MAC ? e.metaKey : e.ctrlKey;\n  this.pointerId = e.pointerId || 0;\n  this.pointerType = goog.events.BrowserEvent.getPointerType_(e);\n  this.state = e.state;\n  this.event_ = e;\n  if (e.defaultPrevented) {\n    // Sync native event state to internal state via super class, where default\n    // prevention is implemented and managed.\n    goog.events.BrowserEvent.superClass_.preventDefault.call(this);\n  }\n};\n\n\n/**\n * Tests to see which button was pressed during the event. This is really only\n * useful in IE and Gecko browsers. And in IE, it's only useful for\n * mousedown/mouseup events, because click only fires for the left mouse button.\n *\n * Safari 2 only reports the left button being clicked, and uses the value '1'\n * instead of 0. Opera only reports a mousedown event for the middle button, and\n * no mouse events for the right button. Opera has default behavior for left and\n * middle click that can only be overridden via a configuration setting.\n *\n * There's a nice table of this mess at http://www.unixpapa.com/js/mouse.html.\n *\n * @param {goog.events.BrowserEvent.MouseButton} button The button\n *     to test for.\n * @return {boolean} True if button was pressed.\n */\ngoog.events.BrowserEvent.prototype.isButton = function(button) {\n  'use strict';\n  return this.event_.button == button;\n};\n\n\n/**\n * Whether this has an \"action\"-producing mouse button.\n *\n * By definition, this includes left-click on windows/linux, and left-click\n * without the ctrl key on Macs.\n *\n * @return {boolean} The result.\n */\ngoog.events.BrowserEvent.prototype.isMouseActionButton = function() {\n  'use strict';\n  // Ctrl+click should never behave like a left-click on mac, regardless of\n  // whether or not the browser will actually ever emit such an event.  If\n  // we see it, treat it like right-click always.\n  return this.isButton(goog.events.BrowserEvent.MouseButton.LEFT) &&\n      !(goog.userAgent.MAC && this.ctrlKey);\n};\n\n\n/**\n * @override\n */\ngoog.events.BrowserEvent.prototype.stopPropagation = function() {\n  'use strict';\n  goog.events.BrowserEvent.superClass_.stopPropagation.call(this);\n  if (this.event_.stopPropagation) {\n    this.event_.stopPropagation();\n  } else {\n    this.event_.cancelBubble = true;\n  }\n};\n\n\n/**\n * @override\n */\ngoog.events.BrowserEvent.prototype.preventDefault = function() {\n  'use strict';\n  goog.events.BrowserEvent.superClass_.preventDefault.call(this);\n  var be = this.event_;\n  if (!be.preventDefault) {\n    be.returnValue = false;\n  } else {\n    be.preventDefault();\n  }\n};\n\n\n/**\n * @return {Event} The underlying browser event object.\n */\ngoog.events.BrowserEvent.prototype.getBrowserEvent = function() {\n  'use strict';\n  return this.event_;\n};\n\n\n/**\n * Extracts the pointer type from the given event.\n * @param {!Event} e\n * @return {string} The pointer type, e.g. 'mouse', 'pen', or 'touch'.\n * @private\n */\ngoog.events.BrowserEvent.getPointerType_ = function(e) {\n  'use strict';\n  if (typeof (e.pointerType) === 'string') {\n    return e.pointerType;\n  }\n  // IE10 uses integer codes for pointer type.\n  // https://msdn.microsoft.com/en-us/library/hh772359(v=vs.85).aspx\n  return goog.events.BrowserEvent.IE_POINTER_TYPE_MAP[e.pointerType] || '';\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Event Types.\n */\n\n\ngoog.provide('goog.events.EventType');\ngoog.provide('goog.events.EventTypeHelpers');\ngoog.provide('goog.events.MouseAsMouseEventType');\ngoog.provide('goog.events.MouseEvents');\ngoog.provide('goog.events.PointerAsMouseEventType');\ngoog.provide('goog.events.PointerAsTouchEventType');\ngoog.provide('goog.events.PointerFallbackEventType');\ngoog.provide('goog.events.PointerTouchFallbackEventType');\n\ngoog.require('goog.events.BrowserFeature');\ngoog.require('goog.userAgent');\n\n\n/**\n * Returns a prefixed event name for the current browser.\n * @param {string} eventName The name of the event.\n * @return {string} The prefixed event name.\n * @private\n */\ngoog.events.EventTypeHelpers.getVendorPrefixedName_ = function(eventName) {\n  'use strict';\n  return goog.userAgent.WEBKIT ? 'webkit' + eventName : eventName.toLowerCase();\n};\n\n\n/**\n * Constants for event names.\n * @enum {string}\n */\ngoog.events.EventType = {\n  // Mouse events\n  CLICK: 'click',\n  RIGHTCLICK: 'rightclick',\n  DBLCLICK: 'dblclick',\n  AUXCLICK: 'auxclick',\n  MOUSEDOWN: 'mousedown',\n  MOUSEUP: 'mouseup',\n  MOUSEOVER: 'mouseover',\n  MOUSEOUT: 'mouseout',\n  MOUSEMOVE: 'mousemove',\n  MOUSEENTER: 'mouseenter',\n  MOUSELEAVE: 'mouseleave',\n\n  // Non-existent event; will never fire. This exists as a mouse counterpart to\n  // POINTERCANCEL.\n  MOUSECANCEL: 'mousecancel',\n\n  // Selection events.\n  // https://www.w3.org/TR/selection-api/\n  SELECTIONCHANGE: 'selectionchange',\n  SELECTSTART: 'selectstart',  // IE, Safari, Chrome\n\n  // Wheel events\n  // http://www.w3.org/TR/DOM-Level-3-Events/#events-wheelevents\n  WHEEL: 'wheel',\n\n  // Key events\n  KEYPRESS: 'keypress',\n  KEYDOWN: 'keydown',\n  KEYUP: 'keyup',\n\n  // Focus\n  BLUR: 'blur',\n  FOCUS: 'focus',\n  DEACTIVATE: 'deactivate',  // IE only\n  FOCUSIN: 'focusin',\n  FOCUSOUT: 'focusout',\n\n  // Forms\n  CHANGE: 'change',\n  RESET: 'reset',\n  SELECT: 'select',\n  SUBMIT: 'submit',\n  INPUT: 'input',\n  PROPERTYCHANGE: 'propertychange',  // IE only\n\n  // Drag and drop\n  DRAGSTART: 'dragstart',\n  DRAG: 'drag',\n  DRAGENTER: 'dragenter',\n  DRAGOVER: 'dragover',\n  DRAGLEAVE: 'dragleave',\n  DROP: 'drop',\n  DRAGEND: 'dragend',\n\n  // Touch events\n  // Note that other touch events exist, but we should follow the W3C list here.\n  // http://www.w3.org/TR/touch-events/#list-of-touchevent-types\n  TOUCHSTART: 'touchstart',\n  TOUCHMOVE: 'touchmove',\n  TOUCHEND: 'touchend',\n  TOUCHCANCEL: 'touchcancel',\n\n  // Misc\n  BEFOREUNLOAD: 'beforeunload',\n  CONSOLEMESSAGE: 'consolemessage',\n  CONTEXTMENU: 'contextmenu',\n  DEVICECHANGE: 'devicechange',\n  DEVICEMOTION: 'devicemotion',\n  DEVICEORIENTATION: 'deviceorientation',\n  DOMCONTENTLOADED: 'DOMContentLoaded',\n  ERROR: 'error',\n  HELP: 'help',\n  LOAD: 'load',\n  LOSECAPTURE: 'losecapture',\n  ORIENTATIONCHANGE: 'orientationchange',\n  READYSTATECHANGE: 'readystatechange',\n  RESIZE: 'resize',\n  SCROLL: 'scroll',\n  UNLOAD: 'unload',\n\n  // Media events\n  CANPLAY: 'canplay',\n  CANPLAYTHROUGH: 'canplaythrough',\n  DURATIONCHANGE: 'durationchange',\n  EMPTIED: 'emptied',\n  ENDED: 'ended',\n  LOADEDDATA: 'loadeddata',\n  LOADEDMETADATA: 'loadedmetadata',\n  PAUSE: 'pause',\n  PLAY: 'play',\n  PLAYING: 'playing',\n  PROGRESS: 'progress',\n  RATECHANGE: 'ratechange',\n  SEEKED: 'seeked',\n  SEEKING: 'seeking',\n  STALLED: 'stalled',\n  SUSPEND: 'suspend',\n  TIMEUPDATE: 'timeupdate',\n  VOLUMECHANGE: 'volumechange',\n  WAITING: 'waiting',\n\n  // Media Source Extensions events\n  // https://www.w3.org/TR/media-source/#mediasource-events\n  SOURCEOPEN: 'sourceopen',\n  SOURCEENDED: 'sourceended',\n  SOURCECLOSED: 'sourceclosed',\n  // https://www.w3.org/TR/media-source/#sourcebuffer-events\n  ABORT: 'abort',\n  UPDATE: 'update',\n  UPDATESTART: 'updatestart',\n  UPDATEEND: 'updateend',\n\n  // HTML 5 History events\n  // See http://www.w3.org/TR/html5/browsers.html#event-definitions-0\n  HASHCHANGE: 'hashchange',\n  PAGEHIDE: 'pagehide',\n  PAGESHOW: 'pageshow',\n  POPSTATE: 'popstate',\n\n  // Copy and Paste\n  // Support is limited. Make sure it works on your favorite browser\n  // before using.\n  // http://www.quirksmode.org/dom/events/cutcopypaste.html\n  COPY: 'copy',\n  PASTE: 'paste',\n  CUT: 'cut',\n  BEFORECOPY: 'beforecopy',\n  BEFORECUT: 'beforecut',\n  BEFOREPASTE: 'beforepaste',\n\n  // HTML5 online/offline events.\n  // http://www.w3.org/TR/offline-webapps/#related\n  ONLINE: 'online',\n  OFFLINE: 'offline',\n\n  // HTML 5 worker events\n  MESSAGE: 'message',\n  CONNECT: 'connect',\n\n  // Service Worker Events - ServiceWorkerGlobalScope context\n  // See https://w3c.github.io/ServiceWorker/#execution-context-events\n  // Note: message event defined in worker events section\n  INSTALL: 'install',\n  ACTIVATE: 'activate',\n  FETCH: 'fetch',\n  FOREIGNFETCH: 'foreignfetch',\n  MESSAGEERROR: 'messageerror',\n\n  // Service Worker Events - Document context\n  // See https://w3c.github.io/ServiceWorker/#document-context-events\n  STATECHANGE: 'statechange',\n  UPDATEFOUND: 'updatefound',\n  CONTROLLERCHANGE: 'controllerchange',\n\n  // CSS animation events.\n  ANIMATIONSTART:\n      goog.events.EventTypeHelpers.getVendorPrefixedName_('AnimationStart'),\n  ANIMATIONEND:\n      goog.events.EventTypeHelpers.getVendorPrefixedName_('AnimationEnd'),\n  ANIMATIONITERATION:\n      goog.events.EventTypeHelpers.getVendorPrefixedName_('AnimationIteration'),\n\n  // CSS transition events. Based on the browser support described at:\n  // https://developer.mozilla.org/en/css/css_transitions#Browser_compatibility\n  TRANSITIONEND:\n      goog.events.EventTypeHelpers.getVendorPrefixedName_('TransitionEnd'),\n\n  // W3C Pointer Events\n  // http://www.w3.org/TR/pointerevents/\n  POINTERDOWN: 'pointerdown',\n  POINTERUP: 'pointerup',\n  POINTERCANCEL: 'pointercancel',\n  POINTERMOVE: 'pointermove',\n  POINTEROVER: 'pointerover',\n  POINTEROUT: 'pointerout',\n  POINTERENTER: 'pointerenter',\n  POINTERLEAVE: 'pointerleave',\n  GOTPOINTERCAPTURE: 'gotpointercapture',\n  LOSTPOINTERCAPTURE: 'lostpointercapture',\n\n  // IE specific events.\n  // See http://msdn.microsoft.com/en-us/library/ie/hh772103(v=vs.85).aspx\n  // Note: these events will be supplanted in IE11.\n  MSGESTURECHANGE: 'MSGestureChange',\n  MSGESTUREEND: 'MSGestureEnd',\n  MSGESTUREHOLD: 'MSGestureHold',\n  MSGESTURESTART: 'MSGestureStart',\n  MSGESTURETAP: 'MSGestureTap',\n  MSGOTPOINTERCAPTURE: 'MSGotPointerCapture',\n  MSINERTIASTART: 'MSInertiaStart',\n  MSLOSTPOINTERCAPTURE: 'MSLostPointerCapture',\n  MSPOINTERCANCEL: 'MSPointerCancel',\n  MSPOINTERDOWN: 'MSPointerDown',\n  MSPOINTERENTER: 'MSPointerEnter',\n  MSPOINTERHOVER: 'MSPointerHover',\n  MSPOINTERLEAVE: 'MSPointerLeave',\n  MSPOINTERMOVE: 'MSPointerMove',\n  MSPOINTEROUT: 'MSPointerOut',\n  MSPOINTEROVER: 'MSPointerOver',\n  MSPOINTERUP: 'MSPointerUp',\n\n  // Native IMEs/input tools events.\n  TEXT: 'text',\n  // The textInput event is supported in IE9+, but only in lower case. All other\n  // browsers use the camel-case event name.\n  TEXTINPUT: goog.userAgent.IE ? 'textinput' : 'textInput',\n  COMPOSITIONSTART: 'compositionstart',\n  COMPOSITIONUPDATE: 'compositionupdate',\n  COMPOSITIONEND: 'compositionend',\n\n  // The beforeinput event is initially only supported in Safari. See\n  // https://bugs.chromium.org/p/chromium/issues/detail?id=342670 for Chrome\n  // implementation tracking.\n  BEFOREINPUT: 'beforeinput',\n\n  // Webview tag events\n  // See https://developer.chrome.com/apps/tags/webview\n  EXIT: 'exit',\n  LOADABORT: 'loadabort',\n  LOADCOMMIT: 'loadcommit',\n  LOADREDIRECT: 'loadredirect',\n  LOADSTART: 'loadstart',\n  LOADSTOP: 'loadstop',\n  RESPONSIVE: 'responsive',\n  SIZECHANGED: 'sizechanged',\n  UNRESPONSIVE: 'unresponsive',\n\n  // HTML5 Page Visibility API.  See details at\n  // `goog.labs.dom.PageVisibilityMonitor`.\n  VISIBILITYCHANGE: 'visibilitychange',\n\n  // LocalStorage event.\n  STORAGE: 'storage',\n\n  // DOM Level 2 mutation events (deprecated).\n  DOMSUBTREEMODIFIED: 'DOMSubtreeModified',\n  DOMNODEINSERTED: 'DOMNodeInserted',\n  DOMNODEREMOVED: 'DOMNodeRemoved',\n  DOMNODEREMOVEDFROMDOCUMENT: 'DOMNodeRemovedFromDocument',\n  DOMNODEINSERTEDINTODOCUMENT: 'DOMNodeInsertedIntoDocument',\n  DOMATTRMODIFIED: 'DOMAttrModified',\n  DOMCHARACTERDATAMODIFIED: 'DOMCharacterDataModified',\n\n  // Print events.\n  BEFOREPRINT: 'beforeprint',\n  AFTERPRINT: 'afterprint',\n\n  // Web app manifest events.\n  BEFOREINSTALLPROMPT: 'beforeinstallprompt',\n  APPINSTALLED: 'appinstalled'\n};\n\n\n/**\n * Returns one of the given pointer fallback event names in order of preference:\n *   1. pointerEventName\n *   2. msPointerEventName\n *   3. fallbackEventName\n * @param {string} pointerEventName\n * @param {string} msPointerEventName\n * @param {string} fallbackEventName\n * @return {string} The supported pointer or fallback (mouse or touch) event\n *     name.\n * @private\n */\ngoog.events.EventTypeHelpers.getPointerFallbackEventName_ = function(\n    pointerEventName, msPointerEventName, fallbackEventName) {\n  'use strict';\n  if (goog.events.BrowserFeature.POINTER_EVENTS) {\n    return pointerEventName;\n  }\n  if (goog.events.BrowserFeature.MSPOINTER_EVENTS) {\n    return msPointerEventName;\n  }\n  return fallbackEventName;\n};\n\n\n/**\n * Constants for pointer event names that fall back to corresponding mouse event\n * names on unsupported platforms. These are intended to be drop-in replacements\n * for corresponding values in `goog.events.EventType`.\n * @enum {string}\n */\ngoog.events.PointerFallbackEventType = {\n  POINTERDOWN: goog.events.EventTypeHelpers.getPointerFallbackEventName_(\n      goog.events.EventType.POINTERDOWN, goog.events.EventType.MSPOINTERDOWN,\n      goog.events.EventType.MOUSEDOWN),\n  POINTERUP: goog.events.EventTypeHelpers.getPointerFallbackEventName_(\n      goog.events.EventType.POINTERUP, goog.events.EventType.MSPOINTERUP,\n      goog.events.EventType.MOUSEUP),\n  POINTERCANCEL: goog.events.EventTypeHelpers.getPointerFallbackEventName_(\n      goog.events.EventType.POINTERCANCEL,\n      goog.events.EventType.MSPOINTERCANCEL,\n      // When falling back to mouse events, there is no MOUSECANCEL equivalent\n      // of POINTERCANCEL. In this case POINTERUP already falls back to MOUSEUP\n      // which represents both UP and CANCEL. POINTERCANCEL does not fall back\n      // to MOUSEUP to prevent listening twice on the same event.\n      goog.events.EventType.MOUSECANCEL),\n  POINTERMOVE: goog.events.EventTypeHelpers.getPointerFallbackEventName_(\n      goog.events.EventType.POINTERMOVE, goog.events.EventType.MSPOINTERMOVE,\n      goog.events.EventType.MOUSEMOVE),\n  POINTEROVER: goog.events.EventTypeHelpers.getPointerFallbackEventName_(\n      goog.events.EventType.POINTEROVER, goog.events.EventType.MSPOINTEROVER,\n      goog.events.EventType.MOUSEOVER),\n  POINTEROUT: goog.events.EventTypeHelpers.getPointerFallbackEventName_(\n      goog.events.EventType.POINTEROUT, goog.events.EventType.MSPOINTEROUT,\n      goog.events.EventType.MOUSEOUT),\n  POINTERENTER: goog.events.EventTypeHelpers.getPointerFallbackEventName_(\n      goog.events.EventType.POINTERENTER, goog.events.EventType.MSPOINTERENTER,\n      goog.events.EventType.MOUSEENTER),\n  POINTERLEAVE: goog.events.EventTypeHelpers.getPointerFallbackEventName_(\n      goog.events.EventType.POINTERLEAVE, goog.events.EventType.MSPOINTERLEAVE,\n      goog.events.EventType.MOUSELEAVE)\n};\n\n\n/**\n * Constants for pointer event names that fall back to corresponding touch event\n * names on unsupported platforms. These are intended to be drop-in replacements\n * for corresponding values in `goog.events.EventType`.\n * @enum {string}\n */\ngoog.events.PointerTouchFallbackEventType = {\n  POINTERDOWN: goog.events.EventTypeHelpers.getPointerFallbackEventName_(\n      goog.events.EventType.POINTERDOWN, goog.events.EventType.MSPOINTERDOWN,\n      goog.events.EventType.TOUCHSTART),\n  POINTERUP: goog.events.EventTypeHelpers.getPointerFallbackEventName_(\n      goog.events.EventType.POINTERUP, goog.events.EventType.MSPOINTERUP,\n      goog.events.EventType.TOUCHEND),\n  POINTERCANCEL: goog.events.EventTypeHelpers.getPointerFallbackEventName_(\n      goog.events.EventType.POINTERCANCEL,\n      goog.events.EventType.MSPOINTERCANCEL, goog.events.EventType.TOUCHCANCEL),\n  POINTERMOVE: goog.events.EventTypeHelpers.getPointerFallbackEventName_(\n      goog.events.EventType.POINTERMOVE, goog.events.EventType.MSPOINTERMOVE,\n      goog.events.EventType.TOUCHMOVE)\n};\n\n\n/**\n * Mapping of mouse event names to underlying browser event names.\n * @typedef {{\n *     MOUSEDOWN: string,\n *     MOUSEUP: string,\n *     MOUSECANCEL:string,\n *     MOUSEMOVE:string,\n *     MOUSEOVER:string,\n *     MOUSEOUT:string,\n *     MOUSEENTER:string,\n *     MOUSELEAVE: string,\n * }}\n */\ngoog.events.MouseEvents;\n\n\n/**\n * An alias for `goog.events.EventType.MOUSE*` event types that is overridden by\n * corresponding `POINTER*` event types.\n * @const {!goog.events.MouseEvents}\n */\ngoog.events.PointerAsMouseEventType = {\n  MOUSEDOWN: goog.events.PointerFallbackEventType.POINTERDOWN,\n  MOUSEUP: goog.events.PointerFallbackEventType.POINTERUP,\n  MOUSECANCEL: goog.events.PointerFallbackEventType.POINTERCANCEL,\n  MOUSEMOVE: goog.events.PointerFallbackEventType.POINTERMOVE,\n  MOUSEOVER: goog.events.PointerFallbackEventType.POINTEROVER,\n  MOUSEOUT: goog.events.PointerFallbackEventType.POINTEROUT,\n  MOUSEENTER: goog.events.PointerFallbackEventType.POINTERENTER,\n  MOUSELEAVE: goog.events.PointerFallbackEventType.POINTERLEAVE\n};\n\n\n/**\n * An alias for `goog.events.EventType.MOUSE*` event types that continue to use\n * mouse events.\n * @const {!goog.events.MouseEvents}\n */\ngoog.events.MouseAsMouseEventType = {\n  MOUSEDOWN: goog.events.EventType.MOUSEDOWN,\n  MOUSEUP: goog.events.EventType.MOUSEUP,\n  MOUSECANCEL: goog.events.EventType.MOUSECANCEL,\n  MOUSEMOVE: goog.events.EventType.MOUSEMOVE,\n  MOUSEOVER: goog.events.EventType.MOUSEOVER,\n  MOUSEOUT: goog.events.EventType.MOUSEOUT,\n  MOUSEENTER: goog.events.EventType.MOUSEENTER,\n  MOUSELEAVE: goog.events.EventType.MOUSELEAVE\n};\n\n\n/**\n * An alias for `goog.events.EventType.TOUCH*` event types that is overridden by\n * corresponding `POINTER*` event types.\n * @enum {string}\n */\ngoog.events.PointerAsTouchEventType = {\n  TOUCHCANCEL: goog.events.PointerTouchFallbackEventType.POINTERCANCEL,\n  TOUCHEND: goog.events.PointerTouchFallbackEventType.POINTERUP,\n  TOUCHMOVE: goog.events.PointerTouchFallbackEventType.POINTERMOVE,\n  TOUCHSTART: goog.events.PointerTouchFallbackEventType.POINTERDOWN\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview An interface for a listenable JavaScript object.\n */\n\ngoog.provide('goog.events.Listenable');\n\ngoog.requireType('goog.events.EventId');\ngoog.requireType('goog.events.EventLike');\ngoog.requireType('goog.events.ListenableKey');\n\n\n/**\n * A listenable interface. A listenable is an object with the ability\n * to dispatch/broadcast events to \"event listeners\" registered via\n * listen/listenOnce.\n *\n * The interface allows for an event propagation mechanism similar\n * to one offered by native browser event targets, such as\n * capture/bubble mechanism, stopping propagation, and preventing\n * default actions. Capture/bubble mechanism depends on the ancestor\n * tree constructed via `#getParentEventTarget`; this tree\n * must be directed acyclic graph. The meaning of default action(s)\n * in preventDefault is specific to a particular use case.\n *\n * Implementations that do not support capture/bubble or can not have\n * a parent listenable can simply not implement any ability to set the\n * parent listenable (and have `#getParentEventTarget` return\n * null).\n *\n * Implementation of this class can be used with or independently from\n * goog.events.\n *\n * Implementation must call `#addImplementation(implClass)`.\n *\n * @interface\n * @see goog.events\n * @see http://www.w3.org/TR/DOM-Level-2-Events/events.html\n */\ngoog.events.Listenable = function() {};\n\n\n/**\n * An expando property to indicate that an object implements\n * goog.events.Listenable.\n *\n * See addImplementation/isImplementedBy.\n *\n * @type {string}\n * @const\n */\ngoog.events.Listenable.IMPLEMENTED_BY_PROP =\n    'closure_listenable_' + ((Math.random() * 1e6) | 0);\n\n\n/**\n * Marks a given class (constructor) as an implementation of\n * Listenable, so that we can query that fact at runtime. The class\n * must have already implemented the interface.\n * @param {function(new:goog.events.Listenable,...)} cls The class constructor.\n *     The corresponding class must have already implemented the interface.\n */\ngoog.events.Listenable.addImplementation = function(cls) {\n  'use strict';\n  cls.prototype[goog.events.Listenable.IMPLEMENTED_BY_PROP] = true;\n};\n\n\n/**\n * @param {?Object} obj The object to check.\n * @return {boolean} Whether a given instance implements Listenable. The\n *     class/superclass of the instance must call addImplementation.\n */\ngoog.events.Listenable.isImplementedBy = function(obj) {\n  'use strict';\n  return !!(obj && obj[goog.events.Listenable.IMPLEMENTED_BY_PROP]);\n};\n\n\n/**\n * Adds an event listener. A listener can only be added once to an\n * object and if it is added again the key for the listener is\n * returned. Note that if the existing listener is a one-off listener\n * (registered via listenOnce), it will no longer be a one-off\n * listener after a call to listen().\n *\n * @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id.\n * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback\n *     method.\n * @param {boolean=} opt_useCapture Whether to fire in capture phase\n *     (defaults to false).\n * @param {SCOPE=} opt_listenerScope Object in whose scope to call the\n *     listener.\n * @return {!goog.events.ListenableKey} Unique key for the listener.\n * @template SCOPE,EVENTOBJ\n */\ngoog.events.Listenable.prototype.listen = function(\n    type, listener, opt_useCapture, opt_listenerScope) {};\n\n\n/**\n * Adds an event listener that is removed automatically after the\n * listener fired once.\n *\n * If an existing listener already exists, listenOnce will do\n * nothing. In particular, if the listener was previously registered\n * via listen(), listenOnce() will not turn the listener into a\n * one-off listener. Similarly, if there is already an existing\n * one-off listener, listenOnce does not modify the listeners (it is\n * still a once listener).\n *\n * @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id.\n * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback\n *     method.\n * @param {boolean=} opt_useCapture Whether to fire in capture phase\n *     (defaults to false).\n * @param {SCOPE=} opt_listenerScope Object in whose scope to call the\n *     listener.\n * @return {!goog.events.ListenableKey} Unique key for the listener.\n * @template SCOPE,EVENTOBJ\n */\ngoog.events.Listenable.prototype.listenOnce = function(\n    type, listener, opt_useCapture, opt_listenerScope) {};\n\n\n/**\n * Removes an event listener which was added with listen() or listenOnce().\n *\n * @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id.\n * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback\n *     method.\n * @param {boolean=} opt_useCapture Whether to fire in capture phase\n *     (defaults to false).\n * @param {SCOPE=} opt_listenerScope Object in whose scope to call\n *     the listener.\n * @return {boolean} Whether any listener was removed.\n * @template SCOPE,EVENTOBJ\n */\ngoog.events.Listenable.prototype.unlisten = function(\n    type, listener, opt_useCapture, opt_listenerScope) {};\n\n\n/**\n * Removes an event listener which was added with listen() by the key\n * returned by listen().\n *\n * @param {!goog.events.ListenableKey} key The key returned by\n *     listen() or listenOnce().\n * @return {boolean} Whether any listener was removed.\n */\ngoog.events.Listenable.prototype.unlistenByKey = function(key) {};\n\n\n/**\n * Dispatches an event (or event like object) and calls all listeners\n * listening for events of this type. The type of the event is decided by the\n * type property on the event object.\n *\n * If any of the listeners returns false OR calls preventDefault then this\n * function will return false.  If one of the capture listeners calls\n * stopPropagation, then the bubble listeners won't fire.\n *\n * @param {?goog.events.EventLike} e Event object.\n * @return {boolean} If anyone called preventDefault on the event object (or\n *     if any of the listeners returns false) this will also return false.\n */\ngoog.events.Listenable.prototype.dispatchEvent = function(e) {};\n\n\n/**\n * Removes all listeners from this listenable. If type is specified,\n * it will only remove listeners of the particular type. otherwise all\n * registered listeners will be removed.\n *\n * @param {string|!goog.events.EventId=} opt_type Type of event to remove,\n *     default is to remove all types.\n * @return {number} Number of listeners removed.\n */\ngoog.events.Listenable.prototype.removeAllListeners = function(opt_type) {};\n\n\n/**\n * Returns the parent of this event target to use for capture/bubble\n * mechanism.\n *\n * NOTE(chrishenry): The name reflects the original implementation of\n * custom event target (`goog.events.EventTarget`). We decided\n * that changing the name is not worth it.\n *\n * @return {?goog.events.Listenable} The parent EventTarget or null if\n *     there is no parent.\n */\ngoog.events.Listenable.prototype.getParentEventTarget = function() {};\n\n\n/**\n * Fires all registered listeners in this listenable for the given\n * type and capture mode, passing them the given eventObject. This\n * does not perform actual capture/bubble. Only implementors of the\n * interface should be using this.\n *\n * @param {string|!goog.events.EventId<EVENTOBJ>} type The type of the\n *     listeners to fire.\n * @param {boolean} capture The capture mode of the listeners to fire.\n * @param {EVENTOBJ} eventObject The event object to fire.\n * @return {boolean} Whether all listeners succeeded without\n *     attempting to prevent default behavior. If any listener returns\n *     false or called goog.events.Event#preventDefault, this returns\n *     false.\n * @template EVENTOBJ\n */\ngoog.events.Listenable.prototype.fireListeners = function(\n    type, capture, eventObject) {};\n\n\n/**\n * Gets all listeners in this listenable for the given type and\n * capture mode.\n *\n * @param {string|!goog.events.EventId} type The type of the listeners to fire.\n * @param {boolean} capture The capture mode of the listeners to fire.\n * @return {!Array<!goog.events.ListenableKey>} An array of registered\n *     listeners.\n * @template EVENTOBJ\n */\ngoog.events.Listenable.prototype.getListeners = function(type, capture) {};\n\n\n/**\n * Gets the goog.events.ListenableKey for the event or null if no such\n * listener is in use.\n *\n * @param {string|!goog.events.EventId<EVENTOBJ>} type The name of the event\n *     without the 'on' prefix.\n * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener The\n *     listener function to get.\n * @param {boolean} capture Whether the listener is a capturing listener.\n * @param {SCOPE=} opt_listenerScope Object in whose scope to call the\n *     listener.\n * @return {?goog.events.ListenableKey} the found listener or null if not found.\n * @template SCOPE,EVENTOBJ\n */\ngoog.events.Listenable.prototype.getListener = function(\n    type, listener, capture, opt_listenerScope) {};\n\n\n/**\n * Whether there is any active listeners matching the specified\n * signature. If either the type or capture parameters are\n * unspecified, the function will match on the remaining criteria.\n *\n * @param {string|!goog.events.EventId<EVENTOBJ>=} opt_type Event type.\n * @param {boolean=} opt_capture Whether to check for capture or bubble\n *     listeners.\n * @return {boolean} Whether there is any active listeners matching\n *     the requested type and/or capture phase.\n * @template EVENTOBJ\n */\ngoog.events.Listenable.prototype.hasListener = function(\n    opt_type, opt_capture) {};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview An interface that describes a single registered listener.\n */\ngoog.provide('goog.events.ListenableKey');\n\ngoog.requireType('goog.events.Listenable');\n\n\n/**\n * An interface that describes a single registered listener.\n * @interface\n */\ngoog.events.ListenableKey = function() {};\n\n\n/**\n * Counter used to create a unique key\n * @type {number}\n * @private\n */\ngoog.events.ListenableKey.counter_ = 0;\n\n\n/**\n * Reserves a key to be used for ListenableKey#key field.\n * @return {number} A number to be used to fill ListenableKey#key\n *     field.\n */\ngoog.events.ListenableKey.reserveKey = function() {\n  'use strict';\n  return ++goog.events.ListenableKey.counter_;\n};\n\n\n/**\n * The source event target.\n * @type {?Object|?goog.events.Listenable}\n */\ngoog.events.ListenableKey.prototype.src;\n\n\n/**\n * The event type the listener is listening to.\n * @type {string}\n */\ngoog.events.ListenableKey.prototype.type;\n\n\n/**\n * The listener function.\n * @type {function(?):?|{handleEvent:function(?):?}|null}\n */\ngoog.events.ListenableKey.prototype.listener;\n\n\n/**\n * Whether the listener works on capture phase.\n * @type {boolean}\n */\ngoog.events.ListenableKey.prototype.capture;\n\n\n/**\n * The 'this' object for the listener function's scope.\n * @type {?Object|undefined}\n */\ngoog.events.ListenableKey.prototype.handler;\n\n\n/**\n * A globally unique number to identify the key.\n * @type {number}\n */\ngoog.events.ListenableKey.prototype.key;\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Listener object.\n * @see ../demos/events.html\n */\n\ngoog.provide('goog.events.Listener');\n\ngoog.require('goog.events.ListenableKey');\ngoog.requireType('goog.events.Listenable');\n\n\n\n/**\n * Simple class that stores information about a listener\n * @param {function(?):?} listener Callback function.\n * @param {Function} proxy Wrapper for the listener that patches the event.\n * @param {EventTarget|goog.events.Listenable} src Source object for\n *     the event.\n * @param {string} type Event type.\n * @param {boolean} capture Whether in capture or bubble phase.\n * @param {Object=} opt_handler Object in whose context to execute the callback.\n * @implements {goog.events.ListenableKey}\n * @constructor\n */\ngoog.events.Listener = function(\n    listener, proxy, src, type, capture, opt_handler) {\n  'use strict';\n  if (goog.events.Listener.ENABLE_MONITORING) {\n    this.creationStack = new Error().stack;\n  }\n\n  /** @override */\n  this.listener = listener;\n\n  /**\n   * A wrapper over the original listener. This is used solely to\n   * handle native browser events (it is used to simulate the capture\n   * phase and to patch the event object).\n   * @type {Function}\n   */\n  this.proxy = proxy;\n\n  /**\n   * Object or node that callback is listening to\n   * @type {EventTarget|goog.events.Listenable}\n   */\n  this.src = src;\n\n  /**\n   * The event type.\n   * @const {string}\n   */\n  this.type = type;\n\n  /**\n   * Whether the listener is being called in the capture or bubble phase\n   * @const {boolean}\n   */\n  this.capture = !!capture;\n\n  /**\n   * Optional object whose context to execute the listener in\n   * @type {Object|undefined}\n   */\n  this.handler = opt_handler;\n\n  /**\n   * The key of the listener.\n   * @const {number}\n   * @override\n   */\n  this.key = goog.events.ListenableKey.reserveKey();\n\n  /**\n   * Whether to remove the listener after it has been called.\n   * @type {boolean}\n   */\n  this.callOnce = false;\n\n  /**\n   * Whether the listener has been removed.\n   * @type {boolean}\n   */\n  this.removed = false;\n};\n\n\n/**\n * @define {boolean} Whether to enable the monitoring of the\n *     goog.events.Listener instances. Switching on the monitoring is only\n *     recommended for debugging because it has a significant impact on\n *     performance and memory usage. If switched off, the monitoring code\n *     compiles down to 0 bytes.\n */\ngoog.events.Listener.ENABLE_MONITORING =\n    goog.define('goog.events.Listener.ENABLE_MONITORING', false);\n\n\n/**\n * If monitoring the goog.events.Listener instances is enabled, stores the\n * creation stack trace of the Disposable instance.\n * @type {string}\n */\ngoog.events.Listener.prototype.creationStack;\n\n\n/**\n * Marks this listener as removed. This also remove references held by\n * this listener object (such as listener and event source).\n */\ngoog.events.Listener.prototype.markAsRemoved = function() {\n  'use strict';\n  this.removed = true;\n  this.listener = null;\n  this.proxy = null;\n  this.src = null;\n  this.handler = null;\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview A map of listeners that provides utility functions to\n * deal with listeners on an event target. Used by\n * `goog.events.EventTarget`.\n *\n * WARNING: Do not use this class from outside goog.events package.\n *\n */\n\ngoog.provide('goog.events.ListenerMap');\n\ngoog.require('goog.array');\ngoog.require('goog.events.Listener');\ngoog.require('goog.object');\ngoog.requireType('goog.events.EventId');\ngoog.requireType('goog.events.Listenable');\ngoog.requireType('goog.events.ListenableKey');\n\n\n\n/**\n * Creates a new listener map.\n * @param {EventTarget|goog.events.Listenable} src The src object.\n * @constructor\n * @final\n */\ngoog.events.ListenerMap = function(src) {\n  'use strict';\n  /** @type {EventTarget|goog.events.Listenable} */\n  this.src = src;\n\n  /**\n   * Maps of event type to an array of listeners.\n   * @type {!Object<string, !Array<!goog.events.Listener>>}\n   */\n  this.listeners = {};\n\n  /**\n   * The count of types in this map that have registered listeners.\n   * @private {number}\n   */\n  this.typeCount_ = 0;\n};\n\n\n/**\n * @return {number} The count of event types in this map that actually\n *     have registered listeners.\n */\ngoog.events.ListenerMap.prototype.getTypeCount = function() {\n  'use strict';\n  return this.typeCount_;\n};\n\n\n/**\n * @return {number} Total number of registered listeners.\n */\ngoog.events.ListenerMap.prototype.getListenerCount = function() {\n  'use strict';\n  var count = 0;\n  for (var type in this.listeners) {\n    count += this.listeners[type].length;\n  }\n  return count;\n};\n\n\n/**\n * Adds an event listener. A listener can only be added once to an\n * object and if it is added again the key for the listener is\n * returned.\n *\n * Note that a one-off listener will not change an existing listener,\n * if any. On the other hand a normal listener will change existing\n * one-off listener to become a normal listener.\n *\n * @param {string|!goog.events.EventId} type The listener event type.\n * @param {!Function} listener This listener callback method.\n * @param {boolean} callOnce Whether the listener is a one-off\n *     listener.\n * @param {boolean=} opt_useCapture The capture mode of the listener.\n * @param {Object=} opt_listenerScope Object in whose scope to call the\n *     listener.\n * @return {!goog.events.ListenableKey} Unique key for the listener.\n */\ngoog.events.ListenerMap.prototype.add = function(\n    type, listener, callOnce, opt_useCapture, opt_listenerScope) {\n  'use strict';\n  var typeStr = type.toString();\n  var listenerArray = this.listeners[typeStr];\n  if (!listenerArray) {\n    listenerArray = this.listeners[typeStr] = [];\n    this.typeCount_++;\n  }\n\n  var listenerObj;\n  var index = goog.events.ListenerMap.findListenerIndex_(\n      listenerArray, listener, opt_useCapture, opt_listenerScope);\n  if (index > -1) {\n    listenerObj = listenerArray[index];\n    if (!callOnce) {\n      // Ensure that, if there is an existing callOnce listener, it is no\n      // longer a callOnce listener.\n      listenerObj.callOnce = false;\n    }\n  } else {\n    listenerObj = new goog.events.Listener(\n        listener, null, this.src, typeStr, !!opt_useCapture, opt_listenerScope);\n    listenerObj.callOnce = callOnce;\n    listenerArray.push(listenerObj);\n  }\n  return listenerObj;\n};\n\n\n/**\n * Removes a matching listener.\n * @param {string|!goog.events.EventId} type The listener event type.\n * @param {!Function} listener This listener callback method.\n * @param {boolean=} opt_useCapture The capture mode of the listener.\n * @param {Object=} opt_listenerScope Object in whose scope to call the\n *     listener.\n * @return {boolean} Whether any listener was removed.\n */\ngoog.events.ListenerMap.prototype.remove = function(\n    type, listener, opt_useCapture, opt_listenerScope) {\n  'use strict';\n  var typeStr = type.toString();\n  if (!(typeStr in this.listeners)) {\n    return false;\n  }\n\n  var listenerArray = this.listeners[typeStr];\n  var index = goog.events.ListenerMap.findListenerIndex_(\n      listenerArray, listener, opt_useCapture, opt_listenerScope);\n  if (index > -1) {\n    var listenerObj = listenerArray[index];\n    listenerObj.markAsRemoved();\n    goog.array.removeAt(listenerArray, index);\n    if (listenerArray.length == 0) {\n      delete this.listeners[typeStr];\n      this.typeCount_--;\n    }\n    return true;\n  }\n  return false;\n};\n\n\n/**\n * Removes the given listener object.\n * @param {!goog.events.ListenableKey} listener The listener to remove.\n * @return {boolean} Whether the listener is removed.\n */\ngoog.events.ListenerMap.prototype.removeByKey = function(listener) {\n  'use strict';\n  var type = listener.type;\n  if (!(type in this.listeners)) {\n    return false;\n  }\n\n  var removed = goog.array.remove(this.listeners[type], listener);\n  if (removed) {\n    /** @type {!goog.events.Listener} */ (listener).markAsRemoved();\n    if (this.listeners[type].length == 0) {\n      delete this.listeners[type];\n      this.typeCount_--;\n    }\n  }\n  return removed;\n};\n\n\n/**\n * Removes all listeners from this map. If opt_type is provided, only\n * listeners that match the given type are removed.\n * @param {string|!goog.events.EventId=} opt_type Type of event to remove.\n * @return {number} Number of listeners removed.\n */\ngoog.events.ListenerMap.prototype.removeAll = function(opt_type) {\n  'use strict';\n  var typeStr = opt_type && opt_type.toString();\n  var count = 0;\n  for (var type in this.listeners) {\n    if (!typeStr || type == typeStr) {\n      var listenerArray = this.listeners[type];\n      for (var i = 0; i < listenerArray.length; i++) {\n        ++count;\n        listenerArray[i].markAsRemoved();\n      }\n      delete this.listeners[type];\n      this.typeCount_--;\n    }\n  }\n  return count;\n};\n\n\n/**\n * Gets all listeners that match the given type and capture mode. The\n * returned array is a copy (but the listener objects are not).\n * @param {string|!goog.events.EventId} type The type of the listeners\n *     to retrieve.\n * @param {boolean} capture The capture mode of the listeners to retrieve.\n * @return {!Array<!goog.events.ListenableKey>} An array of matching\n *     listeners.\n */\ngoog.events.ListenerMap.prototype.getListeners = function(type, capture) {\n  'use strict';\n  var listenerArray = this.listeners[type.toString()];\n  var rv = [];\n  if (listenerArray) {\n    for (var i = 0; i < listenerArray.length; ++i) {\n      var listenerObj = listenerArray[i];\n      if (listenerObj.capture == capture) {\n        rv.push(listenerObj);\n      }\n    }\n  }\n  return rv;\n};\n\n\n/**\n * Gets the goog.events.ListenableKey for the event or null if no such\n * listener is in use.\n *\n * @param {string|!goog.events.EventId} type The type of the listener\n *     to retrieve.\n * @param {!Function} listener The listener function to get.\n * @param {boolean} capture Whether the listener is a capturing listener.\n * @param {Object=} opt_listenerScope Object in whose scope to call the\n *     listener.\n * @return {goog.events.ListenableKey} the found listener or null if not found.\n */\ngoog.events.ListenerMap.prototype.getListener = function(\n    type, listener, capture, opt_listenerScope) {\n  'use strict';\n  var listenerArray = this.listeners[type.toString()];\n  var i = -1;\n  if (listenerArray) {\n    i = goog.events.ListenerMap.findListenerIndex_(\n        listenerArray, listener, capture, opt_listenerScope);\n  }\n  return i > -1 ? listenerArray[i] : null;\n};\n\n\n/**\n * Whether there is a matching listener. If either the type or capture\n * parameters are unspecified, the function will match on the\n * remaining criteria.\n *\n * @param {string|!goog.events.EventId=} opt_type The type of the listener.\n * @param {boolean=} opt_capture The capture mode of the listener.\n * @return {boolean} Whether there is an active listener matching\n *     the requested type and/or capture phase.\n */\ngoog.events.ListenerMap.prototype.hasListener = function(\n    opt_type, opt_capture) {\n  'use strict';\n  var hasType = (opt_type !== undefined);\n  var typeStr = hasType ? opt_type.toString() : '';\n  var hasCapture = (opt_capture !== undefined);\n\n  return goog.object.some(this.listeners, function(listenerArray, type) {\n    'use strict';\n    for (var i = 0; i < listenerArray.length; ++i) {\n      if ((!hasType || listenerArray[i].type == typeStr) &&\n          (!hasCapture || listenerArray[i].capture == opt_capture)) {\n        return true;\n      }\n    }\n\n    return false;\n  });\n};\n\n\n/**\n * Finds the index of a matching goog.events.Listener in the given\n * listenerArray.\n * @param {!Array<!goog.events.Listener>} listenerArray Array of listener.\n * @param {!Function} listener The listener function.\n * @param {boolean=} opt_useCapture The capture flag for the listener.\n * @param {Object=} opt_listenerScope The listener scope.\n * @return {number} The index of the matching listener within the\n *     listenerArray.\n * @private\n */\ngoog.events.ListenerMap.findListenerIndex_ = function(\n    listenerArray, listener, opt_useCapture, opt_listenerScope) {\n  'use strict';\n  for (var i = 0; i < listenerArray.length; ++i) {\n    var listenerObj = listenerArray[i];\n    if (!listenerObj.removed && listenerObj.listener == listener &&\n        listenerObj.capture == !!opt_useCapture &&\n        listenerObj.handler == opt_listenerScope) {\n      return i;\n    }\n  }\n  return -1;\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Utilities for manipulating objects/maps/hashes.\n */\ngoog.module('goog.object');\ngoog.module.declareLegacyNamespace();\n\n/**\n * Calls a function for each element in an object/map/hash.\n * @param {?Object<K,V>} obj The object over which to iterate.\n * @param {function(this:T,V,?,?Object<K,V>):?} f The function to call for every\n *     element. This function takes 3 arguments (the value, the key and the\n *     object) and the return value is ignored.\n * @param {T=} opt_obj This is used as the 'this' object within f.\n * @return {void}\n * @template T,K,V\n */\nfunction forEach(obj, f, opt_obj) {\n  for (const key in obj) {\n    f.call(/** @type {?} */ (opt_obj), obj[key], key, obj);\n  }\n}\n\n/**\n * Calls a function for each element in an object/map/hash. If that call returns\n * true, adds the element to a new object.\n * @param {?Object<K,V>} obj The object over which to iterate.\n * @param {function(this:T,V,?,?Object<K,V>):boolean} f The function to call for\n *     every element. This function takes 3 arguments (the value, the key and\n *     the object) and should return a boolean. If the return value is true the\n *     element is added to the result object. If it is false the element is not\n *     included.\n * @param {T=} opt_obj This is used as the 'this' object within f.\n * @return {!Object<K,V>} a new object in which only elements that passed the\n *     test are present.\n * @template T,K,V\n */\nfunction filter(obj, f, opt_obj) {\n  const res = {};\n  for (const key in obj) {\n    if (f.call(/** @type {?} */ (opt_obj), obj[key], key, obj)) {\n      res[key] = obj[key];\n    }\n  }\n  return res;\n}\n\n/**\n * For every element in an object/map/hash calls a function and inserts the\n * result into a new object.\n * @param {?Object<K,V>} obj The object over which to iterate.\n * @param {function(this:T,V,?,?Object<K,V>):R} f The function to call for every\n *     element. This function takes 3 arguments (the value, the key and the\n *     object) and should return something. The result will be inserted into a\n *     new object.\n * @param {T=} opt_obj This is used as the 'this' object within f.\n * @return {!Object<K,R>} a new object with the results from f.\n * @template T,K,V,R\n */\nfunction map(obj, f, opt_obj) {\n  const res = {};\n  for (const key in obj) {\n    res[key] = f.call(/** @type {?} */ (opt_obj), obj[key], key, obj);\n  }\n  return res;\n}\n\n/**\n * Calls a function for each element in an object/map/hash. If any\n * call returns true, returns true (without checking the rest). If\n * all calls return false, returns false.\n * @param {?Object<K,V>} obj The object to check.\n * @param {function(this:T,V,?,?Object<K,V>):boolean} f The function to call for\n *     every element. This function takes 3 arguments (the value, the key and\n *     the object) and should return a boolean.\n * @param {T=} opt_obj This is used as the 'this' object within f.\n * @return {boolean} true if any element passes the test.\n * @template T,K,V\n */\nfunction some(obj, f, opt_obj) {\n  for (const key in obj) {\n    if (f.call(/** @type {?} */ (opt_obj), obj[key], key, obj)) {\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * Calls a function for each element in an object/map/hash. If\n * all calls return true, returns true. If any call returns false, returns\n * false at this point and does not continue to check the remaining elements.\n * @param {?Object<K,V>} obj The object to check.\n * @param {?function(this:T,V,?,?Object<K,V>):boolean} f The function to call\n *     for every element. This function takes 3 arguments (the value, the key\n *     and the object) and should return a boolean.\n * @param {T=} opt_obj This is used as the 'this' object within f.\n * @return {boolean} false if any element fails the test.\n * @template T,K,V\n */\nfunction every(obj, f, opt_obj) {\n  for (const key in obj) {\n    if (!f.call(/** @type {?} */ (opt_obj), obj[key], key, obj)) {\n      return false;\n    }\n  }\n  return true;\n}\n\n/**\n * Returns the number of key-value pairs in the object map.\n * @param {?Object} obj The object for which to get the number of key-value\n *     pairs.\n * @return {number} The number of key-value pairs in the object map.\n */\nfunction getCount(obj) {\n  let rv = 0;\n  for (const key in obj) {\n    rv++;\n  }\n  return rv;\n}\n\n/**\n * Returns one key from the object map, if any exists.\n * For map literals the returned key will be the first one in most of the\n * browsers (a know exception is Konqueror).\n * @param {?Object} obj The object to pick a key from.\n * @return {string|undefined} The key or undefined if the object is empty.\n */\nfunction getAnyKey(obj) {\n  for (const key in obj) {\n    return key;\n  }\n}\n\n/**\n * Returns one value from the object map, if any exists.\n * For map literals the returned value will be the first one in most of the\n * browsers (a know exception is Konqueror).\n * @param {?Object<K,V>} obj The object to pick a value from.\n * @return {V|undefined} The value or undefined if the object is empty.\n * @template K,V\n */\nfunction getAnyValue(obj) {\n  for (const key in obj) {\n    return obj[key];\n  }\n}\n\n/**\n * Whether the object/hash/map contains the given object as a value.\n * An alias for containsValue(obj, val).\n * @param {?Object<K,V>} obj The object in which to look for val.\n * @param {V} val The object for which to check.\n * @return {boolean} true if val is present.\n * @template K,V\n */\nfunction contains(obj, val) {\n  return containsValue(obj, val);\n}\n\n/**\n * Returns the values of the object/map/hash.\n * @param {?Object<K,V>} obj The object from which to get the values.\n * @return {!Array<V>} The values in the object/map/hash.\n * @template K,V\n */\nfunction getValues(obj) {\n  const res = [];\n  let i = 0;\n  for (const key in obj) {\n    res[i++] = obj[key];\n  }\n  return res;\n}\n\n/**\n * Returns the keys of the object/map/hash.\n * @param {?Object} obj The object from which to get the keys.\n * @return {!Array<string>} Array of property keys.\n */\nfunction getKeys(obj) {\n  const res = [];\n  let i = 0;\n  for (const key in obj) {\n    res[i++] = key;\n  }\n  return res;\n}\n\n/**\n * Get a value from an object multiple levels deep.  This is useful for\n * pulling values from deeply nested objects, such as JSON responses.\n * Example usage: getValueByKeys(jsonObj, 'foo', 'entries', 3)\n * @param {?Object} obj An object to get the value from. Can be array-like.\n * @param {...(string|number|!IArrayLike<number|string>)} var_args A number of\n *     keys (as strings, or numbers, for array-like objects). Can also be\n *     specified as a single array of keys.\n * @return {*} The resulting value. If, at any point, the value for a key in the\n *     current object is null or undefined, returns undefined.\n */\nfunction getValueByKeys(obj, var_args) {\n  const isArrayLike = goog.isArrayLike(var_args);\n  const keys = isArrayLike ?\n      /** @type {!IArrayLike<number|string>} */ (var_args) :\n      arguments;\n\n  // Start with the 2nd parameter for the variable parameters syntax.\n  for (let i = isArrayLike ? 0 : 1; i < keys.length; i++) {\n    if (obj == null) return undefined;\n    obj = obj[keys[i]];\n  }\n\n  return obj;\n}\n\n/**\n * Whether the object/map/hash contains the given key.\n * @param {?Object} obj The object in which to look for key.\n * @param {?} key The key for which to check.\n * @return {boolean} true If the map contains the key.\n */\nfunction containsKey(obj, key) {\n  return obj !== null && key in obj;\n}\n\n/**\n * Whether the object/map/hash contains the given value. This is O(n).\n * @param {?Object<K,V>} obj The object in which to look for val.\n * @param {V} val The value for which to check.\n * @return {boolean} true If the map contains the value.\n * @template K,V\n */\nfunction containsValue(obj, val) {\n  for (const key in obj) {\n    if (obj[key] == val) {\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * Searches an object for an element that satisfies the given condition and\n * returns its key.\n * @param {?Object<K,V>} obj The object to search in.\n * @param {function(this:T,V,string,?Object<K,V>):boolean} f The function to\n *     call for every element. Takes 3 arguments (the value, the key and the\n *     object) and should return a boolean.\n * @param {T=} thisObj An optional \"this\" context for the function.\n * @return {string|undefined} The key of an element for which the function\n *     returns true or undefined if no such element is found.\n * @template T,K,V\n */\nfunction findKey(obj, f, thisObj = undefined) {\n  for (const key in obj) {\n    if (f.call(/** @type {?} */ (thisObj), obj[key], key, obj)) {\n      return key;\n    }\n  }\n  return undefined;\n}\n\n/**\n * Searches an object for an element that satisfies the given condition and\n * returns its value.\n * @param {?Object<K,V>} obj The object to search in.\n * @param {function(this:T,V,string,?Object<K,V>):boolean} f The function to\n *     call for every element. Takes 3 arguments (the value, the key and the\n *     object) and should return a boolean.\n * @param {T=} thisObj An optional \"this\" context for the function.\n * @return {V} The value of an element for which the function returns true or\n *     undefined if no such element is found.\n * @template T,K,V\n */\nfunction findValue(obj, f, thisObj = undefined) {\n  const key = findKey(obj, f, thisObj);\n  return key && obj[key];\n}\n\n/**\n * Whether the object/map/hash is empty.\n * @param {?Object} obj The object to test.\n * @return {boolean} true if obj is empty.\n */\nfunction isEmpty(obj) {\n  for (const key in obj) {\n    return false;\n  }\n  return true;\n}\n\n/**\n * Removes all key value pairs from the object/map/hash.\n * @param {?Object} obj The object to clear.\n * @return {void}\n */\nfunction clear(obj) {\n  for (const i in obj) {\n    delete obj[i];\n  }\n}\n\n/**\n * Removes a key-value pair based on the key.\n * @param {?Object} obj The object from which to remove the key.\n * @param {?} key The key to remove.\n * @return {boolean} Whether an element was removed.\n */\nfunction remove(obj, key) {\n  let rv;\n  if (rv = key in /** @type {!Object} */ (obj)) {\n    delete obj[key];\n  }\n  return rv;\n}\n\n/**\n * Adds a key-value pair to the object. Throws an exception if the key is\n * already in use. Use set if you want to change an existing pair.\n * @param {?Object<K,V>} obj The object to which to add the key-value pair.\n * @param {string} key The key to add.\n * @param {V} val The value to add.\n * @return {void}\n * @template K,V\n */\nfunction add(obj, key, val) {\n  if (obj !== null && key in obj) {\n    throw new Error(`The object already contains the key \"${key}\"`);\n  }\n  set(obj, key, val);\n}\n\n/**\n * Returns the value for the given key.\n * @param {?Object<K,V>} obj The object from which to get the value.\n * @param {string} key The key for which to get the value.\n * @param {R=} val The value to return if no item is found for the given key\n *     (default is undefined).\n * @return {V|R|undefined} The value for the given key.\n * @template K,V,R\n */\nfunction get(obj, key, val = undefined) {\n  if (obj !== null && key in obj) {\n    return obj[key];\n  }\n  return val;\n}\n\n/**\n * Adds a key-value pair to the object/map/hash.\n * @param {?Object<K,V>} obj The object to which to add the key-value pair.\n * @param {string} key The key to add.\n * @param {V} value The value to add.\n * @template K,V\n * @return {void}\n */\nfunction set(obj, key, value) {\n  obj[key] = value;\n}\n\n/**\n * Adds a key-value pair to the object/map/hash if it doesn't exist yet.\n * @param {?Object<K,V>} obj The object to which to add the key-value pair.\n * @param {string} key The key to add.\n * @param {V} value The value to add if the key wasn't present.\n * @return {V} The value of the entry at the end of the function.\n * @template K,V\n */\nfunction setIfUndefined(obj, key, value) {\n  return key in /** @type {!Object} */ (obj) ? obj[key] : (obj[key] = value);\n}\n\n/**\n * Sets a key and value to an object if the key is not set. The value will be\n * the return value of the given function. If the key already exists, the\n * object will not be changed and the function will not be called (the function\n * will be lazily evaluated -- only called if necessary).\n * This function is particularly useful when used with an `Object` which is\n * acting as a cache.\n * @param {?Object<K,V>} obj The object to which to add the key-value pair.\n * @param {string} key The key to add.\n * @param {function():V} f The value to add if the key wasn't present.\n * @return {V} The value of the entry at the end of the function.\n * @template K,V\n */\nfunction setWithReturnValueIfNotSet(obj, key, f) {\n  if (key in obj) {\n    return obj[key];\n  }\n\n  const val = f();\n  obj[key] = val;\n  return val;\n}\n\n/**\n * Compares two objects for equality using === on the values.\n * @param {!Object<K,V>} a\n * @param {!Object<K,V>} b\n * @return {boolean}\n * @template K,V\n */\nfunction equals(a, b) {\n  for (const k in a) {\n    if (!(k in b) || a[k] !== b[k]) {\n      return false;\n    }\n  }\n  for (const k in b) {\n    if (!(k in a)) {\n      return false;\n    }\n  }\n  return true;\n}\n\n/**\n * Returns a shallow clone of the object.\n * @param {?Object<K,V>} obj Object to clone.\n * @return {!Object<K,V>} Clone of the input object.\n * @template K,V\n */\nfunction clone(obj) {\n  const res = {};\n  for (const key in obj) {\n    res[key] = obj[key];\n  }\n  return res;\n}\n\n/**\n * Clones a value. The input may be an Object, Array, or basic type. Objects and\n * arrays will be cloned recursively.\n * WARNINGS:\n * <code>unsafeClone</code> does not detect reference loops. Objects\n * that refer to themselves will cause infinite recursion.\n * <code>unsafeClone</code> is unaware of unique identifiers, and\n * copies UIDs created by <code>getUid</code> into cloned results.\n * @param {T} obj The value to clone.\n * @return {T} A clone of the input value.\n * @template T\n */\nfunction unsafeClone(obj) {\n  if (!obj || typeof obj !== 'object') return obj;\n  if (typeof obj.clone === 'function') return obj.clone();\n  if (typeof Map !== 'undefined' && obj instanceof Map) {\n    return new Map(obj);\n  } else if (typeof Set !== 'undefined' && obj instanceof Set) {\n    return new Set(obj);\n  }\n  const clone = Array.isArray(obj) ? [] :\n      typeof ArrayBuffer === 'function' &&\n          typeof ArrayBuffer.isView === 'function' && ArrayBuffer.isView(obj) &&\n          !(obj instanceof DataView) ?\n                                     new obj.constructor(obj.length) :\n                                     {};\n  for (const key in obj) {\n    clone[key] = unsafeClone(obj[key]);\n  }\n  return clone;\n}\n\n/**\n * Returns a new object in which all the keys and values are interchanged\n * (keys become values and values become keys). If multiple keys map to the\n * same value, the chosen transposed value is implementation-dependent.\n * @param {?Object} obj The object to transpose.\n * @return {!Object} The transposed object.\n */\nfunction transpose(obj) {\n  const transposed = {};\n  for (const key in obj) {\n    transposed[obj[key]] = key;\n  }\n  return transposed;\n}\n\n/**\n * The names of the fields that are defined on Object.prototype.\n * @type {!Array<string>}\n */\nconst PROTOTYPE_FIELDS = [\n  'constructor',\n  'hasOwnProperty',\n  'isPrototypeOf',\n  'propertyIsEnumerable',\n  'toLocaleString',\n  'toString',\n  'valueOf',\n];\n\n/**\n * Extends an object with another object.\n * This operates 'in-place'; it does not create a new Object.\n * Example:\n * var o = {};\n * extend(o, {a: 0, b: 1});\n * o; // {a: 0, b: 1}\n * extend(o, {b: 2, c: 3});\n * o; // {a: 0, b: 2, c: 3}\n * @param {?Object} target The object to modify. Existing properties will be\n *     overwritten if they are also present in one of the objects in `var_args`.\n * @param {...(?Object|undefined)} var_args The objects from which values\n *     will be copied.\n * @return {void}\n * @deprecated Prefer Object.assign\n */\nfunction extend(target, var_args) {\n  let key;\n  let source;\n  for (let i = 1; i < arguments.length; i++) {\n    source = arguments[i];\n    for (key in source) {\n      target[key] = source[key];\n    }\n\n    // For IE the for-in-loop does not contain any properties that are not\n    // enumerable on the prototype object (for example isPrototypeOf from\n    // Object.prototype) and it will also not include 'replace' on objects that\n    // extend String and change 'replace' (not that it is common for anyone to\n    // extend anything except Object).\n\n    for (let j = 0; j < PROTOTYPE_FIELDS.length; j++) {\n      key = PROTOTYPE_FIELDS[j];\n      if (Object.prototype.hasOwnProperty.call(source, key)) {\n        target[key] = source[key];\n      }\n    }\n  }\n}\n\n/**\n * Creates a new object built from the key-value pairs provided as arguments.\n * @param {...*} var_args If only one argument is provided and it is an array\n *     then this is used as the arguments, otherwise even arguments are used as\n *     the property names and odd arguments are used as the property values.\n * @return {!Object} The new object.\n * @throws {!Error} If there are uneven number of arguments or there is only one\n *     non array argument.\n */\nfunction create(var_args) {\n  const argLength = arguments.length;\n  if (argLength == 1 && Array.isArray(arguments[0])) {\n    return create.apply(null, arguments[0]);\n  }\n\n  if (argLength % 2) {\n    throw new Error('Uneven number of arguments');\n  }\n\n  const rv = {};\n  for (let i = 0; i < argLength; i += 2) {\n    rv[arguments[i]] = arguments[i + 1];\n  }\n  return rv;\n}\n\n/**\n * Creates a new object where the property names come from the arguments but\n * the value is always set to true\n * @param {...*} var_args If only one argument is provided and it is an array\n *     then this is used as the arguments, otherwise the arguments are used as\n *     the property names.\n * @return {!Object} The new object.\n */\nfunction createSet(var_args) {\n  const argLength = arguments.length;\n  if (argLength == 1 && Array.isArray(arguments[0])) {\n    return createSet.apply(null, arguments[0]);\n  }\n\n  const rv = {};\n  for (let i = 0; i < argLength; i++) {\n    rv[arguments[i]] = true;\n  }\n  return rv;\n}\n\n/**\n * Creates an immutable view of the underlying object, if the browser\n * supports immutable objects.\n * In default mode, writes to this view will fail silently. In strict mode,\n * they will throw an error.\n * @param {!Object<K,V>} obj An object.\n * @return {!Object<K,V>} An immutable view of that object, or the original\n *     object if this browser does not support immutables.\n * @template K,V\n */\nfunction createImmutableView(obj) {\n  let result = obj;\n  if (Object.isFrozen && !Object.isFrozen(obj)) {\n    result = Object.create(obj);\n    Object.freeze(result);\n  }\n  return result;\n}\n\n/**\n * @param {!Object} obj An object.\n * @return {boolean} Whether this is an immutable view of the object.\n */\nfunction isImmutableView(obj) {\n  return !!Object.isFrozen && Object.isFrozen(obj);\n}\n\n/**\n * Get all properties names on a given Object regardless of enumerability.\n * <p> If the browser does not support `Object.getOwnPropertyNames` nor\n * `Object.getPrototypeOf` then this is equivalent to using\n * `getKeys`\n * @param {?Object} obj The object to get the properties of.\n * @param {boolean=} includeObjectPrototype Whether properties defined on\n *     `Object.prototype` should be included in the result.\n * @param {boolean=} includeFunctionPrototype Whether properties defined on\n *     `Function.prototype` should be included in the result.\n * @return {!Array<string>}\n * @public\n */\nfunction getAllPropertyNames(\n    obj, includeObjectPrototype = undefined,\n    includeFunctionPrototype = undefined) {\n  if (!obj) {\n    return [];\n  }\n\n  // Naively use a for..in loop to get the property names if the browser doesn't\n  // support any other APIs for getting it.\n  if (!Object.getOwnPropertyNames || !Object.getPrototypeOf) {\n    return getKeys(obj);\n  }\n\n  const visitedSet = {};\n\n  // Traverse the prototype chain and add all properties to the visited set.\n  let proto = obj;\n  while (proto && (proto !== Object.prototype || !!includeObjectPrototype) &&\n         (proto !== Function.prototype || !!includeFunctionPrototype)) {\n    const names = Object.getOwnPropertyNames(proto);\n    for (let i = 0; i < names.length; i++) {\n      visitedSet[names[i]] = true;\n    }\n    proto = Object.getPrototypeOf(proto);\n  }\n\n  return getKeys(visitedSet);\n}\n\n/**\n * Given a ES5 or ES6 class reference, return its super class / super\n * constructor.\n * This should be used in rare cases where you need to walk up the inheritance\n * tree (this is generally a bad idea). But this work with ES5 and ES6 classes,\n * unlike relying on the superClass_ property.\n * Note: To start walking up the hierarchy from an instance call this with its\n * `constructor` property; e.g. `getSuperClass(instance.constructor)`.\n * @param {function(new: ?)} constructor\n * @return {?Object}\n */\nfunction getSuperClass(constructor) {\n  const proto = Object.getPrototypeOf(constructor.prototype);\n  return proto && proto.constructor;\n}\n\nexports = {\n  add,\n  clear,\n  clone,\n  contains,\n  containsKey,\n  containsValue,\n  create,\n  createImmutableView,\n  createSet,\n  equals,\n  every,\n  extend,\n  filter,\n  findKey,\n  findValue,\n  forEach,\n  get,\n  getAllPropertyNames,\n  getAnyKey,\n  getAnyValue,\n  getCount,\n  getKeys,\n  getSuperClass,\n  getValueByKeys,\n  getValues,\n  isEmpty,\n  isImmutableView,\n  map,\n  remove,\n  set,\n  setIfUndefined,\n  setWithReturnValueIfNotSet,\n  some,\n  transpose,\n  unsafeClone,\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview An event manager for both native browser event\n * targets and custom JavaScript event targets\n * (`goog.events.Listenable`). This provides an abstraction\n * over browsers' event systems.\n *\n * It also provides a simulation of W3C event model's capture phase in\n * Internet Explorer (IE 8 and below). Caveat: the simulation does not\n * interact well with listeners registered directly on the elements\n * (bypassing goog.events) or even with listeners registered via\n * goog.events in a separate JS binary. In these cases, we provide\n * no ordering guarantees.\n *\n * The listeners will receive a \"patched\" event object. Such event object\n * contains normalized values for certain event properties that differs in\n * different browsers.\n *\n * Example usage:\n * <pre>\n * goog.events.listen(myNode, 'click', function(e) { alert('woo') });\n * goog.events.listen(myNode, 'mouseover', mouseHandler, true);\n * goog.events.unlisten(myNode, 'mouseover', mouseHandler, true);\n * goog.events.removeAll(myNode);\n * </pre>\n *\n *                                            in IE and event object patching]\n *\n * @see ../demos/events.html\n * @see ../demos/event-propagation.html\n * @see ../demos/stopevent.html\n */\n\n// IMPLEMENTATION NOTES:\n// goog.events stores an auxiliary data structure on each EventTarget\n// source being listened on. This allows us to take advantage of GC,\n// having the data structure GC'd when the EventTarget is GC'd. This\n// GC behavior is equivalent to using W3C DOM Events directly.\n\ngoog.provide('goog.events');\ngoog.provide('goog.events.CaptureSimulationMode');\ngoog.provide('goog.events.Key');\ngoog.provide('goog.events.ListenableType');\n\ngoog.require('goog.asserts');\ngoog.require('goog.debug.entryPointRegistry');\ngoog.require('goog.events.BrowserEvent');\ngoog.require('goog.events.BrowserFeature');\ngoog.require('goog.events.Listenable');\ngoog.require('goog.events.ListenerMap');\ngoog.requireType('goog.debug.ErrorHandler');\ngoog.requireType('goog.events.EventId');\ngoog.requireType('goog.events.EventLike');\ngoog.requireType('goog.events.EventWrapper');\ngoog.requireType('goog.events.ListenableKey');\ngoog.requireType('goog.events.Listener');\n\n\n/**\n * @typedef {number|goog.events.ListenableKey}\n */\ngoog.events.Key;\n\n\n/**\n * @typedef {EventTarget|goog.events.Listenable}\n */\ngoog.events.ListenableType;\n\n\n/**\n * Property name on a native event target for the listener map\n * associated with the event target.\n * @private @const {string}\n */\ngoog.events.LISTENER_MAP_PROP_ = 'closure_lm_' + ((Math.random() * 1e6) | 0);\n\n\n/**\n * String used to prepend to IE event types.\n * @const\n * @private\n */\ngoog.events.onString_ = 'on';\n\n\n/**\n * Map of computed \"on<eventname>\" strings for IE event types. Caching\n * this removes an extra object allocation in goog.events.listen which\n * improves IE6 performance.\n * @const\n * @dict\n * @private\n */\ngoog.events.onStringMap_ = {};\n\n\n/**\n * @enum {number} Different capture simulation mode for IE8-.\n */\ngoog.events.CaptureSimulationMode = {\n  /**\n   * Does not perform capture simulation. Will asserts in IE8- when you\n   * add capture listeners.\n   */\n  OFF_AND_FAIL: 0,\n\n  /**\n   * Does not perform capture simulation, silently ignore capture\n   * listeners.\n   */\n  OFF_AND_SILENT: 1,\n\n  /**\n   * Performs capture simulation.\n   */\n  ON: 2\n};\n\n\n/**\n * @define {number} The capture simulation mode for IE8-. By default,\n *     this is ON.\n */\ngoog.events.CAPTURE_SIMULATION_MODE =\n    goog.define('goog.events.CAPTURE_SIMULATION_MODE', 2);\n\n\n/**\n * Estimated count of total native listeners.\n * @private {number}\n */\ngoog.events.listenerCountEstimate_ = 0;\n\n\n/**\n * Adds an event listener for a specific event on a native event\n * target (such as a DOM element) or an object that has implemented\n * {@link goog.events.Listenable}. A listener can only be added once\n * to an object and if it is added again the key for the listener is\n * returned. Note that if the existing listener is a one-off listener\n * (registered via listenOnce), it will no longer be a one-off\n * listener after a call to listen().\n *\n * @param {EventTarget|goog.events.Listenable} src The node to listen\n *     to events on.\n * @param {string|Array<string>|\n *     !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}\n *     type Event type or array of event types.\n * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(?):?}|null}\n *     listener Callback method, or an object with a handleEvent function.\n *     WARNING: passing an Object is now softly deprecated.\n * @param {(boolean|!AddEventListenerOptions)=} opt_options\n * @param {T=} opt_handler Element in whose scope to call the listener.\n * @return {goog.events.Key} Unique key for the listener.\n * @template T,EVENTOBJ\n */\ngoog.events.listen = function(src, type, listener, opt_options, opt_handler) {\n  'use strict';\n  if (opt_options && opt_options.once) {\n    return goog.events.listenOnce(\n        src, type, listener, opt_options, opt_handler);\n  }\n  if (Array.isArray(type)) {\n    for (var i = 0; i < type.length; i++) {\n      goog.events.listen(src, type[i], listener, opt_options, opt_handler);\n    }\n    return null;\n  }\n\n  listener = goog.events.wrapListener(listener);\n  if (goog.events.Listenable.isImplementedBy(src)) {\n    var capture =\n        goog.isObject(opt_options) ? !!opt_options.capture : !!opt_options;\n    return src.listen(\n        /** @type {string|!goog.events.EventId} */ (type), listener, capture,\n        opt_handler);\n  } else {\n    return goog.events.listen_(\n        /** @type {!EventTarget} */ (src), type, listener,\n        /* callOnce */ false, opt_options, opt_handler);\n  }\n};\n\n\n/**\n * Adds an event listener for a specific event on a native event\n * target. A listener can only be added once to an object and if it\n * is added again the key for the listener is returned.\n *\n * Note that a one-off listener will not change an existing listener,\n * if any. On the other hand a normal listener will change existing\n * one-off listener to become a normal listener.\n *\n * @param {EventTarget} src The node to listen to events on.\n * @param {string|?goog.events.EventId<EVENTOBJ>} type Event type.\n * @param {!Function} listener Callback function.\n * @param {boolean} callOnce Whether the listener is a one-off\n *     listener or otherwise.\n * @param {(boolean|!AddEventListenerOptions)=} opt_options\n * @param {Object=} opt_handler Element in whose scope to call the listener.\n * @return {goog.events.ListenableKey} Unique key for the listener.\n * @template EVENTOBJ\n * @private\n */\ngoog.events.listen_ = function(\n    src, type, listener, callOnce, opt_options, opt_handler) {\n  'use strict';\n  if (!type) {\n    throw new Error('Invalid event type');\n  }\n\n  var capture =\n      goog.isObject(opt_options) ? !!opt_options.capture : !!opt_options;\n\n  var listenerMap = goog.events.getListenerMap_(src);\n  if (!listenerMap) {\n    src[goog.events.LISTENER_MAP_PROP_] = listenerMap =\n        new goog.events.ListenerMap(src);\n  }\n\n  var listenerObj = /** @type {goog.events.Listener} */ (\n      listenerMap.add(type, listener, callOnce, capture, opt_handler));\n\n  // If the listenerObj already has a proxy, it has been set up\n  // previously. We simply return.\n  if (listenerObj.proxy) {\n    return listenerObj;\n  }\n\n  var proxy = goog.events.getProxy();\n  listenerObj.proxy = proxy;\n\n  proxy.src = src;\n  proxy.listener = listenerObj;\n\n  // Attach the proxy through the browser's API\n  if (src.addEventListener) {\n    // Don't pass an object as `capture` if the browser doesn't support that.\n    if (!goog.events.BrowserFeature.PASSIVE_EVENTS) {\n      opt_options = capture;\n    }\n    // Don't break tests that expect a boolean.\n    if (opt_options === undefined) opt_options = false;\n    src.addEventListener(type.toString(), proxy, opt_options);\n  } else if (src.attachEvent) {\n    // The else if above used to be an unconditional else. It would call\n    // attachEvent come gws or high water. This would sometimes throw an\n    // exception on IE11, spoiling the day of some callers. The previous\n    // incarnation of this code, from 2007, indicates that it replaced an\n    // earlier still version that caused excess allocations on IE6.\n    src.attachEvent(goog.events.getOnString_(type.toString()), proxy);\n  } else if (src.addListener && src.removeListener) {\n    // In IE, MediaQueryList uses addListener() insteadd of addEventListener. In\n    // Safari, there is no global for the MediaQueryList constructor, so we just\n    // check whether the object \"looks like\" MediaQueryList.\n    goog.asserts.assert(\n        type === 'change', 'MediaQueryList only has a change event');\n    src.addListener(proxy);\n  } else {\n    throw new Error('addEventListener and attachEvent are unavailable.');\n  }\n\n  goog.events.listenerCountEstimate_++;\n  return listenerObj;\n};\n\n\n/**\n * Helper function for returning a proxy function.\n * @return {!Function} A new or reused function object.\n */\ngoog.events.getProxy = function() {\n  'use strict';\n  const proxyCallbackFunction = goog.events.handleBrowserEvent_;\n  const f = function(eventObject) {\n    return proxyCallbackFunction.call(f.src, f.listener, eventObject);\n  };\n  return f;\n};\n\n\n/**\n * Adds an event listener for a specific event on a native event\n * target (such as a DOM element) or an object that has implemented\n * {@link goog.events.Listenable}. After the event has fired the event\n * listener is removed from the target.\n *\n * If an existing listener already exists, listenOnce will do\n * nothing. In particular, if the listener was previously registered\n * via listen(), listenOnce() will not turn the listener into a\n * one-off listener. Similarly, if there is already an existing\n * one-off listener, listenOnce does not modify the listeners (it is\n * still a once listener).\n *\n * @param {EventTarget|goog.events.Listenable} src The node to listen\n *     to events on.\n * @param {string|Array<string>|\n *     !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}\n *     type Event type or array of event types.\n * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(?):?}|null}\n *     listener Callback method.\n * @param {(boolean|!AddEventListenerOptions)=} opt_options\n * @param {T=} opt_handler Element in whose scope to call the listener.\n * @return {goog.events.Key} Unique key for the listener.\n * @template T,EVENTOBJ\n */\ngoog.events.listenOnce = function(\n    src, type, listener, opt_options, opt_handler) {\n  'use strict';\n  if (Array.isArray(type)) {\n    for (var i = 0; i < type.length; i++) {\n      goog.events.listenOnce(src, type[i], listener, opt_options, opt_handler);\n    }\n    return null;\n  }\n\n  listener = goog.events.wrapListener(listener);\n  if (goog.events.Listenable.isImplementedBy(src)) {\n    var capture =\n        goog.isObject(opt_options) ? !!opt_options.capture : !!opt_options;\n    return src.listenOnce(\n        /** @type {string|!goog.events.EventId} */ (type), listener, capture,\n        opt_handler);\n  } else {\n    return goog.events.listen_(\n        /** @type {!EventTarget} */ (src), type, listener,\n        /* callOnce */ true, opt_options, opt_handler);\n  }\n};\n\n\n/**\n * Adds an event listener with a specific event wrapper on a DOM Node or an\n * object that has implemented {@link goog.events.Listenable}. A listener can\n * only be added once to an object.\n *\n * @param {EventTarget|goog.events.Listenable} src The target to\n *     listen to events on.\n * @param {goog.events.EventWrapper} wrapper Event wrapper to use.\n * @param {function(this:T, ?):?|{handleEvent:function(?):?}|null} listener\n *     Callback method, or an object with a handleEvent function.\n * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to\n *     false).\n * @param {T=} opt_handler Element in whose scope to call the listener.\n * @template T\n */\ngoog.events.listenWithWrapper = function(\n    src, wrapper, listener, opt_capt, opt_handler) {\n  'use strict';\n  wrapper.listen(src, listener, opt_capt, opt_handler);\n};\n\n\n/**\n * Removes an event listener which was added with listen().\n *\n * @param {EventTarget|goog.events.Listenable} src The target to stop\n *     listening to events on.\n * @param {string|Array<string>|\n *     !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}\n *     type Event type or array of event types to unlisten to.\n * @param {function(?):?|{handleEvent:function(?):?}|null} listener The\n *     listener function to remove.\n * @param {(boolean|!EventListenerOptions)=} opt_options\n *     whether the listener is fired during the capture or bubble phase of the\n *     event.\n * @param {Object=} opt_handler Element in whose scope to call the listener.\n * @return {?boolean} indicating whether the listener was there to remove.\n * @template EVENTOBJ\n */\ngoog.events.unlisten = function(src, type, listener, opt_options, opt_handler) {\n  'use strict';\n  if (Array.isArray(type)) {\n    for (var i = 0; i < type.length; i++) {\n      goog.events.unlisten(src, type[i], listener, opt_options, opt_handler);\n    }\n    return null;\n  }\n  var capture =\n      goog.isObject(opt_options) ? !!opt_options.capture : !!opt_options;\n\n  listener = goog.events.wrapListener(listener);\n  if (goog.events.Listenable.isImplementedBy(src)) {\n    return src.unlisten(\n        /** @type {string|!goog.events.EventId} */ (type), listener, capture,\n        opt_handler);\n  }\n\n  if (!src) {\n    // TODO(chrishenry): We should tighten the API to only accept\n    // non-null objects, or add an assertion here.\n    return false;\n  }\n\n  var listenerMap = goog.events.getListenerMap_(\n      /** @type {!EventTarget} */ (src));\n  if (listenerMap) {\n    var listenerObj = listenerMap.getListener(\n        /** @type {string|!goog.events.EventId} */ (type), listener, capture,\n        opt_handler);\n    if (listenerObj) {\n      return goog.events.unlistenByKey(listenerObj);\n    }\n  }\n\n  return false;\n};\n\n\n/**\n * Removes an event listener which was added with listen() by the key\n * returned by listen().\n *\n * @param {goog.events.Key} key The key returned by listen() for this\n *     event listener.\n * @return {boolean} indicating whether the listener was there to remove.\n */\ngoog.events.unlistenByKey = function(key) {\n  'use strict';\n  // TODO(chrishenry): Remove this check when tests that rely on this\n  // are fixed.\n  if (typeof key === 'number') {\n    return false;\n  }\n\n  var listener = key;\n  if (!listener || listener.removed) {\n    return false;\n  }\n\n  var src = listener.src;\n  if (goog.events.Listenable.isImplementedBy(src)) {\n    return /** @type {!goog.events.Listenable} */ (src).unlistenByKey(listener);\n  }\n\n  var type = listener.type;\n  var proxy = listener.proxy;\n  if (src.removeEventListener) {\n    src.removeEventListener(type, proxy, listener.capture);\n  } else if (src.detachEvent) {\n    src.detachEvent(goog.events.getOnString_(type), proxy);\n  } else if (src.addListener && src.removeListener) {\n    src.removeListener(proxy);\n  }\n  goog.events.listenerCountEstimate_--;\n\n  var listenerMap = goog.events.getListenerMap_(\n      /** @type {!EventTarget} */ (src));\n  // TODO(chrishenry): Try to remove this conditional and execute the\n  // first branch always. This should be safe.\n  if (listenerMap) {\n    listenerMap.removeByKey(listener);\n    if (listenerMap.getTypeCount() == 0) {\n      // Null the src, just because this is simple to do (and useful\n      // for IE <= 7).\n      listenerMap.src = null;\n      // We don't use delete here because IE does not allow delete\n      // on a window object.\n      src[goog.events.LISTENER_MAP_PROP_] = null;\n    }\n  } else {\n    /** @type {!goog.events.Listener} */ (listener).markAsRemoved();\n  }\n\n  return true;\n};\n\n\n/**\n * Removes an event listener which was added with listenWithWrapper().\n *\n * @param {EventTarget|goog.events.Listenable} src The target to stop\n *     listening to events on.\n * @param {goog.events.EventWrapper} wrapper Event wrapper to use.\n * @param {function(?):?|{handleEvent:function(?):?}|null} listener The\n *     listener function to remove.\n * @param {boolean=} opt_capt In DOM-compliant browsers, this determines\n *     whether the listener is fired during the capture or bubble phase of the\n *     event.\n * @param {Object=} opt_handler Element in whose scope to call the listener.\n */\ngoog.events.unlistenWithWrapper = function(\n    src, wrapper, listener, opt_capt, opt_handler) {\n  'use strict';\n  wrapper.unlisten(src, listener, opt_capt, opt_handler);\n};\n\n\n/**\n * Removes all listeners from an object. You can also optionally\n * remove listeners of a particular type.\n *\n * @param {Object|undefined} obj Object to remove listeners from. Must be an\n *     EventTarget or a goog.events.Listenable.\n * @param {string|!goog.events.EventId=} opt_type Type of event to remove.\n *     Default is all types.\n * @return {number} Number of listeners removed.\n */\ngoog.events.removeAll = function(obj, opt_type) {\n  'use strict';\n  // TODO(chrishenry): Change the type of obj to\n  // (!EventTarget|!goog.events.Listenable).\n\n  if (!obj) {\n    return 0;\n  }\n\n  if (goog.events.Listenable.isImplementedBy(obj)) {\n    return /** @type {?} */ (obj).removeAllListeners(opt_type);\n  }\n\n  var listenerMap = goog.events.getListenerMap_(\n      /** @type {!EventTarget} */ (obj));\n  if (!listenerMap) {\n    return 0;\n  }\n\n  var count = 0;\n  var typeStr = opt_type && opt_type.toString();\n  for (var type in listenerMap.listeners) {\n    if (!typeStr || type == typeStr) {\n      // Clone so that we don't need to worry about unlistenByKey\n      // changing the content of the ListenerMap.\n      var listeners = listenerMap.listeners[type].concat();\n      for (var i = 0; i < listeners.length; ++i) {\n        if (goog.events.unlistenByKey(listeners[i])) {\n          ++count;\n        }\n      }\n    }\n  }\n  return count;\n};\n\n\n/**\n * Gets the listeners for a given object, type and capture phase.\n *\n * @param {Object} obj Object to get listeners for.\n * @param {string|!goog.events.EventId} type Event type.\n * @param {boolean} capture Capture phase?.\n * @return {!Array<!goog.events.Listener>} Array of listener objects.\n */\ngoog.events.getListeners = function(obj, type, capture) {\n  'use strict';\n  if (goog.events.Listenable.isImplementedBy(obj)) {\n    return /** @type {!goog.events.Listenable} */ (obj).getListeners(\n        type, capture);\n  } else {\n    if (!obj) {\n      // TODO(chrishenry): We should tighten the API to accept\n      // !EventTarget|goog.events.Listenable, and add an assertion here.\n      return [];\n    }\n\n    var listenerMap = goog.events.getListenerMap_(\n        /** @type {!EventTarget} */ (obj));\n    return listenerMap ? listenerMap.getListeners(type, capture) : [];\n  }\n};\n\n\n/**\n * Gets the goog.events.Listener for the event or null if no such listener is\n * in use.\n *\n * @param {EventTarget|goog.events.Listenable} src The target from\n *     which to get listeners.\n * @param {?string|!goog.events.EventId<EVENTOBJ>} type The type of the event.\n * @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null} listener The\n *     listener function to get.\n * @param {boolean=} opt_capt In DOM-compliant browsers, this determines\n *                            whether the listener is fired during the\n *                            capture or bubble phase of the event.\n * @param {Object=} opt_handler Element in whose scope to call the listener.\n * @return {goog.events.ListenableKey} the found listener or null if not found.\n * @template EVENTOBJ\n */\ngoog.events.getListener = function(src, type, listener, opt_capt, opt_handler) {\n  'use strict';\n  // TODO(chrishenry): Change type from ?string to string, or add assertion.\n  type = /** @type {string} */ (type);\n  listener = goog.events.wrapListener(listener);\n  var capture = !!opt_capt;\n  if (goog.events.Listenable.isImplementedBy(src)) {\n    return src.getListener(type, listener, capture, opt_handler);\n  }\n\n  if (!src) {\n    // TODO(chrishenry): We should tighten the API to only accept\n    // non-null objects, or add an assertion here.\n    return null;\n  }\n\n  var listenerMap = goog.events.getListenerMap_(\n      /** @type {!EventTarget} */ (src));\n  if (listenerMap) {\n    return listenerMap.getListener(type, listener, capture, opt_handler);\n  }\n  return null;\n};\n\n\n/**\n * Returns whether an event target has any active listeners matching the\n * specified signature. If either the type or capture parameters are\n * unspecified, the function will match on the remaining criteria.\n *\n * @param {EventTarget|goog.events.Listenable} obj Target to get\n *     listeners for.\n * @param {string|!goog.events.EventId=} opt_type Event type.\n * @param {boolean=} opt_capture Whether to check for capture or bubble-phase\n *     listeners.\n * @return {boolean} Whether an event target has one or more listeners matching\n *     the requested type and/or capture phase.\n */\ngoog.events.hasListener = function(obj, opt_type, opt_capture) {\n  'use strict';\n  if (goog.events.Listenable.isImplementedBy(obj)) {\n    return obj.hasListener(opt_type, opt_capture);\n  }\n\n  var listenerMap = goog.events.getListenerMap_(\n      /** @type {!EventTarget} */ (obj));\n  return !!listenerMap && listenerMap.hasListener(opt_type, opt_capture);\n};\n\n\n/**\n * Provides a nice string showing the normalized event objects public members\n * @param {Object} e Event Object.\n * @return {string} String of the public members of the normalized event object.\n */\ngoog.events.expose = function(e) {\n  'use strict';\n  var str = [];\n  for (var key in e) {\n    if (e[key] && e[key].id) {\n      str.push(key + ' = ' + e[key] + ' (' + e[key].id + ')');\n    } else {\n      str.push(key + ' = ' + e[key]);\n    }\n  }\n  return str.join('\\n');\n};\n\n\n/**\n * Returns a string with on prepended to the specified type. This is used for IE\n * which expects \"on\" to be prepended. This function caches the string in order\n * to avoid extra allocations in steady state.\n * @param {string} type Event type.\n * @return {string} The type string with 'on' prepended.\n * @private\n */\ngoog.events.getOnString_ = function(type) {\n  'use strict';\n  if (type in goog.events.onStringMap_) {\n    return goog.events.onStringMap_[type];\n  }\n  return goog.events.onStringMap_[type] = goog.events.onString_ + type;\n};\n\n\n/**\n * Fires an object's listeners of a particular type and phase\n *\n * @param {Object} obj Object whose listeners to call.\n * @param {string|!goog.events.EventId} type Event type.\n * @param {boolean} capture Which event phase.\n * @param {Object} eventObject Event object to be passed to listener.\n * @return {boolean} True if all listeners returned true else false.\n */\ngoog.events.fireListeners = function(obj, type, capture, eventObject) {\n  'use strict';\n  if (goog.events.Listenable.isImplementedBy(obj)) {\n    return /** @type {!goog.events.Listenable} */ (obj).fireListeners(\n        type, capture, eventObject);\n  }\n\n  return goog.events.fireListeners_(obj, type, capture, eventObject);\n};\n\n\n/**\n * Fires an object's listeners of a particular type and phase.\n * @param {Object} obj Object whose listeners to call.\n * @param {string|!goog.events.EventId} type Event type.\n * @param {boolean} capture Which event phase.\n * @param {Object} eventObject Event object to be passed to listener.\n * @return {boolean} True if all listeners returned true else false.\n * @private\n */\ngoog.events.fireListeners_ = function(obj, type, capture, eventObject) {\n  'use strict';\n  /** @type {boolean} */\n  var retval = true;\n\n  var listenerMap = goog.events.getListenerMap_(\n      /** @type {EventTarget} */ (obj));\n  if (listenerMap) {\n    // TODO(chrishenry): Original code avoids array creation when there\n    // is no listener, so we do the same. If this optimization turns\n    // out to be not required, we can replace this with\n    // listenerMap.getListeners(type, capture) instead, which is simpler.\n    var listenerArray = listenerMap.listeners[type.toString()];\n    if (listenerArray) {\n      listenerArray = listenerArray.concat();\n      for (var i = 0; i < listenerArray.length; i++) {\n        var listener = listenerArray[i];\n        // We might not have a listener if the listener was removed.\n        if (listener && listener.capture == capture && !listener.removed) {\n          var result = goog.events.fireListener(listener, eventObject);\n          retval = retval && (result !== false);\n        }\n      }\n    }\n  }\n  return retval;\n};\n\n\n/**\n * Fires a listener with a set of arguments\n *\n * @param {goog.events.Listener} listener The listener object to call.\n * @param {Object} eventObject The event object to pass to the listener.\n * @return {*} Result of listener.\n */\ngoog.events.fireListener = function(listener, eventObject) {\n  'use strict';\n  var listenerFn = listener.listener;\n  var listenerHandler = listener.handler || listener.src;\n\n  if (listener.callOnce) {\n    goog.events.unlistenByKey(listener);\n  }\n  return listenerFn.call(listenerHandler, eventObject);\n};\n\n\n/**\n * Gets the total number of listeners currently in the system.\n * @return {number} Number of listeners.\n * @deprecated This returns estimated count, now that Closure no longer\n * stores a central listener registry. We still return an estimation\n * to keep existing listener-related tests passing. In the near future,\n * this function will be removed.\n */\ngoog.events.getTotalListenerCount = function() {\n  'use strict';\n  return goog.events.listenerCountEstimate_;\n};\n\n\n/**\n * Dispatches an event (or event like object) and calls all listeners\n * listening for events of this type. The type of the event is decided by the\n * type property on the event object.\n *\n * If any of the listeners returns false OR calls preventDefault then this\n * function will return false.  If one of the capture listeners calls\n * stopPropagation, then the bubble listeners won't fire.\n *\n * @param {goog.events.Listenable} src The event target.\n * @param {goog.events.EventLike} e Event object.\n * @return {boolean} If anyone called preventDefault on the event object (or\n *     if any of the handlers returns false) this will also return false.\n *     If there are no handlers, or if all handlers return true, this returns\n *     true.\n */\ngoog.events.dispatchEvent = function(src, e) {\n  'use strict';\n  goog.asserts.assert(\n      goog.events.Listenable.isImplementedBy(src),\n      'Can not use goog.events.dispatchEvent with ' +\n          'non-goog.events.Listenable instance.');\n  return src.dispatchEvent(e);\n};\n\n\n/**\n * Installs exception protection for the browser event entry point using the\n * given error handler.\n *\n * @param {goog.debug.ErrorHandler} errorHandler Error handler with which to\n *     protect the entry point.\n */\ngoog.events.protectBrowserEventEntryPoint = function(errorHandler) {\n  'use strict';\n  goog.events.handleBrowserEvent_ =\n      errorHandler.protectEntryPoint(goog.events.handleBrowserEvent_);\n};\n\n\n/**\n * Handles an event and dispatches it to the correct listeners. This\n * function is a proxy for the real listener the user specified.\n *\n * @param {goog.events.Listener} listener The listener object.\n * @param {Event=} opt_evt Optional event object that gets passed in via the\n *     native event handlers.\n * @return {*} Result of the event handler.\n * @this {EventTarget} The object or Element that fired the event.\n * @private\n */\ngoog.events.handleBrowserEvent_ = function(listener, opt_evt) {\n  'use strict';\n  if (listener.removed) {\n    return true;\n  }\n\n  // Otherwise, simply fire the listener.\n  return goog.events.fireListener(\n      listener, new goog.events.BrowserEvent(opt_evt, this));\n};\n\n\n/**\n * This is used to mark the IE event object so we do not do the Closure pass\n * twice for a bubbling event.\n * @param {Event} e The IE browser event.\n * @private\n */\ngoog.events.markIeEvent_ = function(e) {\n  'use strict';\n  // Only the keyCode and the returnValue can be changed. We use keyCode for\n  // non keyboard events.\n  // event.returnValue is a bit more tricky. It is undefined by default. A\n  // boolean false prevents the default action. In a window.onbeforeunload and\n  // the returnValue is non undefined it will be alerted. However, we will only\n  // modify the returnValue for keyboard events. We can get a problem if non\n  // closure events sets the keyCode or the returnValue\n\n  var useReturnValue = false;\n\n  if (e.keyCode == 0) {\n    // We cannot change the keyCode in case that srcElement is input[type=file].\n    // We could test that that is the case but that would allocate 3 objects.\n    // If we use try/catch we will only allocate extra objects in the case of a\n    // failure.\n\n    try {\n      e.keyCode = -1;\n      return;\n    } catch (ex) {\n      useReturnValue = true;\n    }\n  }\n\n  if (useReturnValue ||\n      /** @type {boolean|undefined} */ (e.returnValue) == undefined) {\n    e.returnValue = true;\n  }\n};\n\n\n/**\n * This is used to check if an IE event has already been handled by the Closure\n * system so we do not do the Closure pass twice for a bubbling event.\n * @param {Event} e  The IE browser event.\n * @return {boolean} True if the event object has been marked.\n * @private\n */\ngoog.events.isMarkedIeEvent_ = function(e) {\n  'use strict';\n  return e.keyCode < 0 || e.returnValue != undefined;\n};\n\n\n/**\n * Counter to create unique event ids.\n * @private {number}\n */\ngoog.events.uniqueIdCounter_ = 0;\n\n\n/**\n * Creates a unique event id.\n *\n * @param {string} identifier The identifier.\n * @return {string} A unique identifier.\n * @idGenerator {unique}\n */\ngoog.events.getUniqueId = function(identifier) {\n  'use strict';\n  return identifier + '_' + goog.events.uniqueIdCounter_++;\n};\n\n\n/**\n * @param {EventTarget} src The source object.\n * @return {goog.events.ListenerMap} A listener map for the given\n *     source object, or null if none exists.\n * @private\n */\ngoog.events.getListenerMap_ = function(src) {\n  'use strict';\n  var listenerMap = src[goog.events.LISTENER_MAP_PROP_];\n  // IE serializes the property as well (e.g. when serializing outer\n  // HTML). So we must check that the value is of the correct type.\n  return listenerMap instanceof goog.events.ListenerMap ? listenerMap : null;\n};\n\n\n/**\n * Expando property for listener function wrapper for Object with\n * handleEvent.\n * @private @const {string}\n */\ngoog.events.LISTENER_WRAPPER_PROP_ =\n    '__closure_events_fn_' + ((Math.random() * 1e9) >>> 0);\n\n\n/**\n * @param {Object|Function} listener The listener function or an\n *     object that contains handleEvent method.\n * @return {!Function} Either the original function or a function that\n *     calls obj.handleEvent. If the same listener is passed to this\n *     function more than once, the same function is guaranteed to be\n *     returned.\n */\ngoog.events.wrapListener = function(listener) {\n  'use strict';\n  goog.asserts.assert(listener, 'Listener can not be null.');\n\n  if (typeof listener === 'function') {\n    return listener;\n  }\n\n  goog.asserts.assert(\n      listener.handleEvent, 'An object listener must have handleEvent method.');\n  if (!listener[goog.events.LISTENER_WRAPPER_PROP_]) {\n    listener[goog.events.LISTENER_WRAPPER_PROP_] = function(e) {\n      'use strict';\n      return /** @type {?} */ (listener).handleEvent(e);\n    };\n  }\n  return listener[goog.events.LISTENER_WRAPPER_PROP_];\n};\n\n\n// Register the browser event handler as an entry point, so that\n// it can be monitored for exception handling, etc.\ngoog.debug.entryPointRegistry.register(\n    /**\n     * @param {function(!Function): !Function} transformer The transforming\n     *     function.\n     */\n    function(transformer) {\n      'use strict';\n      goog.events.handleBrowserEvent_ =\n          transformer(goog.events.handleBrowserEvent_);\n    });\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview A disposable implementation of a custom\n * listenable/event target. See also: documentation for\n * `goog.events.Listenable`.\n *\n * @see ../demos/eventtarget.html\n * @see goog.events.Listenable\n */\n\ngoog.provide('goog.events.EventTarget');\n\ngoog.require('goog.Disposable');\ngoog.require('goog.asserts');\ngoog.require('goog.events');\ngoog.require('goog.events.Event');\ngoog.require('goog.events.Listenable');\ngoog.require('goog.events.ListenerMap');\ngoog.require('goog.object');\ngoog.requireType('goog.events.EventId');\ngoog.requireType('goog.events.EventLike');\ngoog.requireType('goog.events.ListenableKey');\n\n\n\n/**\n * An implementation of `goog.events.Listenable` with full W3C\n * EventTarget-like support (capture/bubble mechanism, stopping event\n * propagation, preventing default actions).\n *\n * You may subclass this class to turn your class into a Listenable.\n *\n * Unless propagation is stopped, an event dispatched by an\n * EventTarget will bubble to the parent returned by\n * `getParentEventTarget`. To set the parent, call\n * `setParentEventTarget`. Subclasses that don't support\n * changing the parent can override the setter to throw an error.\n *\n * Example usage:\n * <pre>\n *   var source = new goog.events.EventTarget();\n *   function handleEvent(e) {\n *     alert('Type: ' + e.type + '; Target: ' + e.target);\n *   }\n *   source.listen('foo', handleEvent);\n *   // Or: goog.events.listen(source, 'foo', handleEvent);\n *   ...\n *   source.dispatchEvent('foo');  // will call handleEvent\n *   ...\n *   source.unlisten('foo', handleEvent);\n *   // Or: goog.events.unlisten(source, 'foo', handleEvent);\n * </pre>\n *\n * @constructor\n * @extends {goog.Disposable}\n * @implements {goog.events.Listenable}\n */\ngoog.events.EventTarget = function() {\n  'use strict';\n  goog.Disposable.call(this);\n\n  /**\n   * Maps of event type to an array of listeners.\n   * @private {!goog.events.ListenerMap}\n   */\n  this.eventTargetListeners_ = new goog.events.ListenerMap(this);\n\n  /**\n   * The object to use for event.target. Useful when mixing in an\n   * EventTarget to another object.\n   * @private {!Object}\n   */\n  this.actualEventTarget_ = this;\n\n  /**\n   * Parent event target, used during event bubbling.\n   *\n   * TODO(chrishenry): Change this to goog.events.Listenable. This\n   * currently breaks people who expect getParentEventTarget to return\n   * goog.events.EventTarget.\n   *\n   * @private {?goog.events.EventTarget}\n   */\n  this.parentEventTarget_ = null;\n};\ngoog.inherits(goog.events.EventTarget, goog.Disposable);\ngoog.events.Listenable.addImplementation(goog.events.EventTarget);\n\n\n/**\n * An artificial cap on the number of ancestors you can have. This is mainly\n * for loop detection.\n * @const {number}\n * @private\n */\ngoog.events.EventTarget.MAX_ANCESTORS_ = 1000;\n\n\n/**\n * Returns the parent of this event target to use for bubbling.\n *\n * @return {goog.events.EventTarget} The parent EventTarget or null if\n *     there is no parent.\n * @override\n */\ngoog.events.EventTarget.prototype.getParentEventTarget = function() {\n  'use strict';\n  return this.parentEventTarget_;\n};\n\n\n/**\n * Sets the parent of this event target to use for capture/bubble\n * mechanism.\n * @param {goog.events.EventTarget} parent Parent listenable (null if none).\n */\ngoog.events.EventTarget.prototype.setParentEventTarget = function(parent) {\n  'use strict';\n  this.parentEventTarget_ = parent;\n};\n\n\n/**\n * Adds an event listener to the event target. The same handler can only be\n * added once per the type. Even if you add the same handler multiple times\n * using the same type then it will only be called once when the event is\n * dispatched.\n *\n * @param {string|!goog.events.EventId} type The type of the event to listen for\n * @param {function(?):?|{handleEvent:function(?):?}|null} handler The function\n *     to handle the event. The handler can also be an object that implements\n *     the handleEvent method which takes the event object as argument.\n * @param {boolean=} opt_capture In DOM-compliant browsers, this determines\n *     whether the listener is fired during the capture or bubble phase\n *     of the event.\n * @param {Object=} opt_handlerScope Object in whose scope to call\n *     the listener.\n * @deprecated Use `#listen` instead, when possible. Otherwise, use\n *     `goog.events.listen` if you are passing Object\n *     (instead of Function) as handler.\n */\ngoog.events.EventTarget.prototype.addEventListener = function(\n    type, handler, opt_capture, opt_handlerScope) {\n  'use strict';\n  goog.events.listen(this, type, handler, opt_capture, opt_handlerScope);\n};\n\n\n/**\n * Removes an event listener from the event target. The handler must be the\n * same object as the one added. If the handler has not been added then\n * nothing is done.\n *\n * @param {string|!goog.events.EventId} type The type of the event to listen for\n * @param {function(?):?|{handleEvent:function(?):?}|null} handler The function\n *     to handle the event. The handler can also be an object that implements\n *     the handleEvent method which takes the event object as argument.\n * @param {boolean=} opt_capture In DOM-compliant browsers, this determines\n *     whether the listener is fired during the capture or bubble phase\n *     of the event.\n * @param {Object=} opt_handlerScope Object in whose scope to call\n *     the listener.\n * @deprecated Use `#unlisten` instead, when possible. Otherwise, use\n *     `goog.events.unlisten` if you are passing Object\n *     (instead of Function) as handler.\n */\ngoog.events.EventTarget.prototype.removeEventListener = function(\n    type, handler, opt_capture, opt_handlerScope) {\n  'use strict';\n  goog.events.unlisten(this, type, handler, opt_capture, opt_handlerScope);\n};\n\n\n/**\n * @param {?goog.events.EventLike} e Event object.\n * @return {boolean} If anyone called preventDefault on the event object (or\n *     if any of the listeners returns false) this will also return false.\n * @override\n */\ngoog.events.EventTarget.prototype.dispatchEvent = function(e) {\n  'use strict';\n  this.assertInitialized_();\n\n  var ancestorsTree, ancestor = this.getParentEventTarget();\n  if (ancestor) {\n    ancestorsTree = [];\n    var ancestorCount = 1;\n    for (; ancestor; ancestor = ancestor.getParentEventTarget()) {\n      ancestorsTree.push(ancestor);\n      goog.asserts.assert(\n          (++ancestorCount < goog.events.EventTarget.MAX_ANCESTORS_),\n          'infinite loop');\n    }\n  }\n\n  return goog.events.EventTarget.dispatchEventInternal_(\n      this.actualEventTarget_, e, ancestorsTree);\n};\n\n\n/**\n * Removes listeners from this object.  Classes that extend EventTarget may\n * need to override this method in order to remove references to DOM Elements\n * and additional listeners.\n * @override\n * @protected\n */\ngoog.events.EventTarget.prototype.disposeInternal = function() {\n  'use strict';\n  goog.events.EventTarget.superClass_.disposeInternal.call(this);\n\n  this.removeAllListeners();\n  this.parentEventTarget_ = null;\n};\n\n\n/**\n * @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id.\n * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback\n *     method.\n * @param {boolean=} opt_useCapture Whether to fire in capture phase\n *     (defaults to false).\n * @param {SCOPE=} opt_listenerScope Object in whose scope to call the\n *     listener.\n * @return {!goog.events.ListenableKey} Unique key for the listener.\n * @template SCOPE,EVENTOBJ\n * @override\n */\ngoog.events.EventTarget.prototype.listen = function(\n    type, listener, opt_useCapture, opt_listenerScope) {\n  'use strict';\n  this.assertInitialized_();\n  return this.eventTargetListeners_.add(\n      String(type), listener, false /* callOnce */, opt_useCapture,\n      opt_listenerScope);\n};\n\n\n/**\n * @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id.\n * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback\n *     method.\n * @param {boolean=} opt_useCapture Whether to fire in capture phase\n *     (defaults to false).\n * @param {SCOPE=} opt_listenerScope Object in whose scope to call the\n *     listener.\n * @return {!goog.events.ListenableKey} Unique key for the listener.\n * @template SCOPE,EVENTOBJ\n * @override\n */\ngoog.events.EventTarget.prototype.listenOnce = function(\n    type, listener, opt_useCapture, opt_listenerScope) {\n  'use strict';\n  return this.eventTargetListeners_.add(\n      String(type), listener, true /* callOnce */, opt_useCapture,\n      opt_listenerScope);\n};\n\n\n/**\n * @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id.\n * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback\n *     method.\n * @param {boolean=} opt_useCapture Whether to fire in capture phase\n *     (defaults to false).\n * @param {SCOPE=} opt_listenerScope Object in whose scope to call\n *     the listener.\n * @return {boolean} Whether any listener was removed.\n * @template SCOPE,EVENTOBJ\n * @override\n */\ngoog.events.EventTarget.prototype.unlisten = function(\n    type, listener, opt_useCapture, opt_listenerScope) {\n  'use strict';\n  return this.eventTargetListeners_.remove(\n      String(type), listener, opt_useCapture, opt_listenerScope);\n};\n\n\n/**\n * @param {!goog.events.ListenableKey} key The key returned by\n *     listen() or listenOnce().\n * @return {boolean} Whether any listener was removed.\n * @override\n */\ngoog.events.EventTarget.prototype.unlistenByKey = function(key) {\n  'use strict';\n  return this.eventTargetListeners_.removeByKey(key);\n};\n\n\n/**\n * @param {string|!goog.events.EventId=} opt_type Type of event to remove,\n *     default is to remove all types.\n * @return {number} Number of listeners removed.\n * @override\n */\ngoog.events.EventTarget.prototype.removeAllListeners = function(opt_type) {\n  'use strict';\n  // TODO(chrishenry): Previously, removeAllListeners can be called on\n  // uninitialized EventTarget, so we preserve that behavior. We\n  // should remove this when usages that rely on that fact are purged.\n  if (!this.eventTargetListeners_) {\n    return 0;\n  }\n  return this.eventTargetListeners_.removeAll(opt_type);\n};\n\n\n/**\n * @param {string|!goog.events.EventId<EVENTOBJ>} type The type of the\n *     listeners to fire.\n * @param {boolean} capture The capture mode of the listeners to fire.\n * @param {EVENTOBJ} eventObject The event object to fire.\n * @return {boolean} Whether all listeners succeeded without\n *     attempting to prevent default behavior. If any listener returns\n *     false or called goog.events.Event#preventDefault, this returns\n *     false.\n * @template EVENTOBJ\n * @override\n */\ngoog.events.EventTarget.prototype.fireListeners = function(\n    type, capture, eventObject) {\n  'use strict';\n  // TODO(chrishenry): Original code avoids array creation when there\n  // is no listener, so we do the same. If this optimization turns\n  // out to be not required, we can replace this with\n  // getListeners(type, capture) instead, which is simpler.\n  var listenerArray = this.eventTargetListeners_.listeners[String(type)];\n  if (!listenerArray) {\n    return true;\n  }\n  listenerArray = listenerArray.concat();\n\n  var rv = true;\n  for (var i = 0; i < listenerArray.length; ++i) {\n    var listener = listenerArray[i];\n    // We might not have a listener if the listener was removed.\n    if (listener && !listener.removed && listener.capture == capture) {\n      var listenerFn = listener.listener;\n      var listenerHandler = listener.handler || listener.src;\n\n      if (listener.callOnce) {\n        this.unlistenByKey(listener);\n      }\n      rv = listenerFn.call(listenerHandler, eventObject) !== false && rv;\n    }\n  }\n\n  return rv && !eventObject.defaultPrevented;\n};\n\n\n/**\n * @param {string|!goog.events.EventId} type The type of the listeners to fire.\n * @param {boolean} capture The capture mode of the listeners to fire.\n * @return {!Array<!goog.events.ListenableKey>} An array of registered\n *     listeners.\n * @template EVENTOBJ\n * @override\n */\ngoog.events.EventTarget.prototype.getListeners = function(type, capture) {\n  'use strict';\n  return this.eventTargetListeners_.getListeners(String(type), capture);\n};\n\n\n/**\n * @param {string|!goog.events.EventId<EVENTOBJ>} type The name of the event\n *     without the 'on' prefix.\n * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener The\n *     listener function to get.\n * @param {boolean} capture Whether the listener is a capturing listener.\n * @param {SCOPE=} opt_listenerScope Object in whose scope to call the\n *     listener.\n * @return {?goog.events.ListenableKey} the found listener or null if not found.\n * @template SCOPE,EVENTOBJ\n * @override\n */\ngoog.events.EventTarget.prototype.getListener = function(\n    type, listener, capture, opt_listenerScope) {\n  'use strict';\n  return this.eventTargetListeners_.getListener(\n      String(type), listener, capture, opt_listenerScope);\n};\n\n\n/**\n * @param {string|!goog.events.EventId<EVENTOBJ>=} opt_type Event type.\n * @param {boolean=} opt_capture Whether to check for capture or bubble\n *     listeners.\n * @return {boolean} Whether there is any active listeners matching\n *     the requested type and/or capture phase.\n * @template EVENTOBJ\n * @override\n */\ngoog.events.EventTarget.prototype.hasListener = function(\n    opt_type, opt_capture) {\n  'use strict';\n  var id = (opt_type !== undefined) ? String(opt_type) : undefined;\n  return this.eventTargetListeners_.hasListener(id, opt_capture);\n};\n\n\n/**\n * Sets the target to be used for `event.target` when firing\n * event. Mainly used for testing. For example, see\n * `goog.testing.events.mixinListenable`.\n * @param {!Object} target The target.\n */\ngoog.events.EventTarget.prototype.setTargetForTesting = function(target) {\n  'use strict';\n  this.actualEventTarget_ = target;\n};\n\n\n/**\n * Asserts that the event target instance is initialized properly.\n * @private\n */\ngoog.events.EventTarget.prototype.assertInitialized_ = function() {\n  'use strict';\n  goog.asserts.assert(\n      this.eventTargetListeners_,\n      'Event target is not initialized. Did you call the superclass ' +\n          '(goog.events.EventTarget) constructor?');\n};\n\n\n/**\n * Dispatches the given event on the ancestorsTree.\n *\n * @param {!Object} target The target to dispatch on.\n * @param {goog.events.Event|Object|string} e The event object.\n * @param {Array<goog.events.Listenable>=} opt_ancestorsTree The ancestors\n *     tree of the target, in reverse order from the closest ancestor\n *     to the root event target. May be null if the target has no ancestor.\n * @return {boolean} If anyone called preventDefault on the event object (or\n *     if any of the listeners returns false) this will also return false.\n * @private\n */\ngoog.events.EventTarget.dispatchEventInternal_ = function(\n    target, e, opt_ancestorsTree) {\n  'use strict';\n  /** @suppress {missingProperties} */\n  var type = e.type || /** @type {string} */ (e);\n\n  // If accepting a string or object, create a custom event object so that\n  // preventDefault and stopPropagation work with the event.\n  if (typeof e === 'string') {\n    e = new goog.events.Event(e, target);\n  } else if (!(e instanceof goog.events.Event)) {\n    var oldEvent = e;\n    e = new goog.events.Event(type, target);\n    goog.object.extend(e, oldEvent);\n  } else {\n    e.target = e.target || target;\n  }\n\n  var rv = true, currentTarget;\n\n  // Executes all capture listeners on the ancestors, if any.\n  if (opt_ancestorsTree) {\n    for (var i = opt_ancestorsTree.length - 1;\n         !e.hasPropagationStopped() && i >= 0; i--) {\n      currentTarget = e.currentTarget = opt_ancestorsTree[i];\n      rv = currentTarget.fireListeners(type, true, e) && rv;\n    }\n  }\n\n  // Executes capture and bubble listeners on the target.\n  if (!e.hasPropagationStopped()) {\n    currentTarget = /** @type {?} */ (e.currentTarget = target);\n    rv = currentTarget.fireListeners(type, true, e) && rv;\n    if (!e.hasPropagationStopped()) {\n      rv = currentTarget.fireListeners(type, false, e) && rv;\n    }\n  }\n\n  // Executes all bubble listeners on the ancestors, if any.\n  if (opt_ancestorsTree) {\n    for (i = 0; !e.hasPropagationStopped() && i < opt_ancestorsTree.length;\n         i++) {\n      currentTarget = e.currentTarget = opt_ancestorsTree[i];\n      rv = currentTarget.fireListeners(type, false, e) && rv;\n    }\n  }\n\n  return rv;\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview JSON utility functions.\n */\n\n\ngoog.provide('goog.json');\ngoog.provide('goog.json.Replacer');\ngoog.provide('goog.json.Reviver');\ngoog.provide('goog.json.Serializer');\n\n\n/**\n * @define {boolean} If true, use the native JSON parsing API.\n * NOTE: The default `goog.json.parse` implementation is able to handle\n * invalid JSON. JSPB used to produce invalid JSON which is not the case\n * anymore so this is safe to enable for parsing JSPB. Using native JSON is\n * faster and safer than the default implementation using `eval`.\n */\ngoog.json.USE_NATIVE_JSON = goog.define('goog.json.USE_NATIVE_JSON', false);\n\n/**\n * @define {boolean} If true, try the native JSON parsing API first. If it\n * fails, log an error and use `eval` instead. This is useful when\n * transitioning to `goog.json.USE_NATIVE_JSON`. The error logger needs to\n * be set by `goog.json.setErrorLogger`. If it is not set then the error\n * is ignored.\n */\ngoog.json.TRY_NATIVE_JSON = goog.define('goog.json.TRY_NATIVE_JSON', true);\n\n\n/**\n * Tests if a string is an invalid JSON string. This only ensures that we are\n * not using any invalid characters\n * @param {string} s The string to test.\n * @return {boolean} True if the input is a valid JSON string.\n */\ngoog.json.isValid = function(s) {\n  'use strict';\n  // All empty whitespace is not valid.\n  if (/^\\s*$/.test(s)) {\n    return false;\n  }\n\n  // This is taken from http://www.json.org/json2.js which is released to the\n  // public domain.\n  // Changes: We dissallow \\u2028 Line separator and \\u2029 Paragraph separator\n  // inside strings.  We also treat \\u2028 and \\u2029 as whitespace which they\n  // are in the RFC but IE and Safari does not match \\s to these so we need to\n  // include them in the reg exps in all places where whitespace is allowed.\n  // We allowed \\x7f inside strings because some tools don't escape it,\n  // e.g. http://www.json.org/java/org/json/JSONObject.java\n\n  // Parsing happens in three stages. In the first stage, we run the text\n  // against regular expressions that look for non-JSON patterns. We are\n  // especially concerned with '()' and 'new' because they can cause invocation,\n  // and '=' because it can cause mutation. But just to be safe, we want to\n  // reject all unexpected forms.\n\n  // We split the first stage into 4 regexp operations in order to work around\n  // crippling inefficiencies in IE's and Safari's regexp engines. First we\n  // replace all backslash pairs with '@' (a non-JSON character). Second, we\n  // replace all simple value tokens with ']' characters, but only when followed\n  // by a colon, comma, closing bracket or end of string. Third, we delete all\n  // open brackets that follow a colon or comma or that begin the text. Finally,\n  // we look to see that the remaining characters are only whitespace or ']' or\n  // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.\n\n  // Don't make these static since they have the global flag.\n  const backslashesRe = /\\\\[\"\\\\\\/bfnrtu]/g;\n  const simpleValuesRe =\n      /(?:\"[^\"\\\\\\n\\r\\u2028\\u2029\\x00-\\x08\\x0a-\\x1f]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?)[\\s\\u2028\\u2029]*(?=:|,|]|}|$)/g;\n  const openBracketsRe = /(?:^|:|,)(?:[\\s\\u2028\\u2029]*\\[)+/g;\n  const remainderRe = /^[\\],:{}\\s\\u2028\\u2029]*$/;\n\n  return remainderRe.test(\n      s.replace(backslashesRe, '@')\n          .replace(simpleValuesRe, ']')\n          .replace(openBracketsRe, ''));\n};\n\n/**\n * Logs a parsing error in `JSON.parse` solvable by using `eval`\n * if `goog.json.TRY_NATIVE_JSON` is enabled.\n * @private {function(string, !Error)} The first parameter is the error message,\n *     the second is the exception thrown by `JSON.parse`.\n */\ngoog.json.errorLogger_ = goog.nullFunction;\n\n\n/**\n * Sets an error logger to use if there's a recoverable parsing error and\n * `goog.json.TRY_NATIVE_JSON` is enabled.\n * @param {function(string, !Error)} errorLogger The first parameter is the\n *     error message, the second is the exception thrown by `JSON.parse`.\n */\ngoog.json.setErrorLogger = function(errorLogger) {\n  'use strict';\n  goog.json.errorLogger_ = errorLogger;\n};\n\n\n/**\n * Parses a JSON string and returns the result. This throws an exception if\n * the string is an invalid JSON string.\n *\n * Note that this is very slow on large strings. Use JSON.parse if possible.\n *\n * @param {*} s The JSON string to parse.\n * @throws Error if s is invalid JSON.\n * @return {Object} The object generated from the JSON string, or null.\n * @deprecated Use JSON.parse.\n */\ngoog.json.parse = goog.json.USE_NATIVE_JSON ?\n    /** @type {function(*):Object} */ (goog.global['JSON']['parse']) :\n    function(s) {\n      'use strict';\n      let error;\n      if (goog.json.TRY_NATIVE_JSON) {\n        try {\n          return goog.global['JSON']['parse'](s);\n        } catch (ex) {\n          error = ex;\n        }\n      }\n      const o = String(s);\n      if (goog.json.isValid(o)) {\n\n        try {\n          const result = /** @type {?Object} */ (eval('(' + o + ')'));\n          if (error) {\n            goog.json.errorLogger_('Invalid JSON: ' + o, error);\n          }\n          return result;\n        } catch (ex) {\n        }\n      }\n      throw new Error('Invalid JSON string: ' + o);\n    };\n\n\n/**\n * JSON replacer, as defined in Section 15.12.3 of the ES5 spec.\n * @see http://ecma-international.org/ecma-262/5.1/#sec-15.12.3\n *\n * TODO(nicksantos): Array should also be a valid replacer.\n *\n * @typedef {function(this:Object, string, *): *}\n */\ngoog.json.Replacer;\n\n\n/**\n * JSON reviver, as defined in Section 15.12.2 of the ES5 spec.\n * @see http://ecma-international.org/ecma-262/5.1/#sec-15.12.3\n *\n * @typedef {function(this:Object, string, *): *}\n */\ngoog.json.Reviver;\n\n\n/**\n * Serializes an object or a value to a JSON string.\n *\n * @param {*} object The object to serialize.\n * @param {?goog.json.Replacer=} opt_replacer A replacer function\n *     called for each (key, value) pair that determines how the value\n *     should be serialized. By defult, this just returns the value\n *     and allows default serialization to kick in.\n * @throws Error if there are loops in the object graph.\n * @return {string} A JSON string representation of the input.\n */\ngoog.json.serialize = goog.json.USE_NATIVE_JSON ?\n    /** @type {function(*, ?goog.json.Replacer=):string} */\n    (goog.global['JSON']['stringify']) :\n    function(object, opt_replacer) {\n      'use strict';\n      // NOTE(nicksantos): Currently, we never use JSON.stringify.\n      //\n      // The last time I evaluated this, JSON.stringify had subtle bugs and\n      // behavior differences on all browsers, and the performance win was not\n      // large enough to justify all the issues. This may change in the future\n      // as browser implementations get better.\n      //\n      // assertSerialize in json_test contains if branches for the cases\n      // that fail.\n      return new goog.json.Serializer(opt_replacer).serialize(object);\n    };\n\n\n\n/**\n * Class that is used to serialize JSON objects to a string.\n * @param {?goog.json.Replacer=} opt_replacer Replacer.\n * @constructor\n */\ngoog.json.Serializer = function(opt_replacer) {\n  'use strict';\n  /**\n   * @type {goog.json.Replacer|null|undefined}\n   * @private\n   */\n  this.replacer_ = opt_replacer;\n};\n\n\n/**\n * Serializes an object or a value to a JSON string.\n *\n * @param {*} object The object to serialize.\n * @throws Error if there are loops in the object graph.\n * @return {string} A JSON string representation of the input.\n */\ngoog.json.Serializer.prototype.serialize = function(object) {\n  'use strict';\n  const sb = [];\n  this.serializeInternal(object, sb);\n  return sb.join('');\n};\n\n\n/**\n * Serializes a generic value to a JSON string\n * @protected\n * @param {*} object The object to serialize.\n * @param {Array<string>} sb Array used as a string builder.\n * @throws Error if there are loops in the object graph.\n */\ngoog.json.Serializer.prototype.serializeInternal = function(object, sb) {\n  'use strict';\n  if (object == null) {\n    // undefined == null so this branch covers undefined as well as null\n    sb.push('null');\n    return;\n  }\n\n  if (typeof object == 'object') {\n    if (Array.isArray(object)) {\n      this.serializeArray(object, sb);\n      return;\n    } else if (\n        object instanceof String || object instanceof Number ||\n        object instanceof Boolean) {\n      object = object.valueOf();\n      // Fall through to switch below.\n    } else {\n      this.serializeObject_(/** @type {!Object} */ (object), sb);\n      return;\n    }\n  }\n\n  switch (typeof object) {\n    case 'string':\n      this.serializeString_(object, sb);\n      break;\n    case 'number':\n      this.serializeNumber_(object, sb);\n      break;\n    case 'boolean':\n      sb.push(String(object));\n      break;\n    case 'function':\n      sb.push('null');\n      break;\n    default:\n      throw new Error('Unknown type: ' + typeof object);\n  }\n};\n\n\n/**\n * Character mappings used internally for goog.string.quote\n * @private\n * @type {!Object}\n */\ngoog.json.Serializer.charToJsonCharCache_ = {\n  '\\\"': '\\\\\"',\n  '\\\\': '\\\\\\\\',\n  '/': '\\\\/',\n  '\\b': '\\\\b',\n  '\\f': '\\\\f',\n  '\\n': '\\\\n',\n  '\\r': '\\\\r',\n  '\\t': '\\\\t',\n\n  '\\x0B': '\\\\u000b'  // '\\v' is not supported in JScript\n};\n\n\n/**\n * Regular expression used to match characters that need to be replaced.\n * The S60 browser has a bug where unicode characters are not matched by\n * regular expressions. The condition below detects such behaviour and\n * adjusts the regular expression accordingly.\n * @private\n * @type {!RegExp}\n */\ngoog.json.Serializer.charsToReplace_ = /\\uffff/.test('\\uffff') ?\n    /[\\\\\\\"\\x00-\\x1f\\x7f-\\uffff]/g :\n    /[\\\\\\\"\\x00-\\x1f\\x7f-\\xff]/g;\n\n\n/**\n * Serializes a string to a JSON string\n * @private\n * @param {string} s The string to serialize.\n * @param {Array<string>} sb Array used as a string builder.\n */\ngoog.json.Serializer.prototype.serializeString_ = function(s, sb) {\n  'use strict';\n  // The official JSON implementation does not work with international\n  // characters.\n  sb.push('\"', s.replace(goog.json.Serializer.charsToReplace_, function(c) {\n    'use strict';\n    // caching the result improves performance by a factor 2-3\n    let rv = goog.json.Serializer.charToJsonCharCache_[c];\n    if (!rv) {\n      rv = '\\\\u' + (c.charCodeAt(0) | 0x10000).toString(16).substr(1);\n      goog.json.Serializer.charToJsonCharCache_[c] = rv;\n    }\n    return rv;\n  }), '\"');\n};\n\n\n/**\n * Serializes a number to a JSON string\n * @private\n * @param {number} n The number to serialize.\n * @param {Array<string>} sb Array used as a string builder.\n */\ngoog.json.Serializer.prototype.serializeNumber_ = function(n, sb) {\n  'use strict';\n  sb.push(isFinite(n) && !isNaN(n) ? String(n) : 'null');\n};\n\n\n/**\n * Serializes an array to a JSON string\n * @param {Array<string>} arr The array to serialize.\n * @param {Array<string>} sb Array used as a string builder.\n * @protected\n */\ngoog.json.Serializer.prototype.serializeArray = function(arr, sb) {\n  'use strict';\n  const l = arr.length;\n  sb.push('[');\n  let sep = '';\n  for (let i = 0; i < l; i++) {\n    sb.push(sep);\n\n    const value = arr[i];\n    this.serializeInternal(\n        this.replacer_ ? this.replacer_.call(arr, String(i), value) : value,\n        sb);\n\n    sep = ',';\n  }\n  sb.push(']');\n};\n\n\n/**\n * Serializes an object to a JSON string\n * @private\n * @param {!Object} obj The object to serialize.\n * @param {Array<string>} sb Array used as a string builder.\n */\ngoog.json.Serializer.prototype.serializeObject_ = function(obj, sb) {\n  'use strict';\n  sb.push('{');\n  let sep = '';\n  for (const key in obj) {\n    if (Object.prototype.hasOwnProperty.call(obj, key)) {\n      const value = obj[key];\n      // Skip functions.\n      if (typeof value != 'function') {\n        sb.push(sep);\n        this.serializeString_(key, sb);\n        sb.push(':');\n\n        this.serializeInternal(\n            this.replacer_ ? this.replacer_.call(obj, key, value) : value, sb);\n\n        sep = ',';\n      }\n    }\n  }\n  sb.push('}');\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\ngoog.module('goog.async.WorkQueue');\ngoog.module.declareLegacyNamespace();\n\nconst FreeList = goog.require('goog.async.FreeList');\nconst {assert} = goog.require('goog.asserts');\n\n// TODO(johnlenz): generalize the WorkQueue if this is used by more\n// than goog.async.run.\n\n\n/**\n * A low GC workqueue. The key elements of this design:\n *   - avoids the need for goog.bind or equivalent by carrying scope\n *   - avoids the need for array reallocation by using a linked list\n *   - minimizes work entry objects allocation by recycling objects\n * @final\n * @struct\n */\nclass WorkQueue {\n  constructor() {\n    this.workHead_ = null;\n    this.workTail_ = null;\n  }\n\n  /**\n   * @param {function()} fn\n   * @param {Object|null|undefined} scope\n   */\n  add(fn, scope) {\n    const item = this.getUnusedItem_();\n    item.set(fn, scope);\n\n    if (this.workTail_) {\n      this.workTail_.next = item;\n      this.workTail_ = item;\n    } else {\n      assert(!this.workHead_);\n      this.workHead_ = item;\n      this.workTail_ = item;\n    }\n  }\n\n  /**\n   * @return {?WorkItem}\n   */\n  remove() {\n    let item = null;\n\n    if (this.workHead_) {\n      item = this.workHead_;\n      this.workHead_ = this.workHead_.next;\n      if (!this.workHead_) {\n        this.workTail_ = null;\n      }\n      item.next = null;\n    }\n    return item;\n  }\n\n  /**\n   * @param {!WorkItem} item\n   */\n  returnUnused(item) {\n    WorkQueue.freelist_.put(item);\n  }\n\n  /**\n   * @return {!WorkItem}\n   * @private\n   */\n  getUnusedItem_() {\n    return WorkQueue.freelist_.get();\n  }\n}\n\n/** @define {number} The maximum number of entries to keep for recycling. */\nWorkQueue.DEFAULT_MAX_UNUSED =\n    goog.define('goog.async.WorkQueue.DEFAULT_MAX_UNUSED', 100);\n\n/** @const @private {!FreeList<!WorkItem>} */\nWorkQueue.freelist_ = new FreeList(\n    () => new WorkItem(), item => item.reset(), WorkQueue.DEFAULT_MAX_UNUSED);\n\n/**\n * @final\n * @struct\n */\nclass WorkItem {\n  constructor() {\n    /** @type {?function()} */\n    this.fn = null;\n    /** @type {?Object|null|undefined} */\n    this.scope = null;\n    /** @type {?WorkItem} */\n    this.next = null;\n  }\n\n  /**\n   * @param {function()} fn\n   * @param {Object|null|undefined} scope\n   */\n  set(fn, scope) {\n    'use strict';\n    this.fn = fn;\n    this.scope = scope;\n    this.next = null;\n  }\n\n  /** Reset the work item so they don't prevent GC before reuse */\n  reset() {\n    this.fn = null;\n    this.scope = null;\n    this.next = null;\n  }\n}\n\nexports = WorkQueue;\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\ngoog.provide('goog.async.run');\n\ngoog.require('goog.async.WorkQueue');\ngoog.require('goog.async.nextTick');\ngoog.require('goog.async.throwException');\n\n/**\n * @define {boolean} If true, use the global Promise to implement goog.async.run\n * assuming either the native, or polyfill version will be used. Does still\n * permit tests to use forceNextTick.\n */\ngoog.ASSUME_NATIVE_PROMISE = goog.define('goog.ASSUME_NATIVE_PROMISE', false);\n\n/**\n * Fires the provided callback just before the current callstack unwinds, or as\n * soon as possible after the current JS execution context.\n * @param {function(this:THIS)} callback\n * @param {THIS=} opt_context Object to use as the \"this value\" when calling\n *     the provided function.\n * @template THIS\n */\ngoog.async.run = function(callback, opt_context) {\n  'use strict';\n  if (!goog.async.run.schedule_) {\n    goog.async.run.initializeRunner_();\n  }\n  if (!goog.async.run.workQueueScheduled_) {\n    // Nothing is currently scheduled, schedule it now.\n    goog.async.run.schedule_();\n    goog.async.run.workQueueScheduled_ = true;\n  }\n\n  goog.async.run.workQueue_.add(callback, opt_context);\n};\n\n\n/**\n * Initializes the function to use to process the work queue.\n * @private\n */\ngoog.async.run.initializeRunner_ = function() {\n  'use strict';\n  if (goog.ASSUME_NATIVE_PROMISE ||\n      (goog.global.Promise && goog.global.Promise.resolve)) {\n    // Use goog.global.Promise instead of just Promise because the relevant\n    // externs may be missing, and don't alias it because this could confuse the\n    // compiler into thinking the polyfill is required when it should be treated\n    // as optional.\n    var promise = goog.global.Promise.resolve(undefined);\n    goog.async.run.schedule_ = function() {\n      'use strict';\n      promise.then(goog.async.run.processWorkQueue);\n    };\n  } else {\n    goog.async.run.schedule_ = function() {\n      'use strict';\n      goog.async.nextTick(goog.async.run.processWorkQueue);\n    };\n  }\n};\n\n\n/**\n * Forces goog.async.run to use nextTick instead of Promise.\n *\n * This should only be done in unit tests. It's useful because MockClock\n * replaces nextTick, but not the browser Promise implementation, so it allows\n * Promise-based code to be tested with MockClock.\n *\n * However, we also want to run promises if the MockClock is no longer in\n * control so we schedule a backup \"setTimeout\" to the unmocked timeout if\n * provided.\n *\n * @param {function(function())=} opt_realSetTimeout\n */\ngoog.async.run.forceNextTick = function(opt_realSetTimeout) {\n  'use strict';\n  goog.async.run.schedule_ = function() {\n    'use strict';\n    goog.async.nextTick(goog.async.run.processWorkQueue);\n    if (opt_realSetTimeout) {\n      opt_realSetTimeout(goog.async.run.processWorkQueue);\n    }\n  };\n};\n\n\n/**\n * The function used to schedule work asynchronousely.\n * @private {function()}\n */\ngoog.async.run.schedule_;\n\n\n/** @private {boolean} */\ngoog.async.run.workQueueScheduled_ = false;\n\n\n/** @private {!goog.async.WorkQueue} */\ngoog.async.run.workQueue_ = new goog.async.WorkQueue();\n\n\nif (goog.DEBUG) {\n  /**\n   * Reset the work queue. Only available for tests in debug mode.\n   */\n  goog.async.run.resetQueue = function() {\n    'use strict';\n    goog.async.run.workQueueScheduled_ = false;\n    goog.async.run.workQueue_ = new goog.async.WorkQueue();\n  };\n\n\n  /**\n   * Resets the scheduler. Only available for tests in debug mode.\n   */\n  goog.async.run.resetSchedulerForTest = function() {\n    goog.async.run.initializeRunner_();\n  };\n}\n\n\n/**\n * Run any pending goog.async.run work items. This function is not intended\n * for general use, but for use by entry point handlers to run items ahead of\n * goog.async.nextTick.\n */\ngoog.async.run.processWorkQueue = function() {\n  'use strict';\n  // NOTE: additional work queue items may be added while processing.\n  var item = null;\n  while (item = goog.async.run.workQueue_.remove()) {\n    try {\n      item.fn.call(item.scope);\n    } catch (e) {\n      goog.async.throwException(e);\n    }\n    goog.async.run.workQueue_.returnUnused(item);\n  }\n\n  // There are no more work items, allow processing to be scheduled again.\n  goog.async.run.workQueueScheduled_ = false;\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Simple freelist.\n *\n * An anterative to goog.structs.SimplePool, it imposes the requirement that the\n * objects in the list contain a \"next\" property that can be used to maintain\n * the pool.\n */\n\ngoog.provide('goog.async.FreeList');\n\n\n/**\n * @template ITEM\n */\ngoog.async.FreeList = class {\n  /**\n   * @param {function():ITEM} create\n   * @param {function(ITEM):void} reset\n   * @param {number} limit\n   */\n  constructor(create, reset, limit) {\n    /** @private @const {number} */\n    this.limit_ = limit;\n    /** @private @const {function()} */\n    this.create_ = create;\n    /** @private @const {function(ITEM):void} */\n    this.reset_ = reset;\n\n    /** @private {number} */\n    this.occupants_ = 0;\n    /** @private {ITEM} */\n    this.head_ = null;\n  }\n\n  /**\n   * @return {ITEM}\n   */\n  get() {\n    let item;\n    if (this.occupants_ > 0) {\n      this.occupants_--;\n      item = this.head_;\n      this.head_ = item.next;\n      item.next = null;\n    } else {\n      item = this.create_();\n    }\n    return item;\n  }\n\n  /**\n   * @param {ITEM} item An item available for possible future reuse.\n   */\n  put(item) {\n    this.reset_(item);\n    if (this.occupants_ < this.limit_) {\n      this.occupants_++;\n      item.next = this.head_;\n      this.head_ = item;\n    }\n  }\n\n  /**\n   * Visible for testing.\n   * @package\n   * @return {number}\n   */\n  occupants() {\n    return this.occupants_;\n  }\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Provides a function to throw an error without interrupting\n * the current execution context.\n */\n\ngoog.module('goog.async.throwException');\ngoog.module.declareLegacyNamespace();\n\n/**\n * Throw an item without interrupting the current execution context.  For\n * example, if processing a group of items in a loop, sometimes it is useful\n * to report an error while still allowing the rest of the batch to be\n * processed.\n * @param {*} exception\n */\nfunction throwException(exception) {\n  // Each throw needs to be in its own context.\n  goog.global.setTimeout(() => {\n    throw exception;\n  }, 0);\n}\nexports = throwException;\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview A timer class to which other classes and objects can listen on.\n * This is only an abstraction above `setInterval`.\n *\n * @see ../demos/timers.html\n */\n\ngoog.provide('goog.Timer');\n\ngoog.require('goog.Promise');\ngoog.require('goog.events.EventTarget');\ngoog.requireType('goog.Thenable');\n\n\n\n/**\n * Class for handling timing events.\n *\n * @param {number=} opt_interval Number of ms between ticks (default: 1ms).\n * @param {Object=} opt_timerObject  An object that has `setTimeout`,\n *     `setInterval`, `clearTimeout` and `clearInterval`\n *     (e.g., `window`).\n * @constructor\n * @extends {goog.events.EventTarget}\n */\ngoog.Timer = function(opt_interval, opt_timerObject) {\n  'use strict';\n  goog.events.EventTarget.call(this);\n\n  /**\n   * Number of ms between ticks\n   * @private {number}\n   */\n  this.interval_ = opt_interval || 1;\n\n  /**\n   * An object that implements `setTimeout`, `setInterval`,\n   * `clearTimeout` and `clearInterval`. We default to the window\n   * object. Changing this on {@link goog.Timer.prototype} changes the object\n   * for all timer instances which can be useful if your environment has some\n   * other implementation of timers than the `window` object.\n   * @private {{setTimeout:!Function, clearTimeout:!Function}}\n   */\n  this.timerObject_ = /** @type {{setTimeout, clearTimeout}} */ (\n      opt_timerObject || goog.Timer.defaultTimerObject);\n\n  /**\n   * Cached `tick_` bound to the object for later use in the timer.\n   * @private {Function}\n   * @const\n   */\n  this.boundTick_ = goog.bind(this.tick_, this);\n\n  /**\n   * Firefox browser often fires the timer event sooner (sometimes MUCH sooner)\n   * than the requested timeout. So we compare the time to when the event was\n   * last fired, and reschedule if appropriate. See also\n   * {@link goog.Timer.intervalScale}.\n   * @private {number}\n   */\n  this.last_ = goog.now();\n};\ngoog.inherits(goog.Timer, goog.events.EventTarget);\n\n\n/**\n * Maximum timeout value.\n *\n * Timeout values too big to fit into a signed 32-bit integer may cause overflow\n * in FF, Safari, and Chrome, resulting in the timeout being scheduled\n * immediately. It makes more sense simply not to schedule these timeouts, since\n * 24.8 days is beyond a reasonable expectation for the browser to stay open.\n *\n * @private {number}\n * @const\n */\ngoog.Timer.MAX_TIMEOUT_ = 2147483647;\n\n\n/**\n * A timer ID that cannot be returned by any known implementation of\n * `window.setTimeout`. Passing this value to `window.clearTimeout`\n * should therefore be a no-op.\n *\n * @private {number}\n * @const\n */\ngoog.Timer.INVALID_TIMEOUT_ID_ = -1;\n\n\n/**\n * Whether this timer is enabled\n * @type {boolean}\n */\ngoog.Timer.prototype.enabled = false;\n\n\n/**\n * An object that implements `setTimeout`, `setInterval`,\n * `clearTimeout` and `clearInterval`. We default to the global\n * object. Changing `goog.Timer.defaultTimerObject` changes the object for\n * all timer instances which can be useful if your environment has some other\n * implementation of timers you'd like to use.\n * @type {{setTimeout, clearTimeout}}\n */\ngoog.Timer.defaultTimerObject = goog.global;\n\n\n/**\n * Variable that controls the timer error correction. If the timer is called\n * before the requested interval times `intervalScale`, which often\n * happens on Mozilla, the timer is rescheduled.\n * @see {@link #last_}\n * @type {number}\n */\ngoog.Timer.intervalScale = 0.8;\n\n\n/**\n * Variable for storing the result of `setInterval`.\n * @private {?number}\n */\ngoog.Timer.prototype.timer_ = null;\n\n\n/**\n * Gets the interval of the timer.\n * @return {number} interval Number of ms between ticks.\n */\ngoog.Timer.prototype.getInterval = function() {\n  'use strict';\n  return this.interval_;\n};\n\n\n/**\n * Sets the interval of the timer.\n * @param {number} interval Number of ms between ticks.\n */\ngoog.Timer.prototype.setInterval = function(interval) {\n  'use strict';\n  this.interval_ = interval;\n  if (this.timer_ && this.enabled) {\n    // Stop and then start the timer to reset the interval.\n    this.stop();\n    this.start();\n  } else if (this.timer_) {\n    this.stop();\n  }\n};\n\n\n/**\n * Callback for the `setTimeout` used by the timer.\n * @private\n */\ngoog.Timer.prototype.tick_ = function() {\n  'use strict';\n  if (this.enabled) {\n    var elapsed = goog.now() - this.last_;\n    if (elapsed > 0 && elapsed < this.interval_ * goog.Timer.intervalScale) {\n      this.timer_ = this.timerObject_.setTimeout(\n          this.boundTick_, this.interval_ - elapsed);\n      return;\n    }\n\n    // Prevents setInterval from registering a duplicate timeout when called\n    // in the timer event handler.\n    if (this.timer_) {\n      this.timerObject_.clearTimeout(this.timer_);\n      this.timer_ = null;\n    }\n\n    this.dispatchTick();\n    // The timer could be stopped in the timer event handler.\n    if (this.enabled) {\n      // Stop and start to ensure there is always only one timeout even if\n      // start is called in the timer event handler.\n      this.stop();\n      this.start();\n    }\n  }\n};\n\n\n/**\n * Dispatches the TICK event. This is its own method so subclasses can override.\n */\ngoog.Timer.prototype.dispatchTick = function() {\n  'use strict';\n  this.dispatchEvent(goog.Timer.TICK);\n};\n\n\n/**\n * Starts the timer.\n */\ngoog.Timer.prototype.start = function() {\n  'use strict';\n  this.enabled = true;\n\n  // If there is no interval already registered, start it now\n  if (!this.timer_) {\n    // IMPORTANT!\n    // window.setInterval in FireFox has a bug - it fires based on\n    // absolute time, rather than on relative time. What this means\n    // is that if a computer is sleeping/hibernating for 24 hours\n    // and the timer interval was configured to fire every 1000ms,\n    // then after the PC wakes up the timer will fire, in rapid\n    // succession, 3600*24 times.\n    // This bug is described here and is already fixed, but it will\n    // take time to propagate, so for now I am switching this over\n    // to setTimeout logic.\n    //     https://bugzilla.mozilla.org/show_bug.cgi?id=376643\n    //\n    this.timer_ = this.timerObject_.setTimeout(this.boundTick_, this.interval_);\n    this.last_ = goog.now();\n  }\n};\n\n\n/**\n * Stops the timer.\n */\ngoog.Timer.prototype.stop = function() {\n  'use strict';\n  this.enabled = false;\n  if (this.timer_) {\n    this.timerObject_.clearTimeout(this.timer_);\n    this.timer_ = null;\n  }\n};\n\n\n/** @override */\ngoog.Timer.prototype.disposeInternal = function() {\n  'use strict';\n  goog.Timer.superClass_.disposeInternal.call(this);\n  this.stop();\n  delete this.timerObject_;\n};\n\n\n/**\n * Constant for the timer's event type.\n * @const\n */\ngoog.Timer.TICK = 'tick';\n\n\n/**\n * Calls the given function once, after the optional pause.\n * <p>\n * The function is always called asynchronously, even if the delay is 0. This\n * is a common trick to schedule a function to run after a batch of browser\n * event processing.\n *\n * @param {function(this:SCOPE)|{handleEvent:function()}|null} listener Function\n *     or object that has a handleEvent method.\n * @param {number=} opt_delay Milliseconds to wait; default is 0.\n * @param {SCOPE=} opt_handler Object in whose scope to call the listener.\n * @return {number} A handle to the timer ID.\n * @template SCOPE\n */\ngoog.Timer.callOnce = function(listener, opt_delay, opt_handler) {\n  'use strict';\n  if (typeof listener === 'function') {\n    if (opt_handler) {\n      listener = goog.bind(listener, opt_handler);\n    }\n  } else if (listener && typeof listener.handleEvent == 'function') {\n    // using typeof to prevent strict js warning\n    listener = goog.bind(listener.handleEvent, listener);\n  } else {\n    throw new Error('Invalid listener argument');\n  }\n\n  if (Number(opt_delay) > goog.Timer.MAX_TIMEOUT_) {\n    // Timeouts greater than MAX_INT return immediately due to integer\n    // overflow in many browsers.  Since MAX_INT is 24.8 days, just don't\n    // schedule anything at all.\n    return goog.Timer.INVALID_TIMEOUT_ID_;\n  } else {\n    return goog.Timer.defaultTimerObject.setTimeout(listener, opt_delay || 0);\n  }\n};\n\n\n/**\n * Clears a timeout initiated by {@link #callOnce}.\n * @param {?number} timerId A timer ID.\n */\ngoog.Timer.clear = function(timerId) {\n  'use strict';\n  goog.Timer.defaultTimerObject.clearTimeout(timerId);\n};\n\n\n/**\n * @param {number} delay Milliseconds to wait.\n * @param {(RESULT|goog.Thenable<RESULT>|Thenable)=} opt_result The value\n *     with which the promise will be resolved.\n * @return {!goog.Promise<RESULT>} A promise that will be resolved after\n *     the specified delay, unless it is canceled first.\n * @template RESULT\n */\ngoog.Timer.promise = function(delay, opt_result) {\n  'use strict';\n  var timerKey = null;\n  return new goog\n      .Promise(function(resolve, reject) {\n        'use strict';\n        timerKey = goog.Timer.callOnce(function() {\n          'use strict';\n          resolve(opt_result);\n        }, delay);\n        if (timerKey == goog.Timer.INVALID_TIMEOUT_ID_) {\n          reject(new Error('Failed to schedule timer.'));\n        }\n      })\n      .thenCatch(function(error) {\n        'use strict';\n        // Clear the timer. The most likely reason is \"cancel\" signal.\n        goog.Timer.clear(timerKey);\n        throw error;\n      });\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Definition of the goog.async.Throttle class.\n *\n * @see ../demos/timers.html\n */\n\ngoog.module('goog.async.Throttle');\ngoog.module.declareLegacyNamespace();\n\nconst Disposable = goog.require('goog.Disposable');\nconst Timer = goog.require('goog.Timer');\n\n\n/**\n * Throttle will perform an action that is passed in no more than once\n * per interval (specified in milliseconds). If it gets multiple signals\n * to perform the action while it is waiting, it will only perform the action\n * once at the end of the interval.\n * @final\n * @template T\n */\nclass Throttle extends Disposable {\n  /**\n   * @param {function(this: T, ...?)} listener Function to callback when the\n   *     action is triggered.\n   * @param {number} interval Interval over which to throttle. The listener can\n   *     only be called once per interval.\n   * @param {T=} handler Object in whose scope to call the listener.\n   */\n  constructor(listener, interval, handler) {\n    super();\n    /**\n     * Function to callback\n     * @type {function(this: T, ...?)}\n     * @private\n     */\n    this.listener_ = handler != null ? listener.bind(handler) : listener;\n\n    /**\n     * Interval for the throttle time\n     * @type {number}\n     * @private\n     */\n    this.interval_ = interval;\n\n    /**\n     * The last arguments passed into `fire`, or null if there is no pending\n     * call.\n     * @private {?IArrayLike}\n     */\n    this.args_ = null;\n\n    /**\n     * Indicates that the action is pending and needs to be fired.\n     * @type {boolean}\n     * @private\n     */\n    this.shouldFire_ = false;\n\n    /**\n     * Indicates the count of nested pauses currently in effect on the throttle.\n     * When this count is not zero, fired actions will be postponed until the\n     * throttle is resumed enough times to drop the pause count to zero.\n     * @type {number}\n     * @private\n     */\n    this.pauseCount_ = 0;\n\n    /**\n     * Timer for scheduling the next callback\n     * @type {?number}\n     * @private\n     */\n    this.timer_ = null;\n  }\n\n  /**\n   * Notifies the throttle that the action has happened. It will throttle\n   * the call so that the callback is not called too often according to the\n   * interval parameter passed to the constructor, passing the arguments\n   * from the last call of this function into the throttled function.\n   * @param {...?} var_args Arguments to pass on to the throttled function.\n   */\n  fire(var_args) {\n    this.args_ = arguments;\n    if (!this.timer_ && !this.pauseCount_) {\n      this.doAction_();\n    } else {\n      this.shouldFire_ = true;\n    }\n  }\n\n  /**\n   * Cancels any pending action callback. The throttle can be restarted by\n   * calling {@link #fire}.\n   */\n  stop() {\n    if (this.timer_) {\n      Timer.clear(this.timer_);\n      this.timer_ = null;\n      this.shouldFire_ = false;\n      this.args_ = null;\n    }\n  }\n\n  /**\n   * Pauses the throttle.  All pending and future action callbacks will be\n   * delayed until the throttle is resumed.  Pauses can be nested.\n   */\n  pause() {\n    this.pauseCount_++;\n  }\n\n  /**\n   * Resumes the throttle.  If doing so drops the pausing count to zero,\n   * pending action callbacks will be executed as soon as possible, but\n   * still no sooner than an interval's delay after the previous call.\n   * Future action callbacks will be executed as normal.\n   */\n  resume() {\n    this.pauseCount_--;\n    if (!this.pauseCount_ && this.shouldFire_ && !this.timer_) {\n      this.shouldFire_ = false;\n      this.doAction_();\n    }\n  }\n\n  /** @override */\n  disposeInternal() {\n    super.disposeInternal();\n    this.stop();\n  }\n\n  /**\n   * Handler for the timer to fire the throttle\n   * @private\n   */\n  onTimer_() {\n    this.timer_ = null;\n\n    if (this.shouldFire_ && !this.pauseCount_) {\n      this.shouldFire_ = false;\n      this.doAction_();\n    }\n  }\n\n  /**\n   * Calls the callback\n   * @private\n   */\n  doAction_() {\n    this.timer_ = Timer.callOnce(() => this.onTimer_(), this.interval_);\n    const args = this.args_;\n    // release memory first so it always happens even if listener throws\n    this.args_ = null;\n    this.listener_.apply(null, args);\n  }\n}\n\nexports = Throttle;\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Class to create objects which want to handle multiple events\n * and have their listeners easily cleaned up via a dispose method.\n *\n * Example:\n * <pre>\n * function Something() {\n *   Something.base(this);\n *\n *   ... set up object ...\n *\n *   // Add event listeners\n *   this.listen(this.starEl, goog.events.EventType.CLICK, this.handleStar);\n *   this.listen(this.headerEl, goog.events.EventType.CLICK, this.expand);\n *   this.listen(this.collapseEl, goog.events.EventType.CLICK, this.collapse);\n *   this.listen(this.infoEl, goog.events.EventType.MOUSEOVER, this.showHover);\n *   this.listen(this.infoEl, goog.events.EventType.MOUSEOUT, this.hideHover);\n * }\n * goog.inherits(Something, goog.events.EventHandler);\n *\n * Something.prototype.disposeInternal = function() {\n *   Something.base(this, 'disposeInternal');\n *   goog.dom.removeNode(this.container);\n * };\n *\n *\n * // Then elsewhere:\n *\n * var activeSomething = null;\n * function openSomething() {\n *   activeSomething = new Something();\n * }\n *\n * function closeSomething() {\n *   if (activeSomething) {\n *     activeSomething.dispose();  // Remove event listeners\n *     activeSomething = null;\n *   }\n * }\n * </pre>\n */\n\ngoog.provide('goog.events.EventHandler');\n\ngoog.require('goog.Disposable');\ngoog.require('goog.events');\ngoog.require('goog.object');\ngoog.requireType('goog.events.Event');\ngoog.requireType('goog.events.EventId');\ngoog.requireType('goog.events.EventTarget');\ngoog.requireType('goog.events.EventWrapper');\n\n\n\n/**\n * Super class for objects that want to easily manage a number of event\n * listeners.  It allows a short cut to listen and also provides a quick way\n * to remove all events listeners belonging to this object.\n * @param {SCOPE=} opt_scope Object in whose scope to call the listeners.\n * @constructor\n * @extends {goog.Disposable}\n * @template SCOPE\n */\ngoog.events.EventHandler = function(opt_scope) {\n  'use strict';\n  goog.Disposable.call(this);\n  // TODO(mknichel): Rename this to this.scope_ and fix the classes in google3\n  // that access this private variable. :(\n  this.handler_ = opt_scope;\n\n  /**\n   * Keys for events that are being listened to.\n   * @type {!Object<!goog.events.Key>}\n   * @private\n   */\n  this.keys_ = {};\n};\ngoog.inherits(goog.events.EventHandler, goog.Disposable);\n\n\n/**\n * Utility array used to unify the cases of listening for an array of types\n * and listening for a single event, without using recursion or allocating\n * an array each time.\n * @type {!Array<string>}\n * @const\n * @private\n */\ngoog.events.EventHandler.typeArray_ = [];\n\n\n/**\n * Listen to an event on a Listenable.  If the function is omitted then the\n * EventHandler's handleEvent method will be used.\n * @param {goog.events.ListenableType} src Event source.\n * @param {string|Array<string>|\n *     !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}\n *     type Event type to listen for or array of event types.\n * @param {function(this:SCOPE, EVENTOBJ):?|{handleEvent:function(?):?}|null=}\n *     opt_fn Optional callback function to be used as the listener or an object\n *     with handleEvent function.\n * @param {(boolean|!AddEventListenerOptions)=} opt_options\n * @return {THIS} This object, allowing for chaining of calls.\n * @this {THIS}\n * @template EVENTOBJ, THIS\n */\ngoog.events.EventHandler.prototype.listen = function(\n    src, type, opt_fn, opt_options) {\n  'use strict';\n  var self = /** @type {!goog.events.EventHandler} */ (this);\n  return self.listen_(src, type, opt_fn, opt_options);\n};\n\n\n/**\n * Listen to an event on a Listenable.  If the function is omitted then the\n * EventHandler's handleEvent method will be used.\n * @param {goog.events.ListenableType} src Event source.\n * @param {string|Array<string>|\n *     !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}\n *     type Event type to listen for or array of event types.\n * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(this:T, ?):?}|\n *     null|undefined} fn Optional callback function to be used as the\n *     listener or an object with handleEvent function.\n * @param {boolean|!AddEventListenerOptions|undefined} options\n * @param {T} scope Object in whose scope to call the listener.\n * @return {THIS} This object, allowing for chaining of calls.\n * @this {THIS}\n * @template T, EVENTOBJ, THIS\n */\ngoog.events.EventHandler.prototype.listenWithScope = function(\n    src, type, fn, options, scope) {\n  'use strict';\n  var self = /** @type {!goog.events.EventHandler} */ (this);\n  // TODO(mknichel): Deprecate this function.\n  return self.listen_(src, type, fn, options, scope);\n};\n\n\n/**\n * Listen to an event on a Listenable.  If the function is omitted then the\n * EventHandler's handleEvent method will be used.\n * @param {goog.events.ListenableType} src Event source.\n * @param {string|Array<string>|\n *     !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}\n *     type Event type to listen for or array of event types.\n * @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null=} opt_fn\n *     Optional callback function to be used as the listener or an object with\n *     handleEvent function.\n * @param {(boolean|!AddEventListenerOptions)=} opt_options\n * @param {Object=} opt_scope Object in whose scope to call the listener.\n * @return {THIS} This object, allowing for chaining of calls.\n * @this {THIS}\n * @template EVENTOBJ, THIS\n * @private\n */\ngoog.events.EventHandler.prototype.listen_ = function(\n    src, type, opt_fn, opt_options, opt_scope) {\n  'use strict';\n  var self = /** @type {!goog.events.EventHandler} */ (this);\n  if (!Array.isArray(type)) {\n    if (type) {\n      goog.events.EventHandler.typeArray_[0] = type.toString();\n    }\n    type = goog.events.EventHandler.typeArray_;\n  }\n  for (var i = 0; i < type.length; i++) {\n    var listenerObj = goog.events.listen(\n        src, type[i], opt_fn || self.handleEvent, opt_options || false,\n        opt_scope || self.handler_ || self);\n\n    if (!listenerObj) {\n      // When goog.events.listen run on OFF_AND_FAIL or OFF_AND_SILENT\n      // (goog.events.CaptureSimulationMode) in IE8-, it will return null\n      // value.\n      return self;\n    }\n\n    var key = listenerObj.key;\n    self.keys_[key] = listenerObj;\n  }\n\n  return self;\n};\n\n\n/**\n * Listen to an event on a Listenable.  If the function is omitted, then the\n * EventHandler's handleEvent method will be used. After the event has fired the\n * event listener is removed from the target. If an array of event types is\n * provided, each event type will be listened to once.\n * @param {goog.events.ListenableType} src Event source.\n * @param {string|Array<string>|\n *     !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}\n *     type Event type to listen for or array of event types.\n * @param {function(this:SCOPE, EVENTOBJ):?|{handleEvent:function(?):?}|null=}\n * opt_fn\n *    Optional callback function to be used as the listener or an object with\n *    handleEvent function.\n * @param {(boolean|!AddEventListenerOptions)=} opt_options\n * @return {THIS} This object, allowing for chaining of calls.\n * @this {THIS}\n * @template EVENTOBJ, THIS\n */\ngoog.events.EventHandler.prototype.listenOnce = function(\n    src, type, opt_fn, opt_options) {\n  'use strict';\n  var self = /** @type {!goog.events.EventHandler} */ (this);\n  return self.listenOnce_(src, type, opt_fn, opt_options);\n};\n\n\n/**\n * Listen to an event on a Listenable.  If the function is omitted, then the\n * EventHandler's handleEvent method will be used. After the event has fired the\n * event listener is removed from the target. If an array of event types is\n * provided, each event type will be listened to once.\n * @param {goog.events.ListenableType} src Event source.\n * @param {string|Array<string>|\n *     !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}\n *     type Event type to listen for or array of event types.\n * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(this:T, ?):?}|\n *     null|undefined} fn Optional callback function to be used as the\n *     listener or an object with handleEvent function.\n * @param {boolean|undefined} capture Optional whether to use capture phase.\n * @param {T} scope Object in whose scope to call the listener.\n * @return {THIS} This object, allowing for chaining of calls.\n * @this {THIS}\n * @template T, EVENTOBJ, THIS\n */\ngoog.events.EventHandler.prototype.listenOnceWithScope = function(\n    src, type, fn, capture, scope) {\n  'use strict';\n  var self = /** @type {!goog.events.EventHandler} */ (this);\n  // TODO(mknichel): Deprecate this function.\n  return self.listenOnce_(src, type, fn, capture, scope);\n};\n\n\n/**\n * Listen to an event on a Listenable.  If the function is omitted, then the\n * EventHandler's handleEvent method will be used. After the event has fired\n * the event listener is removed from the target. If an array of event types is\n * provided, each event type will be listened to once.\n * @param {goog.events.ListenableType} src Event source.\n * @param {string|Array<string>|\n *     !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}\n *     type Event type to listen for or array of event types.\n * @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null=} opt_fn\n *    Optional callback function to be used as the listener or an object with\n *    handleEvent function.\n * @param {(boolean|!AddEventListenerOptions)=} opt_options\n * @param {Object=} opt_scope Object in whose scope to call the listener.\n * @return {THIS} This object, allowing for chaining of calls.\n * @this {THIS}\n * @template EVENTOBJ, THIS\n * @private\n */\ngoog.events.EventHandler.prototype.listenOnce_ = function(\n    src, type, opt_fn, opt_options, opt_scope) {\n  'use strict';\n  var self = /** @type {!goog.events.EventHandler} */ (this);\n  if (Array.isArray(type)) {\n    for (var i = 0; i < type.length; i++) {\n      self.listenOnce_(src, type[i], opt_fn, opt_options, opt_scope);\n    }\n  } else {\n    var listenerObj = goog.events.listenOnce(\n        src, type, opt_fn || self.handleEvent, opt_options,\n        opt_scope || self.handler_ || self);\n    if (!listenerObj) {\n      // When goog.events.listen run on OFF_AND_FAIL or OFF_AND_SILENT\n      // (goog.events.CaptureSimulationMode) in IE8-, it will return null\n      // value.\n      return self;\n    }\n\n    var key = listenerObj.key;\n    self.keys_[key] = listenerObj;\n  }\n\n  return self;\n};\n\n\n/**\n * Adds an event listener with a specific event wrapper on a DOM Node or an\n * object that has implemented {@link goog.events.EventTarget}. A listener can\n * only be added once to an object.\n *\n * @param {EventTarget|goog.events.EventTarget} src The node to listen to\n *     events on.\n * @param {goog.events.EventWrapper} wrapper Event wrapper to use.\n * @param {function(this:SCOPE, ?):?|{handleEvent:function(?):?}|null} listener\n *     Callback method, or an object with a handleEvent function.\n * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to\n *     false).\n * @return {THIS} This object, allowing for chaining of calls.\n * @this {THIS}\n * @template THIS\n */\ngoog.events.EventHandler.prototype.listenWithWrapper = function(\n    src, wrapper, listener, opt_capt) {\n  'use strict';\n  var self = /** @type {!goog.events.EventHandler} */ (this);\n  // TODO(mknichel): Remove the opt_scope from this function and then\n  // templatize it.\n  return self.listenWithWrapper_(src, wrapper, listener, opt_capt);\n};\n\n\n/**\n * Adds an event listener with a specific event wrapper on a DOM Node or an\n * object that has implemented {@link goog.events.EventTarget}. A listener can\n * only be added once to an object.\n *\n * @param {EventTarget|goog.events.EventTarget} src The node to listen to\n *     events on.\n * @param {goog.events.EventWrapper} wrapper Event wrapper to use.\n * @param {function(this:T, ?):?|{handleEvent:function(this:T, ?):?}|null}\n *     listener Optional callback function to be used as the\n *     listener or an object with handleEvent function.\n * @param {boolean|undefined} capture Optional whether to use capture phase.\n * @param {T} scope Object in whose scope to call the listener.\n * @return {THIS} This object, allowing for chaining of calls.\n * @this {THIS}\n * @template T, THIS\n */\ngoog.events.EventHandler.prototype.listenWithWrapperAndScope = function(\n    src, wrapper, listener, capture, scope) {\n  'use strict';\n  var self = /** @type {!goog.events.EventHandler} */ (this);\n  // TODO(mknichel): Deprecate this function.\n  return self.listenWithWrapper_(src, wrapper, listener, capture, scope);\n};\n\n\n/**\n * Adds an event listener with a specific event wrapper on a DOM Node or an\n * object that has implemented {@link goog.events.EventTarget}. A listener can\n * only be added once to an object.\n *\n * @param {EventTarget|goog.events.EventTarget} src The node to listen to\n *     events on.\n * @param {goog.events.EventWrapper} wrapper Event wrapper to use.\n * @param {function(?):?|{handleEvent:function(?):?}|null} listener Callback\n *     method, or an object with a handleEvent function.\n * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to\n *     false).\n * @param {Object=} opt_scope Element in whose scope to call the listener.\n * @return {THIS} This object, allowing for chaining of calls.\n * @this {THIS}\n * @template THIS\n * @private\n */\ngoog.events.EventHandler.prototype.listenWithWrapper_ = function(\n    src, wrapper, listener, opt_capt, opt_scope) {\n  'use strict';\n  var self = /** @type {!goog.events.EventHandler} */ (this);\n  wrapper.listen(\n      src, listener, opt_capt, opt_scope || self.handler_ || self, self);\n  return self;\n};\n\n\n/**\n * @return {number} Number of listeners registered by this handler.\n */\ngoog.events.EventHandler.prototype.getListenerCount = function() {\n  'use strict';\n  var count = 0;\n  for (var key in this.keys_) {\n    if (Object.prototype.hasOwnProperty.call(this.keys_, key)) {\n      count++;\n    }\n  }\n  return count;\n};\n\n\n/**\n * Unlistens on an event.\n * @param {goog.events.ListenableType} src Event source.\n * @param {string|Array<string>|\n *     !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}\n *     type Event type or array of event types to unlisten to.\n * @param {function(this:?, EVENTOBJ):?|{handleEvent:function(?):?}|null=}\n *     opt_fn Optional callback function to be used as the listener or an object\n *     with handleEvent function.\n * @param {(boolean|!EventListenerOptions)=} opt_options\n * @param {Object=} opt_scope Object in whose scope to call the listener.\n * @return {THIS} This object, allowing for chaining of calls.\n * @this {THIS}\n * @template EVENTOBJ, THIS\n */\ngoog.events.EventHandler.prototype.unlisten = function(\n    src, type, opt_fn, opt_options, opt_scope) {\n  'use strict';\n  var self = /** @type {!goog.events.EventHandler} */ (this);\n  if (Array.isArray(type)) {\n    for (var i = 0; i < type.length; i++) {\n      self.unlisten(src, type[i], opt_fn, opt_options, opt_scope);\n    }\n  } else {\n    var capture =\n        goog.isObject(opt_options) ? !!opt_options.capture : !!opt_options;\n    var listener = goog.events.getListener(\n        src, type, opt_fn || self.handleEvent, capture,\n        opt_scope || self.handler_ || self);\n\n    if (listener) {\n      goog.events.unlistenByKey(listener);\n      delete self.keys_[listener.key];\n    }\n  }\n\n  return self;\n};\n\n\n/**\n * Removes an event listener which was added with listenWithWrapper().\n *\n * @param {EventTarget|goog.events.EventTarget} src The target to stop\n *     listening to events on.\n * @param {goog.events.EventWrapper} wrapper Event wrapper to use.\n * @param {function(?):?|{handleEvent:function(?):?}|null} listener The\n *     listener function to remove.\n * @param {boolean=} opt_capt In DOM-compliant browsers, this determines\n *     whether the listener is fired during the capture or bubble phase of the\n *     event.\n * @param {Object=} opt_scope Element in whose scope to call the listener.\n * @return {THIS} This object, allowing for chaining of calls.\n * @this {THIS}\n * @template THIS\n */\ngoog.events.EventHandler.prototype.unlistenWithWrapper = function(\n    src, wrapper, listener, opt_capt, opt_scope) {\n  'use strict';\n  var self = /** @type {!goog.events.EventHandler} */ (this);\n  wrapper.unlisten(\n      src, listener, opt_capt, opt_scope || self.handler_ || self, self);\n  return self;\n};\n\n\n/**\n * Unlistens to all events.\n */\ngoog.events.EventHandler.prototype.removeAll = function() {\n  'use strict';\n  goog.object.forEach(this.keys_, function(listenerObj, key) {\n    'use strict';\n    if (this.keys_.hasOwnProperty(key)) {\n      goog.events.unlistenByKey(listenerObj);\n    }\n  }, this);\n\n  this.keys_ = {};\n};\n\n\n/**\n * Disposes of this EventHandler and removes all listeners that it registered.\n * @override\n * @protected\n */\ngoog.events.EventHandler.prototype.disposeInternal = function() {\n  'use strict';\n  goog.events.EventHandler.superClass_.disposeInternal.call(this);\n  this.removeAll();\n};\n\n\n/**\n * Default event handler\n * @param {goog.events.Event} e Event object.\n */\ngoog.events.EventHandler.prototype.handleEvent = function(e) {\n  'use strict';\n  throw new Error('EventHandler.handleEvent not implemented');\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Provides a utility for tracing and debugging WebChannel\n *     requests.\n *\n */\n\n\ngoog.provide('goog.labs.net.webChannel.WebChannelDebug');\n\ngoog.require('goog.json');\ngoog.require('goog.log');\ngoog.requireType('goog.Uri');\ngoog.requireType('goog.net.XmlHttp.ReadyState');\n\n\n\n/**\n * Logs and keeps a buffer of debugging info for the Channel.\n *\n * @constructor\n * @struct\n * @final\n */\ngoog.labs.net.webChannel.WebChannelDebug = function() {\n  'use strict';\n  /**\n   * The logger instance.\n   * @const\n   * @private {?goog.log.Logger}\n   */\n  this.logger_ = goog.log.getLogger('goog.labs.net.webChannel.WebChannelDebug');\n\n  /**\n   * Whether to enable redact. Defaults to true.\n   * @private {boolean}\n   */\n  this.redactEnabled_ = true;\n};\n\n\ngoog.scope(function() {\n'use strict';\nvar WebChannelDebug = goog.labs.net.webChannel.WebChannelDebug;\n\n\n/**\n * Turns off redact.\n */\nWebChannelDebug.prototype.disableRedact = function() {\n  'use strict';\n  this.redactEnabled_ = false;\n};\n\n\n/**\n * Logs that the browser went offline during the lifetime of a request.\n * @param {goog.Uri} url The URL being requested.\n */\nWebChannelDebug.prototype.browserOfflineResponse = function(url) {\n  'use strict';\n  this.info(function() {\n    'use strict';\n    return 'BROWSER_OFFLINE: ' + url;\n  });\n};\n\n\n/**\n * Logs an XmlHttp request..\n * @param {string} verb The request type (GET/POST).\n * @param {goog.Uri} uri The request destination.\n * @param {string|number|undefined} id The request id.\n * @param {number} attempt Which attempt # the request was.\n * @param {?string} postData The data posted in the request.\n */\nWebChannelDebug.prototype.xmlHttpChannelRequest = function(\n    verb, uri, id, attempt, postData) {\n  'use strict';\n  var self = this;\n  this.info(function() {\n    'use strict';\n    return 'XMLHTTP REQ (' + id + ') [attempt ' + attempt + ']: ' + verb +\n        '\\n' + uri + '\\n' + self.maybeRedactPostData_(postData);\n  });\n};\n\n\n/**\n * Logs the meta data received from an XmlHttp request.\n * @param {string} verb The request type (GET/POST).\n * @param {goog.Uri} uri The request destination.\n * @param {string|number|undefined} id The request id.\n * @param {number} attempt Which attempt # the request was.\n * @param {goog.net.XmlHttp.ReadyState} readyState The ready state.\n * @param {number} statusCode The HTTP status code.\n */\nWebChannelDebug.prototype.xmlHttpChannelResponseMetaData = function(\n    verb, uri, id, attempt, readyState, statusCode) {\n  'use strict';\n  this.info(function() {\n    'use strict';\n    return 'XMLHTTP RESP (' + id + ') [ attempt ' + attempt + ']: ' + verb +\n        '\\n' + uri + '\\n' + readyState + ' ' + statusCode;\n  });\n};\n\n\n/**\n * Logs the response data received from an XmlHttp request.\n * @param {string|number|undefined} id The request id.\n * @param {?string} responseText The response text.\n * @param {?string=} opt_desc Optional request description.\n */\nWebChannelDebug.prototype.xmlHttpChannelResponseText = function(\n    id, responseText, opt_desc) {\n  'use strict';\n  var self = this;\n  this.info(function() {\n    'use strict';\n    return 'XMLHTTP TEXT (' + id + '): ' + self.redactResponse_(responseText) +\n        (opt_desc ? ' ' + opt_desc : '');\n  });\n};\n\n\n/**\n * Logs a request timeout.\n * @param {goog.Uri} uri The uri that timed out.\n */\nWebChannelDebug.prototype.timeoutResponse = function(uri) {\n  'use strict';\n  this.info(function() {\n    'use strict';\n    return 'TIMEOUT: ' + uri;\n  });\n};\n\n\n/**\n * Logs a debug message.\n * @param {!goog.log.Loggable} text The message.\n */\nWebChannelDebug.prototype.debug = function(text) {\n  'use strict';\n  goog.log.fine(this.logger_, text);\n};\n\n\n/**\n * Logs an exception\n * @param {Error} e The error or error event.\n * @param {goog.log.Loggable=} opt_msg The optional message,\n *     defaults to 'Exception'.\n */\nWebChannelDebug.prototype.dumpException = function(e, opt_msg) {\n  'use strict';\n  goog.log.error(this.logger_, opt_msg || 'Exception', e);\n};\n\n\n/**\n * Logs an info message.\n * @param {!goog.log.Loggable} text The message.\n */\nWebChannelDebug.prototype.info = function(text) {\n  'use strict';\n  goog.log.info(this.logger_, text);\n};\n\n\n/**\n * Logs a warning message.\n * @param {!goog.log.Loggable} text The message.\n */\nWebChannelDebug.prototype.warning = function(text) {\n  'use strict';\n  goog.log.warning(this.logger_, text);\n};\n\n\n/**\n * Logs a severe message.\n * @param {!goog.log.Loggable} text The message.\n */\nWebChannelDebug.prototype.severe = function(text) {\n  'use strict';\n  goog.log.error(this.logger_, text);\n};\n\n\n/**\n * Removes potentially private data from a response so that we don't\n * accidentally save private and personal data to the server logs.\n * @param {?string} responseText A JSON response to clean.\n * @return {?string} The cleaned response.\n * @private\n */\nWebChannelDebug.prototype.redactResponse_ = function(responseText) {\n  'use strict';\n  if (!this.redactEnabled_) {\n    return responseText;\n  }\n\n  if (!responseText) {\n    return null;\n  }\n\n  try {\n    var responseArray = JSON.parse(responseText);\n    if (responseArray) {\n      for (var i = 0; i < responseArray.length; i++) {\n        if (Array.isArray(responseArray[i])) {\n          this.maybeRedactArray_(responseArray[i]);\n        }\n      }\n    }\n\n    return goog.json.serialize(responseArray);\n  } catch (e) {\n    this.debug('Exception parsing expected JS array - probably was not JS');\n    return responseText;\n  }\n};\n\n\n/**\n * Removes data from a response array that may be sensitive.\n * @param {!Array<?>} array The array to clean.\n * @private\n */\nWebChannelDebug.prototype.maybeRedactArray_ = function(array) {\n  'use strict';\n  if (array.length < 2) {\n    return;\n  }\n  var dataPart = array[1];\n  if (!Array.isArray(dataPart)) {\n    return;\n  }\n  if (dataPart.length < 1) {\n    return;\n  }\n\n  var type = dataPart[0];\n  if (type != 'noop' && type != 'stop' && type != 'close') {\n    // redact all fields in the array\n    for (var i = 1; i < dataPart.length; i++) {\n      dataPart[i] = '';\n    }\n  }\n};\n\n\n/**\n * Removes potentially private data from a request POST body so that we don't\n * accidentally save private and personal data to the server logs.\n * @param {?string} data The data string to clean.\n * @return {?string} The data string with sensitive data replaced by 'redacted'.\n * @private\n */\nWebChannelDebug.prototype.maybeRedactPostData_ = function(data) {\n  'use strict';\n  if (!this.redactEnabled_) {\n    return data;\n  }\n\n  if (!data) {\n    return null;\n  }\n  var out = '';\n  var params = data.split('&');\n  for (var i = 0; i < params.length; i++) {\n    var param = params[i];\n    var keyValue = param.split('=');\n    if (keyValue.length > 1) {\n      var key = keyValue[0];\n      var value = keyValue[1];\n\n      var keyParts = key.split('_');\n      if (keyParts.length >= 2 && keyParts[1] == 'type') {\n        out += key + '=' + value + '&';\n      } else {\n        out += key + '=' +\n            'redacted' +\n            '&';\n      }\n    }\n  }\n  return out;\n};\n});  // goog.scope\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Static utilities for collecting stats associated with\n * ChannelRequest.\n *\n */\n\n\ngoog.provide('goog.labs.net.webChannel.requestStats');\ngoog.provide('goog.labs.net.webChannel.requestStats.Event');\ngoog.provide('goog.labs.net.webChannel.requestStats.ServerReachability');\ngoog.provide('goog.labs.net.webChannel.requestStats.ServerReachabilityEvent');\ngoog.provide('goog.labs.net.webChannel.requestStats.Stat');\ngoog.provide('goog.labs.net.webChannel.requestStats.StatEvent');\ngoog.provide('goog.labs.net.webChannel.requestStats.TimingEvent');\n\ngoog.require('goog.events.Event');\ngoog.require('goog.events.EventTarget');\n\n\ngoog.scope(function() {\n'use strict';\nconst requestStats = goog.labs.net.webChannel.requestStats;\n\n\n/**\n * Events fired.\n * @const\n */\nrequestStats.Event = {};\n\n\n/**\n * Singleton event target for firing stat events\n * @type {?goog.events.EventTarget}\n * @private\n */\nrequestStats.eventTarget_ = null;\n\n/**\n * Singleton event target for firing stat events\n * @return {!goog.events.EventTarget}\n * @private\n */\nrequestStats.getStatEventTarget_ = function() {\n  'use strict';\n  requestStats.eventTarget_ =\n      requestStats.eventTarget_ || new goog.events.EventTarget();\n  return requestStats.eventTarget_;\n};\n\n/**\n * The type of event that occurs every time some information about how reachable\n * the server is is discovered.\n */\nrequestStats.Event.SERVER_REACHABILITY_EVENT = 'serverreachability';\n\n\n/**\n * Types of events which reveal information about the reachability of the\n * server.\n * @enum {number}\n */\nrequestStats.ServerReachability = {\n  REQUEST_MADE: 1,\n  REQUEST_SUCCEEDED: 2,\n  REQUEST_FAILED: 3,\n  BACK_CHANNEL_ACTIVITY: 4  // any response data received\n};\n\n\n\n/**\n * Event class for SERVER_REACHABILITY_EVENT.\n *\n * @param {goog.events.EventTarget} target The stat event target for\n       the channel.\n * @param {requestStats.ServerReachability} reachabilityType\n *     The reachability event type.\n * @constructor\n * @extends {goog.events.Event}\n */\nrequestStats.ServerReachabilityEvent = function(target, reachabilityType) {\n  'use strict';\n  goog.events.Event.call(\n      this, requestStats.Event.SERVER_REACHABILITY_EVENT, target);\n\n  /**\n   * @type {requestStats.ServerReachability}\n   */\n  this.reachabilityType = reachabilityType;\n};\ngoog.inherits(requestStats.ServerReachabilityEvent, goog.events.Event);\n\n\n/**\n * Notify the channel that a particular fine grained network event has occurred.\n * Should be considered package-private.\n * @param {requestStats.ServerReachability} reachabilityType\n *     The reachability event type.\n */\nrequestStats.notifyServerReachabilityEvent = function(reachabilityType) {\n  'use strict';\n  const target = requestStats.getStatEventTarget_();\n  target.dispatchEvent(\n      new requestStats.ServerReachabilityEvent(target, reachabilityType));\n};\n\n\n/**\n * Stat Event that fires when things of interest happen that may be useful for\n * applications to know about for stats or debugging purposes.\n */\nrequestStats.Event.STAT_EVENT = 'statevent';\n\n\n/**\n * Enum that identifies events for statistics that are interesting to track.\n * @enum {number}\n */\nrequestStats.Stat = {\n  /** Event indicating a new connection attempt. */\n  CONNECT_ATTEMPT: 0,\n\n  /** Event indicating a connection error due to a general network problem. */\n  ERROR_NETWORK: 1,\n\n  /**\n   * Event indicating a connection error that isn't due to a general network\n   * problem.\n   */\n  ERROR_OTHER: 2,\n\n  /** Event indicating the start of test stage one. */\n  TEST_STAGE_ONE_START: 3,\n\n  /** Event indicating the start of test stage two. */\n  TEST_STAGE_TWO_START: 4,\n\n  /** Event indicating the first piece of test data was received. */\n  TEST_STAGE_TWO_DATA_ONE: 5,\n\n  /**\n   * Event indicating that the second piece of test data was received and it was\n   * received separately from the first.\n   */\n  TEST_STAGE_TWO_DATA_TWO: 6,\n\n  /** Event indicating both pieces of test data were received simultaneously. */\n  TEST_STAGE_TWO_DATA_BOTH: 7,\n\n  /** Event indicating stage one of the test request failed. */\n  TEST_STAGE_ONE_FAILED: 8,\n\n  /** Event indicating stage two of the test request failed. */\n  TEST_STAGE_TWO_FAILED: 9,\n\n  /**\n   * Event indicating that a buffering proxy is likely between the client and\n   * the server.\n   */\n  PROXY: 10,\n\n  /**\n   * Event indicating that no buffering proxy is likely between the client and\n   * the server.\n   */\n  NOPROXY: 11,\n\n  /** Event indicating an unknown SID error. */\n  REQUEST_UNKNOWN_SESSION_ID: 12,\n\n  /** Event indicating a bad status code was received. */\n  REQUEST_BAD_STATUS: 13,\n\n  /** Event indicating incomplete data was received */\n  REQUEST_INCOMPLETE_DATA: 14,\n\n  /** Event indicating bad data was received */\n  REQUEST_BAD_DATA: 15,\n\n  /** Event indicating no data was received when data was expected. */\n  REQUEST_NO_DATA: 16,\n\n  /** Event indicating a request timeout. */\n  REQUEST_TIMEOUT: 17,\n\n  /**\n   * Event indicating that the server never received our hanging GET and so it\n   * is being retried.\n   */\n  BACKCHANNEL_MISSING: 18,\n\n  /**\n   * Event indicating that we have determined that our hanging GET is not\n   * receiving data when it should be. Thus it is dead dead and will be retried.\n   */\n  BACKCHANNEL_DEAD: 19,\n\n  /**\n   * The browser declared itself offline during the lifetime of a request, or\n   * was offline when a request was initially made.\n   */\n  BROWSER_OFFLINE: 20\n};\n\n\n\n/**\n * Event class for STAT_EVENT.\n *\n * @param {goog.events.EventTarget} eventTarget The stat event target for\n       the channel.\n * @param {requestStats.Stat} stat The stat.\n * @constructor\n * @extends {goog.events.Event}\n */\nrequestStats.StatEvent = function(eventTarget, stat) {\n  'use strict';\n  goog.events.Event.call(this, requestStats.Event.STAT_EVENT, eventTarget);\n\n  /**\n   * The stat\n   * @type {requestStats.Stat}\n   */\n  this.stat = stat;\n};\ngoog.inherits(requestStats.StatEvent, goog.events.Event);\n\n\n/**\n * Returns the singleton event target for stat events.\n * @return {!goog.events.EventTarget} The event target for stat events.\n */\nrequestStats.getStatEventTarget = function() {\n  'use strict';\n  return requestStats.getStatEventTarget_();\n};\n\n\n/**\n * Helper function to call the stat event callback.\n * @param {requestStats.Stat} stat The stat.\n */\nrequestStats.notifyStatEvent = function(stat) {\n  'use strict';\n  const target = requestStats.getStatEventTarget_();\n  target.dispatchEvent(new requestStats.StatEvent(target, stat));\n};\n\n\n/**\n * An event that fires when POST requests complete successfully, indicating\n * the size of the POST and the round trip time.\n */\nrequestStats.Event.TIMING_EVENT = 'timingevent';\n\n\n\n/**\n * Event class for requestStats.Event.TIMING_EVENT\n *\n * @param {goog.events.EventTarget} target The stat event target for\n       the channel.\n * @param {number} size The number of characters in the POST data.\n * @param {number} rtt The total round trip time from POST to response in MS.\n * @param {number} retries The number of times the POST had to be retried.\n * @constructor\n * @extends {goog.events.Event}\n */\nrequestStats.TimingEvent = function(target, size, rtt, retries) {\n  'use strict';\n  goog.events.Event.call(this, requestStats.Event.TIMING_EVENT, target);\n\n  /**\n   * @type {number}\n   */\n  this.size = size;\n\n  /**\n   * @type {number}\n   */\n  this.rtt = rtt;\n\n  /**\n   * @type {number}\n   */\n  this.retries = retries;\n};\ngoog.inherits(requestStats.TimingEvent, goog.events.Event);\n\n\n/**\n * Helper function to notify listeners about POST request performance.\n *\n * @param {number} size Number of characters in the POST data.\n * @param {number} rtt The amount of time from POST start to response.\n * @param {number} retries The number of times the POST had to be retried.\n */\nrequestStats.notifyTimingEvent = function(size, rtt, retries) {\n  'use strict';\n  const target = requestStats.getStatEventTarget_();\n  target.dispatchEvent(\n      new requestStats.TimingEvent(target, size, rtt, retries));\n};\n\n\n/**\n * Allows the application to set an execution hooks for when a channel\n * starts processing requests. This is useful to track timing or logging\n * special information. The function takes no parameters and return void.\n * @param {Function} startHook  The function for the start hook.\n */\nrequestStats.setStartThreadExecutionHook = function(startHook) {\n  'use strict';\n  requestStats.startExecutionHook_ = startHook;\n};\n\n\n/**\n * Allows the application to set an execution hooks for when a channel\n * stops processing requests. This is useful to track timing or logging\n * special information. The function takes no parameters and return void.\n * @param {Function} endHook  The function for the end hook.\n */\nrequestStats.setEndThreadExecutionHook = function(endHook) {\n  'use strict';\n  requestStats.endExecutionHook_ = endHook;\n};\n\n\n/**\n * Application provided execution hook for the start hook.\n *\n * @type {Function}\n * @private\n */\nrequestStats.startExecutionHook_ = function() {};\n\n\n/**\n * Application provided execution hook for the end hook.\n *\n * @type {Function}\n * @private\n */\nrequestStats.endExecutionHook_ = function() {};\n\n\n/**\n * Helper function to call the start hook\n */\nrequestStats.onStartExecution = function() {\n  'use strict';\n  requestStats.startExecutionHook_();\n};\n\n\n/**\n * Helper function to call the end hook\n */\nrequestStats.onEndExecution = function() {\n  'use strict';\n  requestStats.endExecutionHook_();\n};\n\n\n/**\n * Wrapper around SafeTimeout which calls the start and end execution hooks\n * with a try...finally block.\n * @param {Function} fn The callback function.\n * @param {number} ms The time in MS for the timer.\n * @return {number} The ID of the timer.\n */\nrequestStats.setTimeout = function(fn, ms) {\n  'use strict';\n  if (typeof fn !== 'function') {\n    throw new Error('Fn must not be null and must be a function');\n  }\n  return goog.global.setTimeout(function() {\n    'use strict';\n    requestStats.onStartExecution();\n    try {\n      fn();\n    } finally {\n      requestStats.onEndExecution();\n    }\n  }, ms);\n};\n});  // goog.scope\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Error codes shared between goog.net.IframeIo and\n * goog.net.XhrIo.\n */\n\ngoog.provide('goog.net.ErrorCode');\n\n\n/**\n * Error codes\n * @enum {number}\n */\ngoog.net.ErrorCode = {\n\n  /**\n   * There is no error condition.\n   */\n  NO_ERROR: 0,\n\n  /**\n   * The most common error from iframeio, unfortunately, is that the browser\n   * responded with an error page that is classed as a different domain. The\n   * situations, are when a browser error page  is shown -- 404, access denied,\n   * DNS failure, connection reset etc.)\n   *\n   */\n  ACCESS_DENIED: 1,\n\n  /**\n   * Currently the only case where file not found will be caused is when the\n   * code is running on the local file system and a non-IE browser makes a\n   * request to a file that doesn't exist.\n   */\n  FILE_NOT_FOUND: 2,\n\n  /**\n   * If Firefox shows a browser error page, such as a connection reset by\n   * server or access denied, then it will fail silently without the error or\n   * load handlers firing.\n   */\n  FF_SILENT_ERROR: 3,\n\n  /**\n   * Custom error provided by the client through the error check hook.\n   */\n  CUSTOM_ERROR: 4,\n\n  /**\n   * Exception was thrown while processing the request.\n   */\n  EXCEPTION: 5,\n\n  /**\n   * The Http response returned a non-successful http status code.\n   */\n  HTTP_ERROR: 6,\n\n  /**\n   * The request was aborted.\n   */\n  ABORT: 7,\n\n  /**\n   * The request timed out.\n   */\n  TIMEOUT: 8,\n\n  /**\n   * The resource is not available offline.\n   */\n  OFFLINE: 9,\n};\n\n\n/**\n * Returns a friendly error message for an error code. These messages are for\n * debugging and are not localized.\n * @param {goog.net.ErrorCode} errorCode An error code.\n * @return {string} A message for debugging.\n */\ngoog.net.ErrorCode.getDebugMessage = function(errorCode) {\n  'use strict';\n  switch (errorCode) {\n    case goog.net.ErrorCode.NO_ERROR:\n      return 'No Error';\n\n    case goog.net.ErrorCode.ACCESS_DENIED:\n      return 'Access denied to content document';\n\n    case goog.net.ErrorCode.FILE_NOT_FOUND:\n      return 'File not found';\n\n    case goog.net.ErrorCode.FF_SILENT_ERROR:\n      return 'Firefox silently errored';\n\n    case goog.net.ErrorCode.CUSTOM_ERROR:\n      return 'Application custom error';\n\n    case goog.net.ErrorCode.EXCEPTION:\n      return 'An exception occurred';\n\n    case goog.net.ErrorCode.HTTP_ERROR:\n      return 'Http response at 400 or 500 level';\n\n    case goog.net.ErrorCode.ABORT:\n      return 'Request was aborted';\n\n    case goog.net.ErrorCode.TIMEOUT:\n      return 'Request timed out';\n\n    case goog.net.ErrorCode.OFFLINE:\n      return 'The resource is not available offline';\n\n    default:\n      return 'Unrecognized error code';\n  }\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Common events for the network classes.\n */\n\n\ngoog.provide('goog.net.EventType');\n\n\n/**\n * Event names for network events\n * @enum {string}\n */\ngoog.net.EventType = {\n  COMPLETE: 'complete',\n  SUCCESS: 'success',\n  ERROR: 'error',\n  ABORT: 'abort',\n  READY: 'ready',\n  READY_STATE_CHANGE: 'readystatechange',\n  TIMEOUT: 'timeout',\n  INCREMENTAL_DATA: 'incrementaldata',\n  PROGRESS: 'progress',\n  // DOWNLOAD_PROGRESS and UPLOAD_PROGRESS are special events dispatched by\n  // goog.net.XhrIo to allow binding listeners specific to each type of\n  // progress.\n  DOWNLOAD_PROGRESS: 'downloadprogress',\n  UPLOAD_PROGRESS: 'uploadprogress',\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Interface for a factory for creating XMLHttpRequest objects\n * and metadata about them.\n */\n\ngoog.provide('goog.net.XmlHttpFactory');\n\n/** @suppress {extraRequire} Typedef. */\ngoog.require('goog.net.XhrLike');\n\n\n\n/**\n * Abstract base class for an XmlHttpRequest factory.\n * @constructor\n */\ngoog.net.XmlHttpFactory = function() {};\n\n\n/**\n * Cache of options - we only actually call internalGetOptions once.\n * @type {?Object}\n * @private\n */\ngoog.net.XmlHttpFactory.prototype.cachedOptions_ = null;\n\n\n/**\n * @return {!goog.net.XhrLike.OrNative} A new XhrLike instance.\n */\ngoog.net.XmlHttpFactory.prototype.createInstance = goog.abstractMethod;\n\n\n/**\n * @return {Object} Options describing how xhr objects obtained from this\n *     factory should be used.\n */\ngoog.net.XmlHttpFactory.prototype.getOptions = function() {\n  'use strict';\n  return this.cachedOptions_ ||\n      (this.cachedOptions_ = this.internalGetOptions());\n};\n\n\n/**\n * Override this method in subclasses to preserve the caching offered by\n * getOptions().\n * @return {Object} Options describing how xhr objects obtained from this\n *     factory should be used.\n * @protected\n */\ngoog.net.XmlHttpFactory.prototype.internalGetOptions = goog.abstractMethod;\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview The API spec for the WebChannel messaging library.\n *\n * Similar to HTML5 WebSocket, WebChannel offers an abstraction for\n * point-to-point socket-like communication between a browser client and\n * a remote origin.\n *\n * WebChannels are created via <code>WebChannel</code>. Multiple WebChannels\n * may be multiplexed over the same WebChannelTransport, which encapsulates\n * the underlying physical connectivity over standard wire protocols\n * such as HTTP.\n *\n * A WebChannel in turn represents a logical communication channel between\n * the client and server endpoint. A WebChannel remains open for as long\n * as the client or server endpoint allows.\n *\n * Messages are delivered in-order and reliably over the same WebChannel,\n * and the choice of the underlying wire protocols is completely transparent\n * to the API users.\n *\n * Note that we have no immediate plan to move this API out of labs. While\n * the implementation is production ready, the API is subject to change.\n */\n\ngoog.provide('goog.net.WebChannel');\ngoog.provide('goog.net.WebChannel.Options');\n\ngoog.require('goog.events');\ngoog.require('goog.events.Event');\ngoog.require('goog.events.Listenable');\ngoog.require('goog.net.XmlHttpFactory');\n\n\n\n/**\n * A WebChannel represents a logical bi-directional channel over which the\n * client communicates with a remote server that holds the other endpoint\n * of the channel. A WebChannel is always created in the context of a shared\n * {@link WebChannelTransport} instance. It is up to the underlying client-side\n * and server-side implementations to decide how or when multiplexing is\n * to be enabled.\n *\n * @interface\n * @extends {goog.events.Listenable}\n */\ngoog.net.WebChannel = function() {};\n\n\n\n/**\n * This interface defines a pluggable API to allow WebChannel runtime to support\n * customized algorithms in order to recover from transient failures such as\n * those failures caused by network or proxies (intermediaries).\n *\n * The algorithm may also choose to fail-fast, e.g. switch the client to some\n * offline mode.\n *\n * Extra measurements and logging could also be implemented in the custom\n * module, which has the full knowledge of all the state transitions\n * (due to failures).\n *\n * A default algorithm will be provided by the webchannel library itself. Custom\n * algorithms are expected to be tailored to specific client platforms or\n * networking environments, e.g. mobile, cellular network.\n *\n * @interface\n */\ngoog.net.WebChannel.FailureRecovery = function() {};\n\n\n/**\n * Configuration spec for newly created WebChannel instances.\n *\n * WebChannels are configured in the context of the containing\n * {@link WebChannelTransport}. The configuration parameters are specified\n * when a new instance of WebChannel is created via {@link WebChannelTransport}.\n * @record\n */\ngoog.net.WebChannel.Options = function() {};\n\n/**\n * Transport-metadata support.\n *\n * Custom HTTP headers to be added to every message sent to the\n * server. This object is mutable, and custom headers may be changed, removed,\n * or added during the runtime after a channel has been opened.\n *\n * Custom headers may trigger CORS preflight. See other related options.\n * @type {!Object<string, string>|undefined}\n */\ngoog.net.WebChannel.Options.prototype.messageHeaders;\n\n/**\n * Transport-metadata support.\n *\n * Similar to messageHeaders, but any custom HTTP headers will\n * be sent only once when the channel is opened as part of the handshae request.\n * Typical usage is to send an auth header to the server, which only checks\n * the auth header at the time during the handshake when the channel is opened.\n * @type {!Object<string, string>|undefined}\n */\ngoog.net.WebChannel.Options.prototype.initMessageHeaders;\n\n/**\n * Sent as initMessageHeaders via X-WebChannel-Content-Type,\n * to inform the server the MIME type of WebChannel messages.\n * @type {string|undefined}\n */\ngoog.net.WebChannel.Options.prototype.messageContentType;\n\n/**\n * Transport-metadata support.\n *\n * Custom url query parameters to be added to every message\n * sent to the server. This object is mutable, and custom parameters may be\n * changed, removed or added during the runtime after a channel has been opened.\n *\n * TODO: initMessageUrlParams\n * TODO: closeMessageUrlParams  (custom url query params to be added to the\n * channel-close message. Custom headers are not supported due to the use of\n * SendBeacon)\n *\n * @type {!Object<string, string>|undefined}\n */\ngoog.net.WebChannel.Options.prototype.messageUrlParams;\n\n/**\n * Whether a special header should be added to\n * each message so that the server can dispatch webchannel messages without\n * knowing the URL path prefix. Defaults to false.\n * @type {boolean|undefined}\n */\ngoog.net.WebChannel.Options.prototype.clientProtocolHeaderRequired;\n\n/**\n * The maximum number of in-flight HTTP requests allowed\n * when SPDY is enabled. Currently we only detect SPDY in Chrome.\n * This parameter defaults to 10. When SPDY is not enabled, this parameter\n * will have no effect.\n * @type {number|undefined}\n */\ngoog.net.WebChannel.Options.prototype.concurrentRequestLimit;\n\n/**\n * Setting this to true to allow the use of sub-domains\n * (as configured by the server) to send XHRs with the CORS withCredentials\n * bit set to true.\n * @type {boolean|undefined}\n */\ngoog.net.WebChannel.Options.prototype.supportsCrossDomainXhr;\n\n/**\n * Whether to bypass v8 encoding of client-sent messages.\n * This defaults to false now due to legacy servers. New applications should\n * always configure this option to true.\n * @type {boolean|undefined}\n */\ngoog.net.WebChannel.Options.prototype.sendRawJson;\n\n/**\n * The URL parameter name that contains the session id (for sticky routing of\n * HTTP requests). When this param is specified, a server that supports this\n * option will respond with an opaque session id as part of the initial\n * handshake (via the X-HTTP-Session-Id header); and all the subsequent requests\n * will contain the httpSessionIdParam. This option will take precedence over\n * any duplicated parameter specified with messageUrlParams, whose value will be\n * ignored.\n * @type {string|undefined}\n */\ngoog.net.WebChannel.Options.prototype.httpSessionIdParam;\n\n/**\n * The URL parameter name to allow custom HTTP\n * headers to be overwritten as a URL param to bypass CORS preflight.\n *\n * @type {string|undefined}\n */\ngoog.net.WebChannel.Options.prototype.httpHeadersOverwriteParam;\n\n/**\n * Whether to encode Options.initMessageHeaders in the HTTP request body.\n * This option defaults to false. If true, Options.httpHeadersOverwriteParam\n * will be ignored.\n *\n * This option should not be set if Options.fastHandshake is set (which\n * uses GET for handshake).\n *\n * Web-only feature.\n *\n * @type {boolean|undefined}\n */\ngoog.net.WebChannel.Options.prototype.encodeInitMessageHeaders;\n\n/**\n * Whether to force long-polling from client to server.\n * This defaults to false. Long-polling may be necessary when a (MITM) proxy\n * is buffering data sent by the server.\n * @type {boolean|undefined}\n */\ngoog.net.WebChannel.Options.prototype.forceLongPolling;\n\n/**\n * Whether to enable automatic detection of buffering proxies. In the presence\n * of any buffering proxy, webchannel will use long-polling to send messages\n * from the server to the client. This option defaults to false.\n * Currently when fastHandshake is enabled, this option will be ignored.\n * Compared to \"forceLongPolling\", this option may introduce up to 2-RTT\n * extra latency for delivering messages generated immediately after the\n * handshake.\n * @type {boolean|undefined}\n */\ngoog.net.WebChannel.Options.prototype.detectBufferingProxy;\n\n/**\n * Enable true 0-RTT message delivery, including\n * leveraging QUIC 0-RTT (which requires GET to be used). This option\n * defaults to false. Note it is allowed to send messages before Open event is\n * received, after a channel has been opened. In order to enable 0-RTT,\n * messages will be encoded as part of URL and therefore there needs be a size\n * limit for those initial messages that are sent immediately as part of the\n * GET handshake request. With sendRawJson=true, this limit is currently set\n * to 4K chars and data beyond this limit will be buffered till the handshake\n * (1-RTT) finishes. With sendRawJson=false, it's up to the application\n * to limit the amount of data that is sent as part of the handshake.\n * @type {boolean|undefined}\n */\ngoog.net.WebChannel.Options.prototype.fastHandshake;\n\n/**\n * Enable the blocking RPC semantics for the handshake:\n * 1) the completion of handshake is blocked by the server-side application\n * logic for handling the handshake (HTTP) request; 2) the client application\n * will inspect the handshake (HTTP) response headers as generated\n * by the server application (v.s. by only the webchannel runtime). This option\n * defaults to false.\n * @type {boolean|undefined}\n */\ngoog.net.WebChannel.Options.prototype.blockingHandshake;\n\n/**\n * Whether to disable logging redact. By default, redact is\n * enabled to remove any message payload or user-provided info\n * from closure logs.\n * @type {boolean|undefined}\n */\ngoog.net.WebChannel.Options.prototype.disableRedact;\n\n/**\n * Inform the server about the client profile to enable\n * customized configs that are optimized for certain clients or environments.\n * Currently this information is sent via X-WebChannel-Client-Profile header.\n * @type {string|undefined}\n */\ngoog.net.WebChannel.Options.prototype.clientProfile;\n\n/**\n * The internal channel parameter name to allow\n * experimental channel configurations. Supported options include fastfail,\n * baseRetryDelayMs, retryDelaySeedMs, forwardChannelMaxRetries and\n * forwardChannelRequestTimeoutMs. Note that these options are subject to\n * change.\n * @type {!Object<string, boolean|number>|undefined}\n */\ngoog.net.WebChannel.Options.prototype.internalChannelParams;\n\n/**\n * Allows the caller to override the factory used to create\n * XMLHttpRequest objects. This is introduced to disable CORS on firefox OS.\n * @type {!goog.net.XmlHttpFactory|undefined}\n */\ngoog.net.WebChannel.Options.prototype.xmlHttpFactory;\n\n/**\n * Client-side thresholds that decide when to refresh\n * an underlying HTTP request, to limit memory consumption due to XHR buffering\n * or compression context. The client-side thresholds should be significantly\n * smaller than the server-side thresholds. This allows the client to eliminate\n * any latency introduced by request refreshing, i.e. an RTT window during which\n * messages may be buffered on the server-side. Supported params include\n * totalBytesReceived, totalDurationMs.\n * @type {!Object<string, number>|undefined}\n */\ngoog.net.WebChannel.Options.prototype.requestRefreshThresholds;\n\n/**\n * This is an experimental feature to use WHATWG Fetch/streams (when supported)\n * for the backchannel. If a custom 'xmlHttpFactory' is speficied, this option\n * will not be effective. This option defaults to false now and will eventually\n * be turned on by default.\n * @type {boolean|undefined}\n */\ngoog.net.WebChannel.Options.prototype.useFetchStreams;\n\n/**\n * Opt-in to enable Chrome origin trials from the WebChannel client. See\n * https://github.com/GoogleChrome/OriginTrials\n *\n * Origin trial history:\n * - fetch upload (11/2020 - 07/2021)\n * https://developers.chrome.com/origintrials/#/view_trial/3524066708417413121\n *\n * Participating in the origin trials will help Chrome to release new Web\n * platform features sooner, which will in turn help improve WebChannel\n * performance.\n *\n * Origin trials are not expected to interfere with WebChannel wire messages\n * and should not introduce any noticeable overhead.\n *\n * This is enabled by default with any on-going origin-trial.\n *\n * @type {boolean|undefined}\n */\ngoog.net.WebChannel.Options.prototype.enableOriginTrials;\n\n\n/**\n * Types that are allowed as message data.\n *\n * Note that JS objects (sent by the client) can only have string encoded\n * values due to the limitation of the current wire protocol.\n *\n * Unicode strings (sent by the server) may or may not need be escaped, as\n * decided by the server.\n *\n * @typedef {(!ArrayBuffer|!Blob|!Object<string, !Object|string>|!Array|string)}\n */\ngoog.net.WebChannel.MessageData;\n\n\n/**\n * Open the WebChannel against the URI specified in the constructor.\n */\ngoog.net.WebChannel.prototype.open = goog.abstractMethod;\n\n\n/**\n * Close the WebChannel.\n *\n * This is a full close (shutdown) with no guarantee of FIFO delivery in respect\n * to any in-flight messages sent to the server.\n *\n * If you need such a guarantee, see the Half the halfClose() method.\n */\ngoog.net.WebChannel.prototype.close = goog.abstractMethod;\n\n\n/**\n * Half-close the WebChannel.\n *\n * Half-close semantics:\n * 1. delivered as a regular message in FIFO programming order\n * 2. the server is expected to return a half-close too (with or without\n *    application involved), which will trigger a full close (shutdown)\n *    on the client side\n * 3. for now, the half-close event defined for server-initiated\n *    half-close is not exposed to the client application\n * 4. a client-side half-close may be triggered internally when the client\n *    receives a half-close from the server; and the client is expected to\n *    do a full close after the half-close is acked and delivered\n *    on the server-side.\n * 5. Full close is always a forced one. See the close() method.\n *\n * New messages sent after halfClose() will be dropped.\n *\n * NOTE: This is not yet implemented, and will throw an exception if called.\n */\ngoog.net.WebChannel.prototype.halfClose = goog.abstractMethod;\n\n\n/**\n * Sends a message to the server that maintains the other endpoint of\n * the WebChannel.\n *\n * O-RTT behavior:\n * 1. messages sent before open() is called will always be delivered as\n *    part of the handshake, i.e. with 0-RTT\n * 2. messages sent after open() is called but before the OPEN event\n *    is received will be delivered as part of the handshake if\n *    send() is called from the same execution context as open().\n * 3. otherwise, those messages will be buffered till the handshake\n *    is completed (which will fire the OPEN event).\n *\n * @param {!goog.net.WebChannel.MessageData} message The message to send.\n */\ngoog.net.WebChannel.prototype.send = goog.abstractMethod;\n\n\n/**\n * Common events fired by WebChannels.\n * @enum {string}\n */\ngoog.net.WebChannel.EventType = {\n  /** Dispatched when the channel is opened. */\n  OPEN: goog.events.getUniqueId('open'),\n\n  /** Dispatched when the channel is closed. */\n  CLOSE: goog.events.getUniqueId('close'),\n\n  /**\n   * Dispatched when the channel is aborted due to errors.\n   *\n   * For backward compatibility reasons, a CLOSE event will also be\n   * dispatched, following the ERROR event, which indicates that the channel\n   * has been completely shutdown .\n   */\n  ERROR: goog.events.getUniqueId('error'),\n\n  /** Dispatched when the channel has received a new message. */\n  MESSAGE: goog.events.getUniqueId('message')\n};\n\n\n\n/**\n * The event interface for the MESSAGE event.\n *\n * @constructor\n * @extends {goog.events.Event}\n */\ngoog.net.WebChannel.MessageEvent = function() {\n  'use strict';\n  goog.net.WebChannel.MessageEvent.base(\n      this, 'constructor', goog.net.WebChannel.EventType.MESSAGE);\n};\ngoog.inherits(goog.net.WebChannel.MessageEvent, goog.events.Event);\n\n\n/**\n * The content of the message received from the server.\n *\n * @type {!goog.net.WebChannel.MessageData}\n */\ngoog.net.WebChannel.MessageEvent.prototype.data;\n\n\n/**\n * The metadata key when the MESSAGE event represents a metadata message.\n *\n * @type {string|undefined}\n */\ngoog.net.WebChannel.MessageEvent.prototype.metadataKey;\n\n\n/**\n * Metadata as HTTP status code. Typically sent before the channel is\n * half-closed by the server. To be implemented.\n *\n * @type {number|undefined}\n */\ngoog.net.WebChannel.MessageEvent.prototype.statusCode;\n\n\n/**\n * Metadata as HTTP headers. Typically sent before the channel is\n * half-closed by the server. To be implemented.\n *\n * @type {!Object<string, string>|undefined}\n */\ngoog.net.WebChannel.MessageEvent.prototype.responseHeaders;\n\n\n/**\n * WebChannel level error conditions.\n *\n * Summary of error debugging and reporting in WebChannel:\n *\n * Network Error\n * 1. By default the webchannel library will set the error status to\n *    NETWORK_ERROR when a channel has to be aborted or closed. NETWORK_ERROR\n *    may be recovered by the application by retrying and opening a new channel.\n * 2. There may be lost messages (not acked by the server) when a channel is\n *    aborted. Currently we don't have a public API to retrieve messages that\n *    are waiting to be acked on the client side. File a bug if you think it\n *    is useful to expose such an API.\n * 3. Details of why a channel fails are available via closure debug logs,\n *    and stats events (see webchannel/requeststats.js). Those are internal\n *    stats and are subject to change. File a bug if you think it's useful to\n *    version and expose such stats as part of the WebChannel API.\n *\n * Server Error\n * 1. SERVER_ERROR is intended to indicate a non-recoverable condition, e.g.\n *    when auth fails.\n * 2. We don't currently generate any such errors, because most of the time\n *    it's the responsibility of upper-layer frameworks or the application\n *    itself to indicate to the client why a webchannel has been failed\n *    by the server.\n * 3. When a channel is failed by the server explicitly, we still signal\n *    NETWORK_ERROR to the client. Explicit server failure may happen when the\n *    server does a fail-over, or becomes overloaded, or conducts a forced\n *    shutdown etc.\n * 4. We use some heuristic to decide if the network (aka cloud) is down\n *    v.s. the actual server is down.\n *\n *  RuntimeProperties.getLastStatusCode is a useful state that we expose to\n *  the client to indicate the HTTP response status code of the last HTTP\n *  request initiated by the WebChannel client library, for debugging\n *  purposes only.\n *\n *  See WebChannel.Options.backChannelFailureRecovery and\n *  WebChannel.FailureRecovery to install a custom failure-recovery algorithm.\n *\n * @enum {number}\n */\ngoog.net.WebChannel.ErrorStatus = {\n  /** No error has occurred. */\n  OK: 0,\n\n  /** Communication to the server has failed. */\n  NETWORK_ERROR: 1,\n\n  /** The server fails to accept or process the WebChannel. */\n  SERVER_ERROR: 2\n};\n\n\n\n/**\n * The event interface for the ERROR event.\n *\n * @constructor\n * @extends {goog.events.Event}\n */\ngoog.net.WebChannel.ErrorEvent = function() {\n  'use strict';\n  goog.net.WebChannel.ErrorEvent.base(\n      this, 'constructor', goog.net.WebChannel.EventType.ERROR);\n};\ngoog.inherits(goog.net.WebChannel.ErrorEvent, goog.events.Event);\n\n\n/**\n * The error status.\n *\n * @type {!goog.net.WebChannel.ErrorStatus}\n */\ngoog.net.WebChannel.ErrorEvent.prototype.status;\n\n\n/**\n * @return {!goog.net.WebChannel.RuntimeProperties} The runtime properties\n * of the WebChannel instance.\n */\ngoog.net.WebChannel.prototype.getRuntimeProperties = goog.abstractMethod;\n\n\n\n/**\n * The runtime properties of the WebChannel instance.\n *\n * This class is defined for debugging and monitoring purposes, as well as for\n * runtime functions that the application may choose to manage by itself.\n *\n * @interface\n */\ngoog.net.WebChannel.RuntimeProperties = function() {};\n\n\n/**\n * @return {number} The effective limit for the number of concurrent HTTP\n * requests that are allowed to be made for sending messages from the client\n * to the server. When SPDY is not enabled, this limit will be one.\n */\ngoog.net.WebChannel.RuntimeProperties.prototype.getConcurrentRequestLimit =\n    goog.abstractMethod;\n\n\n/**\n * For applications that need support multiple channels (e.g. from\n * different tabs) to the same origin, use this method to decide if SPDY is\n * enabled and therefore it is safe to open multiple channels.\n *\n * If SPDY is disabled, the application may choose to limit the number of active\n * channels to one or use other means such as sub-domains to work around\n * the browser connection limit.\n *\n * @return {boolean} Whether SPDY is enabled for the origin against which\n * the channel is created.\n */\ngoog.net.WebChannel.RuntimeProperties.prototype.isSpdyEnabled =\n    goog.abstractMethod;\n\n\n/**\n * @return {number} The number of requests (for sending messages to the server)\n * that are pending. If this number is approaching the value of\n * getConcurrentRequestLimit(), client-to-server message delivery may experience\n * a higher latency.\n */\ngoog.net.WebChannel.RuntimeProperties.prototype.getPendingRequestCount =\n    goog.abstractMethod;\n\n\n/**\n * For applications to query the current HTTP session id, sent by the server\n * during the initial handshake.\n *\n * @return {?string} the HTTP session id or null if no HTTP session is in use.\n */\ngoog.net.WebChannel.RuntimeProperties.prototype.getHttpSessionId =\n    goog.abstractMethod;\n\n\n/**\n * Experimental API.\n *\n * This method generates an in-band commit request to the server, which will\n * ack the commit request as soon as all messages sent prior to this commit\n * request have been committed by the application.\n *\n * Committing a message has a stronger semantics than delivering a message\n * to the application. Detail spec:\n * https://github.com/bidiweb/webchannel/blob/master/commit.md\n *\n * Timeout or cancellation is not supported and the application is expected to\n * abort the channel if the commit-ack fails to arrive in time.\n *\n * ===\n *\n * This is currently implemented only in the client layer and the commit\n * callback will be invoked after all the pending client-sent messages have been\n * delivered by the server-side webchannel endpoint. This semantics is\n * different and weaker than what's required for end-to-end ack which requires\n * the server application to ack the in-order delivery of messages that are sent\n * before the commit request is issued.\n *\n * Commit should only be called after the channel open event is received.\n * Duplicated commits are allowed and only the last callback is guaranteed.\n * Commit called after the channel has been closed will be ignored.\n *\n * @param {function()} callback The callback will be invoked once an\n * ack has been received for the current commit or any newly issued commit.\n */\ngoog.net.WebChannel.RuntimeProperties.prototype.commit = goog.abstractMethod;\n\n\n/**\n * This method may be used by the application to recover from a peer failure\n * or to enable sender-initiated flow-control.\n *\n * Detail spec: https://github.com/bidiweb/webchannel/blob/master/commit.md\n *\n * Note that the caller should NOT modify the list of returned messages.\n *\n * @return {!Array<!goog.net.WebChannel.MessageData>} The list of messages that\n * have not received commit-ack from the server; or if no commit has been\n * issued, the list of messages that have not been delivered to the server\n * application.\n */\ngoog.net.WebChannel.RuntimeProperties.prototype.getNonAckedMessages =\n    goog.abstractMethod;\n\n\n/**\n * A low water-mark message count to notify the application when the\n * flow-control condition is cleared, that is, when the application is\n * able to send more messages.\n *\n * We expect the application to configure a high water-mark message count,\n * which is checked via getNonAckedMessageCount(). When the high water-mark\n * is exceeded, the application should install a callback via this method\n * to be notified when to start to send new messages.\n *\n * This is not yet implemented.\n *\n * @param {number} count The low water-mark count. It is an error to pass\n * a non-positive value.\n * @param {function()} callback The call back to notify the application\n * when NonAckedMessageCount is below the specified low water-mark count.\n * Any previously registered callback is cleared. This new callback will\n * be cleared once it has been fired, or when the channel is closed or aborted.\n */\ngoog.net.WebChannel.RuntimeProperties.prototype.notifyNonAckedMessageCount =\n    goog.abstractMethod;\n\n\n/**\n * Experimental API.\n *\n * This method registers a callback to handle the commit request sent\n * by the server. Commit protocol spec:\n * https://github.com/bidiweb/webchannel/blob/master/commit.md\n *\n * This is not yet implemented.\n *\n * @param {function(!Object)} callback The callback will take an opaque\n * commitId which needs be passed back to the server when an ack-commit\n * response is generated by the client application, via ackCommit().\n */\ngoog.net.WebChannel.RuntimeProperties.prototype.onCommit = goog.abstractMethod;\n\n\n/**\n * Experimental API.\n *\n * This method is used by the application to generate an ack-commit response\n * for the given commitId. Commit protocol spec:\n * https://github.com/bidiweb/webchannel/blob/master/commit.md\n *\n * This is not yet implemented.\n *\n * @param {!Object} commitId The commitId which denotes the commit request\n * from the server that needs be ack'ed.\n */\ngoog.net.WebChannel.RuntimeProperties.prototype.ackCommit = goog.abstractMethod;\n\n\n/**\n * Transport-metadata support.\n *\n * TODO: getLastResponseHeaders (only for non-200 status)\n * TODO: getInitStatusCode   (handshake)\n * TODO: getInitResponseHeaders  (handshake)\n *\n * Note that response headers from client-initiated close (abort) are not\n * available.\n *\n * In future when client-initiated half-close is supported, its response status\n * will be available via this API.\n *\n * @return {number} The non-200 HTTP status code received that causes the\n * channel to be aborted.\n */\ngoog.net.WebChannel.RuntimeProperties.prototype.getLastStatusCode =\n    goog.abstractMethod;\n\n\n/**\n * Enum to indicate the current recovery state.\n *\n * @enum {string}\n */\ngoog.net.WebChannel.FailureRecovery.State = {\n  /** Initial state. */\n  INIT: 'init',\n\n  /** Once a failure has been detected. */\n  FAILED: 'failed',\n\n  /**\n   * Once a recovery operation has been issued, e.g. a new request to resume\n   * communication.\n   */\n  RECOVERING: 'recovering',\n\n  /** The channel has been closed.  */\n  CLOSED: 'closed'\n};\n\n\n/**\n * Enum to indicate different failure conditions as detected by the webchannel\n * runtime.\n *\n * This enum is to be used only between the runtime and FailureRecovery module,\n * and new states are expected to be introduced in future.\n *\n * @enum {string}\n */\ngoog.net.WebChannel.FailureRecovery.FailureCondition = {\n  /**\n   * The HTTP response returned a non-successful http status code.\n   */\n  HTTP_ERROR: 'http_error',\n\n  /**\n   * The request was aborted.\n   */\n  ABORT: 'abort',\n\n  /**\n   * The request timed out.\n   */\n  TIMEOUT: 'timeout',\n\n  /**\n   * Exception was thrown while processing the request/response.\n   */\n  EXCEPTION: 'exception'\n};\n\n\n/**\n * @return {!goog.net.WebChannel.FailureRecovery.State} the current state,\n * mainly for debugging use.\n */\ngoog.net.WebChannel.FailureRecovery.prototype.getState = goog.abstractMethod;\n\n\n/**\n * This method is for WebChannel runtime to set the current failure condition\n * and to provide a callback for the algorithm to signal to the runtime\n * when it is time to issue a recovery operation, e.g. a new request to the\n * server.\n *\n * Supported transitions include:\n *   INIT->FAILED\n *   FAILED->FAILED (re-entry ok)\n *   RECOVERY->FAILED.\n *\n * Ignored if state == CLOSED.\n *\n * Advanced implementations are expected to track all the state transitions\n * and their timestamps for monitoring purposes.\n *\n * @param {!goog.net.WebChannel.FailureRecovery.FailureCondition} failure The\n * new failure condition generated by the WebChannel runtime.\n * @param {!Function} operation The callback function to the WebChannel\n * runtime to issue a recovery operation, e.g. a new request. E.g. the default\n * recovery algorithm will issue timeout-based recovery operations.\n * Post-condition for the callback: state transition to RECOVERING.\n *\n * @return {!goog.net.WebChannel.FailureRecovery.State} The updated state\n * as decided by the failure recovery module. Upon a recoverable failure event,\n * the state is transitioned to RECOVERING; or the state is transitioned to\n * FAILED which indicates a fail-fast decision for the runtime to execute.\n */\ngoog.net.WebChannel.FailureRecovery.prototype.setFailure = goog.abstractMethod;\n\n\n/**\n * The Webchannel runtime needs call this method when webchannel is closed or\n * aborted.\n *\n * Once the instance is closed, any access to the instance will be a no-op.\n */\ngoog.net.WebChannel.FailureRecovery.prototype.close = goog.abstractMethod;\n\n\n/**\n * A request header to indicate to the server the messaging protocol\n * each HTTP message is speaking.\n *\n * @type {string}\n */\ngoog.net.WebChannel.X_CLIENT_PROTOCOL = 'X-Client-Protocol';\n\n\n/**\n * The value for x-client-protocol when the messaging protocol is WebChannel.\n *\n * @type {string}\n */\ngoog.net.WebChannel.X_CLIENT_PROTOCOL_WEB_CHANNEL = 'webchannel';\n\n\n/**\n * A response header for the server to signal the wire-protocol that\n * the browser establishes with the server (or proxy), e.g. \"spdy\" (aka http/2)\n * \"quic\". This information avoids the need to use private APIs to decide if\n * HTTP requests are multiplexed etc.\n *\n * @type {string}\n */\ngoog.net.WebChannel.X_CLIENT_WIRE_PROTOCOL = 'X-Client-Wire-Protocol';\n\n\n/**\n * A response header for the server to send back the HTTP session id as part of\n * the initial handshake. The value of the HTTP session id is opaque to the\n * WebChannel protocol.\n *\n * @type {string}\n */\ngoog.net.WebChannel.X_HTTP_SESSION_ID = 'X-HTTP-Session-Id';\n\n\n/**\n * A response header for the server to send back any initial response data as a\n * header to avoid any possible buffering by an intermediary, which may\n * be undesired during the handshake.\n *\n * @type {string}\n */\ngoog.net.WebChannel.X_HTTP_INITIAL_RESPONSE = 'X-HTTP-Initial-Response';\n\n\n/**\n * A request header for specifying the content-type of WebChannel messages,\n * e.g. application-defined JSON encoding styles. Currently this header\n * is sent by the client via initMessageHeaders when the channel is opened.\n *\n * @type {string}\n */\ngoog.net.WebChannel.X_WEBCHANNEL_CONTENT_TYPE = 'X-WebChannel-Content-Type';\n\n\n/**\n * A request header for specifying the client profile in order to apply\n * customized config params on the server side, e.g. timeouts.\n *\n * @type {string}\n */\ngoog.net.WebChannel.X_WEBCHANNEL_CLIENT_PROFILE = 'X-WebChannel-Client-Profile';\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Low level handling of XMLHttpRequest.\n */\n\ngoog.provide('goog.net.DefaultXmlHttpFactory');\ngoog.provide('goog.net.XmlHttp');\ngoog.provide('goog.net.XmlHttp.OptionType');\ngoog.provide('goog.net.XmlHttp.ReadyState');\ngoog.provide('goog.net.XmlHttpDefines');\n\ngoog.require('goog.asserts');\ngoog.require('goog.net.WrapperXmlHttpFactory');\ngoog.require('goog.net.XmlHttpFactory');\ngoog.requireType('goog.net.XhrLike');\n\n\n/**\n * Static class for creating XMLHttpRequest objects.\n * @return {!goog.net.XhrLike.OrNative} A new XMLHttpRequest object.\n */\ngoog.net.XmlHttp = function() {\n  'use strict';\n  return goog.net.XmlHttp.factory_.createInstance();\n};\n\n\n/**\n * @define {boolean} Whether to assume XMLHttpRequest exists. Setting this to\n *     true bypasses the ActiveX probing code.\n * NOTE(ruilopes): Due to the way JSCompiler works, this define *will not* strip\n * out the ActiveX probing code from binaries.  To achieve this, use\n * `goog.net.XmlHttpDefines.ASSUME_NATIVE_XHR` instead.\n * TODO(ruilopes): Collapse both defines.\n */\ngoog.net.XmlHttp.ASSUME_NATIVE_XHR =\n    goog.define('goog.net.XmlHttp.ASSUME_NATIVE_XHR', false);\n\n\n/** @const */\ngoog.net.XmlHttpDefines = {};\n\n\n/**\n * @define {boolean} Whether to assume XMLHttpRequest exists. Setting this to\n *     true eliminates the ActiveX probing code.\n */\ngoog.net.XmlHttpDefines.ASSUME_NATIVE_XHR =\n    goog.define('goog.net.XmlHttpDefines.ASSUME_NATIVE_XHR', false);\n\n\n/**\n * Gets the options to use with the XMLHttpRequest objects obtained using\n * the static methods.\n * @return {Object} The options.\n */\ngoog.net.XmlHttp.getOptions = function() {\n  'use strict';\n  return goog.net.XmlHttp.factory_.getOptions();\n};\n\n\n/**\n * Type of options that an XmlHttp object can have.\n * @enum {number}\n */\ngoog.net.XmlHttp.OptionType = {\n  /**\n   * Whether a goog.nullFunction should be used to clear the onreadystatechange\n   * handler instead of null.\n   */\n  USE_NULL_FUNCTION: 0,\n\n  /**\n   * NOTE(user): In IE if send() errors on a *local* request the readystate\n   * is still changed to COMPLETE.  We need to ignore it and allow the\n   * try/catch around send() to pick up the error.\n   */\n  LOCAL_REQUEST_ERROR: 1,\n};\n\n\n/**\n * Status constants for XMLHTTP, matches:\n * https://msdn.microsoft.com/en-us/library/ms534361(v=vs.85).aspx\n * @enum {number}\n */\ngoog.net.XmlHttp.ReadyState = {\n  /**\n   * Constant for when xmlhttprequest.readyState is uninitialized\n   */\n  UNINITIALIZED: 0,\n\n  /**\n   * Constant for when xmlhttprequest.readyState is loading.\n   */\n  LOADING: 1,\n\n  /**\n   * Constant for when xmlhttprequest.readyState is loaded.\n   */\n  LOADED: 2,\n\n  /**\n   * Constant for when xmlhttprequest.readyState is in an interactive state.\n   */\n  INTERACTIVE: 3,\n\n  /**\n   * Constant for when xmlhttprequest.readyState is completed\n   */\n  COMPLETE: 4,\n};\n\n\n/**\n * The global factory instance for creating XMLHttpRequest objects.\n * @type {goog.net.XmlHttpFactory}\n * @private\n */\ngoog.net.XmlHttp.factory_;\n\n\n/**\n * Sets the factories for creating XMLHttpRequest objects and their options.\n * @param {Function} factory The factory for XMLHttpRequest objects.\n * @param {Function} optionsFactory The factory for options.\n * @deprecated Use setGlobalFactory instead.\n */\ngoog.net.XmlHttp.setFactory = function(factory, optionsFactory) {\n  'use strict';\n  goog.net.XmlHttp.setGlobalFactory(new goog.net.WrapperXmlHttpFactory(\n      goog.asserts.assert(factory), goog.asserts.assert(optionsFactory)));\n};\n\n\n/**\n * Sets the global factory object.\n * @param {!goog.net.XmlHttpFactory} factory New global factory object.\n */\ngoog.net.XmlHttp.setGlobalFactory = function(factory) {\n  'use strict';\n  goog.net.XmlHttp.factory_ = factory;\n};\n\n\n\n/**\n * Default factory to use when creating xhr objects.  You probably shouldn't be\n * instantiating this directly, but rather using it via goog.net.XmlHttp.\n * @extends {goog.net.XmlHttpFactory}\n * @constructor\n */\ngoog.net.DefaultXmlHttpFactory = function() {\n  'use strict';\n  goog.net.XmlHttpFactory.call(this);\n};\ngoog.inherits(goog.net.DefaultXmlHttpFactory, goog.net.XmlHttpFactory);\n\n\n/** @override */\ngoog.net.DefaultXmlHttpFactory.prototype.createInstance = function() {\n  'use strict';\n  const progId = this.getProgId_();\n  if (progId) {\n    return new ActiveXObject(progId);\n  } else {\n    return new XMLHttpRequest();\n  }\n};\n\n\n/** @override */\ngoog.net.DefaultXmlHttpFactory.prototype.internalGetOptions = function() {\n  'use strict';\n  const progId = this.getProgId_();\n  const options = {};\n  if (progId) {\n    options[goog.net.XmlHttp.OptionType.USE_NULL_FUNCTION] = true;\n    options[goog.net.XmlHttp.OptionType.LOCAL_REQUEST_ERROR] = true;\n  }\n  return options;\n};\n\n\n/**\n * The ActiveX PROG ID string to use to create xhr's in IE. Lazily initialized.\n * @type {string|undefined}\n * @private\n */\ngoog.net.DefaultXmlHttpFactory.prototype.ieProgId_;\n\n\n/**\n * Initialize the private state used by other functions.\n * @return {string} The ActiveX PROG ID string to use to create xhr's in IE.\n * @private\n */\ngoog.net.DefaultXmlHttpFactory.prototype.getProgId_ = function() {\n  'use strict';\n  if (goog.net.XmlHttp.ASSUME_NATIVE_XHR ||\n      goog.net.XmlHttpDefines.ASSUME_NATIVE_XHR) {\n    return '';\n  }\n\n  // The following blog post describes what PROG IDs to use to create the\n  // XMLHTTP object in Internet Explorer:\n  // http://blogs.msdn.com/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx\n  // However we do not (yet) fully trust that this will be OK for old versions\n  // of IE on Win9x so we therefore keep the last 2.\n  if (!this.ieProgId_ && typeof XMLHttpRequest == 'undefined' &&\n      typeof ActiveXObject != 'undefined') {\n    // Candidate Active X types.\n    const ACTIVE_X_IDENTS = [\n      'MSXML2.XMLHTTP.6.0',\n      'MSXML2.XMLHTTP.3.0',\n      'MSXML2.XMLHTTP',\n      'Microsoft.XMLHTTP',\n    ];\n    for (let i = 0; i < ACTIVE_X_IDENTS.length; i++) {\n      const candidate = ACTIVE_X_IDENTS[i];\n\n      try {\n        new ActiveXObject(candidate);\n        // NOTE(user): cannot assign progid and return candidate in one line\n        // because JSCompiler complaings: BUG 658126\n        this.ieProgId_ = candidate;\n        return candidate;\n      } catch (e) {\n        // do nothing; try next choice\n      }\n    }\n\n    // couldn't find any matches\n    throw new Error(\n        'Could not create ActiveXObject. ActiveX might be disabled,' +\n        ' or MSXML might not be installed');\n  }\n\n  return /** @type {string} */ (this.ieProgId_);\n};\n\n\n// Set the global factory to an instance of the default factory.\ngoog.net.XmlHttp.setGlobalFactory(new goog.net.DefaultXmlHttpFactory());\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Definition of the ChannelRequest class. The request\n * object encapsulates the logic for making a single request, either for the\n * forward channel, back channel, or test channel, to the server. It contains\n * the logic for the two types of transports we use:\n * XMLHTTP and Image request. It provides timeout detection. More transports\n * to be added in future, such as Fetch, WebSocket.\n *\n */\n\n\ngoog.provide('goog.labs.net.webChannel.ChannelRequest');\n\ngoog.require('goog.Timer');\ngoog.require('goog.asserts');\ngoog.require('goog.async.Throttle');\ngoog.require('goog.dispose');\ngoog.require('goog.events.EventHandler');\ngoog.require('goog.labs.net.webChannel.Channel');\ngoog.require('goog.labs.net.webChannel.WebChannelDebug');\ngoog.require('goog.labs.net.webChannel.environment');\ngoog.require('goog.labs.net.webChannel.requestStats');\ngoog.require('goog.net.ErrorCode');\ngoog.require('goog.net.EventType');\ngoog.require('goog.net.WebChannel');\ngoog.require('goog.net.XmlHttp');\ngoog.require('goog.object');\ngoog.require('goog.string');\ngoog.require('goog.userAgent');\ngoog.requireType('goog.Uri');\ngoog.requireType('goog.events.Event');\ngoog.requireType('goog.labs.net.webChannel.Wire.QueuedMap');\ngoog.requireType('goog.net.XhrIo');\n\n\n\n/**\n * A new ChannelRequest is created for each request to the server.\n *\n * @param {goog.labs.net.webChannel.Channel} channel\n *     The channel that owns this request.\n * @param {goog.labs.net.webChannel.WebChannelDebug} channelDebug A\n *     WebChannelDebug to use for logging.\n * @param {string=} opt_sessionId The session id for the channel.\n * @param {string|number=} opt_requestId The request id for this request.\n * @param {number=} opt_retryId The retry id for this request.\n * @constructor\n * @struct\n * @final\n */\ngoog.labs.net.webChannel.ChannelRequest = function(\n    channel, channelDebug, opt_sessionId, opt_requestId, opt_retryId) {\n  'use strict';\n  /**\n   * The channel object that owns the request.\n   * @private {goog.labs.net.webChannel.Channel}\n   */\n  this.channel_ = channel;\n\n  /**\n   * The channel debug to use for logging\n   * @private {goog.labs.net.webChannel.WebChannelDebug}\n   */\n  this.channelDebug_ = channelDebug;\n\n  /**\n   * The Session ID for the channel.\n   * @private {string|undefined}\n   */\n  this.sid_ = opt_sessionId;\n\n  /**\n   * The RID (request ID) for the request.\n   * @private {string|number|undefined}\n   */\n  this.rid_ = opt_requestId;\n\n  /**\n   * The attempt number of the current request.\n   * @private {number}\n   */\n  this.retryId_ = opt_retryId || 1;\n\n  /**\n   * An object to keep track of the channel request event listeners.\n   * @private {!goog.events.EventHandler<\n   *     !goog.labs.net.webChannel.ChannelRequest>}\n   */\n  this.eventHandler_ = new goog.events.EventHandler(this);\n\n  /**\n   * The timeout in ms before failing the request.\n   * @private {number}\n   */\n  this.timeout_ = goog.labs.net.webChannel.ChannelRequest.TIMEOUT_MS_;\n\n  /**\n   * A timer for polling responseText in browsers that don't fire\n   * onreadystatechange during incremental loading of responseText.\n   * @private {goog.Timer}\n   */\n  this.pollingTimer_ =\n      new goog.Timer(goog.labs.net.webChannel.environment.getPollingInterval());\n\n  /**\n   * Extra HTTP headers to add to all the requests sent to the server.\n   * @private {?Object}\n   */\n  this.extraHeaders_ = null;\n\n\n  /**\n   * Whether the request was successful. This is only set to true after the\n   * request successfully completes.\n   * @private {boolean}\n   */\n  this.successful_ = false;\n\n\n  /**\n   * The TimerID of the timer used to detect if the request has timed-out.\n   * @type {?number}\n   * @private\n   */\n  this.watchDogTimerId_ = null;\n\n  /**\n   * The time in the future when the request will timeout.\n   * @private {?number}\n   */\n  this.watchDogTimeoutTime_ = null;\n\n  /**\n   * The time the request started.\n   * @private {?number}\n   */\n  this.requestStartTime_ = null;\n\n  /**\n   * The type of request (XMLHTTP, IMG)\n   * @private {?number}\n   */\n  this.type_ = null;\n\n  /**\n   * The base Uri for the request. The includes all the parameters except the\n   * one that indicates the retry number.\n   * @private {?goog.Uri}\n   */\n  this.baseUri_ = null;\n\n  /**\n   * The request Uri that was actually used for the most recent request attempt.\n   * @private {?goog.Uri}\n   */\n  this.requestUri_ = null;\n\n  /**\n   * The post data, if the request is a post.\n   * @private {?string}\n   */\n  this.postData_ = null;\n\n  /**\n   * An array of pending messages that we have either received a non-successful\n   * response for, or no response at all, and which therefore may or may not\n   * have been received by the server.\n   * @private {!Array<goog.labs.net.webChannel.Wire.QueuedMap>}\n   */\n  this.pendingMessages_ = [];\n\n  /**\n   * The XhrLte request if the request is using XMLHTTP\n   * @private {?goog.net.XhrIo}\n   */\n  this.xmlHttp_ = null;\n\n  /**\n   * The position of where the next unprocessed chunk starts in the response\n   * text.\n   * @private {number}\n   */\n  this.xmlHttpChunkStart_ = 0;\n\n  /**\n   * The verb (Get or Post) for the request.\n   * @private {?string}\n   */\n  this.verb_ = null;\n\n  /**\n   * The last error if the request failed.\n   * @private {?goog.labs.net.webChannel.ChannelRequest.Error}\n   */\n  this.lastError_ = null;\n\n  /**\n   * The last status code received.\n   * @private {number}\n   */\n  this.lastStatusCode_ = -1;\n\n  /**\n   * Whether the request has been cancelled due to a call to cancel.\n   * @private {boolean}\n   */\n  this.cancelled_ = false;\n\n  /**\n   * A throttle time in ms for readystatechange events for the backchannel.\n   * Useful for throttling when ready state is INTERACTIVE (partial data).\n   * If set to zero no throttle is used.\n   *\n   * See WebChannelBase.prototype.readyStateChangeThrottleMs_\n   *\n   * @private {number}\n   */\n  this.readyStateChangeThrottleMs_ = 0;\n\n  /**\n   * The throttle for readystatechange events for the current request, or null\n   * if there is none.\n   * @private {?goog.async.Throttle}\n   */\n  this.readyStateChangeThrottle_ = null;\n\n  /**\n   * Whether to the result is expected to be encoded for chunking and thus\n   * requires decoding.\n   * @private {boolean}\n   */\n  this.decodeChunks_ = false;\n\n  /**\n   * Whether to decode x-http-initial-response.\n   * @private {boolean}\n   */\n  this.decodeInitialResponse_ = false;\n\n  /**\n   * Whether x-http-initial-response has been decoded (dispatched).\n   * @private {boolean}\n   */\n  this.initialResponseDecoded_ = false;\n\n  /**\n   * Whether the first byte of response body has arrived, for a successful\n   * response.\n   * @private {boolean}\n   */\n  this.firstByteReceived_ = false;\n\n  /**\n   * The current state of fetch responses if webchannel is using WHATWG\n   * fetch/streams.\n   * @private {!goog.labs.net.webChannel.FetchResponseState}\n   */\n  this.fetchResponseState_ = new goog.labs.net.webChannel.FetchResponseState();\n};\n\n/**\n * A collection of fetch/stream properties.\n * @struct\n * @constructor\n */\ngoog.labs.net.webChannel.FetchResponseState = function() {\n  'use strict';\n  /**\n   * The TextDecoder for decoding Uint8Array responses from fetch request.\n   * @type {?goog.global.TextDecoder}\n   */\n  this.textDecoder = null;\n\n  /**\n   * The unconsumed response text from the fetch requests.\n   * @type {string}\n   */\n  this.responseBuffer = '';\n\n  /**\n   * Whether or not the response body has arrived.\n   * @type {boolean}\n   */\n  this.responseArrivedForFetch = false;\n};\n\n\ngoog.scope(function() {\n'use strict';\nconst WebChannel = goog.net.WebChannel;\nconst Channel = goog.labs.net.webChannel.Channel;\nconst ChannelRequest = goog.labs.net.webChannel.ChannelRequest;\nconst FetchResponseState = goog.labs.net.webChannel.FetchResponseState;\nconst requestStats = goog.labs.net.webChannel.requestStats;\nconst WebChannelDebug = goog.labs.net.webChannel.WebChannelDebug;\nconst environment = goog.labs.net.webChannel.environment;\n\n/**\n * Default timeout in MS for a request. The server must return data within this\n * time limit for the request to not timeout.\n * @private {number}\n */\nChannelRequest.TIMEOUT_MS_ = 45 * 1000;\n\n\n/**\n * Enum for channel requests type\n * @enum {number}\n * @private\n */\nChannelRequest.Type_ = {\n  /**\n   * XMLHTTP requests.\n   */\n  XML_HTTP: 1,\n\n  /**\n   * IMG requests.\n   */\n  CLOSE_REQUEST: 2\n};\n\n\n/**\n * Enum type for identifying an error.\n * @enum {number}\n */\nChannelRequest.Error = {\n  /**\n   * Errors due to a non-200 status code.\n   */\n  STATUS: 0,\n\n  /**\n   * Errors due to no data being returned.\n   */\n  NO_DATA: 1,\n\n  /**\n   * Errors due to a timeout.\n   */\n  TIMEOUT: 2,\n\n  /**\n   * Errors due to the server returning an unknown.\n   */\n  UNKNOWN_SESSION_ID: 3,\n\n  /**\n   * Errors due to bad data being received.\n   */\n  BAD_DATA: 4,\n\n  /**\n   * Errors due to the handler throwing an exception.\n   */\n  HANDLER_EXCEPTION: 5,\n\n  /**\n   * The browser declared itself offline during the request.\n   */\n  BROWSER_OFFLINE: 6\n};\n\n\n/**\n * Returns a useful error string for debugging based on the specified error\n * code.\n * @param {?ChannelRequest.Error} errorCode The error code.\n * @param {number} statusCode The HTTP status code.\n * @return {string} The error string for the given code combination.\n */\nChannelRequest.errorStringFromCode = function(errorCode, statusCode) {\n  'use strict';\n  switch (errorCode) {\n    case ChannelRequest.Error.STATUS:\n      return 'Non-200 return code (' + statusCode + ')';\n    case ChannelRequest.Error.NO_DATA:\n      return 'XMLHTTP failure (no data)';\n    case ChannelRequest.Error.TIMEOUT:\n      return 'HttpConnection timeout';\n    default:\n      return 'Unknown error';\n  }\n};\n\n\n/**\n * Sentinel value used to indicate an invalid chunk in a multi-chunk response.\n * @private {!Object}\n */\nChannelRequest.INVALID_CHUNK_ = {};\n\n\n/**\n * Sentinel value used to indicate an incomplete chunk in a multi-chunk\n * response.\n * @private {!Object}\n */\nChannelRequest.INCOMPLETE_CHUNK_ = {};\n\n\n/**\n * Returns whether XHR streaming is supported on this browser.\n *\n * @return {boolean} Whether XHR streaming is supported.\n * @see http://code.google.com/p/closure-library/issues/detail?id=346\n */\nChannelRequest.supportsXhrStreaming = function() {\n  'use strict';\n  return !goog.userAgent.IE || goog.userAgent.isDocumentModeOrHigher(10);\n};\n\n\n/**\n * Sets extra HTTP headers to add to all the requests sent to the server.\n *\n * @param {Object} extraHeaders The HTTP headers.\n */\nChannelRequest.prototype.setExtraHeaders = function(extraHeaders) {\n  'use strict';\n  this.extraHeaders_ = extraHeaders;\n};\n\n\n/**\n * Overrides the default HTTP method.\n *\n * @param {string} verb The HTTP method\n */\nChannelRequest.prototype.setVerb = function(verb) {\n  'use strict';\n  this.verb_ = verb;\n};\n\n\n/**\n * Sets the timeout for a request\n *\n * @param {number} timeout   The timeout in MS for when we fail the request.\n */\nChannelRequest.prototype.setTimeout = function(timeout) {\n  'use strict';\n  this.timeout_ = timeout;\n};\n\n\n/**\n * Sets the throttle for handling onreadystatechange events for the request.\n *\n * @param {number} throttle The throttle in ms.  A value of zero indicates\n *     no throttle.\n */\nChannelRequest.prototype.setReadyStateChangeThrottle = function(throttle) {\n  'use strict';\n  this.readyStateChangeThrottleMs_ = throttle;\n};\n\n\n/**\n * Sets the pending messages that this request is handling.\n *\n * @param {!Array<goog.labs.net.webChannel.Wire.QueuedMap>} pendingMessages\n *     The pending messages for this request.\n */\nChannelRequest.prototype.setPendingMessages = function(pendingMessages) {\n  'use strict';\n  this.pendingMessages_ = pendingMessages;\n};\n\n\n/**\n * Gets the pending messages that this request is handling, in case of a retry.\n *\n * @return {!Array<goog.labs.net.webChannel.Wire.QueuedMap>} The pending\n *     messages for this request.\n */\nChannelRequest.prototype.getPendingMessages = function() {\n  'use strict';\n  return this.pendingMessages_;\n};\n\n\n/**\n * Uses XMLHTTP to send an HTTP POST to the server.\n *\n * @param {goog.Uri} uri  The uri of the request.\n * @param {?string} postData  The data for the post body.\n * @param {boolean} decodeChunks  Whether to the result is expected to be\n *     encoded for chunking and thus requires decoding.\n */\nChannelRequest.prototype.xmlHttpPost = function(uri, postData, decodeChunks) {\n  'use strict';\n  this.type_ = ChannelRequest.Type_.XML_HTTP;\n  this.baseUri_ = uri.clone().makeUnique();\n  this.postData_ = postData;\n  this.decodeChunks_ = decodeChunks;\n  this.sendXmlHttp_(null /* hostPrefix */);\n};\n\n\n/**\n * Uses XMLHTTP to send an HTTP GET to the server.\n *\n * @param {goog.Uri} uri  The uri of the request.\n * @param {boolean} decodeChunks  Whether to the result is expected to be\n *     encoded for chunking and thus requires decoding.\n * @param {?string} hostPrefix  The host prefix, if we might be using a\n *     secondary domain.  Note that it should also be in the URL, adding this\n *     won't cause it to be added to the URL.\n */\nChannelRequest.prototype.xmlHttpGet = function(uri, decodeChunks, hostPrefix) {\n  'use strict';\n  this.type_ = ChannelRequest.Type_.XML_HTTP;\n  this.baseUri_ = uri.clone().makeUnique();\n  this.postData_ = null;\n  this.decodeChunks_ = decodeChunks;\n\n  this.sendXmlHttp_(hostPrefix);\n};\n\n\n/**\n * Sends a request via XMLHTTP according to the current state of the request\n * object.\n *\n * @param {?string} hostPrefix The host prefix, if we might be using a secondary\n *     domain.\n * @private\n */\nChannelRequest.prototype.sendXmlHttp_ = function(hostPrefix) {\n  'use strict';\n  this.requestStartTime_ = Date.now();\n  this.ensureWatchDogTimer_();\n\n  // clone the base URI to create the request URI. The request uri has the\n  // attempt number as a parameter which helps in debugging.\n  this.requestUri_ = this.baseUri_.clone();\n  this.requestUri_.setParameterValues('t', this.retryId_);\n\n  // send the request either as a POST or GET\n  this.xmlHttpChunkStart_ = 0;\n  const useSecondaryDomains = this.channel_.shouldUseSecondaryDomains();\n  this.fetchResponseState_ = new FetchResponseState();\n  // If the request is a GET request, start a backchannel to transfer streaming\n  // data. Note that WebChannel GET request can also be used for closing the\n  // channel as in method ChannelRequest#sendCloseRequest.\n  // The second parameter of Channel#createXhrIo is JS only.\n  this.xmlHttp_ = this.channel_.createXhrIo(\n      useSecondaryDomains ? hostPrefix : null, !this.postData_);\n\n  if (this.readyStateChangeThrottleMs_ > 0) {\n    this.readyStateChangeThrottle_ = new goog.async.Throttle(\n        goog.bind(this.xmlHttpHandler_, this, this.xmlHttp_),\n        this.readyStateChangeThrottleMs_);\n  }\n\n  this.eventHandler_.listen(\n      this.xmlHttp_, goog.net.EventType.READY_STATE_CHANGE,\n      this.readyStateChangeHandler_);\n\n  const headers =\n      this.extraHeaders_ ? goog.object.clone(this.extraHeaders_) : {};\n  if (this.postData_) {\n    if (!this.verb_) {\n      this.verb_ = 'POST';\n    }\n    headers['Content-Type'] = 'application/x-www-form-urlencoded';\n    this.xmlHttp_.send(this.requestUri_, this.verb_, this.postData_, headers);\n  } else {\n    this.verb_ = 'GET';\n    this.xmlHttp_.send(this.requestUri_, this.verb_, null, headers);\n  }\n  requestStats.notifyServerReachabilityEvent(\n      requestStats.ServerReachability.REQUEST_MADE);\n  this.channelDebug_.xmlHttpChannelRequest(\n      this.verb_, this.requestUri_, this.rid_, this.retryId_, this.postData_);\n};\n\n\n/**\n * Handles a readystatechange event.\n * @param {goog.events.Event} evt The event.\n * @private\n */\nChannelRequest.prototype.readyStateChangeHandler_ = function(evt) {\n  'use strict';\n  const xhr = /** @type {goog.net.XhrIo} */ (evt.target);\n  const throttle = this.readyStateChangeThrottle_;\n  if (throttle &&\n      xhr.getReadyState() == goog.net.XmlHttp.ReadyState.INTERACTIVE) {\n    // Only throttle in the partial data case.\n    this.channelDebug_.debug('Throttling readystatechange.');\n    throttle.fire();\n  } else {\n    // If we haven't throttled, just handle response directly.\n    this.xmlHttpHandler_(xhr);\n  }\n};\n\n\n/**\n * XmlHttp handler\n * @param {goog.net.XhrIo} xmlhttp The XhrIo object for the current request.\n * @private\n */\nChannelRequest.prototype.xmlHttpHandler_ = function(xmlhttp) {\n  'use strict';\n  requestStats.onStartExecution();\n\n  try {\n    if (xmlhttp == this.xmlHttp_) {\n      this.onXmlHttpReadyStateChanged_();\n    } else {\n      this.channelDebug_.warning(\n          'Called back with an ' +\n          'unexpected xmlhttp');\n    }\n  } catch (ex) {\n    this.channelDebug_.debug('Failed call to OnXmlHttpReadyStateChanged_');\n    if (this.hasResponseBody_()) {\n      const channelRequest = this;\n      this.channelDebug_.dumpException(ex, function() {\n        'use strict';\n        return 'ResponseText: ' + channelRequest.xmlHttp_.getResponseText();\n      });\n    } else {\n      this.channelDebug_.dumpException(ex, 'No response text');\n    }\n  } finally {\n    requestStats.onEndExecution();\n  }\n};\n\n\n/**\n * Called by the readystate handler for XMLHTTP requests.\n *\n * @private\n */\nChannelRequest.prototype.onXmlHttpReadyStateChanged_ = function() {\n  'use strict';\n  const readyState = this.xmlHttp_.getReadyState();\n  const errorCode = this.xmlHttp_.getLastErrorCode();\n  const statusCode = this.xmlHttp_.getStatus();\n\n  // we get partial results in browsers that support ready state interactive.\n  // We also make sure that getResponseText is not null in interactive mode\n  // before we continue.\n  if (readyState < goog.net.XmlHttp.ReadyState.INTERACTIVE ||\n      (readyState == goog.net.XmlHttp.ReadyState.INTERACTIVE &&\n       !environment.isPollingRequired() &&  // otherwise, go on to startPolling\n       !this.hasResponseBody_())) {\n    return;  // not yet ready\n  }\n\n  // Dispatch any appropriate network events.\n  if (!this.cancelled_ && readyState == goog.net.XmlHttp.ReadyState.COMPLETE &&\n      errorCode != goog.net.ErrorCode.ABORT) {\n    // Pretty conservative, these are the only known scenarios which we'd\n    // consider indicative of a truly non-functional network connection.\n    if (errorCode == goog.net.ErrorCode.TIMEOUT || statusCode <= 0) {\n      requestStats.notifyServerReachabilityEvent(\n          requestStats.ServerReachability.REQUEST_FAILED);\n    } else {\n      requestStats.notifyServerReachabilityEvent(\n          requestStats.ServerReachability.REQUEST_SUCCEEDED);\n    }\n  }\n\n  // got some data so cancel the watchdog timer\n  this.cancelWatchDogTimer_();\n\n  const status = this.xmlHttp_.getStatus();\n  this.lastStatusCode_ = status;\n  const responseText = this.decodeXmlHttpResponse_();\n\n  if (!this.hasResponseBody_()) {\n    const channelRequest = this;\n    this.channelDebug_.debug(function() {\n      'use strict';\n      return 'No response text for uri ' + channelRequest.requestUri_ +\n          ' status ' + status;\n    });\n  }\n  this.successful_ = (status == 200);\n\n  this.channelDebug_.xmlHttpChannelResponseMetaData(\n      /** @type {string} */ (this.verb_), this.requestUri_, this.rid_,\n      this.retryId_, readyState, status);\n\n  if (!this.successful_) {\n    if (status == 400 && responseText.indexOf('Unknown SID') > 0) {\n      // the server error string will include 'Unknown SID' which indicates the\n      // server doesn't know about the session (maybe it got restarted, maybe\n      // the user got moved to another server, etc.,). Handlers can special\n      // case this error\n      this.lastError_ = ChannelRequest.Error.UNKNOWN_SESSION_ID;\n      requestStats.notifyStatEvent(\n          requestStats.Stat.REQUEST_UNKNOWN_SESSION_ID);\n      this.channelDebug_.warning('XMLHTTP Unknown SID (' + this.rid_ + ')');\n    } else {\n      this.lastError_ = ChannelRequest.Error.STATUS;\n      requestStats.notifyStatEvent(requestStats.Stat.REQUEST_BAD_STATUS);\n      this.channelDebug_.warning(\n          'XMLHTTP Bad status ' + status + ' (' + this.rid_ + ')');\n    }\n    this.cleanup_();\n    this.dispatchFailure_();\n    return;\n  }\n\n  if (this.shouldCheckInitialResponse_()) {\n    const initialResponse = this.getInitialResponse_();\n    if (initialResponse) {\n      this.channelDebug_.xmlHttpChannelResponseText(\n          this.rid_, initialResponse,\n          'Initial handshake response via ' +\n              WebChannel.X_HTTP_INITIAL_RESPONSE);\n      this.initialResponseDecoded_ = true;\n      this.safeOnRequestData_(initialResponse);\n    } else {\n      this.successful_ = false;\n      this.lastError_ = ChannelRequest.Error.UNKNOWN_SESSION_ID;  // fail-fast\n      requestStats.notifyStatEvent(\n          requestStats.Stat.REQUEST_UNKNOWN_SESSION_ID);\n      this.channelDebug_.warning(\n          'XMLHTTP Missing X_HTTP_INITIAL_RESPONSE' +\n          ' (' + this.rid_ + ')');\n      this.cleanup_();\n      this.dispatchFailure_();\n      return;\n    }\n  }\n\n  if (this.decodeChunks_) {\n    this.decodeNextChunks_(readyState, responseText);\n    if (environment.isPollingRequired() && this.successful_ &&\n        readyState == goog.net.XmlHttp.ReadyState.INTERACTIVE) {\n      this.startPolling_();\n    }\n  } else {\n    this.channelDebug_.xmlHttpChannelResponseText(\n        this.rid_, responseText, null);\n    this.safeOnRequestData_(responseText);\n  }\n\n  if (readyState == goog.net.XmlHttp.ReadyState.COMPLETE) {\n    this.cleanup_();\n  }\n\n  if (!this.successful_) {\n    return;\n  }\n\n  if (!this.cancelled_) {\n    if (readyState == goog.net.XmlHttp.ReadyState.COMPLETE) {\n      this.channel_.onRequestComplete(this);\n    } else {\n      // The default is false, the result from this callback shouldn't carry\n      // over to the next callback, otherwise the request looks successful if\n      // the watchdog timer gets called\n      this.successful_ = false;\n      this.ensureWatchDogTimer_();\n    }\n  }\n};\n\n\n/**\n * Whether we need check the initial-response header that is sent during the\n * fast handshake.\n *\n * @return {boolean} true if the initial-response header is yet to be processed.\n * @private\n */\nChannelRequest.prototype.shouldCheckInitialResponse_ = function() {\n  'use strict';\n  return this.decodeInitialResponse_ && !this.initialResponseDecoded_;\n};\n\n\n/**\n * Queries the initial response header that is sent during the handshake.\n *\n * @return {?string} The non-empty header value or null.\n * @private\n */\nChannelRequest.prototype.getInitialResponse_ = function() {\n  'use strict';\n  if (this.xmlHttp_) {\n    const value = this.xmlHttp_.getStreamingResponseHeader(\n        WebChannel.X_HTTP_INITIAL_RESPONSE);\n    if (value && !goog.string.isEmptyOrWhitespace(value)) {\n      return value;\n    }\n  }\n\n  return null;\n};\n\n\n/**\n * Check if the initial response header has been handled.\n *\n * @return {boolean} true if X_HTTP_INITIAL_RESPONSE has been handled.\n */\nChannelRequest.prototype.isInitialResponseDecoded = function() {\n  'use strict';\n  return this.initialResponseDecoded_;\n};\n\n\n/**\n * Decodes X_HTTP_INITIAL_RESPONSE if present.\n */\nChannelRequest.prototype.setDecodeInitialResponse = function() {\n  'use strict';\n  this.decodeInitialResponse_ = true;\n};\n\n\n\n/**\n * Decodes the responses from XhrIo object.\n * @returns {string} responseText\n * @private\n */\nChannelRequest.prototype.decodeXmlHttpResponse_ = function() {\n  'use strict';\n  if (!this.useFetchStreamsForResponse_()) {\n    return this.xmlHttp_.getResponseText();\n  }\n  const responseChunks =\n      /** @type {!Array<!Uint8Array>} */ (this.xmlHttp_.getResponse());\n  let responseText = '';\n  const responseLength = responseChunks.length;\n  const requestCompleted =\n      this.xmlHttp_.getReadyState() == goog.net.XmlHttp.ReadyState.COMPLETE;\n  if (!this.fetchResponseState_.textDecoder) {\n    if (typeof TextDecoder === 'undefined') {\n      this.channelDebug_.severe(\n          'TextDecoder is not supported by this browser.');\n      this.cleanup_();\n      this.dispatchFailure_();\n      return '';\n    }\n    this.fetchResponseState_.textDecoder = new goog.global.TextDecoder();\n  }\n  for (let i = 0; i < responseLength; i++) {\n    this.fetchResponseState_.responseArrivedForFetch = true;\n    const isLastChunk = requestCompleted && i == responseLength - 1;\n    responseText += this.fetchResponseState_.textDecoder.decode(\n        responseChunks[i], {stream: isLastChunk});\n  }\n  responseChunks.splice(0, responseLength);\n  this.fetchResponseState_.responseBuffer += responseText;\n  this.xmlHttpChunkStart_ = 0;\n  return this.fetchResponseState_.responseBuffer;\n};\n\n\n/**\n * Whether or not the response has response body.\n * @private\n * @returns {boolean}\n */\nChannelRequest.prototype.hasResponseBody_ = function() {\n  'use strict';\n  if (!this.xmlHttp_) {\n    return false;\n  }\n  if (this.fetchResponseState_.responseArrivedForFetch) {\n    return true;\n  }\n  return !(!this.xmlHttp_.getResponseText() && !this.xmlHttp_.getResponse());\n};\n\n/**\n * Whether or not the response body is streamed.\n * @private\n * @returns {boolean}\n */\nChannelRequest.prototype.useFetchStreamsForResponse_ = function() {\n  'use strict';\n  if (!this.xmlHttp_) {\n    return false;\n  }\n  return (\n      this.verb_ == 'GET' && this.type_ != ChannelRequest.Type_.CLOSE_REQUEST &&\n      this.channel_.usesFetchStreams());\n};\n\n\n/**\n * Resets the response buffer if the saved chunk has been processed.\n * @private\n * @param {string|!Object|undefined} chunkText\n */\nChannelRequest.prototype.maybeResetBuffer_ = function(chunkText) {\n  'use strict';\n  if (this.useFetchStreamsForResponse_() &&\n      chunkText != ChannelRequest.INCOMPLETE_CHUNK_ &&\n      chunkText != ChannelRequest.INVALID_CHUNK_) {\n    this.fetchResponseState_.responseBuffer = '';\n    this.xmlHttpChunkStart_ = 0;\n  }\n};\n\n\n/**\n * Decodes the next set of available chunks in the response.\n * @param {number} readyState The value of readyState.\n * @param {string} responseText The value of responseText.\n * @private\n */\nChannelRequest.prototype.decodeNextChunks_ = function(\n    readyState, responseText) {\n  'use strict';\n  let decodeNextChunksSuccessful = true;\n\n  let chunkText;\n  while (!this.cancelled_ && this.xmlHttpChunkStart_ < responseText.length) {\n    chunkText = this.getNextChunk_(responseText);\n    if (chunkText == ChannelRequest.INCOMPLETE_CHUNK_) {\n      if (readyState == goog.net.XmlHttp.ReadyState.COMPLETE) {\n        // should have consumed entire response when the request is done\n        this.lastError_ = ChannelRequest.Error.BAD_DATA;\n        requestStats.notifyStatEvent(requestStats.Stat.REQUEST_INCOMPLETE_DATA);\n        decodeNextChunksSuccessful = false;\n      }\n      this.channelDebug_.xmlHttpChannelResponseText(\n          this.rid_, null, '[Incomplete Response]');\n      break;\n    } else if (chunkText == ChannelRequest.INVALID_CHUNK_) {\n      this.lastError_ = ChannelRequest.Error.BAD_DATA;\n      requestStats.notifyStatEvent(requestStats.Stat.REQUEST_BAD_DATA);\n      this.channelDebug_.xmlHttpChannelResponseText(\n          this.rid_, responseText, '[Invalid Chunk]');\n      decodeNextChunksSuccessful = false;\n      break;\n    } else {\n      this.channelDebug_.xmlHttpChannelResponseText(\n          this.rid_, /** @type {string} */ (chunkText), null);\n      this.safeOnRequestData_(/** @type {string} */ (chunkText));\n    }\n  }\n\n  this.maybeResetBuffer_(chunkText);\n\n  if (readyState == goog.net.XmlHttp.ReadyState.COMPLETE &&\n      responseText.length == 0 &&\n      !this.fetchResponseState_.responseArrivedForFetch) {\n    // also an error if we didn't get any response\n    this.lastError_ = ChannelRequest.Error.NO_DATA;\n    requestStats.notifyStatEvent(requestStats.Stat.REQUEST_NO_DATA);\n    decodeNextChunksSuccessful = false;\n  }\n\n  this.successful_ = this.successful_ && decodeNextChunksSuccessful;\n\n  if (!decodeNextChunksSuccessful) {\n    // malformed response - we make this trigger retry logic\n    this.channelDebug_.xmlHttpChannelResponseText(\n        this.rid_, responseText, '[Invalid Chunked Response]');\n    this.cleanup_();\n    this.dispatchFailure_();\n  } else {\n    if (responseText.length > 0 && !this.firstByteReceived_) {\n      this.firstByteReceived_ = true;\n      this.channel_.onFirstByteReceived(this, responseText);\n    }\n  }\n};\n\n\n/**\n * Polls the response for new data.\n * @private\n */\nChannelRequest.prototype.pollResponse_ = function() {\n  'use strict';\n  if (!this.xmlHttp_) {\n    return;  // already closed\n  }\n  const readyState = this.xmlHttp_.getReadyState();\n  const responseText = this.xmlHttp_.getResponseText();\n  if (this.xmlHttpChunkStart_ < responseText.length) {\n    this.cancelWatchDogTimer_();\n    this.decodeNextChunks_(readyState, responseText);\n    if (this.successful_ &&\n        readyState != goog.net.XmlHttp.ReadyState.COMPLETE) {\n      this.ensureWatchDogTimer_();\n    }\n  }\n};\n\n\n/**\n * Starts a polling interval for changes to responseText of the\n * XMLHttpRequest, for browsers that don't fire onreadystatechange\n * as data comes in incrementally.  This timer is disabled in\n * cleanup_().\n * @private\n */\nChannelRequest.prototype.startPolling_ = function() {\n  'use strict';\n  this.eventHandler_.listen(\n      this.pollingTimer_, goog.Timer.TICK, this.pollResponse_);\n  this.pollingTimer_.start();\n};\n\n\n/**\n * Returns the next chunk of a chunk-encoded response. This is not standard\n * HTTP chunked encoding because browsers don't expose the chunk boundaries to\n * the application through XMLHTTP. So we have an additional chunk encoding at\n * the application level that lets us tell where the beginning and end of\n * individual responses are so that we can only try to eval a complete JS array.\n *\n * The encoding is the size of the chunk encoded as a decimal string followed\n * by a newline followed by the data.\n *\n * @param {string} responseText The response text from the XMLHTTP response.\n * @return {string|!Object} The next chunk string or a sentinel object\n *                         indicating a special condition.\n * @private\n */\nChannelRequest.prototype.getNextChunk_ = function(responseText) {\n  'use strict';\n  const sizeStartIndex = this.xmlHttpChunkStart_;\n  const sizeEndIndex = responseText.indexOf('\\n', sizeStartIndex);\n  if (sizeEndIndex == -1) {\n    return ChannelRequest.INCOMPLETE_CHUNK_;\n  }\n\n  const sizeAsString = responseText.substring(sizeStartIndex, sizeEndIndex);\n  const size = Number(sizeAsString);\n  if (isNaN(size)) {\n    return ChannelRequest.INVALID_CHUNK_;\n  }\n\n  const chunkStartIndex = sizeEndIndex + 1;\n  if (chunkStartIndex + size > responseText.length) {\n    return ChannelRequest.INCOMPLETE_CHUNK_;\n  }\n\n  const chunkText = responseText.substr(chunkStartIndex, size);\n  this.xmlHttpChunkStart_ = chunkStartIndex + size;\n  return chunkText;\n};\n\n\n/**\n * Uses an IMG tag or navigator.sendBeacon to send an HTTP get to the server.\n *\n * This is only currently used to terminate the connection, as an IMG tag is\n * the most reliable way to send something to the server while the page\n * is getting torn down.\n *\n * Navigator.sendBeacon is available on Chrome and Firefox as a formal\n * solution to ensure delivery without blocking window close. See\n * https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon\n *\n * For Chrome Apps, sendBeacon is always necessary due to Content Security\n * Policy (CSP) violation of using an IMG tag.\n *\n * For react-native, we use xhr to send the actual close request, and assume\n * there is no page-close issue with react-native.\n *\n * @param {goog.Uri} uri The uri to send a request to.\n */\nChannelRequest.prototype.sendCloseRequest = function(uri) {\n  'use strict';\n  this.type_ = ChannelRequest.Type_.CLOSE_REQUEST;\n  this.baseUri_ = uri.clone().makeUnique();\n\n  let requestSent = false;\n\n  if (goog.global.navigator && goog.global.navigator.sendBeacon) {\n    // empty string body to avoid 413 error on chrome < 41\n    requestSent =\n        goog.global.navigator.sendBeacon(this.baseUri_.toString(), '');\n  }\n\n  if (!requestSent && goog.global.Image) {\n    const eltImg = new Image();\n    eltImg.src = this.baseUri_;\n    requestSent = true;\n  }\n\n  if (!requestSent) {\n    // no handler is set to match the sendBeacon/Image behavior\n    this.xmlHttp_ = this.channel_.createXhrIo(null);\n    this.xmlHttp_.send(this.baseUri_);\n  }\n\n  this.requestStartTime_ = Date.now();\n  this.ensureWatchDogTimer_();\n};\n\n\n/**\n * Cancels the request no matter what the underlying transport is.\n */\nChannelRequest.prototype.cancel = function() {\n  'use strict';\n  this.cancelled_ = true;\n  this.cleanup_();\n};\n\n\n/**\n * Resets the timeout.\n *\n * @param {number=} opt_timeout The new timeout\n */\nChannelRequest.prototype.resetTimeout = function(opt_timeout) {\n  'use strict';\n  if (opt_timeout) {\n    this.setTimeout(opt_timeout);\n  }\n  // restart only if a timer is currently set\n  if (this.watchDogTimerId_) {\n    this.cancelWatchDogTimer_();\n    this.ensureWatchDogTimer_();\n  }\n};\n\n\n/**\n * Ensures that there is watchdog timeout which is used to ensure that\n * the connection completes in time.\n *\n * @private\n */\nChannelRequest.prototype.ensureWatchDogTimer_ = function() {\n  'use strict';\n  this.watchDogTimeoutTime_ = Date.now() + this.timeout_;\n  this.startWatchDogTimer_(this.timeout_);\n};\n\n\n/**\n * Starts the watchdog timer which is used to ensure that the connection\n * completes in time.\n * @param {number} time The number of milliseconds to wait.\n * @private\n */\nChannelRequest.prototype.startWatchDogTimer_ = function(time) {\n  'use strict';\n  if (this.watchDogTimerId_ != null) {\n    // assertion\n    throw new Error('WatchDog timer not null');\n  }\n  this.watchDogTimerId_ =\n      requestStats.setTimeout(goog.bind(this.onWatchDogTimeout_, this), time);\n};\n\n\n/**\n * Cancels the watchdog timer if it has been started.\n *\n * @private\n */\nChannelRequest.prototype.cancelWatchDogTimer_ = function() {\n  'use strict';\n  if (this.watchDogTimerId_) {\n    goog.global.clearTimeout(this.watchDogTimerId_);\n    this.watchDogTimerId_ = null;\n  }\n};\n\n\n/**\n * Called when the watchdog timer is triggered. It also handles a case where it\n * is called too early which we suspect may be happening sometimes\n * (not sure why)\n *\n * @private\n */\nChannelRequest.prototype.onWatchDogTimeout_ = function() {\n  'use strict';\n  this.watchDogTimerId_ = null;\n  const now = Date.now();\n  goog.asserts.assert(\n      this.watchDogTimeoutTime_, 'WatchDog timeout time missing?');\n  if (now - this.watchDogTimeoutTime_ >= 0) {\n    this.handleTimeout_();\n  } else {\n    // got called too early for some reason\n    this.channelDebug_.warning('WatchDog timer called too early');\n    this.startWatchDogTimer_(this.watchDogTimeoutTime_ - now);\n  }\n};\n\n\n/**\n * Called when the request has actually timed out. Will cleanup and notify the\n * channel of the failure.\n *\n * @private\n */\nChannelRequest.prototype.handleTimeout_ = function() {\n  'use strict';\n  if (this.successful_) {\n    // Should never happen.\n    this.channelDebug_.severe(\n        'Received watchdog timeout even though request loaded successfully');\n  }\n\n  this.channelDebug_.timeoutResponse(this.requestUri_);\n\n  // IMG or SendBeacon requests never notice if they were successful,\n  // and always 'time out'. This fact says nothing about reachability.\n  if (this.type_ != ChannelRequest.Type_.CLOSE_REQUEST) {\n    requestStats.notifyServerReachabilityEvent(\n        requestStats.ServerReachability.REQUEST_FAILED);\n    requestStats.notifyStatEvent(requestStats.Stat.REQUEST_TIMEOUT);\n  }\n\n  this.cleanup_();\n\n  // Set error and dispatch failure.\n  // This is called for CLOSE_REQUEST too to ensure channel_.onRequestComplete.\n  this.lastError_ = ChannelRequest.Error.TIMEOUT;\n  this.dispatchFailure_();\n};\n\n\n/**\n * Notifies the channel that this request failed.\n * @private\n */\nChannelRequest.prototype.dispatchFailure_ = function() {\n  'use strict';\n  if (this.channel_.isClosed() || this.cancelled_) {\n    return;\n  }\n\n  this.channel_.onRequestComplete(this);\n};\n\n\n/**\n * Cleans up the objects used to make the request. This function is\n * idempotent.\n *\n * @private\n */\nChannelRequest.prototype.cleanup_ = function() {\n  'use strict';\n  this.cancelWatchDogTimer_();\n\n  goog.dispose(this.readyStateChangeThrottle_);\n  this.readyStateChangeThrottle_ = null;\n\n  // Stop the polling timer, if necessary.\n  this.pollingTimer_.stop();\n\n  // Unhook all event handlers.\n  this.eventHandler_.removeAll();\n\n  if (this.xmlHttp_) {\n    // clear out this.xmlHttp_ before aborting so we handle getting reentered\n    // inside abort\n    const xmlhttp = this.xmlHttp_;\n    this.xmlHttp_ = null;\n    xmlhttp.abort();\n    xmlhttp.dispose();\n  }\n};\n\n\n/**\n * Indicates whether the request was successful. Only valid after the handler\n * is called to indicate completion of the request.\n *\n * @return {boolean} True if the request succeeded.\n */\nChannelRequest.prototype.getSuccess = function() {\n  'use strict';\n  return this.successful_;\n};\n\n\n/**\n * If the request was not successful, returns the reason.\n *\n * @return {?ChannelRequest.Error}  The last error.\n */\nChannelRequest.prototype.getLastError = function() {\n  'use strict';\n  return this.lastError_;\n};\n\n\n/**\n * Returns the status code of the last request.\n * @return {number} The status code of the last request.\n */\nChannelRequest.prototype.getLastStatusCode = function() {\n  'use strict';\n  return this.lastStatusCode_;\n};\n\n\n/**\n * Returns the session id for this channel.\n *\n * @return {string|undefined} The session ID.\n */\nChannelRequest.prototype.getSessionId = function() {\n  'use strict';\n  return this.sid_;\n};\n\n\n/**\n * Returns the request id for this request. Each request has a unique request\n * id and the request IDs are a sequential increasing count.\n *\n * @return {string|number|undefined} The request ID.\n */\nChannelRequest.prototype.getRequestId = function() {\n  'use strict';\n  return this.rid_;\n};\n\n\n/**\n * Returns the data for a post, if this request is a post.\n *\n * @return {?string} The POST data provided by the request initiator.\n */\nChannelRequest.prototype.getPostData = function() {\n  'use strict';\n  return this.postData_;\n};\n\n\n/**\n * Returns the XhrIo request object.\n *\n * @return {?goog.net.XhrIo} Any XhrIo request created for this object.\n */\nChannelRequest.prototype.getXhr = function() {\n  'use strict';\n  return this.xmlHttp_;\n};\n\n\n/**\n * Returns the time that the request started, if it has started.\n *\n * @return {?number} The time the request started, as returned by Date.now().\n */\nChannelRequest.prototype.getRequestStartTime = function() {\n  'use strict';\n  return this.requestStartTime_;\n};\n\n\n/**\n * Helper to call the callback's onRequestData, which catches any\n * exception.\n * @param {string} data The request data.\n * @private\n */\nChannelRequest.prototype.safeOnRequestData_ = function(data) {\n  'use strict';\n  try {\n    this.channel_.onRequestData(this, data);\n    const stats = requestStats.ServerReachability;\n    requestStats.notifyServerReachabilityEvent(stats.BACK_CHANNEL_ACTIVITY);\n  } catch (e) {\n    // Dump debug info, but keep going without closing the channel.\n    this.channelDebug_.dumpException(e, 'Error in httprequest callback');\n  }\n};\n\n\n/**\n * Convenience factory method.\n *\n * @param {Channel} channel The channel object that owns this request.\n * @param {WebChannelDebug} channelDebug A WebChannelDebug to use for logging.\n * @param {string=} opt_sessionId  The session id for the channel.\n * @param {string|number=} opt_requestId  The request id for this request.\n * @param {number=} opt_retryId  The retry id for this request.\n * @return {!ChannelRequest} The created channel request.\n */\nChannelRequest.createChannelRequest = function(\n    channel, channelDebug, opt_sessionId, opt_requestId, opt_retryId) {\n  'use strict';\n  return new ChannelRequest(\n      channel, channelDebug, opt_sessionId, opt_requestId, opt_retryId);\n};\n});  // goog.scope\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview A single module to define user-agent specific environment\n * details.\n *\n */\n\ngoog.module('goog.labs.net.webChannel.environment');\n\ngoog.module.declareLegacyNamespace();\n\nvar userAgent = goog.require('goog.userAgent');\n\n\n/**\n * The default polling interval in millis for Edge.\n *\n * Currently on edge, new-chunk events may be not be fired (at all) if a new\n * chunk arrives within 50ms following the previous chunk. This may be fixed\n * in future, which requires changes to the whatwg spec too.\n *\n * @private @const {number}\n */\nvar EDGE_POLLING_INTERVAL_ = 125;\n\n\n/**\n * History:\n *\n * IE11 is still using Trident, the traditional engine for IE.\n * Edge is using EdgeHTML, a fork of Trident. We are seeing the same issue\n * on IE-11 (reported in 2017), so treat IE the same as Edge for now.\n *\n * We used to do polling for Opera (only) with an 250ms interval, because Opera\n * only fires readyState == INTERACTIVE once. Opera switched to WebKit in 2013,\n * and then to Blink (chrome).\n *\n * TODO(user): check the raw UA string to keep polling for old, mobile operas\n * that may still be affected. For old Opera, double the polling interval\n * to 250ms.\n *\n * @return {boolean} True if polling is required with XHR.\n */\nexports.isPollingRequired = function() {\n  return userAgent.EDGE_OR_IE;\n};\n\n\n/**\n * How often to poll (in MS) for changes to responseText in browsers that don't\n * fire onreadystatechange during incremental loading of the response body.\n *\n * @return {number|undefined} The polling interval (MS) for the current U-A;\n * or undefined if polling is not supposed to be enabled.\n */\nexports.getPollingInterval = function() {\n  if (userAgent.EDGE_OR_IE) {\n    return EDGE_POLLING_INTERVAL_;\n  }\n\n  return undefined;\n};\n\n/**\n * Origin trial token for google.com\n *\n * https://developers.chrome.com/origintrials/#/trials\n *\n * http://googlechrome.github.io/OriginTrials/check-token.html\n * Origin: https://google.com:443\n * Matches Subdomains? Yes\n * Matches Third-party? Yes\n * Feature: FetchUploadStreaming\n * Up to Chrome 95 (ends with the rollout of next Chrome release), no later\n * than Nov 9, 2021\n *\n * Token for googleapis.com will be registered after google.com's is deployed.\n *\n */\nconst OT_TOKEN_GOOGLE_COM =\n    'A0eNbltY1nd4MP7XTHXnTxWogDL6mWTdgIIKfKOTJoUHNbFFMZQBoiHHjJ9UK9lgYndWFaxOWR7ld8uUjcWmcwIAAAB/eyJvcmlnaW4iOiJodHRwczovL2dvb2dsZS5jb206NDQzIiwiZmVhdHVyZSI6IkZldGNoVXBsb2FkU3RyZWFtaW5nIiwiZXhwaXJ5IjoxNjM2NTAyMzk5LCJpc1N1YmRvbWFpbiI6dHJ1ZSwiaXNUaGlyZFBhcnR5Ijp0cnVlfQ==';\n\n\n/**\n * Creates ReadableStream to upload\n * @return {!ReadableStream} ReadableStream to upload\n */\nfunction createStream() {\n  const encoder = new goog.global.TextEncoder();\n  return new goog.global.ReadableStream({\n    start: controller => {\n      for (const obj of ['test\\r\\n', 'test\\r\\n']) {\n        controller.enqueue(encoder.encode(obj));\n      }\n      controller.close();\n    }\n  });\n}\n\n/**\n * Detect the user agent is chrome and its version is higher than M90.\n * This code is hard-coded from goog.labs.userAgent.browser to avoid file size\n * increasing.\n * @return {boolean} Whether the above is true.\n */\nfunction isChromeM90OrHigher() {\n  const userAgentStr = function() {\n    const navigator = goog.global.navigator;\n    if (navigator) {\n      const userAgent = navigator.userAgent;\n      if (userAgent) {\n        return userAgent;\n      }\n    }\n    return '';\n  }();\n\n  const matchUserAgent = function(str) {\n    return userAgentStr.indexOf(str) != -1;\n  };\n\n  if (!matchUserAgent('Chrome') || matchUserAgent('Edg')) {\n    return false;\n  }\n\n  const match = /Chrome\\/(\\d+)/.exec(userAgentStr);\n  const chromeVersion = parseInt(match[1], 10);\n  return chromeVersion >= 90;\n}\n\n/**\n * Detect the URL origin is *.google.com.\n * @param {string} url The target URL.\n * @return {boolean} Whether the above is true.\n */\nfunction isUrlGoogle(url) {\n  const match = /\\/\\/([^\\/]+)\\//.exec(url);\n  if (!match) {\n    return false;\n  }\n  const origin = match[1];\n  return origin.endsWith('google.com');\n}\n\n/**\n * The flag to run the origin trials code only once.\n */\nlet isStartOriginTrialsCalled = false;\n\n/**\n * For Fetch/upload OT, make three requests against the server endpoint.\n * POST requests contain only dummy payload.\n *\n * https://developers.chrome.com/origintrials/#/view_trial/3524066708417413121\n *\n * This function is expected to be called from background during the handshake.\n * Exceptions will be logged by the caller.\n *\n * No stats or logs are collected on the client-side. To be disabled once the\n * OT is expired.\n *\n * @param {string} path The base URL path for the requests\n * @param {function(*)} logError A function to execute when exceptions are\n *     caught.\n */\nexports.startOriginTrials = function(path, logError) {\n  if (isStartOriginTrialsCalled) {\n    return;\n  }\n  isStartOriginTrialsCalled = true;\n  // NE: may need check if path has already contains query params?\n\n  // Accept only Chrome M90 or later due to service worker support.\n  if (!isChromeM90OrHigher()) {\n    return;\n  }\n\n  // Accept only only google.com and subdoamins.\n  if (!isUrlGoogle(path)) {\n    return;\n  }\n  // Since 3P OT is not supported yet, we should check the current page matches\n  // the path (absolute one?) to disable this OT for cross-origin calls\n  if (!window || !window.document || !isUrlGoogle(window.document.URL)) {\n    return;\n  }\n\n  // Enable origin trial by injecting OT <meta> tag\n  const tokenElement =\n      /** @type {! HTMLMetaElement} */ (document.createElement('meta'));\n  tokenElement.httpEquiv = 'origin-trial';\n  tokenElement.content = OT_TOKEN_GOOGLE_COM;\n  // appendChild() synchronously enables OT.\n  document.head.appendChild(tokenElement);\n\n  // Check if fetch upload stream is actually enabled.\n  // By the spec, Streaming request doesn't has the Content-Type header:\n  // https://fetch.spec.whatwg.org/#concept-bodyinit-extract\n  // If Chrome doesn't support Streaming, the body stream is converted to a\n  // string \"[object ReadableStream]\" for fallback then it has \"Content-Type:\n  // text/plain;charset=UTF-8\".\n  const supportsRequestStreams = !new Request('', {\n                                    body: new ReadableStream(),\n                                    method: 'POST',\n                                  }).headers.has('Content-Type');\n  if (!supportsRequestStreams) {\n    return;\n  }\n\n  // 1st req:  path?ot=1\n  // non-streaming upload request\n  goog.global.fetch(`${path}?ot=1`, {method: 'POST', body: 'test\\r\\n'})\n      .catch(logError);\n\n  // 2nd req:  path?ot=2\n  // h2-only streaming upload request\n  goog.global\n      .fetch(`${path}?ot=2`, {\n        method: 'POST',\n        body: createStream(),\n        allowHTTP1ForStreamingUpload: false,\n      })\n      .catch(logError);\n\n  // 3rd req:  path?ot=3\n  // h1-allowed streaming upload request\n  goog.global\n      .fetch(`${path}?ot=3`, {\n        method: 'POST',\n        body: createStream(),\n        allowHTTP1ForStreamingUpload: true,\n      })\n      .catch(logError);\n\n  // Example calling a Chrome API:\n  // goog.global.chrome.loadTimes().wasFetchedViaSpdy\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Base WebChannel implementation.\n */\n\n\ngoog.provide('goog.labs.net.webChannel.WebChannelBase');\n\ngoog.require('goog.Uri');\ngoog.require('goog.array');\ngoog.require('goog.asserts');\ngoog.require('goog.async.run');\ngoog.require('goog.collections.maps');\ngoog.require('goog.json');\ngoog.require('goog.labs.net.webChannel.Channel');\ngoog.require('goog.labs.net.webChannel.ChannelRequest');\ngoog.require('goog.labs.net.webChannel.ConnectionState');\ngoog.require('goog.labs.net.webChannel.ForwardChannelRequestPool');\ngoog.require('goog.labs.net.webChannel.WebChannelDebug');\ngoog.require('goog.labs.net.webChannel.Wire');\ngoog.require('goog.labs.net.webChannel.WireV8');\ngoog.require('goog.labs.net.webChannel.environment');\ngoog.require('goog.labs.net.webChannel.netUtils');\ngoog.require('goog.labs.net.webChannel.requestStats');\ngoog.require('goog.net.FetchXmlHttpFactory');\ngoog.require('goog.net.WebChannel');\ngoog.require('goog.net.XhrIo');\ngoog.require('goog.net.XmlHttpFactory');\ngoog.require('goog.net.rpc.HttpCors');\ngoog.require('goog.object');\ngoog.require('goog.string');\ngoog.require('goog.structs');\n\ngoog.scope(function() {\n'use strict';\nconst WebChannel = goog.net.WebChannel;\nconst ChannelRequest = goog.labs.net.webChannel.ChannelRequest;\nconst ConnectionState = goog.labs.net.webChannel.ConnectionState;\nconst ForwardChannelRequestPool =\n    goog.labs.net.webChannel.ForwardChannelRequestPool;\nconst WebChannelDebug = goog.labs.net.webChannel.WebChannelDebug;\nconst Wire = goog.labs.net.webChannel.Wire;\nconst WireV8 = goog.labs.net.webChannel.WireV8;\nconst environment = goog.labs.net.webChannel.environment;\nconst netUtils = goog.labs.net.webChannel.netUtils;\nconst requestStats = goog.labs.net.webChannel.requestStats;\n\nconst httpCors = goog.module.get('goog.net.rpc.HttpCors');\n\n/**\n * @define {boolean} If WebChannel should compile with Origin Trial features.\n */\nconst ALLOW_ORIGIN_TRIAL_FEATURES =\n    goog.define('goog.net.webChannel.ALLOW_ORIGIN_TRIAL_FEATURES', true);\n\n/**\n * Gets an internal channel parameter in a type-safe way.\n *\n * @param {string} paramName the key of the parameter to fetch.\n * @param {!T} defaultValue the default value to return\n * @param {!goog.net.WebChannel.Options=} options Configuration for the\n *        WebChannel instance.\n * @return {T}\n * @template T\n */\nfunction getInternalChannelParam(paramName, defaultValue, options) {\n  if (!options || !options.internalChannelParams) {\n    return defaultValue;\n  }\n  return /** @type {T} */ (options.internalChannelParams[paramName]) ||\n      defaultValue;\n}\n\n/**\n * This WebChannel implementation is branched off goog.net.BrowserChannel\n * for now. Ongoing changes to goog.net.BrowserChannel will be back\n * ported to this implementation as needed.\n *\n * @param {!goog.net.WebChannel.Options=} opt_options Configuration for the\n *        WebChannel instance.\n * @param {number=} opt_clientVersion An application-specific version number\n *        that is sent to the server when connected.\n * @param {!ConnectionState=} opt_conn Previously determined connection\n *        conditions.\n * @constructor\n * @struct\n * @implements {goog.labs.net.webChannel.Channel}\n */\ngoog.labs.net.webChannel.WebChannelBase = function(\n    opt_options, opt_clientVersion, opt_conn) {\n  'use strict';\n  /**\n   * The client library version (capabilities).\n   * @private {number}\n   */\n  this.clientVersion_ = opt_clientVersion || 0;\n\n  /**\n   * The server library version (capabilities).\n   * @private {number}\n   */\n  this.serverVersion_ = 0;\n\n\n  /**\n   * An array of queued maps that need to be sent to the server.\n   * @private {!Array<Wire.QueuedMap>}\n   */\n  this.outgoingMaps_ = [];\n\n  /**\n   * The channel debug used for logging\n   * @private {!WebChannelDebug}\n   */\n  this.channelDebug_ = new WebChannelDebug();\n\n  /**\n   * Connectivity state.\n   * @private {!ConnectionState}\n   */\n  this.connState_ = opt_conn || new ConnectionState();\n\n  /**\n   * Extra HTTP headers to add to all the requests sent to the server.\n   * @private {?Object}\n   */\n  this.extraHeaders_ = null;\n\n  /**\n   * Extra HTTP headers to add to the init request(s) sent to the server.\n   * @private {?Object}\n   */\n  this.initHeaders_ = null;\n\n  /**\n   * @private {?string} The URL param name to overwrite custom HTTP headers\n   * to bypass CORS preflight.\n   */\n  this.httpHeadersOverwriteParam_ = null;\n\n  /**\n   * Extra parameters to add to all the requests sent to the server.\n   * @private {?Object}\n   */\n  this.extraParams_ = null;\n\n  /**\n   * Parameter name for the http session id.\n   * @private {?string}\n   */\n  this.httpSessionIdParam_ = null;\n\n  /**\n   * The http session id, to be sent with httpSessionIdParam_ with each\n   * request after the initial handshake.\n   * @private {?string}\n   */\n  this.httpSessionId_ = null;\n\n  /**\n   * The ChannelRequest object for the backchannel.\n   * @private {?ChannelRequest}\n   */\n  this.backChannelRequest_ = null;\n\n  /**\n   * The relative path (in the context of the page hosting the browser channel)\n   * for making requests to the server.\n   * @private {?string}\n   */\n  this.path_ = null;\n\n  /**\n   * The absolute URI for the forwardchannel request.\n   * @private {?goog.Uri}\n   */\n  this.forwardChannelUri_ = null;\n\n  /**\n   * The absolute URI for the backchannel request.\n   * @private {?goog.Uri}\n   */\n  this.backChannelUri_ = null;\n\n  /**\n   * A subdomain prefix for using a subdomain in IE for the backchannel\n   * requests.\n   * @private {?string}\n   */\n  this.hostPrefix_ = null;\n\n  /**\n   * Whether we allow the use of a subdomain in IE for the backchannel requests.\n   * @private {boolean}\n   */\n  this.allowHostPrefix_ = true;\n\n  /**\n   * The next id to use for the RID (request identifier) parameter. This\n   * identifier uniquely identifies the forward channel request.\n   * @private {number}\n   */\n  this.nextRid_ = 0;\n\n  /**\n   * The id to use for the next outgoing map. This identifier uniquely\n   * identifies a sent map.\n   * @private {number}\n   */\n  this.nextMapId_ = 0;\n\n  /**\n   * Whether to fail forward-channel requests after one try or a few tries.\n   * @private {boolean}\n   */\n  this.failFast_ = getInternalChannelParam('failFast', false, opt_options);\n\n  /**\n   * The handler that receive callbacks for state changes and data.\n   * @private {?goog.labs.net.webChannel.WebChannelBase.Handler}\n   */\n  this.handler_ = null;\n\n  /**\n   * Timer identifier for asynchronously making a forward channel request.\n   * This is set to true if the func is scheduled with async.run, which\n   * is equivalent to setTimeout(0).\n   * @private {?number|?boolean}\n   */\n  this.forwardChannelTimerId_ = null;\n\n  /**\n   * Timer identifier for asynchronously making a back channel request.\n   * @private {?number}\n   */\n  this.backChannelTimerId_ = null;\n\n  /**\n   * Timer identifier for the timer that waits for us to retry the backchannel\n   * in the case where it is dead and no longer receiving data.\n   * @private {?number}\n   */\n  this.deadBackChannelTimerId_ = null;\n\n  /**\n   * Whether the client's network conditions can support streamed responses.\n   * @private {?boolean}\n   */\n  this.enableStreaming_ = null;\n\n  /**\n   * Whether streaming mode is allowed. In certain debugging situations, it's\n   * useful to disable this.\n   * @private {boolean}\n   */\n  this.allowStreamingMode_ = true;\n\n  /**\n   * The array identifier of the last array received from the server for the\n   * backchannel request.\n   * @private {number}\n   */\n  this.lastArrayId_ = -1;\n\n  /**\n   * The array id of the last array sent by the server that we know about.\n   * @private {number}\n   */\n  this.lastPostResponseArrayId_ = -1;\n\n  /**\n   * The last status code received (until `State.CLOSED` is reached).\n   * @private {number}\n   */\n  this.lastStatusCode_ = -1;\n\n  /**\n   * Number of times we have retried the current forward channel request.\n   * @private {number}\n   */\n  this.forwardChannelRetryCount_ = 0;\n\n  /**\n   * Number of times in a row that we have retried the current back channel\n   * request and received no data.\n   * @private {number}\n   */\n  this.backChannelRetryCount_ = 0;\n\n  /**\n   * The attempt id for the current back channel request. Starts at 1 and\n   * increments for each reconnect. The server uses this to log if our\n   * connection is flaky or not.\n   * @private {number}\n   */\n  this.backChannelAttemptId_ = 0;\n\n  /**\n   * The base part of the time before firing next retry request. Default is 5\n   * seconds. Note that a random delay is added (see {@link retryDelaySeedMs_})\n   * for all retries, and linear backoff is applied to the sum for subsequent\n   * retries.\n   * @private {number}\n   */\n  this.baseRetryDelayMs_ =\n      getInternalChannelParam('baseRetryDelayMs', 5 * 1000, opt_options);\n\n  /**\n   * A random time between 0 and this number of MS is added to the\n   * {@link baseRetryDelayMs_}. Default is 10 seconds.\n   * @private {number}\n   */\n  this.retryDelaySeedMs_ =\n      getInternalChannelParam('retryDelaySeedMs', 10 * 1000, opt_options);\n\n  /**\n   * Maximum number of attempts to connect to the server for forward channel\n   * requests. Defaults to 2.\n   * @private {number}\n   */\n  this.forwardChannelMaxRetries_ =\n      getInternalChannelParam('forwardChannelMaxRetries', 2, opt_options);\n\n  /**\n   * The timeout in milliseconds for a forward channel request. Defaults to 20\n   * seconds. Note that part of this timeout can be randomized.\n   * @private {number}\n   */\n  this.forwardChannelRequestTimeoutMs_ = getInternalChannelParam(\n      'forwardChannelRequestTimeoutMs', 20 * 1000, opt_options);\n\n  /**\n   * The custom factory used to create XMLHttpRequest objects.\n   * @private {!goog.net.XmlHttpFactory | undefined}\n   */\n  this.xmlHttpFactory_ =\n      (opt_options && opt_options.xmlHttpFactory) || undefined;\n\n  /**\n   * Whether or not this channel uses WHATWG Fetch/streams.\n   * @private {boolean}\n   */\n  this.usesFetchStreams_ =\n      (opt_options && opt_options.useFetchStreams) || false;\n\n  /**\n   * The timeout in milliseconds for a back channel request. Defaults to using\n   * the timeout configured in ChannelRequest (45s). If server-side\n   * keepaliveInterval is known to the client, set the backchannel request\n   * timeout to 1.5 * keepaliveInterval (ms).\n   *\n   * @private {number|undefined}\n   */\n  this.backChannelRequestTimeoutMs_ = undefined;\n\n  /**\n   * A throttle time in ms for readystatechange events for the backchannel.\n   * Useful for throttling when ready state is INTERACTIVE (partial data).\n   *\n   * This throttle is useful if the server sends large data chunks down the\n   * backchannel.  It prevents examining XHR partial data on every readystate\n   * change event.  This is useful because large chunks can trigger hundreds\n   * of readystatechange events, each of which takes ~5ms or so to handle,\n   * in turn making the UI unresponsive for a significant period.\n   *\n   * If set to zero no throttle is used.\n   * @private {number}\n   */\n  this.readyStateChangeThrottleMs_ = 0;\n\n  /**\n   * Whether cross origin requests are supported for the channel.\n   *\n   * See {@link goog.net.XhrIo#setWithCredentials}.\n   * @private {boolean}\n   */\n  this.supportsCrossDomainXhrs_ =\n      (opt_options && opt_options.supportsCrossDomainXhr) || false;\n\n  /**\n   * The current session id.\n   * @private {string}\n   */\n  this.sid_ = '';\n\n  /**\n   * The current ChannelRequest pool for the forward channel.\n   * @private {!ForwardChannelRequestPool}\n   */\n  this.forwardChannelRequestPool_ = new ForwardChannelRequestPool(\n      opt_options && opt_options.concurrentRequestLimit);\n\n  /**\n   * The V8 codec.\n   * @private {!WireV8}\n   */\n  this.wireCodec_ = new WireV8();\n\n  /**\n   * Whether to turn on the fast handshake behavior.\n   *\n   * @private {boolean}\n   */\n  this.fastHandshake_ = (opt_options && opt_options.fastHandshake) || false;\n\n  /**\n   * Whether to encode initMessageHeaders in the body.\n   *\n   * @private {boolean}\n   */\n  this.encodeInitMessageHeaders_ =\n      (opt_options && opt_options.encodeInitMessageHeaders) || false;\n\n  if (this.fastHandshake_ && this.encodeInitMessageHeaders_) {\n    this.channelDebug_.warning(\n        'Ignore encodeInitMessageHeaders because fastHandshake is set.');\n    this.encodeInitMessageHeaders_ = false;\n  }\n\n  /**\n   * Whether to signal to the server to enable blocking handshake.\n   *\n   * @private {boolean}\n   */\n  this.blockingHandshake_ =\n      (opt_options && opt_options.blockingHandshake) || false;\n\n\n  if (opt_options && opt_options.disableRedact) {\n    this.channelDebug_.disableRedact();\n  }\n\n  if (opt_options && opt_options.forceLongPolling) {\n    this.allowStreamingMode_ = false;\n  }\n\n  /**\n   * Whether to detect buffering proxies.\n   *\n   * fastHandshake + detectBufferingProxy are yet to be implemented.\n   *\n   * @private {boolean}\n   */\n  this.detectBufferingProxy_ =\n      (!this.fastHandshake_ && this.allowStreamingMode_ && opt_options &&\n       opt_options.detectBufferingProxy) ||\n      false;\n\n  /**\n   * Callback when all the pending client-sent messages have been flushed.\n   *\n   * @private {function()|undefined}\n   */\n  this.forwardChannelFlushedCallback_ = undefined;\n\n  /**\n   * TODO(user): move all backchannel states to its own class similar to\n   * forwardchannelrequestpool.js and log more stats.\n   *\n   * The estimated handshake RTT (ms) as measured from when the handshake\n   * request is sent and when the handshake response headers are received.\n   * If the value is 0, the RTT is unknown.\n   *\n   * @private {number}\n   */\n  this.handshakeRttMs_ = 0;\n\n  /**\n   * If BP detection is done or still in progress.\n   * Should only be checked when detectBufferingProxy is turned on.\n   * @private {boolean}\n   */\n  this.bpDetectionDone_ = false;\n\n  /**\n   * The timer for detecting buffering proxy. This needs be reset with each\n   * backchannel request. If this is not null, bpDetectionDone_ == false.\n   * @private {?number}\n   */\n  this.bpDetectionTimerId_ = null;\n\n  /***\n   * Whether to attempt Chrome Origin Trials as part of the handshake.\n   * @private @const {boolean}\n   */\n  this.enableOriginTrials_ = ALLOW_ORIGIN_TRIAL_FEATURES &&\n      (!opt_options || opt_options.enableOriginTrials !== false);\n\n  /**\n   * The array of non-acked maps at the time of channel close. Refer to\n   * `getNonAckedMessagesWithClosedChannel()` API for definitions of non-acked\n   * messages.\n   *\n   * @private {?Array<!Wire.QueuedMap>}\n   */\n  this.nonAckedMapsAtChannelClose_ = null;\n};\n\nconst WebChannelBase = goog.labs.net.webChannel.WebChannelBase;\n\n\n/**\n * The channel version that we negotiated with the server for this session.\n * Starts out as the version we request, and then is changed to the negotiated\n * version after the initial open.\n * @private {number}\n */\nWebChannelBase.prototype.channelVersion_ = Wire.LATEST_CHANNEL_VERSION;\n\n\n/**\n * Enum type for the channel state machine.\n * @enum {number}\n */\nWebChannelBase.State = {\n  /** The channel is closed. */\n  CLOSED: 0,\n\n  /** The channel has been initialized but hasn't yet initiated a connection. */\n  INIT: 1,\n\n  /** The channel is in the process of opening a connection to the server. */\n  OPENING: 2,\n\n  /** The channel is open. */\n  OPENED: 3\n};\n\n\n/**\n * The current state of the WebChannel.\n * @private {!WebChannelBase.State}\n */\nWebChannelBase.prototype.state_ = WebChannelBase.State.INIT;\n\n\n/**\n * The timeout in milliseconds for a forward channel request.\n * @type {number}\n */\nWebChannelBase.FORWARD_CHANNEL_RETRY_TIMEOUT = 20 * 1000;\n\n\n/**\n * Maximum number of attempts to connect to the server for back channel\n * requests.\n * @type {number}\n */\nWebChannelBase.BACK_CHANNEL_MAX_RETRIES = 3;\n\n\n/**\n * A number in MS of how long we guess the maxmium amount of time a round trip\n * to the server should take. In the future this could be substituted with a\n * real measurement of the RTT.\n * @type {number}\n */\nWebChannelBase.RTT_ESTIMATE = 3 * 1000;\n\n\n/**\n * When retrying for an inactive channel, we will multiply the total delay by\n * this number.\n * @type {number}\n */\nWebChannelBase.INACTIVE_CHANNEL_RETRY_FACTOR = 2;\n\n\n/**\n * Enum type for identifying an error.\n * @enum {number}\n */\nWebChannelBase.Error = {\n  /** Value that indicates no error has occurred. */\n  OK: 0,\n\n  /** An error due to a request failing. */\n  REQUEST_FAILED: 2,\n\n  /** An error due to the user being logged out. */\n  LOGGED_OUT: 4,\n\n  /** An error due to server response which contains no data. */\n  NO_DATA: 5,\n\n  /** An error due to a server response indicating an unknown session id */\n  UNKNOWN_SESSION_ID: 6,\n\n  /** An error due to a server response requesting to stop the channel. */\n  STOP: 7,\n\n  /** A general network error. */\n  NETWORK: 8,\n\n  /** An error due to bad data being returned from the server. */\n  BAD_DATA: 10,\n\n  /** An error due to a response that is not parsable. */\n  BAD_RESPONSE: 11\n};\n\n\n/**\n * Internal enum type for the two channel types.\n * @enum {number}\n * @private\n */\nWebChannelBase.ChannelType_ = {\n  FORWARD_CHANNEL: 1,\n\n  BACK_CHANNEL: 2\n};\n\n\n/**\n * The maximum number of maps that can be sent in one POST. Should match\n * MAX_MAPS_PER_REQUEST on the server code.\n * @type {number}\n * @private\n */\nWebChannelBase.MAX_MAPS_PER_REQUEST_ = 1000;\n\n\n/**\n * The maximum number of utf-8 chars that can be sent in one GET to enable 0-RTT\n * handshake.\n *\n *  @const @private {number}\n */\nWebChannelBase.MAX_CHARS_PER_GET_ = 4 * 1024;\n\n\n/**\n * A guess at a cutoff at which to no longer assume the backchannel is dead\n * when we are slow to receive data. Number in bytes.\n *\n * Assumption: The worst bandwidth we work on is 50 kilobits/sec\n * 50kbits/sec * (1 byte / 8 bits) * 6 sec dead backchannel timeout\n * @type {number}\n */\nWebChannelBase.OUTSTANDING_DATA_BACKCHANNEL_RETRY_CUTOFF = 37500;\n\n\n/**\n * @return {number} The server version or 0 if undefined\n */\nWebChannelBase.prototype.getServerVersion = function() {\n  'use strict';\n  return this.serverVersion_;\n};\n\n\n/**\n * @return {!ForwardChannelRequestPool} The forward channel request pool.\n */\nWebChannelBase.prototype.getForwardChannelRequestPool = function() {\n  'use strict';\n  return this.forwardChannelRequestPool_;\n};\n\n\n/**\n * @return {!Object} The codec object.\n */\nWebChannelBase.prototype.getWireCodec = function() {\n  'use strict';\n  return this.wireCodec_;\n};\n\n\n/**\n * Returns the logger.\n *\n * @return {!WebChannelDebug} The channel debug object.\n */\nWebChannelBase.prototype.getChannelDebug = function() {\n  'use strict';\n  return this.channelDebug_;\n};\n\n\n/**\n * Sets the logger.\n *\n * @param {!WebChannelDebug} channelDebug The channel debug object.\n */\nWebChannelBase.prototype.setChannelDebug = function(channelDebug) {\n  'use strict';\n  this.channelDebug_ = channelDebug;\n};\n\n\n/**\n * Starts the channel. This initiates connections to the server.\n *\n * @param {string} channelPath  The path for the channel connection.\n * @param {!Object=} opt_extraParams Extra parameter keys and values to add to\n *     the requests.\n * @param {string=} opt_oldSessionId  Session ID from a previous session.\n * @param {number=} opt_oldArrayId  The last array ID from a previous session.\n */\nWebChannelBase.prototype.connect = function(\n    channelPath, opt_extraParams, opt_oldSessionId, opt_oldArrayId) {\n  'use strict';\n  this.channelDebug_.debug('connect()');\n\n  this.startOriginTrials_(channelPath);\n\n  requestStats.notifyStatEvent(requestStats.Stat.CONNECT_ATTEMPT);\n\n  this.path_ = channelPath;\n  this.extraParams_ = opt_extraParams || {};\n\n  // Attach parameters about the previous session if reconnecting.\n  if (opt_oldSessionId && opt_oldArrayId !== undefined) {\n    this.extraParams_['OSID'] = opt_oldSessionId;\n    this.extraParams_['OAID'] = opt_oldArrayId;\n  }\n\n  this.enableStreaming_ = this.allowStreamingMode_;\n  this.connectChannel_();\n};\n\n\n/**\n * Disconnects and closes the channel.\n */\nWebChannelBase.prototype.disconnect = function() {\n  'use strict';\n  this.channelDebug_.debug('disconnect()');\n\n  this.cancelRequests_();\n\n  if (this.state_ == WebChannelBase.State.OPENED) {\n    const rid = this.nextRid_++;\n    const uri = this.forwardChannelUri_.clone();\n    uri.setParameterValue('SID', this.sid_);\n    uri.setParameterValue('RID', rid);\n    uri.setParameterValue('TYPE', 'terminate');\n\n    this.addAdditionalParams_(uri);\n\n    const request = ChannelRequest.createChannelRequest(\n        this, this.channelDebug_, this.sid_, rid);\n    request.sendCloseRequest(uri);\n  }\n\n  this.onClose_();\n};\n\n\n/**\n * Returns the session id of the channel. Only available after the\n * channel has been opened.\n * @return {string} Session ID.\n */\nWebChannelBase.prototype.getSessionId = function() {\n  'use strict';\n  return this.sid_;\n};\n\n\n/**\n * Starts the connection.\n * @private\n */\nWebChannelBase.prototype.connectChannel_ = function() {\n  'use strict';\n  this.channelDebug_.debug('connectChannel_()');\n  this.ensureInState_(WebChannelBase.State.INIT, WebChannelBase.State.CLOSED);\n  this.forwardChannelUri_ =\n      this.getForwardChannelUri(/** @type {string} */ (this.path_));\n  this.ensureForwardChannel_();\n};\n\n\n/**\n * Starts the Origin Trials.\n * @param {string} channelPath  The path for the channel connection.\n * @private\n */\nWebChannelBase.prototype.startOriginTrials_ = function(channelPath) {\n  'use strict';\n\n  if (!this.enableOriginTrials_) {\n    return;\n  }\n\n  this.channelDebug_.info('Origin Trials enabled.');\n  goog.async.run(goog.bind(this.runOriginTrials_, this, channelPath));\n};\n\n\n/**\n * Runs the Origin Trials.\n * @param {string} channelPath  The path for the channel connection.\n * @private\n */\nWebChannelBase.prototype.runOriginTrials_ = function(channelPath) {\n  'use strict';\n\n  try {\n    // Since startOriginTrials might throw exceptions asynchronously, we should\n    // capture it in promise-catch.\n    environment.startOriginTrials(channelPath, e => {\n      this.channelDebug_.dumpException(\n          /** @type {?Error} */ (e), 'Error in running origin trials');\n    });\n    this.channelDebug_.info('Origin Trials invoked: ' + channelPath);\n  } catch (e) {\n    this.channelDebug_.dumpException(e, 'Error in running origin trials');\n  }\n};\n\n\n/**\n * Cancels backchannel request.\n * @private\n */\nWebChannelBase.prototype.cancelBackChannelRequest_ = function() {\n  'use strict';\n  if (this.backChannelRequest_) {\n    this.clearBpDetectionTimer_();\n    this.backChannelRequest_.cancel();\n    this.backChannelRequest_ = null;\n  }\n};\n\n\n/**\n * Cancels all outstanding requests.\n * @private\n */\nWebChannelBase.prototype.cancelRequests_ = function() {\n  'use strict';\n  this.cancelBackChannelRequest_();\n\n  if (this.backChannelTimerId_) {\n    goog.global.clearTimeout(this.backChannelTimerId_);\n    this.backChannelTimerId_ = null;\n  }\n\n  this.clearDeadBackchannelTimer_();\n\n  this.forwardChannelRequestPool_.cancel();\n\n  if (this.forwardChannelTimerId_) {\n    this.clearForwardChannelTimer_();\n  }\n};\n\n\n/**\n * Clears the forward channel timer.\n * @private\n */\nWebChannelBase.prototype.clearForwardChannelTimer_ = function() {\n  'use strict';\n  if (typeof this.forwardChannelTimerId_ === 'number') {\n    goog.global.clearTimeout(this.forwardChannelTimerId_);\n  }\n\n  this.forwardChannelTimerId_ = null;\n};\n\n\n/**\n * Returns the extra HTTP headers to add to all the requests sent to the server.\n *\n * @return {Object} The HTTP headers, or null.\n */\nWebChannelBase.prototype.getExtraHeaders = function() {\n  'use strict';\n  return this.extraHeaders_;\n};\n\n\n/**\n * Sets extra HTTP headers to add to all the requests sent to the server.\n *\n * @param {Object} extraHeaders The HTTP headers, or null.\n */\nWebChannelBase.prototype.setExtraHeaders = function(extraHeaders) {\n  'use strict';\n  this.extraHeaders_ = extraHeaders;\n};\n\n\n/**\n * Returns the extra HTTP headers to add to the init requests\n * sent to the server.\n *\n * @return {Object} The HTTP headers, or null.\n */\nWebChannelBase.prototype.getInitHeaders = function() {\n  'use strict';\n  return this.initHeaders_;\n};\n\n\n/**\n * Sets extra HTTP headers to add to the init requests sent to the server.\n *\n * @param {Object} initHeaders The HTTP headers, or null.\n */\nWebChannelBase.prototype.setInitHeaders = function(initHeaders) {\n  'use strict';\n  this.initHeaders_ = initHeaders;\n};\n\n\n/**\n * Sets the URL param name to overwrite custom HTTP headers.\n *\n * @param {string} httpHeadersOverwriteParam The URL param name.\n */\nWebChannelBase.prototype.setHttpHeadersOverwriteParam = function(\n    httpHeadersOverwriteParam) {\n  'use strict';\n  this.httpHeadersOverwriteParam_ = httpHeadersOverwriteParam;\n};\n\n\n/**\n * @override\n */\nWebChannelBase.prototype.setHttpSessionIdParam = function(httpSessionIdParam) {\n  'use strict';\n  this.httpSessionIdParam_ = httpSessionIdParam;\n};\n\n\n/**\n * @override\n */\nWebChannelBase.prototype.getHttpSessionIdParam = function() {\n  'use strict';\n  return this.httpSessionIdParam_;\n};\n\n\n/**\n * @override\n */\nWebChannelBase.prototype.setHttpSessionId = function(httpSessionId) {\n  'use strict';\n  this.httpSessionId_ = httpSessionId;\n};\n\n\n/**\n * @override\n */\nWebChannelBase.prototype.getHttpSessionId = function() {\n  'use strict';\n  return this.httpSessionId_;\n};\n\n\n/**\n * Sets the throttle for handling onreadystatechange events for the request.\n *\n * @param {number} throttle The throttle in ms.  A value of zero indicates\n *     no throttle.\n */\nWebChannelBase.prototype.setReadyStateChangeThrottle = function(throttle) {\n  'use strict';\n  this.readyStateChangeThrottleMs_ = throttle;\n};\n\n\n/**\n * Sets whether cross origin requests are supported for the channel.\n *\n * Setting this allows the creation of requests to secondary domains and\n * sends XHRs with the CORS withCredentials bit set to true.\n *\n * In order for cross-origin requests to work, the server will also need to set\n * CORS response headers as per:\n * https://developer.mozilla.org/en-US/docs/HTTP_access_control\n *\n * See {@link goog.net.XhrIo#setWithCredentials}.\n * @param {boolean} supportCrossDomain Whether cross domain XHRs are supported.\n */\nWebChannelBase.prototype.setSupportsCrossDomainXhrs = function(\n    supportCrossDomain) {\n  'use strict';\n  this.supportsCrossDomainXhrs_ = supportCrossDomain;\n};\n\n\n/**\n * Returns the handler used for channel callback events.\n *\n * @return {WebChannelBase.Handler} The handler.\n */\nWebChannelBase.prototype.getHandler = function() {\n  'use strict';\n  return this.handler_;\n};\n\n\n/**\n * Sets the handler used for channel callback events.\n * @param {WebChannelBase.Handler} handler The handler to set.\n */\nWebChannelBase.prototype.setHandler = function(handler) {\n  'use strict';\n  this.handler_ = handler;\n};\n\n\n/**\n * Returns whether the channel allows the use of a subdomain. There may be\n * cases where this isn't allowed.\n * @return {boolean} Whether a host prefix is allowed.\n */\nWebChannelBase.prototype.getAllowHostPrefix = function() {\n  'use strict';\n  return this.allowHostPrefix_;\n};\n\n\n/**\n * Sets whether the channel allows the use of a subdomain. There may be cases\n * where this isn't allowed, for example, logging in with troutboard where\n * using a subdomain causes Apache to force the user to authenticate twice.\n * @param {boolean} allowHostPrefix Whether a host prefix is allowed.\n */\nWebChannelBase.prototype.setAllowHostPrefix = function(allowHostPrefix) {\n  'use strict';\n  this.allowHostPrefix_ = allowHostPrefix;\n};\n\n\n/**\n * Returns whether the channel is buffered or not.  This may be\n * queried in the WebChannelBase.okToMakeRequest() callback.\n *\n * @return {boolean} Whether the channel is buffered.\n */\nWebChannelBase.prototype.isBuffered = function() {\n  'use strict';\n  return !this.enableStreaming_;\n};\n\n\n/**\n * Returns whether streaming mode is allowed. In certain debugging situations,\n * it's useful for the application to have a way to disable streaming mode for a\n * user.\n\n * @return {boolean} Whether streaming mode is allowed.\n */\nWebChannelBase.prototype.getAllowStreamingMode = function() {\n  'use strict';\n  return this.allowStreamingMode_;\n};\n\n\n/**\n * Sets whether streaming mode is allowed. In certain debugging situations, it's\n * useful for the application to have a way to disable streaming mode for a\n * user.\n * @param {boolean} allowStreamingMode  Whether streaming mode is allowed.\n */\nWebChannelBase.prototype.setAllowStreamingMode = function(allowStreamingMode) {\n  'use strict';\n  this.allowStreamingMode_ = allowStreamingMode;\n};\n\n\n/**\n * Sends a request to the server. The format of the request is a Map data\n * structure of key/value pairs. These maps are then encoded in a format\n * suitable for the wire and then reconstituted as a Map data structure that\n * the server can process.\n * @param {!Object|!goog.collections.maps.MapLike} map The map to send.\n * @param {!Object=} opt_context The context associated with the map.\n */\nWebChannelBase.prototype.sendMap = function(map, opt_context) {\n  'use strict';\n  goog.asserts.assert(\n      this.state_ != WebChannelBase.State.CLOSED,\n      'Invalid operation: sending map when state is closed');\n\n  // We can only send 1000 maps per POST, but typically we should never have\n  // that much to send, so warn if we exceed that (we still send all the maps).\n  if (this.outgoingMaps_.length == WebChannelBase.MAX_MAPS_PER_REQUEST_) {\n    // severe() is temporary so that we get these uploaded and can figure out\n    // what's causing them. Afterwards can change to warning().\n    this.channelDebug_.severe(function() {\n      'use strict';\n      return 'Already have ' + WebChannelBase.MAX_MAPS_PER_REQUEST_ +\n          ' queued maps upon queueing ' + goog.json.serialize(map);\n    });\n  }\n\n  this.outgoingMaps_.push(\n      new Wire.QueuedMap(this.nextMapId_++, map, opt_context));\n\n  // Messages need be buffered during OPENING to avoid server-side race\n  if (this.state_ == WebChannelBase.State.OPENED) {\n    this.ensureForwardChannel_();\n  }\n};\n\n\n/**\n * When set to true, this changes the behavior of the forward channel so it\n * will not retry requests; it will fail after one network failure, and if\n * there was already one network failure, the request will fail immediately.\n * @param {boolean} failFast  Whether or not to fail fast.\n */\nWebChannelBase.prototype.setFailFast = function(failFast) {\n  'use strict';\n  this.failFast_ = failFast;\n  this.channelDebug_.info('setFailFast: ' + failFast);\n  if ((this.forwardChannelRequestPool_.hasPendingRequest() ||\n       this.forwardChannelTimerId_) &&\n      this.forwardChannelRetryCount_ > this.getForwardChannelMaxRetries()) {\n    const self = this;\n    this.channelDebug_.info(function() {\n      'use strict';\n      return 'Retry count ' + self.forwardChannelRetryCount_ +\n          ' > new maxRetries ' + self.getForwardChannelMaxRetries() +\n          '. Fail immediately!';\n    });\n\n    if (!this.forwardChannelRequestPool_.forceComplete(\n            goog.bind(this.onRequestComplete, this))) {\n      // i.e., this.forwardChannelTimerId_\n      this.clearForwardChannelTimer_();\n      // The error code from the last failed request is gone, so just use a\n      // generic one.\n      this.signalError_(WebChannelBase.Error.REQUEST_FAILED);\n    }\n  }\n};\n\n\n/**\n * @return {number} The max number of forward-channel retries, which will be 0\n * in fail-fast mode.\n */\nWebChannelBase.prototype.getForwardChannelMaxRetries = function() {\n  'use strict';\n  return this.failFast_ ? 0 : this.forwardChannelMaxRetries_;\n};\n\n\n/**\n * Sets the maximum number of attempts to connect to the server for forward\n * channel requests.\n * @param {number} retries The maximum number of attempts.\n */\nWebChannelBase.prototype.setForwardChannelMaxRetries = function(retries) {\n  'use strict';\n  this.forwardChannelMaxRetries_ = retries;\n};\n\n\n/**\n * Sets the timeout for a forward channel request.\n * @param {number} timeoutMs The timeout in milliseconds.\n */\nWebChannelBase.prototype.setForwardChannelRequestTimeout = function(timeoutMs) {\n  'use strict';\n  this.forwardChannelRequestTimeoutMs_ = timeoutMs;\n};\n\n\n/**\n * @return {number} The max number of back-channel retries, which is a constant.\n */\nWebChannelBase.prototype.getBackChannelMaxRetries = function() {\n  'use strict';\n  // Back-channel retries is a constant.\n  return WebChannelBase.BACK_CHANNEL_MAX_RETRIES;\n};\n\n\n/**\n * @override\n */\nWebChannelBase.prototype.isClosed = function() {\n  'use strict';\n  return this.state_ == WebChannelBase.State.CLOSED;\n};\n\n\n/**\n * Returns the channel state.\n * @return {WebChannelBase.State} The current state of the channel.\n */\nWebChannelBase.prototype.getState = function() {\n  'use strict';\n  return this.state_;\n};\n\n\n/**\n * @return {number} The last status code received (until `State.CLOSED` is\n * reached).\n */\nWebChannelBase.prototype.getLastStatusCode = function() {\n  'use strict';\n  return this.lastStatusCode_;\n};\n\n\n/**\n * @return {number} The last array id received.\n */\nWebChannelBase.prototype.getLastArrayId = function() {\n  'use strict';\n  return this.lastArrayId_;\n};\n\n\n/**\n * Returns whether there are outstanding requests servicing the channel.\n * @return {boolean} true if there are outstanding requests.\n */\nWebChannelBase.prototype.hasOutstandingRequests = function() {\n  'use strict';\n  return this.getOutstandingRequests_() != 0;\n};\n\n\n/**\n * Returns the number of outstanding requests.\n * @return {number} The number of outstanding requests to the server.\n * @private\n */\nWebChannelBase.prototype.getOutstandingRequests_ = function() {\n  'use strict';\n  let count = 0;\n  if (this.backChannelRequest_) {\n    count++;\n  }\n  count += this.forwardChannelRequestPool_.getRequestCount();\n  return count;\n};\n\n\n/**\n * Ensures that a forward channel request is scheduled.\n * @private\n */\nWebChannelBase.prototype.ensureForwardChannel_ = function() {\n  'use strict';\n  if (this.forwardChannelRequestPool_.isFull()) {\n    // enough connection in process - no need to start a new request\n    return;\n  }\n\n  if (this.forwardChannelTimerId_) {\n    // no need to start a new request - one is already scheduled\n    return;\n  }\n\n  // Use async.run instead of setTimeout(0) to avoid the 1s message delay\n  // from chrome/firefox background tabs\n  this.forwardChannelTimerId_ = true;\n  goog.async.run(this.onStartForwardChannelTimer_, this);\n\n  this.forwardChannelRetryCount_ = 0;\n};\n\n\n/**\n * Schedules a forward-channel retry for the specified request, unless the max\n * retries has been reached.\n * @param {!ChannelRequest} request The failed request to retry.\n * @return {boolean} true iff a retry was scheduled.\n * @private\n */\nWebChannelBase.prototype.maybeRetryForwardChannel_ = function(request) {\n  'use strict';\n  if (this.forwardChannelRequestPool_.getRequestCount() >=\n      this.forwardChannelRequestPool_.getMaxSize() -\n          (this.forwardChannelTimerId_ ? 1 : 0)) {\n    // Should be impossible to be called in this state.\n    this.channelDebug_.severe('Unexpected retry request is scheduled.');\n    return false;\n  }\n\n  if (this.forwardChannelTimerId_) {\n    this.channelDebug_.debug(\n        'Use the retry request that is already scheduled.');\n    this.outgoingMaps_ =\n        request.getPendingMessages().concat(this.outgoingMaps_);\n    return true;\n  }\n\n  // No retry for open_() and fail-fast\n  if (this.state_ == WebChannelBase.State.INIT ||\n      this.state_ == WebChannelBase.State.OPENING ||\n      (this.forwardChannelRetryCount_ >= this.getForwardChannelMaxRetries())) {\n    return false;\n  }\n\n  this.channelDebug_.debug('Going to retry POST');\n\n  this.forwardChannelTimerId_ = requestStats.setTimeout(\n      goog.bind(this.onStartForwardChannelTimer_, this, request),\n      this.getRetryTime_(this.forwardChannelRetryCount_));\n  this.forwardChannelRetryCount_++;\n  return true;\n};\n\n\n/**\n * Timer callback for ensureForwardChannel\n * @param {ChannelRequest=} opt_retryRequest A failed request\n * to retry.\n * @private\n */\nWebChannelBase.prototype.onStartForwardChannelTimer_ = function(\n    opt_retryRequest) {\n  'use strict';\n  // null is possible if scheduled with async.run\n  if (this.forwardChannelTimerId_) {\n    this.forwardChannelTimerId_ = null;\n    this.startForwardChannel_(opt_retryRequest);\n  }\n};\n\n\n/**\n * Begins a new forward channel operation to the server.\n * @param {ChannelRequest=} opt_retryRequest A failed request to retry.\n * @private\n */\nWebChannelBase.prototype.startForwardChannel_ = function(opt_retryRequest) {\n  'use strict';\n  this.channelDebug_.debug('startForwardChannel_');\n  if (!this.okToMakeRequest_()) {\n    return;  // channel is cancelled\n  } else if (this.state_ == WebChannelBase.State.INIT) {\n    if (opt_retryRequest) {\n      this.channelDebug_.severe('Not supposed to retry the open');\n      return;\n    }\n    this.open_();\n    this.state_ = WebChannelBase.State.OPENING;\n  } else if (this.state_ == WebChannelBase.State.OPENED) {\n    if (opt_retryRequest) {\n      this.makeForwardChannelRequest_(opt_retryRequest);\n      return;\n    }\n\n    if (this.outgoingMaps_.length == 0) {\n      this.channelDebug_.debug(\n          'startForwardChannel_ returned: ' +\n          'nothing to send');\n      // no need to start a new forward channel request\n      return;\n    }\n\n    if (this.forwardChannelRequestPool_.isFull()) {\n      // Should be impossible to be called in this state.\n      this.channelDebug_.severe(\n          'startForwardChannel_ returned: ' +\n          'connection already in progress');\n      return;\n    }\n\n    this.makeForwardChannelRequest_();\n    this.channelDebug_.debug('startForwardChannel_ finished, sent request');\n  }\n};\n\n\n/**\n * Establishes a new channel session with the server.\n * @private\n */\nWebChannelBase.prototype.open_ = function() {\n  'use strict';\n  this.channelDebug_.debug('open_()');\n  this.nextRid_ = Math.floor(Math.random() * 100000);\n\n  const rid = this.nextRid_++;\n  const request =\n      ChannelRequest.createChannelRequest(this, this.channelDebug_, '', rid);\n\n  // mix the init headers\n  let extraHeaders = this.extraHeaders_;\n  if (this.initHeaders_) {\n    if (extraHeaders) {\n      extraHeaders = goog.object.clone(extraHeaders);\n      goog.object.extend(extraHeaders, this.initHeaders_);\n    } else {\n      extraHeaders = this.initHeaders_;\n    }\n  }\n\n  if (this.httpHeadersOverwriteParam_ === null &&\n      !this.encodeInitMessageHeaders_) {\n    request.setExtraHeaders(extraHeaders);\n    extraHeaders = null;\n  }\n\n  let requestText = this.dequeueOutgoingMaps_(\n      request,\n      this.fastHandshake_ ? this.getMaxNumMessagesForFastHandshake_() :\n                            WebChannelBase.MAX_MAPS_PER_REQUEST_);\n\n  const uri = this.forwardChannelUri_.clone();\n  uri.setParameterValue('RID', rid);\n\n  if (this.clientVersion_ > 0) {\n    uri.setParameterValue('CVER', this.clientVersion_);\n  }\n\n  // http-session-id to be generated as the response\n  if (this.getHttpSessionIdParam()) {\n    uri.setParameterValue(\n        WebChannel.X_HTTP_SESSION_ID, this.getHttpSessionIdParam());\n  }\n\n  this.addAdditionalParams_(uri);\n\n  if (extraHeaders) {\n    if (this.encodeInitMessageHeaders_) {\n      let encodedHeaders =\n          httpCors.generateEncodedHttpHeadersOverwriteParam(extraHeaders);\n      requestText = 'headers=' + encodedHeaders + '&' + requestText;\n    } else if (this.httpHeadersOverwriteParam_) {\n      httpCors.setHttpHeadersWithOverwriteParam(\n          uri, this.httpHeadersOverwriteParam_, extraHeaders);\n    }  // else - should not happen\n  }\n\n  this.forwardChannelRequestPool_.addRequest(request);\n\n  if (this.blockingHandshake_) {\n    uri.setParameterValue('TYPE', 'init');  // default to blocking in future\n  }\n\n  // Check the option and use GET to enable QUIC 0-RTT\n  if (this.fastHandshake_) {\n    uri.setParameterValue('$req', requestText);\n\n    // enable handshake upgrade\n    uri.setParameterValue('SID', 'null');\n    request.setDecodeInitialResponse();\n\n    request.xmlHttpPost(uri, null, true);  // Send as a GET\n  } else {\n    request.xmlHttpPost(uri, requestText, true);\n  }\n};\n\n\n/**\n * @return {number} The number of raw JSON messages to be encoded\n * with the fast-handshake (GET) request, including zero. If messages are not\n * encoded as raw JSON data, return WebChannelBase.MAX_MAPS_PER_REQUEST_\n * @private\n */\nWebChannelBase.prototype.getMaxNumMessagesForFastHandshake_ = function() {\n  'use strict';\n  let total = 0;\n  for (let i = 0; i < this.outgoingMaps_.length; i++) {\n    const map = this.outgoingMaps_[i];\n    const size = map.getRawDataSize();\n    if (size === undefined) {\n      break;\n    }\n    total += size;\n\n    if (total > WebChannelBase.MAX_CHARS_PER_GET_) {\n      return i;\n    }\n\n    if (total === WebChannelBase.MAX_CHARS_PER_GET_ ||\n        i === this.outgoingMaps_.length - 1) {\n      return i + 1;\n    }\n  }\n\n  return WebChannelBase.MAX_MAPS_PER_REQUEST_;\n};\n\n\n\n/**\n * Makes a forward channel request using XMLHTTP.\n * @param {!ChannelRequest=} opt_retryRequest A failed request to retry.\n * @private\n */\nWebChannelBase.prototype.makeForwardChannelRequest_ = function(\n    opt_retryRequest) {\n  'use strict';\n  let rid;\n  if (opt_retryRequest) {\n    rid = opt_retryRequest.getRequestId();  // Reuse the same RID for a retry\n  } else {\n    rid = this.nextRid_++;\n  }\n\n  const uri = this.forwardChannelUri_.clone();\n  uri.setParameterValue('SID', this.sid_);\n  uri.setParameterValue('RID', rid);\n  uri.setParameterValue('AID', this.lastArrayId_);\n\n  this.addAdditionalParams_(uri);\n\n  if (this.httpHeadersOverwriteParam_ && this.extraHeaders_) {\n    httpCors.setHttpHeadersWithOverwriteParam(\n        uri, this.httpHeadersOverwriteParam_, this.extraHeaders_);\n  }\n\n  const request = ChannelRequest.createChannelRequest(\n      this, this.channelDebug_, this.sid_, rid,\n      this.forwardChannelRetryCount_ + 1);\n\n  if (this.httpHeadersOverwriteParam_ === null) {\n    request.setExtraHeaders(this.extraHeaders_);\n  }\n\n  let requestText;\n  if (opt_retryRequest) {\n    this.requeuePendingMaps_(opt_retryRequest);\n  }\n  requestText =\n      this.dequeueOutgoingMaps_(request, WebChannelBase.MAX_MAPS_PER_REQUEST_);\n\n  // Randomize from 50%-100% of the forward channel timeout to avoid\n  // a big hit if servers happen to die at once.\n  request.setTimeout(\n      Math.round(this.forwardChannelRequestTimeoutMs_ * 0.50) +\n      Math.round(this.forwardChannelRequestTimeoutMs_ * 0.50 * Math.random()));\n  this.forwardChannelRequestPool_.addRequest(request);\n  request.xmlHttpPost(uri, requestText, true);\n};\n\n\n/**\n * Adds additional query parameters from `extraParams_` and `handler_` to the\n * given URI.\n * @param {!goog.Uri} uri The URI to add the parameters to.\n * @private\n */\nWebChannelBase.prototype.addAdditionalParams_ = function(uri) {\n  'use strict';\n  if (this.extraParams_) {\n    goog.object.forEach(this.extraParams_, function(value, key) {\n      'use strict';\n      uri.setParameterValue(key, value);\n    });\n  }\n\n  if (this.handler_) {\n    const params = this.handler_.getAdditionalParams(this);\n    if (params) {\n      goog.structs.forEach(params, function(value, key, coll) {\n        'use strict';\n        uri.setParameterValue(key, value);\n      });\n    }\n  }\n};\n\n\n/**\n * Returns the request text from the outgoing maps and resets it.\n * @param {!ChannelRequest} request The new request for sending the messages.\n * @param {number} maxNum The maximum number of messages to be encoded\n * @return {string} The encoded request text created from all the currently\n *                  queued outgoing maps.\n * @private\n */\nWebChannelBase.prototype.dequeueOutgoingMaps_ = function(request, maxNum) {\n  'use strict';\n  const count = Math.min(this.outgoingMaps_.length, maxNum);\n\n  const badMapHandler = this.handler_ ?\n      goog.bind(this.handler_.badMapError, this.handler_, this) :\n      null;\n  const result = this.wireCodec_.encodeMessageQueue(\n      this.outgoingMaps_, count, badMapHandler);\n\n  request.setPendingMessages(this.outgoingMaps_.splice(0, count));\n\n  return result;\n};\n\n\n/**\n * Requeues unacknowledged sent arrays for retransmission in the next forward\n * channel request.\n * @param {!ChannelRequest} retryRequest A failed request to retry.\n * @private\n */\nWebChannelBase.prototype.requeuePendingMaps_ = function(retryRequest) {\n  'use strict';\n  this.outgoingMaps_ =\n      retryRequest.getPendingMessages().concat(this.outgoingMaps_);\n};\n\n\n/**\n * Ensures there is a backchannel request for receiving data from the server.\n * @private\n */\nWebChannelBase.prototype.ensureBackChannel_ = function() {\n  'use strict';\n  if (this.backChannelRequest_) {\n    // already have one\n    return;\n  }\n\n  if (this.backChannelTimerId_) {\n    // no need to start a new request - one is already scheduled\n    return;\n  }\n\n  this.backChannelAttemptId_ = 1;\n\n  // Use async.run instead of setTimeout(0) to avoid the 1s message delay\n  // from chrome/firefox background tabs\n  // backChannelTimerId_ stays unset, as with setTimeout(0)\n  goog.async.run(this.onStartBackChannelTimer_, this);\n\n  this.backChannelRetryCount_ = 0;\n};\n\n\n/**\n * Schedules a back-channel retry, unless the max retries has been reached.\n * @return {boolean} true iff a retry was scheduled.\n * @private\n */\nWebChannelBase.prototype.maybeRetryBackChannel_ = function() {\n  'use strict';\n  if (this.backChannelRequest_ || this.backChannelTimerId_) {\n    // Should be impossible to be called in this state.\n    this.channelDebug_.severe('Request already in progress');\n    return false;\n  }\n\n  if (this.backChannelRetryCount_ >= this.getBackChannelMaxRetries()) {\n    return false;\n  }\n\n  this.channelDebug_.debug('Going to retry GET');\n\n  this.backChannelAttemptId_++;\n  this.backChannelTimerId_ = requestStats.setTimeout(\n      goog.bind(this.onStartBackChannelTimer_, this),\n      this.getRetryTime_(this.backChannelRetryCount_));\n  this.backChannelRetryCount_++;\n  return true;\n};\n\n\n/**\n * Timer callback for ensureBackChannel_.\n * @private\n */\nWebChannelBase.prototype.onStartBackChannelTimer_ = function() {\n  'use strict';\n  this.backChannelTimerId_ = null;\n  this.startBackChannel_();\n\n  if (!this.detectBufferingProxy_) {\n    return;\n  }\n\n  if (this.bpDetectionDone_) {\n    return;\n  }\n\n  if (this.backChannelRequest_ == null || this.handshakeRttMs_ <= 0) {\n    this.channelDebug_.warning(\n        'Skip bpDetectionTimerId_ ' + this.backChannelRequest_ + ' ' +\n        this.handshakeRttMs_);\n    return;\n  }\n\n  // This goes with each new request until bpDetectionDone_\n  const bpDetectionTimeout = 2 * this.handshakeRttMs_;\n  this.channelDebug_.info('BP detection timer enabled: ' + bpDetectionTimeout);\n\n  this.bpDetectionTimerId_ = requestStats.setTimeout(\n      goog.bind(this.onBpDetectionTimer_, this), bpDetectionTimeout);\n};\n\n\n/**\n * Timer callback for bpDetection.\n * @private\n */\nWebChannelBase.prototype.onBpDetectionTimer_ = function() {\n  'use strict';\n  if (!this.bpDetectionTimerId_) {\n    this.channelDebug_.warning('Invalid operation.');\n    return;\n  }\n\n  this.bpDetectionTimerId_ = null;\n  this.channelDebug_.info('BP detection timeout reached.');\n\n  goog.asserts.assert(\n      this.backChannelRequest_ != null,\n      'Invalid state: no backchannel request');\n\n  // We wait for extra response payload in addition to just headers to\n  // cancel the timer.\n  if (this.backChannelRequest_.getXhr() != null) {\n    const responseData = this.backChannelRequest_.getXhr().getResponseText();\n    if (responseData) {\n      this.channelDebug_.warning(\n          'Timer should have been cancelled : ' + responseData);\n    }\n  }\n\n  // Enable long-polling\n  this.channelDebug_.info(\n      'Buffering proxy detected and switch to long-polling!');\n  this.enableStreaming_ = false;\n\n  this.bpDetectionDone_ = true;\n  requestStats.notifyStatEvent(requestStats.Stat.PROXY);\n\n  // Cancel the request and start a new one immediately\n  this.cancelBackChannelRequest_();\n  this.startBackChannel_();\n};\n\n\n/**\n * Clears the timer for BP detection.\n * @private\n */\nWebChannelBase.prototype.clearBpDetectionTimer_ = function() {\n  'use strict';\n  if (this.bpDetectionTimerId_ != null) {\n    this.channelDebug_.debug('Cancel the BP detection timer.');\n    goog.global.clearTimeout(this.bpDetectionTimerId_);\n    this.bpDetectionTimerId_ = null;\n  }\n};\n\n\n/**\n * Begins a new back channel operation to the server.\n * @private\n */\nWebChannelBase.prototype.startBackChannel_ = function() {\n  'use strict';\n  if (!this.okToMakeRequest_()) {\n    // channel is cancelled\n    return;\n  }\n\n  this.channelDebug_.debug('Creating new HttpRequest');\n  this.backChannelRequest_ = ChannelRequest.createChannelRequest(\n      this, this.channelDebug_, this.sid_, 'rpc', this.backChannelAttemptId_);\n\n  if (this.httpHeadersOverwriteParam_ === null) {\n    this.backChannelRequest_.setExtraHeaders(this.extraHeaders_);\n  }\n\n  this.backChannelRequest_.setReadyStateChangeThrottle(\n      this.readyStateChangeThrottleMs_);\n  const uri = this.backChannelUri_.clone();\n  uri.setParameterValue('RID', 'rpc');\n  uri.setParameterValue('SID', this.sid_);\n  uri.setParameterValue('CI', this.enableStreaming_ ? '0' : '1');\n  uri.setParameterValue('AID', this.lastArrayId_);\n  uri.setParameterValue('TYPE', 'xmlhttp');\n\n  this.addAdditionalParams_(uri);\n\n  if (this.httpHeadersOverwriteParam_ && this.extraHeaders_) {\n    httpCors.setHttpHeadersWithOverwriteParam(\n        uri, this.httpHeadersOverwriteParam_, this.extraHeaders_);\n  }\n\n  if (this.backChannelRequestTimeoutMs_) {\n    this.backChannelRequest_.setTimeout(this.backChannelRequestTimeoutMs_);\n  }\n\n  this.backChannelRequest_.xmlHttpGet(\n      uri, true /* decodeChunks */, this.hostPrefix_);\n\n  this.channelDebug_.debug('New Request created');\n};\n\n\n/**\n * Gives the handler a chance to return an error code and stop channel\n * execution. A handler might want to do this to check that the user is still\n * logged in, for example.\n * @private\n * @return {boolean} If it's OK to make a request.\n */\nWebChannelBase.prototype.okToMakeRequest_ = function() {\n  'use strict';\n  if (this.handler_) {\n    const result = this.handler_.okToMakeRequest(this);\n    if (result != WebChannelBase.Error.OK) {\n      this.channelDebug_.debug(\n          'Handler returned error code from okToMakeRequest');\n      this.signalError_(result);\n      return false;\n    }\n  }\n  return true;\n};\n\n\n/**\n * @override\n */\nWebChannelBase.prototype.onFirstByteReceived = function(request, responseText) {\n  'use strict';\n  if (this.backChannelRequest_ == request && this.detectBufferingProxy_) {\n    if (!this.bpDetectionDone_) {\n      this.channelDebug_.info(\n          'Great, no buffering proxy detected. Bytes received: ' +\n          responseText.length);\n      goog.asserts.assert(\n          this.bpDetectionTimerId_, 'Timer should not have been cancelled.');\n      this.clearBpDetectionTimer_();\n      this.bpDetectionDone_ = true;\n      requestStats.notifyStatEvent(requestStats.Stat.NOPROXY);\n    }\n  }\n};\n\n\n/**\n * @override\n */\nWebChannelBase.prototype.onRequestData = function(request, responseText) {\n  'use strict';\n  if (this.state_ == WebChannelBase.State.CLOSED ||\n      (this.backChannelRequest_ != request &&\n       !this.forwardChannelRequestPool_.hasRequest(request))) {\n    // either CLOSED or a request we don't know about (perhaps an old request)\n    return;\n  }\n\n  // first to check if request has been upgraded to backchannel\n  if (!request.isInitialResponseDecoded() &&\n      this.forwardChannelRequestPool_.hasRequest(request) &&\n      this.state_ == WebChannelBase.State.OPENED) {\n    let response;\n    try {\n      response = this.wireCodec_.decodeMessage(responseText);\n    } catch (ex) {\n      response = null;\n    }\n    if (Array.isArray(response) && response.length == 3) {\n      this.handlePostResponse_(/** @type {!Array<?>} */ (response), request);\n      this.onForwardChannelFlushed_();\n    } else {\n      this.channelDebug_.debug('Bad POST response data returned');\n      this.signalError_(WebChannelBase.Error.BAD_RESPONSE);\n    }\n  } else {\n    if (request.isInitialResponseDecoded() ||\n        this.backChannelRequest_ == request) {\n      this.clearDeadBackchannelTimer_();\n    }\n\n    if (!goog.string.isEmptyOrWhitespace(responseText)) {\n      let response = this.wireCodec_.decodeMessage(responseText);\n      this.onInput_(/** @type {!Array<?>} */ (response), request);\n    }\n  }\n};\n\n\n/**\n * Checks if we need call the flush callback.\n *\n * @private\n */\nWebChannelBase.prototype.onForwardChannelFlushed_ = function() {\n  'use strict';\n  if (this.forwardChannelRequestPool_.getRequestCount() <= 1) {\n    if (this.forwardChannelFlushedCallback_) {\n      try {\n        this.forwardChannelFlushedCallback_();\n      } catch (ex) {\n        this.channelDebug_.dumpException(\n            ex, 'Exception from forwardChannelFlushedCallback_ ');\n      }\n      // reset\n      this.forwardChannelFlushedCallback_ = undefined;\n    }\n  }\n};\n\n\n/**\n * Handles a POST response from the server.\n * @param {Array<number>} responseValues The key value pairs in\n *     the POST response.\n * @param {!ChannelRequest} forwardReq The forward channel request that\n * triggers this function call.\n * @private\n */\nWebChannelBase.prototype.handlePostResponse_ = function(\n    responseValues, forwardReq) {\n  'use strict';\n  // The first response value is set to 0 if server is missing backchannel.\n  if (responseValues[0] == 0) {\n    this.handleBackchannelMissing_(forwardReq);\n    return;\n  }\n  this.lastPostResponseArrayId_ = responseValues[1];\n  const outstandingArrays = this.lastPostResponseArrayId_ - this.lastArrayId_;\n  if (0 < outstandingArrays) {\n    const numOutstandingBackchannelBytes = responseValues[2];\n    this.channelDebug_.debug(\n        numOutstandingBackchannelBytes + ' bytes (in ' + outstandingArrays +\n        ' arrays) are outstanding on the BackChannel');\n    if (!this.shouldRetryBackChannel_(numOutstandingBackchannelBytes)) {\n      return;\n    }\n    if (!this.deadBackChannelTimerId_) {\n      // We expect to receive data within 2 RTTs or we retry the backchannel.\n      this.deadBackChannelTimerId_ = requestStats.setTimeout(\n          goog.bind(this.onBackChannelDead_, this),\n          2 * WebChannelBase.RTT_ESTIMATE);\n    }\n  }\n};\n\n\n/**\n * Handles a POST response from the server telling us that it has detected that\n * we have no hanging GET connection.\n * @param {!ChannelRequest} forwardReq The forward channel request that\n * triggers this function call.\n * @private\n */\nWebChannelBase.prototype.handleBackchannelMissing_ = function(forwardReq) {\n  'use strict';\n  // As long as the back channel was started before the POST was sent,\n  // we should retry the backchannel. We give a slight buffer of RTT_ESTIMATE\n  // so as not to excessively retry the backchannel\n  this.channelDebug_.debug('Server claims our backchannel is missing.');\n  if (this.backChannelTimerId_) {\n    this.channelDebug_.debug('But we are currently starting the request.');\n    return;\n  } else if (!this.backChannelRequest_) {\n    this.channelDebug_.warning('We do not have a BackChannel established');\n  } else if (\n      this.backChannelRequest_.getRequestStartTime() +\n          WebChannelBase.RTT_ESTIMATE <\n      forwardReq.getRequestStartTime()) {\n    this.clearDeadBackchannelTimer_();\n    this.cancelBackChannelRequest_();\n  } else {\n    return;\n  }\n  this.maybeRetryBackChannel_();\n  requestStats.notifyStatEvent(requestStats.Stat.BACKCHANNEL_MISSING);\n};\n\n\n/**\n * Determines whether we should start the process of retrying a possibly\n * dead backchannel.\n * @param {number} outstandingBytes The number of bytes for which the server has\n *     not yet received acknowledgement.\n * @return {boolean} Whether to start the backchannel retry timer.\n * @private\n */\nWebChannelBase.prototype.shouldRetryBackChannel_ = function(outstandingBytes) {\n  'use strict';\n  // Not too many outstanding bytes, not buffered and not after a retry.\n  return outstandingBytes <\n      WebChannelBase.OUTSTANDING_DATA_BACKCHANNEL_RETRY_CUTOFF &&\n      !this.isBuffered() && this.backChannelRetryCount_ == 0;\n};\n\n\n/**\n * Decides which host prefix should be used, if any.  If there is a handler,\n * allows the handler to validate a host prefix provided by the server, and\n * optionally override it.\n * @param {?string} serverHostPrefix The host prefix provided by the server.\n * @return {?string} The host prefix to actually use, if any. Will return null\n *     if the use of host prefixes was disabled via setAllowHostPrefix().\n * @override\n */\nWebChannelBase.prototype.correctHostPrefix = function(serverHostPrefix) {\n  'use strict';\n  if (this.allowHostPrefix_) {\n    if (this.handler_) {\n      return this.handler_.correctHostPrefix(serverHostPrefix);\n    }\n    return serverHostPrefix;\n  }\n  return null;\n};\n\n\n/**\n * Handles the timer that indicates that our backchannel is no longer able to\n * successfully receive data from the server.\n * @private\n */\nWebChannelBase.prototype.onBackChannelDead_ = function() {\n  'use strict';\n  if (this.deadBackChannelTimerId_ != null) {\n    this.deadBackChannelTimerId_ = null;\n    this.cancelBackChannelRequest_();\n    this.maybeRetryBackChannel_();\n    requestStats.notifyStatEvent(requestStats.Stat.BACKCHANNEL_DEAD);\n  }\n};\n\n\n/**\n * Clears the timer that indicates that our backchannel is no longer able to\n * successfully receive data from the server.\n * @private\n */\nWebChannelBase.prototype.clearDeadBackchannelTimer_ = function() {\n  'use strict';\n  if (this.deadBackChannelTimerId_ != null) {\n    goog.global.clearTimeout(this.deadBackChannelTimerId_);\n    this.deadBackChannelTimerId_ = null;\n  }\n};\n\n\n/**\n * Returns whether or not the given error/status combination is fatal or not.\n * On fatal errors we immediately close the session rather than retrying the\n * failed request.\n * @param {?ChannelRequest.Error} error The error code for the\n * failed request.\n * @param {number} statusCode The last HTTP status code.\n * @return {boolean} Whether or not the error is fatal.\n * @private\n */\nWebChannelBase.isFatalError_ = function(error, statusCode) {\n  'use strict';\n  return error == ChannelRequest.Error.UNKNOWN_SESSION_ID ||\n      (error == ChannelRequest.Error.STATUS && statusCode > 0);\n};\n\n\n/**\n * @override\n */\nWebChannelBase.prototype.onRequestComplete = function(request) {\n  'use strict';\n  this.channelDebug_.debug('Request complete');\n  let type;\n  let pendingMessages = null;\n  if (this.backChannelRequest_ == request) {\n    this.clearDeadBackchannelTimer_();\n    this.clearBpDetectionTimer_();\n    this.backChannelRequest_ = null;\n    type = WebChannelBase.ChannelType_.BACK_CHANNEL;\n  } else if (this.forwardChannelRequestPool_.hasRequest(request)) {\n    pendingMessages = request.getPendingMessages();\n    this.forwardChannelRequestPool_.removeRequest(request);\n    type = WebChannelBase.ChannelType_.FORWARD_CHANNEL;\n  } else {\n    // return if it was an old request from a previous session\n    return;\n  }\n\n  if (this.state_ == WebChannelBase.State.CLOSED) {\n    return;\n  }\n\n  this.lastStatusCode_ = request.getLastStatusCode();\n\n  if (request.getSuccess()) {\n    if (type == WebChannelBase.ChannelType_.FORWARD_CHANNEL) {\n      const size = request.getPostData() ? request.getPostData().length : 0;\n      requestStats.notifyTimingEvent(\n          size, Date.now() - request.getRequestStartTime(),\n          this.forwardChannelRetryCount_);\n      this.ensureForwardChannel_();\n      this.onSuccess_(request);\n    } else {  // i.e., back-channel\n      this.ensureBackChannel_();\n    }\n    return;\n  }\n  // Else unsuccessful. Fall through.\n\n  const lastError = request.getLastError();\n  if (!WebChannelBase.isFatalError_(lastError, this.lastStatusCode_)) {\n    // Maybe retry.\n    const self = this;\n    this.channelDebug_.debug(function() {\n      'use strict';\n      return 'Maybe retrying, last error: ' +\n          ChannelRequest.errorStringFromCode(lastError, self.lastStatusCode_);\n    });\n    if (type == WebChannelBase.ChannelType_.FORWARD_CHANNEL) {\n      if (this.maybeRetryForwardChannel_(request)) {\n        return;\n      }\n    }\n    if (type == WebChannelBase.ChannelType_.BACK_CHANNEL) {\n      if (this.maybeRetryBackChannel_()) {\n        return;\n      }\n    }\n    // Else exceeded max retries. Fall through.\n    this.channelDebug_.debug('Exceeded max number of retries');\n  } else {\n    // Else fatal error. Fall through and mark the pending maps as failed.\n    this.channelDebug_.debug('Not retrying due to error type');\n  }\n\n\n  // Abort the channel now\n\n  // Record pending messages from the failed request\n  if (pendingMessages && pendingMessages.length > 0) {\n    this.forwardChannelRequestPool_.addPendingMessages(pendingMessages);\n  }\n\n  this.channelDebug_.debug('Error: HTTP request failed');\n  switch (lastError) {\n    case ChannelRequest.Error.NO_DATA:\n      this.signalError_(WebChannelBase.Error.NO_DATA);\n      break;\n    case ChannelRequest.Error.BAD_DATA:\n      this.signalError_(WebChannelBase.Error.BAD_DATA);\n      break;\n    case ChannelRequest.Error.UNKNOWN_SESSION_ID:\n      this.signalError_(WebChannelBase.Error.UNKNOWN_SESSION_ID);\n      break;\n    default:\n      this.signalError_(WebChannelBase.Error.REQUEST_FAILED);\n      break;\n  }\n};\n\n\n/**\n * @param {number} retryCount Number of retries so far.\n * @return {number} Time in ms before firing next retry request.\n * @private\n */\nWebChannelBase.prototype.getRetryTime_ = function(retryCount) {\n  'use strict';\n  let retryTime = this.baseRetryDelayMs_ +\n      Math.floor(Math.random() * this.retryDelaySeedMs_);\n  if (!this.isActive()) {\n    this.channelDebug_.debug('Inactive channel');\n    retryTime = retryTime * WebChannelBase.INACTIVE_CHANNEL_RETRY_FACTOR;\n  }\n  // Backoff for subsequent retries\n  retryTime *= retryCount;\n  return retryTime;\n};\n\n\n/**\n * @param {number} baseDelayMs The base part of the retry delay, in ms.\n * @param {number} delaySeedMs A random delay between 0 and this is added to\n *     the base part.\n */\nWebChannelBase.prototype.setRetryDelay = function(baseDelayMs, delaySeedMs) {\n  'use strict';\n  this.baseRetryDelayMs_ = baseDelayMs;\n  this.retryDelaySeedMs_ = delaySeedMs;\n};\n\n\n/**\n * Apply any handshake control headers.\n * @param {!ChannelRequest} request The underlying request object\n * @private\n */\nWebChannelBase.prototype.applyControlHeaders_ = function(request) {\n  'use strict';\n  const xhr = request.getXhr();\n  if (xhr) {\n    const clientProtocol =\n        xhr.getStreamingResponseHeader(WebChannel.X_CLIENT_WIRE_PROTOCOL);\n    if (clientProtocol) {\n      this.forwardChannelRequestPool_.applyClientProtocol(clientProtocol);\n    }\n\n    if (this.getHttpSessionIdParam()) {\n      const httpSessionIdHeader =\n          xhr.getStreamingResponseHeader(WebChannel.X_HTTP_SESSION_ID);\n      if (httpSessionIdHeader) {\n        this.setHttpSessionId(httpSessionIdHeader);\n        // update the cached uri\n        const httpSessionIdParam = this.getHttpSessionIdParam();\n\n        this.forwardChannelUri_.setParameterValue(\n            /** @type {string} */ (httpSessionIdParam),  // never null\n            httpSessionIdHeader);\n      } else {\n        this.channelDebug_.warning(\n            'Missing X_HTTP_SESSION_ID in the handshake response');\n      }\n    }\n  }\n};\n\n\n/**\n * Processes the data returned by the server.\n * @param {!Array<!Array<?>>} respArray The response array returned\n *     by the server.\n * @param {!ChannelRequest} request The underlying request object\n * @private\n */\nWebChannelBase.prototype.onInput_ = function(respArray, request) {\n  'use strict';\n  const batch =\n      this.handler_ && this.handler_.channelHandleMultipleArrays ? [] : null;\n  for (let i = 0; i < respArray.length; i++) {\n    let nextArray = respArray[i];\n    this.lastArrayId_ = nextArray[0];\n    nextArray = nextArray[1];\n    if (this.state_ == WebChannelBase.State.OPENING) {\n      if (nextArray[0] == 'c') {\n        this.sid_ = nextArray[1];\n        this.hostPrefix_ = this.correctHostPrefix(nextArray[2]);\n\n        const negotiatedVersion = nextArray[3];\n        if (negotiatedVersion != null) {\n          this.channelVersion_ = negotiatedVersion;\n          this.channelDebug_.info('VER=' + this.channelVersion_);\n        }\n\n        const negotiatedServerVersion = nextArray[4];\n        if (negotiatedServerVersion != null) {\n          this.serverVersion_ = negotiatedServerVersion;\n          this.channelDebug_.info('SVER=' + this.serverVersion_);\n        }\n\n        // CVER=22\n        const serverKeepaliveMs = nextArray[5];\n        if (serverKeepaliveMs != null &&\n            typeof serverKeepaliveMs === 'number' && serverKeepaliveMs > 0) {\n          const timeout = 1.5 * serverKeepaliveMs;\n          this.backChannelRequestTimeoutMs_ = timeout;\n          this.channelDebug_.info('backChannelRequestTimeoutMs_=' + timeout);\n        }\n\n        this.applyControlHeaders_(request);\n\n        this.state_ = WebChannelBase.State.OPENED;\n        if (this.handler_) {\n          this.handler_.channelOpened(this);\n        }\n\n        if (this.detectBufferingProxy_) {\n          this.handshakeRttMs_ = Date.now() - request.getRequestStartTime();\n          this.channelDebug_.info(\n              'Handshake RTT: ' + this.handshakeRttMs_ + 'ms');\n        }\n\n        this.startBackchannelAfterHandshake_(request);\n\n        if (this.outgoingMaps_.length > 0) {\n          this.ensureForwardChannel_();\n        }\n      } else if (nextArray[0] == 'stop' || nextArray[0] == 'close') {\n        // treat close also as an abort\n        this.signalError_(WebChannelBase.Error.STOP);\n      }\n    } else if (this.state_ == WebChannelBase.State.OPENED) {\n      if (nextArray[0] == 'stop' || nextArray[0] == 'close') {\n        if (batch && !(batch.length === 0)) {\n          this.handler_.channelHandleMultipleArrays(this, batch);\n          batch.length = 0;\n        }\n        if (nextArray[0] == 'stop') {\n          this.signalError_(WebChannelBase.Error.STOP);\n        } else {\n          this.disconnect();\n        }\n      } else if (nextArray[0] == 'noop') {\n        // ignore - noop to keep connection happy\n      } else {\n        if (batch) {\n          batch.push(nextArray);\n        } else if (this.handler_) {\n          this.handler_.channelHandleArray(this, nextArray);\n        }\n      }\n      // We have received useful data on the back-channel, so clear its retry\n      // count. We do this because back-channels by design do not complete\n      // quickly, so on a flaky connection we could have many fail to complete\n      // fully but still deliver a lot of data before they fail. We don't want\n      // to count such failures towards the retry limit, because we don't want\n      // to give up on a session if we can still receive data.\n      this.backChannelRetryCount_ = 0;\n    }\n  }\n  if (batch && !(batch.length === 0)) {\n    this.handler_.channelHandleMultipleArrays(this, batch);\n  }\n};\n\n\n/**\n * Starts the backchannel after the handshake.\n *\n * @param {!ChannelRequest} request The underlying request object\n * @private\n */\nWebChannelBase.prototype.startBackchannelAfterHandshake_ = function(request) {\n  'use strict';\n  this.backChannelUri_ = this.getBackChannelUri(\n      this.hostPrefix_, /** @type {string} */ (this.path_));\n\n  if (request.isInitialResponseDecoded()) {\n    this.channelDebug_.debug('Upgrade the handshake request to a backchannel.');\n    this.forwardChannelRequestPool_.removeRequest(request);\n    request.resetTimeout(this.backChannelRequestTimeoutMs_);\n    this.backChannelRequest_ = request;\n  } else {\n    this.ensureBackChannel_();\n  }\n};\n\n\n/**\n * Helper to ensure the channel is in the expected state.\n * @param {...number} var_args The channel must be in one of the indicated\n *     states.\n * @private\n */\nWebChannelBase.prototype.ensureInState_ = function(var_args) {\n  'use strict';\n  goog.asserts.assert(\n      goog.array.contains(arguments, this.state_),\n      'Unexpected channel state: %s', this.state_);\n};\n\n\n/**\n * Signals an error has occurred.\n * @param {WebChannelBase.Error} error The error code for the failure.\n * @private\n */\nWebChannelBase.prototype.signalError_ = function(error) {\n  'use strict';\n  this.channelDebug_.info('Error code ' + error);\n  if (error == WebChannelBase.Error.REQUEST_FAILED) {\n    // Create a separate Internet connection to check\n    // if it's a server error or user's network error.\n    let imageUri = null;\n    if (this.handler_) {\n      imageUri = this.handler_.getNetworkTestImageUri(this);\n    }\n    netUtils.testNetwork(goog.bind(this.testNetworkCallback_, this), imageUri);\n  } else {\n    requestStats.notifyStatEvent(requestStats.Stat.ERROR_OTHER);\n  }\n  this.onError_(error);\n};\n\n\n/**\n * Callback for netUtils.testNetwork during error handling.\n * @param {boolean} networkUp Whether the network is up.\n * @private\n */\nWebChannelBase.prototype.testNetworkCallback_ = function(networkUp) {\n  'use strict';\n  if (networkUp) {\n    this.channelDebug_.info('Successfully pinged google.com');\n    requestStats.notifyStatEvent(requestStats.Stat.ERROR_OTHER);\n  } else {\n    this.channelDebug_.info('Failed to ping google.com');\n    requestStats.notifyStatEvent(requestStats.Stat.ERROR_NETWORK);\n    // Do not call onError_ again to eliminate duplicated Error events.\n  }\n};\n\n\n/**\n * Called when messages have been successfully sent from the queue.\n * @param {!ChannelRequest} request The request object\n * @private\n */\nWebChannelBase.prototype.onSuccess_ = function(request) {\n  'use strict';\n  if (this.handler_) {\n    this.handler_.channelSuccess(this, request);\n  }\n};\n\n\n/**\n * Called when we've determined the final error for a channel. It closes the\n * notifiers the handler of the error and closes the channel.\n * @param {WebChannelBase.Error} error  The error code for the failure.\n * @private\n */\nWebChannelBase.prototype.onError_ = function(error) {\n  'use strict';\n  this.channelDebug_.debug('HttpChannel: error - ' + error);\n  this.state_ = WebChannelBase.State.CLOSED;\n  if (this.handler_) {\n    this.handler_.channelError(this, error);\n  }\n  this.onClose_();\n  this.cancelRequests_();\n};\n\n\n/**\n * Called when the channel has been closed. It notifiers the handler of the\n * event, and reports any pending or undelivered maps.\n * @private\n */\nWebChannelBase.prototype.onClose_ = function() {\n  'use strict';\n  this.state_ = WebChannelBase.State.CLOSED;\n  this.nonAckedMapsAtChannelClose_ = [];\n  if (this.handler_) {\n    const pendingMessages =\n        this.forwardChannelRequestPool_.getPendingMessages();\n\n    if (pendingMessages.length == 0 && this.outgoingMaps_.length == 0) {\n      this.handler_.channelClosed(this);\n    } else {\n      this.channelDebug_.debug(\n          () => 'Number of undelivered maps' +\n              ', pending: ' + pendingMessages.length +\n              ', outgoing: ' + this.outgoingMaps_.length);\n\n      goog.array.extend(this.nonAckedMapsAtChannelClose_, pendingMessages);\n      goog.array.extend(this.nonAckedMapsAtChannelClose_, this.outgoingMaps_);\n\n      this.forwardChannelRequestPool_.clearPendingMessages();\n\n      const copyOfUndeliveredMaps = goog.array.clone(this.outgoingMaps_);\n      this.outgoingMaps_.length = 0;\n\n      this.handler_.channelClosed(this, pendingMessages, copyOfUndeliveredMaps);\n    }\n  }\n};\n\n/**\n * @return {!Array<!Wire.QueuedMap>} Returns the list of non-acked maps, both\n * during an active channel or after the channel is closed. Refer to the\n * `getNonAckedMessages()` API for definitions of non-acked messages.\n */\nWebChannelBase.prototype.getNonAckedMaps = function() {\n  if (this.state_ == WebChannelBase.State.CLOSED) {\n    goog.asserts.assert(\n        this.nonAckedMapsAtChannelClose_ != null,\n        'nonAckedMapsAtChannelClose_ is not set after channel close.');\n    return this.nonAckedMapsAtChannelClose_;\n  }\n\n  // The underlying message objects are not cloned and thus exposes a mutability\n  // risk, but is chosen to make strict equality (i.e. ===) checks possible for\n  // callers.\n  let unAckedMaps = [];\n  goog.array.extend(\n      unAckedMaps, this.forwardChannelRequestPool_.getPendingMessages());\n  goog.array.extend(unAckedMaps, this.outgoingMaps_);\n\n  return unAckedMaps;\n};\n\n\n/**\n * @override\n */\nWebChannelBase.prototype.getForwardChannelUri = function(path) {\n  'use strict';\n  const uri = this.createDataUri(null, path);\n  this.channelDebug_.debug('GetForwardChannelUri: ' + uri);\n  return uri;\n};\n\n\n/**\n * @override\n */\nWebChannelBase.prototype.getConnectionState = function() {\n  'use strict';\n  return this.connState_;\n};\n\n\n/**\n * @override\n */\nWebChannelBase.prototype.getBackChannelUri = function(hostPrefix, path) {\n  'use strict';\n  const uri = this.createDataUri(\n      this.shouldUseSecondaryDomains() ? hostPrefix : null, path);\n  this.channelDebug_.debug('GetBackChannelUri: ' + uri);\n  return uri;\n};\n\n\n/**\n * @override\n */\nWebChannelBase.prototype.createDataUri = function(\n    hostPrefix, path, opt_overridePort) {\n  'use strict';\n  let uri = goog.Uri.parse(path);\n  const uriAbsolute = (uri.getDomain() != '');\n  if (uriAbsolute) {\n    if (hostPrefix) {\n      uri.setDomain(hostPrefix + '.' + uri.getDomain());\n    }\n\n    uri.setPort(opt_overridePort || uri.getPort());\n  } else {\n    const locationPage = goog.global.location;\n    let hostName;\n    if (hostPrefix) {\n      hostName = hostPrefix + '.' + locationPage.hostname;\n    } else {\n      hostName = locationPage.hostname;\n    }\n\n    const port = opt_overridePort || +locationPage.port;\n\n    uri = goog.Uri.create(locationPage.protocol, null, hostName, port, path);\n  }\n\n  const param = this.getHttpSessionIdParam();\n  const value = this.getHttpSessionId();\n  if (param && value) {\n    uri.setParameterValue(param, value);\n  }\n\n  // Add the protocol version to the URI.\n  uri.setParameterValue('VER', this.channelVersion_);\n\n  this.addAdditionalParams_(uri);\n\n  return uri;\n};\n\n/**\n * @override\n * @param {?string} hostPrefix The host prefix, if we need an XhrIo object\n *     capable of calling a secondary domain.\n * @param {boolean=} isStreaming Whether or not fetch/streams are enabled for\n *     the underlying HTTP request.\n * @return {!goog.net.XhrIo} A new XhrIo object.\n */\nWebChannelBase.prototype.createXhrIo = function(hostPrefix, isStreaming) {\n  'use strict';\n  if (hostPrefix && !this.supportsCrossDomainXhrs_) {\n    throw new Error('Can\\'t create secondary domain capable XhrIo object.');\n  }\n  let xhr;\n  if (isStreaming && this.usesFetchStreams_ && !this.xmlHttpFactory_) {\n    xhr = new goog.net.XhrIo(\n        new goog.net.FetchXmlHttpFactory({streamBinaryChunks: true}));\n  } else {\n    xhr = new goog.net.XhrIo(this.xmlHttpFactory_);\n  }\n  xhr.setWithCredentials(this.supportsCrossDomainXhrs_);\n  return xhr;\n};\n\n\n/**\n * @override\n */\nWebChannelBase.prototype.isActive = function() {\n  'use strict';\n  return !!this.handler_ && this.handler_.isActive(this);\n};\n\n\n/**\n * @override\n */\nWebChannelBase.prototype.shouldUseSecondaryDomains = function() {\n  'use strict';\n  return this.supportsCrossDomainXhrs_;\n};\n\n\n/**\n * Sets (overwrites) the forward channel flush callback.\n *\n * @param {function()} callback The callback to be invoked.\n */\nWebChannelBase.prototype.setForwardChannelFlushCallback = function(callback) {\n  'use strict';\n  this.forwardChannelFlushedCallback_ = callback;\n};\n\n\n/**\n * Abstract base class for the channel handler\n * @constructor\n * @struct\n */\nWebChannelBase.Handler = function() {};\n\n\n/**\n * Callback handler for when a batch of response arrays is received from the\n * server. When null, batched dispatching is disabled.\n * @type {?function(!WebChannelBase, !Array<!Array<?>>)}\n */\nWebChannelBase.Handler.prototype.channelHandleMultipleArrays = null;\n\n\n/**\n * Whether it's okay to make a request to the server. A handler can return\n * false if the channel should fail. For example, if the user has logged out,\n * the handler may want all requests to fail immediately.\n * @param {WebChannelBase} channel The channel.\n * @return {WebChannelBase.Error} An error code. The code should\n * return WebChannelBase.Error.OK to indicate it's okay. Any other\n * error code will cause a failure.\n */\nWebChannelBase.Handler.prototype.okToMakeRequest = function(channel) {\n  'use strict';\n  return WebChannelBase.Error.OK;\n};\n\n\n/**\n * Indicates the WebChannel has successfully negotiated with the server\n * and can now send and receive data.\n * @param {WebChannelBase} channel The channel.\n */\nWebChannelBase.Handler.prototype.channelOpened = function(channel) {};\n\n\n/**\n * New input is available for the application to process.\n *\n * @param {WebChannelBase} channel The channel.\n * @param {Array<?>} array The data array.\n */\nWebChannelBase.Handler.prototype.channelHandleArray = function(\n    channel, array) {};\n\n\n/**\n * Indicates messages that have been successfully sent on the channel.\n *\n * @param {WebChannelBase} channel The channel.\n * @param {!ChannelRequest} request The request object that contains\n *     the pending messages that have been successfully delivered to the server.\n */\nWebChannelBase.Handler.prototype.channelSuccess = function(channel, request) {};\n\n\n/**\n * Indicates an error occurred on the WebChannel.\n *\n * @param {WebChannelBase} channel The channel.\n * @param {WebChannelBase.Error} error The error code.\n */\nWebChannelBase.Handler.prototype.channelError = function(channel, error) {};\n\n\n/**\n * Indicates the WebChannel is closed. Also notifies about which maps,\n * if any, that may not have been delivered to the server.\n * @param {WebChannelBase} channel The channel.\n * @param {Array<Wire.QueuedMap>=} opt_pendingMaps The\n *     array of pending maps, which may or may not have been delivered to the\n *     server.\n * @param {Array<Wire.QueuedMap>=} opt_undeliveredMaps\n *     The array of undelivered maps, which have definitely not been delivered\n *     to the server.\n */\nWebChannelBase.Handler.prototype.channelClosed = function(\n    channel, opt_pendingMaps, opt_undeliveredMaps) {};\n\n\n/**\n * Gets any parameters that should be added at the time another connection is\n * made to the server.\n * @param {WebChannelBase} channel The channel.\n * @return {!Object} Extra parameter keys and values to add to the requests.\n */\nWebChannelBase.Handler.prototype.getAdditionalParams = function(channel) {\n  'use strict';\n  return {};\n};\n\n\n/**\n * Gets the URI of an image that can be used to test network connectivity.\n * @param {WebChannelBase} channel The channel.\n * @return {goog.Uri?} A custom URI to load for the network test.\n */\nWebChannelBase.Handler.prototype.getNetworkTestImageUri = function(channel) {\n  'use strict';\n  return null;\n};\n\n\n/**\n * Gets whether this channel is currently active. This is used to determine the\n * length of time to wait before retrying.\n * @param {WebChannelBase} channel The channel.\n * @return {boolean} Whether the channel is currently active.\n */\nWebChannelBase.Handler.prototype.isActive = function(channel) {\n  'use strict';\n  return true;\n};\n\n/**\n * Whether or not this channel uses WHATWG Fetch/streams.\n * @override\n * @return {boolean}\n */\nWebChannelBase.prototype.usesFetchStreams = function() {\n  'use strict';\n  return this.usesFetchStreams_;\n};\n\n\n/**\n * Called by the channel if enumeration of the map throws an exception.\n * @param {WebChannelBase} channel The channel.\n * @param {Object} map The map that can't be enumerated.\n */\nWebChannelBase.Handler.prototype.badMapError = function(channel, map) {};\n\n\n/**\n * Allows the handler to override a host prefix provided by the server. Will\n * be called whenever the channel has received such a prefix and is considering\n * its use.\n * @param {?string} serverHostPrefix The host prefix provided by the server.\n * @return {?string} The host prefix the client should use.\n */\nWebChannelBase.Handler.prototype.correctHostPrefix = function(\n    serverHostPrefix) {\n  'use strict';\n  return serverHostPrefix;\n};\n});  // goog.scope\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Class for parsing and formatting URIs.\n *\n * This package is deprecated in favour of the Closure URL package (goog.url)\n * when manipulating URIs for use by a browser. This package uses regular\n * expressions to parse a potential URI which can fall out of sync with how a\n * browser will actually interpret the URI. See\n * `goog.uri.utils.setUrlPackageSupportLoggingHandler` for one way to identify\n * URIs that should instead be parsed using the URL package.\n *\n * Use goog.Uri(string) to parse a URI string.  Use goog.Uri.create(...) to\n * create a new instance of the goog.Uri object from Uri parts.\n *\n * e.g: <code>var myUri = new goog.Uri(window.location);</code>\n *\n * Implements RFC 3986 for parsing/formatting URIs.\n * http://www.ietf.org/rfc/rfc3986.txt\n *\n * Some changes have been made to the interface (more like .NETs), though the\n * internal representation is now of un-encoded parts, this will change the\n * behavior slightly.\n */\n\ngoog.provide('goog.Uri');\ngoog.provide('goog.Uri.QueryData');\n\ngoog.require('goog.array');\ngoog.require('goog.asserts');\ngoog.require('goog.collections.maps');\ngoog.require('goog.string');\ngoog.require('goog.structs');\ngoog.require('goog.uri.utils');\ngoog.require('goog.uri.utils.ComponentIndex');\ngoog.require('goog.uri.utils.StandardQueryParam');\n\n\n\n/**\n * This class contains setters and getters for the parts of the URI.\n * The <code>getXyz</code>/<code>setXyz</code> methods return the decoded part\n * -- so<code>goog.Uri.parse('/foo%20bar').getPath()</code> will return the\n * decoded path, <code>/foo bar</code>.\n *\n * Reserved characters (see RFC 3986 section 2.2) can be present in\n * their percent-encoded form in scheme, domain, and path URI components and\n * will not be auto-decoded. For example:\n * <code>goog.Uri.parse('rel%61tive/path%2fto/resource').getPath()</code> will\n * return <code>relative/path%2fto/resource</code>.\n *\n * The constructor accepts an optional unparsed, raw URI string.  The parser\n * is relaxed, so special characters that aren't escaped but don't cause\n * ambiguities will not cause parse failures.\n *\n * All setters return <code>this</code> and so may be chained, a la\n * <code>goog.Uri.parse('/foo').setFragment('part').toString()</code>.\n *\n * @param {*=} opt_uri Optional string URI to parse\n *        (use goog.Uri.create() to create a URI from parts), or if\n *        a goog.Uri is passed, a clone is created.\n * @param {boolean=} opt_ignoreCase If true, #getParameterValue will ignore\n * the case of the parameter name.\n *\n * @throws URIError If opt_uri is provided and URI is malformed (that is,\n *     if decodeURIComponent fails on any of the URI components).\n * @constructor\n * @struct\n */\ngoog.Uri = function(opt_uri, opt_ignoreCase) {\n  'use strict';\n  /**\n   * Scheme such as \"http\".\n   * @private {string}\n   */\n  this.scheme_ = '';\n\n  /**\n   * User credentials in the form \"username:password\".\n   * @private {string}\n   */\n  this.userInfo_ = '';\n\n  /**\n   * Domain part, e.g. \"www.google.com\".\n   * @private {string}\n   */\n  this.domain_ = '';\n\n  /**\n   * Port, e.g. 8080.\n   * @private {?number}\n   */\n  this.port_ = null;\n\n  /**\n   * Path, e.g. \"/tests/img.png\".\n   * @private {string}\n   */\n  this.path_ = '';\n\n  /**\n   * The fragment without the #.\n   * @private {string}\n   */\n  this.fragment_ = '';\n\n  /**\n   * Whether or not this Uri should be treated as Read Only.\n   * @private {boolean}\n   */\n  this.isReadOnly_ = false;\n\n  /**\n   * Whether or not to ignore case when comparing query params.\n   * @private {boolean}\n   */\n  this.ignoreCase_ = false;\n\n  /**\n   * Object representing query data.\n   * @private {!goog.Uri.QueryData}\n   */\n  this.queryData_;\n\n  // Parse in the uri string\n  var m;\n  if (opt_uri instanceof goog.Uri) {\n    this.ignoreCase_ = (opt_ignoreCase !== undefined) ? opt_ignoreCase :\n                                                        opt_uri.getIgnoreCase();\n    this.setScheme(opt_uri.getScheme());\n    this.setUserInfo(opt_uri.getUserInfo());\n    this.setDomain(opt_uri.getDomain());\n    this.setPort(opt_uri.getPort());\n    this.setPath(opt_uri.getPath());\n    this.setQueryData(opt_uri.getQueryData().clone());\n    this.setFragment(opt_uri.getFragment());\n  } else if (opt_uri && (m = goog.uri.utils.split(String(opt_uri)))) {\n    this.ignoreCase_ = !!opt_ignoreCase;\n\n    // Set the parts -- decoding as we do so.\n    // COMPATIBILITY NOTE - In IE, unmatched fields may be empty strings,\n    // whereas in other browsers they will be undefined.\n    this.setScheme(m[goog.uri.utils.ComponentIndex.SCHEME] || '', true);\n    this.setUserInfo(m[goog.uri.utils.ComponentIndex.USER_INFO] || '', true);\n    this.setDomain(m[goog.uri.utils.ComponentIndex.DOMAIN] || '', true);\n    this.setPort(m[goog.uri.utils.ComponentIndex.PORT]);\n    this.setPath(m[goog.uri.utils.ComponentIndex.PATH] || '', true);\n    this.setQueryData(m[goog.uri.utils.ComponentIndex.QUERY_DATA] || '', true);\n    this.setFragment(m[goog.uri.utils.ComponentIndex.FRAGMENT] || '', true);\n\n  } else {\n    this.ignoreCase_ = !!opt_ignoreCase;\n    this.queryData_ = new goog.Uri.QueryData(null, this.ignoreCase_);\n  }\n};\n\n\n/**\n * Parameter name added to stop caching.\n * @type {string}\n */\ngoog.Uri.RANDOM_PARAM = goog.uri.utils.StandardQueryParam.RANDOM;\n\n\n/**\n * @return {string} The string form of the url.\n * @override\n */\ngoog.Uri.prototype.toString = function() {\n  'use strict';\n  var out = [];\n\n  var scheme = this.getScheme();\n  if (scheme) {\n    out.push(\n        goog.Uri.encodeSpecialChars_(\n            scheme, goog.Uri.reDisallowedInSchemeOrUserInfo_, true),\n        ':');\n  }\n\n  var domain = this.getDomain();\n  if (domain || scheme == 'file') {\n    out.push('//');\n\n    var userInfo = this.getUserInfo();\n    if (userInfo) {\n      out.push(\n          goog.Uri.encodeSpecialChars_(\n              userInfo, goog.Uri.reDisallowedInSchemeOrUserInfo_, true),\n          '@');\n    }\n\n    out.push(goog.Uri.removeDoubleEncoding_(goog.string.urlEncode(domain)));\n\n    var port = this.getPort();\n    if (port != null) {\n      out.push(':', String(port));\n    }\n  }\n\n  var path = this.getPath();\n  if (path) {\n    if (this.hasDomain() && path.charAt(0) != '/') {\n      out.push('/');\n    }\n    out.push(goog.Uri.encodeSpecialChars_(\n        path,\n        path.charAt(0) == '/' ? goog.Uri.reDisallowedInAbsolutePath_ :\n                                goog.Uri.reDisallowedInRelativePath_,\n        true));\n  }\n\n  var query = this.getEncodedQuery();\n  if (query) {\n    out.push('?', query);\n  }\n\n  var fragment = this.getFragment();\n  if (fragment) {\n    out.push(\n        '#',\n        goog.Uri.encodeSpecialChars_(\n            fragment, goog.Uri.reDisallowedInFragment_));\n  }\n  return out.join('');\n};\n\n\n/**\n * Resolves the given relative URI (a goog.Uri object), using the URI\n * represented by this instance as the base URI.\n *\n * There are several kinds of relative URIs:<br>\n * 1. foo - replaces the last part of the path, the whole query and fragment<br>\n * 2. /foo - replaces the path, the query and fragment<br>\n * 3. //foo - replaces everything from the domain on.  foo is a domain name<br>\n * 4. ?foo - replace the query and fragment<br>\n * 5. #foo - replace the fragment only\n *\n * Additionally, if relative URI has a non-empty path, all \"..\" and \".\"\n * segments will be resolved, as described in RFC 3986.\n *\n * @param {!goog.Uri} relativeUri The relative URI to resolve.\n * @return {!goog.Uri} The resolved URI.\n */\ngoog.Uri.prototype.resolve = function(relativeUri) {\n  'use strict';\n  var absoluteUri = this.clone();\n\n  // we satisfy these conditions by looking for the first part of relativeUri\n  // that is not blank and applying defaults to the rest\n\n  var overridden = relativeUri.hasScheme();\n\n  if (overridden) {\n    absoluteUri.setScheme(relativeUri.getScheme());\n  } else {\n    overridden = relativeUri.hasUserInfo();\n  }\n\n  if (overridden) {\n    absoluteUri.setUserInfo(relativeUri.getUserInfo());\n  } else {\n    overridden = relativeUri.hasDomain();\n  }\n\n  if (overridden) {\n    absoluteUri.setDomain(relativeUri.getDomain());\n  } else {\n    overridden = relativeUri.hasPort();\n  }\n\n  var path = relativeUri.getPath();\n  if (overridden) {\n    absoluteUri.setPort(relativeUri.getPort());\n  } else {\n    overridden = relativeUri.hasPath();\n    if (overridden) {\n      // resolve path properly\n      if (path.charAt(0) != '/') {\n        // path is relative\n        if (this.hasDomain() && !this.hasPath()) {\n          // RFC 3986, section 5.2.3, case 1\n          path = '/' + path;\n        } else {\n          // RFC 3986, section 5.2.3, case 2\n          var lastSlashIndex = absoluteUri.getPath().lastIndexOf('/');\n          if (lastSlashIndex != -1) {\n            path = absoluteUri.getPath().substr(0, lastSlashIndex + 1) + path;\n          }\n        }\n      }\n      path = goog.Uri.removeDotSegments(path);\n    }\n  }\n\n  if (overridden) {\n    absoluteUri.setPath(path);\n  } else {\n    overridden = relativeUri.hasQuery();\n  }\n\n  if (overridden) {\n    absoluteUri.setQueryData(relativeUri.getQueryData().clone());\n  } else {\n    overridden = relativeUri.hasFragment();\n  }\n\n  if (overridden) {\n    absoluteUri.setFragment(relativeUri.getFragment());\n  }\n\n  return absoluteUri;\n};\n\n\n/**\n * Clones the URI instance.\n * @return {!goog.Uri} New instance of the URI object.\n */\ngoog.Uri.prototype.clone = function() {\n  'use strict';\n  return new goog.Uri(this);\n};\n\n\n/**\n * @return {string} The encoded scheme/protocol for the URI.\n */\ngoog.Uri.prototype.getScheme = function() {\n  'use strict';\n  return this.scheme_;\n};\n\n\n/**\n * Sets the scheme/protocol.\n * @throws URIError If opt_decode is true and newScheme is malformed (that is,\n *     if decodeURIComponent fails).\n * @param {string} newScheme New scheme value.\n * @param {boolean=} opt_decode Optional param for whether to decode new value.\n * @return {!goog.Uri} Reference to this URI object.\n */\ngoog.Uri.prototype.setScheme = function(newScheme, opt_decode) {\n  'use strict';\n  this.enforceReadOnly();\n  this.scheme_ =\n      opt_decode ? goog.Uri.decodeOrEmpty_(newScheme, true) : newScheme;\n\n  // remove an : at the end of the scheme so somebody can pass in\n  // window.location.protocol\n  if (this.scheme_) {\n    this.scheme_ = this.scheme_.replace(/:$/, '');\n  }\n  return this;\n};\n\n\n/**\n * @return {boolean} Whether the scheme has been set.\n */\ngoog.Uri.prototype.hasScheme = function() {\n  'use strict';\n  return !!this.scheme_;\n};\n\n\n/**\n * @return {string} The decoded user info.\n */\ngoog.Uri.prototype.getUserInfo = function() {\n  'use strict';\n  return this.userInfo_;\n};\n\n\n/**\n * Sets the userInfo.\n * @throws URIError If opt_decode is true and newUserInfo is malformed (that is,\n *     if decodeURIComponent fails).\n * @param {string} newUserInfo New userInfo value.\n * @param {boolean=} opt_decode Optional param for whether to decode new value.\n * @return {!goog.Uri} Reference to this URI object.\n */\ngoog.Uri.prototype.setUserInfo = function(newUserInfo, opt_decode) {\n  'use strict';\n  this.enforceReadOnly();\n  this.userInfo_ =\n      opt_decode ? goog.Uri.decodeOrEmpty_(newUserInfo) : newUserInfo;\n  return this;\n};\n\n\n/**\n * @return {boolean} Whether the user info has been set.\n */\ngoog.Uri.prototype.hasUserInfo = function() {\n  'use strict';\n  return !!this.userInfo_;\n};\n\n\n/**\n * @return {string} The decoded domain.\n */\ngoog.Uri.prototype.getDomain = function() {\n  'use strict';\n  return this.domain_;\n};\n\n\n/**\n * Sets the domain.\n * @throws URIError If opt_decode is true and newDomain is malformed (that is,\n *     if decodeURIComponent fails).\n * @param {string} newDomain New domain value.\n * @param {boolean=} opt_decode Optional param for whether to decode new value.\n * @return {!goog.Uri} Reference to this URI object.\n */\ngoog.Uri.prototype.setDomain = function(newDomain, opt_decode) {\n  'use strict';\n  this.enforceReadOnly();\n  this.domain_ =\n      opt_decode ? goog.Uri.decodeOrEmpty_(newDomain, true) : newDomain;\n  return this;\n};\n\n\n/**\n * @return {boolean} Whether the domain has been set.\n */\ngoog.Uri.prototype.hasDomain = function() {\n  'use strict';\n  return !!this.domain_;\n};\n\n\n/**\n * @return {?number} The port number.\n */\ngoog.Uri.prototype.getPort = function() {\n  'use strict';\n  return this.port_;\n};\n\n\n/**\n * Sets the port number.\n * @param {*} newPort Port number. Will be explicitly casted to a number.\n * @return {!goog.Uri} Reference to this URI object.\n */\ngoog.Uri.prototype.setPort = function(newPort) {\n  'use strict';\n  this.enforceReadOnly();\n\n  if (newPort) {\n    newPort = Number(newPort);\n    if (isNaN(newPort) || newPort < 0) {\n      throw new Error('Bad port number ' + newPort);\n    }\n    this.port_ = newPort;\n  } else {\n    this.port_ = null;\n  }\n\n  return this;\n};\n\n\n/**\n * @return {boolean} Whether the port has been set.\n */\ngoog.Uri.prototype.hasPort = function() {\n  'use strict';\n  return this.port_ != null;\n};\n\n\n/**\n * @return {string} The decoded path.\n */\ngoog.Uri.prototype.getPath = function() {\n  'use strict';\n  return this.path_;\n};\n\n\n/**\n * Sets the path.\n * @throws URIError If opt_decode is true and newPath is malformed (that is,\n *     if decodeURIComponent fails).\n * @param {string} newPath New path value.\n * @param {boolean=} opt_decode Optional param for whether to decode new value.\n * @return {!goog.Uri} Reference to this URI object.\n */\ngoog.Uri.prototype.setPath = function(newPath, opt_decode) {\n  'use strict';\n  this.enforceReadOnly();\n  this.path_ = opt_decode ? goog.Uri.decodeOrEmpty_(newPath, true) : newPath;\n  return this;\n};\n\n\n/**\n * @return {boolean} Whether the path has been set.\n */\ngoog.Uri.prototype.hasPath = function() {\n  'use strict';\n  return !!this.path_;\n};\n\n\n/**\n * @return {boolean} Whether the query string has been set.\n */\ngoog.Uri.prototype.hasQuery = function() {\n  'use strict';\n  return this.queryData_.toString() !== '';\n};\n\n\n/**\n * Sets the query data.\n * @param {goog.Uri.QueryData|string|undefined} queryData QueryData object.\n * @param {boolean=} opt_decode Optional param for whether to decode new value.\n *     Applies only if queryData is a string.\n * @return {!goog.Uri} Reference to this URI object.\n */\ngoog.Uri.prototype.setQueryData = function(queryData, opt_decode) {\n  'use strict';\n  this.enforceReadOnly();\n\n  if (queryData instanceof goog.Uri.QueryData) {\n    this.queryData_ = queryData;\n    this.queryData_.setIgnoreCase(this.ignoreCase_);\n  } else {\n    if (!opt_decode) {\n      // QueryData accepts encoded query string, so encode it if\n      // opt_decode flag is not true.\n      queryData = goog.Uri.encodeSpecialChars_(\n          queryData, goog.Uri.reDisallowedInQuery_);\n    }\n    this.queryData_ = new goog.Uri.QueryData(queryData, this.ignoreCase_);\n  }\n\n  return this;\n};\n\n\n/**\n * Sets the URI query.\n * @param {string} newQuery New query value.\n * @param {boolean=} opt_decode Optional param for whether to decode new value.\n * @return {!goog.Uri} Reference to this URI object.\n */\ngoog.Uri.prototype.setQuery = function(newQuery, opt_decode) {\n  'use strict';\n  return this.setQueryData(newQuery, opt_decode);\n};\n\n\n/**\n * @return {string} The encoded URI query, not including the ?.\n */\ngoog.Uri.prototype.getEncodedQuery = function() {\n  'use strict';\n  return this.queryData_.toString();\n};\n\n\n/**\n * @return {string} The decoded URI query, not including the ?.\n */\ngoog.Uri.prototype.getDecodedQuery = function() {\n  'use strict';\n  return this.queryData_.toDecodedString();\n};\n\n\n/**\n * Returns the query data.\n * @return {!goog.Uri.QueryData} QueryData object.\n */\ngoog.Uri.prototype.getQueryData = function() {\n  'use strict';\n  return this.queryData_;\n};\n\n\n/**\n * @return {string} The encoded URI query, not including the ?.\n *\n * Warning: This method, unlike other getter methods, returns encoded\n * value, instead of decoded one.\n */\ngoog.Uri.prototype.getQuery = function() {\n  'use strict';\n  return this.getEncodedQuery();\n};\n\n\n/**\n * Sets the value of the named query parameters, clearing previous values for\n * that key.\n *\n * @param {string} key The parameter to set.\n * @param {*} value The new value. Value does not need to be encoded.\n * @return {!goog.Uri} Reference to this URI object.\n */\ngoog.Uri.prototype.setParameterValue = function(key, value) {\n  'use strict';\n  this.enforceReadOnly();\n  this.queryData_.set(key, value);\n  return this;\n};\n\n\n/**\n * Sets the values of the named query parameters, clearing previous values for\n * that key.  Not new values will currently be moved to the end of the query\n * string.\n *\n * So, <code>goog.Uri.parse('foo?a=b&c=d&e=f').setParameterValues('c', ['new'])\n * </code> yields <tt>foo?a=b&e=f&c=new</tt>.</p>\n *\n * @param {string} key The parameter to set.\n * @param {*} values The new values. If values is a single\n *     string then it will be treated as the sole value. Values do not need to\n *     be encoded.\n * @return {!goog.Uri} Reference to this URI object.\n */\ngoog.Uri.prototype.setParameterValues = function(key, values) {\n  'use strict';\n  this.enforceReadOnly();\n\n  if (!Array.isArray(values)) {\n    values = [String(values)];\n  }\n\n  this.queryData_.setValues(key, values);\n\n  return this;\n};\n\n\n/**\n * Returns the value<b>s</b> for a given cgi parameter as a list of decoded\n * query parameter values.\n * @param {string} name The parameter to get values for.\n * @return {!Array<?>} The values for a given cgi parameter as a list of\n *     decoded query parameter values.\n */\ngoog.Uri.prototype.getParameterValues = function(name) {\n  'use strict';\n  return this.queryData_.getValues(name);\n};\n\n\n/**\n * Returns the first value for a given cgi parameter or undefined if the given\n * parameter name does not appear in the query string.\n * @param {string} paramName Unescaped parameter name.\n * @return {string|undefined} The first value for a given cgi parameter or\n *     undefined if the given parameter name does not appear in the query\n *     string.\n */\ngoog.Uri.prototype.getParameterValue = function(paramName) {\n  'use strict';\n  return /** @type {string|undefined} */ (this.queryData_.get(paramName));\n};\n\n\n/**\n * @return {string} The URI fragment, not including the #.\n */\ngoog.Uri.prototype.getFragment = function() {\n  'use strict';\n  return this.fragment_;\n};\n\n\n/**\n * Sets the URI fragment.\n * @throws URIError If opt_decode is true and newFragment is malformed (that is,\n *     if decodeURIComponent fails).\n * @param {string} newFragment New fragment value.\n * @param {boolean=} opt_decode Optional param for whether to decode new value.\n * @return {!goog.Uri} Reference to this URI object.\n */\ngoog.Uri.prototype.setFragment = function(newFragment, opt_decode) {\n  'use strict';\n  this.enforceReadOnly();\n  this.fragment_ =\n      opt_decode ? goog.Uri.decodeOrEmpty_(newFragment) : newFragment;\n  return this;\n};\n\n\n/**\n * @return {boolean} Whether the URI has a fragment set.\n */\ngoog.Uri.prototype.hasFragment = function() {\n  'use strict';\n  return !!this.fragment_;\n};\n\n\n/**\n * Returns true if this has the same domain as that of uri2.\n * @param {!goog.Uri} uri2 The URI object to compare to.\n * @return {boolean} true if same domain; false otherwise.\n */\ngoog.Uri.prototype.hasSameDomainAs = function(uri2) {\n  'use strict';\n  return ((!this.hasDomain() && !uri2.hasDomain()) ||\n          this.getDomain() == uri2.getDomain()) &&\n      ((!this.hasPort() && !uri2.hasPort()) ||\n       this.getPort() == uri2.getPort());\n};\n\n\n/**\n * Adds a random parameter to the Uri.\n * @return {!goog.Uri} Reference to this Uri object.\n */\ngoog.Uri.prototype.makeUnique = function() {\n  'use strict';\n  this.enforceReadOnly();\n  this.setParameterValue(goog.Uri.RANDOM_PARAM, goog.string.getRandomString());\n\n  return this;\n};\n\n\n/**\n * Removes the named query parameter.\n *\n * @param {string} key The parameter to remove.\n * @return {!goog.Uri} Reference to this URI object.\n */\ngoog.Uri.prototype.removeParameter = function(key) {\n  'use strict';\n  this.enforceReadOnly();\n  this.queryData_.remove(key);\n  return this;\n};\n\n\n/**\n * Sets whether Uri is read only. If this goog.Uri is read-only,\n * enforceReadOnly_ will be called at the start of any function that may modify\n * this Uri.\n * @param {boolean} isReadOnly whether this goog.Uri should be read only.\n * @return {!goog.Uri} Reference to this Uri object.\n */\ngoog.Uri.prototype.setReadOnly = function(isReadOnly) {\n  'use strict';\n  this.isReadOnly_ = isReadOnly;\n  return this;\n};\n\n\n/**\n * @return {boolean} Whether the URI is read only.\n */\ngoog.Uri.prototype.isReadOnly = function() {\n  'use strict';\n  return this.isReadOnly_;\n};\n\n\n/**\n * Checks if this Uri has been marked as read only, and if so, throws an error.\n * This should be called whenever any modifying function is called.\n */\ngoog.Uri.prototype.enforceReadOnly = function() {\n  'use strict';\n  if (this.isReadOnly_) {\n    throw new Error('Tried to modify a read-only Uri');\n  }\n};\n\n\n/**\n * Sets whether to ignore case.\n * NOTE: If there are already key/value pairs in the QueryData, and\n * ignoreCase_ is set to false, the keys will all be lower-cased.\n * @param {boolean} ignoreCase whether this goog.Uri should ignore case.\n * @return {!goog.Uri} Reference to this Uri object.\n */\ngoog.Uri.prototype.setIgnoreCase = function(ignoreCase) {\n  'use strict';\n  this.ignoreCase_ = ignoreCase;\n  if (this.queryData_) {\n    this.queryData_.setIgnoreCase(ignoreCase);\n  }\n  return this;\n};\n\n\n/**\n * @return {boolean} Whether to ignore case.\n */\ngoog.Uri.prototype.getIgnoreCase = function() {\n  'use strict';\n  return this.ignoreCase_;\n};\n\n\n//==============================================================================\n// Static members\n//==============================================================================\n\n\n/**\n * Creates a uri from the string form.  Basically an alias of new goog.Uri().\n * If a Uri object is passed to parse then it will return a clone of the object.\n *\n * @throws URIError If parsing the URI is malformed. The passed URI components\n *     should all be parseable by decodeURIComponent.\n * @param {*} uri Raw URI string or instance of Uri\n *     object.\n * @param {boolean=} opt_ignoreCase Whether to ignore the case of parameter\n * names in #getParameterValue.\n * @return {!goog.Uri} The new URI object.\n */\ngoog.Uri.parse = function(uri, opt_ignoreCase) {\n  'use strict';\n  return uri instanceof goog.Uri ? uri.clone() :\n                                   new goog.Uri(uri, opt_ignoreCase);\n};\n\n\n/**\n * Creates a new goog.Uri object from unencoded parts.\n *\n * @param {?string=} opt_scheme Scheme/protocol or full URI to parse.\n * @param {?string=} opt_userInfo username:password.\n * @param {?string=} opt_domain www.google.com.\n * @param {?number=} opt_port 9830.\n * @param {?string=} opt_path /some/path/to/a/file.html.\n * @param {string|goog.Uri.QueryData=} opt_query a=1&b=2.\n * @param {?string=} opt_fragment The fragment without the #.\n * @param {boolean=} opt_ignoreCase Whether to ignore parameter name case in\n *     #getParameterValue.\n *\n * @return {!goog.Uri} The new URI object.\n */\ngoog.Uri.create = function(\n    opt_scheme, opt_userInfo, opt_domain, opt_port, opt_path, opt_query,\n    opt_fragment, opt_ignoreCase) {\n  'use strict';\n  var uri = new goog.Uri(null, opt_ignoreCase);\n\n  // Only set the parts if they are defined and not empty strings.\n  opt_scheme && uri.setScheme(opt_scheme);\n  opt_userInfo && uri.setUserInfo(opt_userInfo);\n  opt_domain && uri.setDomain(opt_domain);\n  opt_port && uri.setPort(opt_port);\n  opt_path && uri.setPath(opt_path);\n  opt_query && uri.setQueryData(opt_query);\n  opt_fragment && uri.setFragment(opt_fragment);\n\n  return uri;\n};\n\n\n/**\n * Resolves a relative Uri against a base Uri, accepting both strings and\n * Uri objects.\n *\n * @param {*} base Base Uri.\n * @param {*} rel Relative Uri.\n * @return {!goog.Uri} Resolved uri.\n */\ngoog.Uri.resolve = function(base, rel) {\n  'use strict';\n  if (!(base instanceof goog.Uri)) {\n    base = goog.Uri.parse(base);\n  }\n\n  if (!(rel instanceof goog.Uri)) {\n    rel = goog.Uri.parse(rel);\n  }\n\n  return base.resolve(rel);\n};\n\n\n/**\n * Removes dot segments in given path component, as described in\n * RFC 3986, section 5.2.4.\n *\n * @param {string} path A non-empty path component.\n * @return {string} Path component with removed dot segments.\n */\ngoog.Uri.removeDotSegments = function(path) {\n  'use strict';\n  if (path == '..' || path == '.') {\n    return '';\n\n  } else if (\n      !goog.string.contains(path, './') && !goog.string.contains(path, '/.')) {\n    // This optimization detects uris which do not contain dot-segments,\n    // and as a consequence do not require any processing.\n    return path;\n\n  } else {\n    var leadingSlash = goog.string.startsWith(path, '/');\n    var segments = path.split('/');\n    var out = [];\n\n    for (var pos = 0; pos < segments.length;) {\n      var segment = segments[pos++];\n\n      if (segment == '.') {\n        if (leadingSlash && pos == segments.length) {\n          out.push('');\n        }\n      } else if (segment == '..') {\n        if (out.length > 1 || out.length == 1 && out[0] != '') {\n          out.pop();\n        }\n        if (leadingSlash && pos == segments.length) {\n          out.push('');\n        }\n      } else {\n        out.push(segment);\n        leadingSlash = true;\n      }\n    }\n\n    return out.join('/');\n  }\n};\n\n\n/**\n * Decodes a value or returns the empty string if it isn't defined or empty.\n * @throws URIError If decodeURIComponent fails to decode val.\n * @param {string|undefined} val Value to decode.\n * @param {boolean=} opt_preserveReserved If true, restricted characters will\n *     not be decoded.\n * @return {string} Decoded value.\n * @private\n */\ngoog.Uri.decodeOrEmpty_ = function(val, opt_preserveReserved) {\n  'use strict';\n  // Don't use UrlDecode() here because val is not a query parameter.\n  if (!val) {\n    return '';\n  }\n\n  // decodeURI has the same output for '%2f' and '%252f'. We double encode %25\n  // so that we can distinguish between the 2 inputs. This is later undone by\n  // removeDoubleEncoding_.\n  return opt_preserveReserved ? decodeURI(val.replace(/%25/g, '%2525')) :\n                                decodeURIComponent(val);\n};\n\n\n/**\n * If unescapedPart is non null, then escapes any characters in it that aren't\n * valid characters in a url and also escapes any special characters that\n * appear in extra.\n *\n * @param {*} unescapedPart The string to encode.\n * @param {RegExp} extra A character set of characters in [\\01-\\177].\n * @param {boolean=} opt_removeDoubleEncoding If true, remove double percent\n *     encoding.\n * @return {?string} null iff unescapedPart == null.\n * @private\n */\ngoog.Uri.encodeSpecialChars_ = function(\n    unescapedPart, extra, opt_removeDoubleEncoding) {\n  'use strict';\n  if (typeof unescapedPart === 'string') {\n    var encoded = encodeURI(unescapedPart).replace(extra, goog.Uri.encodeChar_);\n    if (opt_removeDoubleEncoding) {\n      // encodeURI double-escapes %XX sequences used to represent restricted\n      // characters in some URI components, remove the double escaping here.\n      encoded = goog.Uri.removeDoubleEncoding_(encoded);\n    }\n    return encoded;\n  }\n  return null;\n};\n\n\n/**\n * Converts a character in [\\01-\\177] to its unicode character equivalent.\n * @param {string} ch One character string.\n * @return {string} Encoded string.\n * @private\n */\ngoog.Uri.encodeChar_ = function(ch) {\n  'use strict';\n  var n = ch.charCodeAt(0);\n  return '%' + ((n >> 4) & 0xf).toString(16) + (n & 0xf).toString(16);\n};\n\n\n/**\n * Removes double percent-encoding from a string.\n * @param  {string} doubleEncodedString String\n * @return {string} String with double encoding removed.\n * @private\n */\ngoog.Uri.removeDoubleEncoding_ = function(doubleEncodedString) {\n  'use strict';\n  return doubleEncodedString.replace(/%25([0-9a-fA-F]{2})/g, '%$1');\n};\n\n\n/**\n * Regular expression for characters that are disallowed in the scheme or\n * userInfo part of the URI.\n * @type {RegExp}\n * @private\n */\ngoog.Uri.reDisallowedInSchemeOrUserInfo_ = /[#\\/\\?@]/g;\n\n\n/**\n * Regular expression for characters that are disallowed in a relative path.\n * Colon is included due to RFC 3986 3.3.\n * @type {RegExp}\n * @private\n */\ngoog.Uri.reDisallowedInRelativePath_ = /[\\#\\?:]/g;\n\n\n/**\n * Regular expression for characters that are disallowed in an absolute path.\n * @type {RegExp}\n * @private\n */\ngoog.Uri.reDisallowedInAbsolutePath_ = /[\\#\\?]/g;\n\n\n/**\n * Regular expression for characters that are disallowed in the query.\n * @type {RegExp}\n * @private\n */\ngoog.Uri.reDisallowedInQuery_ = /[\\#\\?@]/g;\n\n\n/**\n * Regular expression for characters that are disallowed in the fragment.\n * @type {RegExp}\n * @private\n */\ngoog.Uri.reDisallowedInFragment_ = /#/g;\n\n\n/**\n * Checks whether two URIs have the same domain.\n * @param {string} uri1String First URI string.\n * @param {string} uri2String Second URI string.\n * @return {boolean} true if the two URIs have the same domain; false otherwise.\n */\ngoog.Uri.haveSameDomain = function(uri1String, uri2String) {\n  'use strict';\n  // Differs from goog.uri.utils.haveSameDomain, since this ignores scheme.\n  // TODO(gboyer): Have this just call goog.uri.util.haveSameDomain.\n  var pieces1 = goog.uri.utils.split(uri1String);\n  var pieces2 = goog.uri.utils.split(uri2String);\n  return pieces1[goog.uri.utils.ComponentIndex.DOMAIN] ==\n      pieces2[goog.uri.utils.ComponentIndex.DOMAIN] &&\n      pieces1[goog.uri.utils.ComponentIndex.PORT] ==\n      pieces2[goog.uri.utils.ComponentIndex.PORT];\n};\n\n\n\n/**\n * Class used to represent URI query parameters.  It is essentially a hash of\n * name-value pairs, though a name can be present more than once.\n *\n * Has the same interface as the collections in goog.structs.\n *\n * @param {?string=} opt_query Optional encoded query string to parse into\n *     the object.\n * @param {boolean=} opt_ignoreCase If true, ignore the case of the parameter\n *     name in #get.\n * @constructor\n * @struct\n * @final\n */\ngoog.Uri.QueryData = function(opt_query, opt_ignoreCase) {\n  'use strict';\n  /**\n   * The map containing name/value or name/array-of-values pairs.\n   * May be null if it requires parsing from the query string.\n   *\n   * We need to use a Map because we cannot guarantee that the key names will\n   * not be problematic for IE.\n   *\n   * @private {?Map<string, !Array<*>>}\n   */\n  this.keyMap_ = null;\n\n  /**\n   * The number of params, or null if it requires computing.\n   * @private {?number}\n   */\n  this.count_ = null;\n\n  /**\n   * Encoded query string, or null if it requires computing from the key map.\n   * @private {?string}\n   */\n  this.encodedQuery_ = opt_query || null;\n\n  /**\n   * If true, ignore the case of the parameter name in #get.\n   * @private {boolean}\n   */\n  this.ignoreCase_ = !!opt_ignoreCase;\n};\n\n\n/**\n * If the underlying key map is not yet initialized, it parses the\n * query string and fills the map with parsed data.\n * @private\n */\ngoog.Uri.QueryData.prototype.ensureKeyMapInitialized_ = function() {\n  'use strict';\n  if (!this.keyMap_) {\n    this.keyMap_ = /** @type {!Map<string, !Array<*>>} */ (new Map());\n    this.count_ = 0;\n    if (this.encodedQuery_) {\n      var self = this;\n      goog.uri.utils.parseQueryData(this.encodedQuery_, function(name, value) {\n        'use strict';\n        self.add(goog.string.urlDecode(name), value);\n      });\n    }\n  }\n};\n\n\n/**\n * Creates a new query data instance from a map of names and values.\n *\n * @param {!goog.collections.maps.MapLike<string, ?>|!Object} map Map of string\n *     parameter names to parameter value. If parameter value is an array, it is\n *     treated as if the key maps to each individual value in the\n *     array.\n * @param {boolean=} opt_ignoreCase If true, ignore the case of the parameter\n *     name in #get.\n * @return {!goog.Uri.QueryData} The populated query data instance.\n */\ngoog.Uri.QueryData.createFromMap = function(map, opt_ignoreCase) {\n  'use strict';\n  var keys = goog.structs.getKeys(map);\n  if (typeof keys == 'undefined') {\n    throw new Error('Keys are undefined');\n  }\n\n  var queryData = new goog.Uri.QueryData(null, opt_ignoreCase);\n  var values = goog.structs.getValues(map);\n  for (var i = 0; i < keys.length; i++) {\n    var key = keys[i];\n    var value = values[i];\n    if (!Array.isArray(value)) {\n      queryData.add(key, value);\n    } else {\n      queryData.setValues(key, value);\n    }\n  }\n  return queryData;\n};\n\n\n/**\n * Creates a new query data instance from parallel arrays of parameter names\n * and values. Allows for duplicate parameter names. Throws an error if the\n * lengths of the arrays differ.\n *\n * @param {!Array<string>} keys Parameter names.\n * @param {!Array<?>} values Parameter values.\n * @param {boolean=} opt_ignoreCase If true, ignore the case of the parameter\n *     name in #get.\n * @return {!goog.Uri.QueryData} The populated query data instance.\n */\ngoog.Uri.QueryData.createFromKeysValues = function(\n    keys, values, opt_ignoreCase) {\n  'use strict';\n  if (keys.length != values.length) {\n    throw new Error('Mismatched lengths for keys/values');\n  }\n  var queryData = new goog.Uri.QueryData(null, opt_ignoreCase);\n  for (var i = 0; i < keys.length; i++) {\n    queryData.add(keys[i], values[i]);\n  }\n  return queryData;\n};\n\n\n/**\n * @return {?number} The number of parameters.\n */\ngoog.Uri.QueryData.prototype.getCount = function() {\n  'use strict';\n  this.ensureKeyMapInitialized_();\n  return this.count_;\n};\n\n\n/**\n * Adds a key value pair.\n * @param {string} key Name.\n * @param {*} value Value.\n * @return {!goog.Uri.QueryData} Instance of this object.\n */\ngoog.Uri.QueryData.prototype.add = function(key, value) {\n  'use strict';\n  this.ensureKeyMapInitialized_();\n  this.invalidateCache_();\n\n  key = this.getKeyName_(key);\n  var values = this.keyMap_.get(key);\n  if (!values) {\n    this.keyMap_.set(key, (values = []));\n  }\n  values.push(value);\n  this.count_ = goog.asserts.assertNumber(this.count_) + 1;\n  return this;\n};\n\n\n/**\n * Removes all the params with the given key.\n * @param {string} key Name.\n * @return {boolean} Whether any parameter was removed.\n */\ngoog.Uri.QueryData.prototype.remove = function(key) {\n  'use strict';\n  this.ensureKeyMapInitialized_();\n\n  key = this.getKeyName_(key);\n  if (this.keyMap_.has(key)) {\n    this.invalidateCache_();\n\n    // Decrement parameter count.\n    this.count_ =\n        goog.asserts.assertNumber(this.count_) - this.keyMap_.get(key).length;\n    return this.keyMap_.delete(key);\n  }\n  return false;\n};\n\n\n/**\n * Clears the parameters.\n */\ngoog.Uri.QueryData.prototype.clear = function() {\n  'use strict';\n  this.invalidateCache_();\n  this.keyMap_ = null;\n  this.count_ = 0;\n};\n\n\n/**\n * @return {boolean} Whether we have any parameters.\n */\ngoog.Uri.QueryData.prototype.isEmpty = function() {\n  'use strict';\n  this.ensureKeyMapInitialized_();\n  return this.count_ == 0;\n};\n\n\n/**\n * Whether there is a parameter with the given name\n * @param {string} key The parameter name to check for.\n * @return {boolean} Whether there is a parameter with the given name.\n */\ngoog.Uri.QueryData.prototype.containsKey = function(key) {\n  'use strict';\n  this.ensureKeyMapInitialized_();\n  key = this.getKeyName_(key);\n  return this.keyMap_.has(key);\n};\n\n\n/**\n * Whether there is a parameter with the given value.\n * @param {*} value The value to check for.\n * @return {boolean} Whether there is a parameter with the given value.\n */\ngoog.Uri.QueryData.prototype.containsValue = function(value) {\n  'use strict';\n  // NOTE(arv): This solution goes through all the params even if it was the\n  // first param. We can get around this by not reusing code or by switching to\n  // iterators.\n  var vals = this.getValues();\n  return goog.array.contains(vals, value);\n};\n\n\n/**\n * Runs a callback on every key-value pair in the map, including duplicate keys.\n * This won't maintain original order when duplicate keys are interspersed (like\n * getKeys() / getValues()).\n * @param {function(this:SCOPE, ?, string, !goog.Uri.QueryData)} f\n * @param {SCOPE=} opt_scope The value of \"this\" inside f.\n * @template SCOPE\n */\ngoog.Uri.QueryData.prototype.forEach = function(f, opt_scope) {\n  'use strict';\n  this.ensureKeyMapInitialized_();\n  this.keyMap_.forEach(function(values, key) {\n    'use strict';\n    values.forEach(function(value) {\n      'use strict';\n      f.call(opt_scope, value, key, this);\n    }, this);\n  }, this);\n};\n\n\n/**\n * Returns all the keys of the parameters. If a key is used multiple times\n * it will be included multiple times in the returned array\n * @return {!Array<string>} All the keys of the parameters.\n */\ngoog.Uri.QueryData.prototype.getKeys = function() {\n  'use strict';\n  this.ensureKeyMapInitialized_();\n  // We need to get the values to know how many keys to add.\n  const vals = Array.from(this.keyMap_.values());\n  const keys = Array.from(this.keyMap_.keys());\n  const rv = [];\n  for (let i = 0; i < keys.length; i++) {\n    const val = vals[i];\n    for (let j = 0; j < val.length; j++) {\n      rv.push(keys[i]);\n    }\n  }\n  return rv;\n};\n\n\n/**\n * Returns all the values of the parameters with the given name. If the query\n * data has no such key this will return an empty array. If no key is given\n * all values wil be returned.\n * @param {string=} opt_key The name of the parameter to get the values for.\n * @return {!Array<?>} All the values of the parameters with the given name.\n */\ngoog.Uri.QueryData.prototype.getValues = function(opt_key) {\n  'use strict';\n  this.ensureKeyMapInitialized_();\n  let rv = [];\n  if (typeof opt_key === 'string') {\n    if (this.containsKey(opt_key)) {\n      rv = rv.concat(this.keyMap_.get(this.getKeyName_(opt_key)));\n    }\n  } else {\n    // Return all values.\n    const values = Array.from(this.keyMap_.values());\n    for (let i = 0; i < values.length; i++) {\n      rv = rv.concat(values[i]);\n    }\n  }\n  return rv;\n};\n\n\n/**\n * Sets a key value pair and removes all other keys with the same value.\n *\n * @param {string} key Name.\n * @param {*} value Value.\n * @return {!goog.Uri.QueryData} Instance of this object.\n */\ngoog.Uri.QueryData.prototype.set = function(key, value) {\n  'use strict';\n  this.ensureKeyMapInitialized_();\n  this.invalidateCache_();\n\n  // TODO(chrishenry): This could be better written as\n  // this.remove(key), this.add(key, value), but that would reorder\n  // the key (since the key is first removed and then added at the\n  // end) and we would have to fix unit tests that depend on key\n  // ordering.\n  key = this.getKeyName_(key);\n  if (this.containsKey(key)) {\n    this.count_ =\n        goog.asserts.assertNumber(this.count_) - this.keyMap_.get(key).length;\n  }\n  this.keyMap_.set(key, [value]);\n  this.count_ = goog.asserts.assertNumber(this.count_) + 1;\n  return this;\n};\n\n\n/**\n * Returns the first value associated with the key. If the query data has no\n * such key this will return undefined or the optional default.\n * @param {string} key The name of the parameter to get the value for.\n * @param {*=} opt_default The default value to return if the query data\n *     has no such key.\n * @return {*} The first string value associated with the key, or opt_default\n *     if there's no value.\n */\ngoog.Uri.QueryData.prototype.get = function(key, opt_default) {\n  'use strict';\n  if (!key) {\n    return opt_default;\n  }\n  var values = this.getValues(key);\n  return values.length > 0 ? String(values[0]) : opt_default;\n};\n\n\n/**\n * Sets the values for a key. If the key already exists, this will\n * override all of the existing values that correspond to the key.\n * @param {string} key The key to set values for.\n * @param {!Array<?>} values The values to set.\n */\ngoog.Uri.QueryData.prototype.setValues = function(key, values) {\n  'use strict';\n  this.remove(key);\n\n  if (values.length > 0) {\n    this.invalidateCache_();\n    this.keyMap_.set(this.getKeyName_(key), goog.array.clone(values));\n    this.count_ = goog.asserts.assertNumber(this.count_) + values.length;\n  }\n};\n\n\n/**\n * @return {string} Encoded query string.\n * @override\n */\ngoog.Uri.QueryData.prototype.toString = function() {\n  'use strict';\n  if (this.encodedQuery_) {\n    return this.encodedQuery_;\n  }\n\n  if (!this.keyMap_) {\n    return '';\n  }\n\n  const sb = [];\n\n  // In the past, we use this.getKeys() and this.getVals(), but that\n  // generates a lot of allocations as compared to simply iterating\n  // over the keys.\n  const keys = Array.from(this.keyMap_.keys());\n  for (var i = 0; i < keys.length; i++) {\n    const key = keys[i];\n    const encodedKey = goog.string.urlEncode(key);\n    const val = this.getValues(key);\n    for (var j = 0; j < val.length; j++) {\n      var param = encodedKey;\n      // Ensure that null and undefined are encoded into the url as\n      // literal strings.\n      if (val[j] !== '') {\n        param += '=' + goog.string.urlEncode(val[j]);\n      }\n      sb.push(param);\n    }\n  }\n\n  return this.encodedQuery_ = sb.join('&');\n};\n\n\n/**\n * @throws URIError If URI is malformed (that is, if decodeURIComponent fails on\n *     any of the URI components).\n * @return {string} Decoded query string.\n */\ngoog.Uri.QueryData.prototype.toDecodedString = function() {\n  'use strict';\n  return goog.Uri.decodeOrEmpty_(this.toString());\n};\n\n\n/**\n * Invalidate the cache.\n * @private\n */\ngoog.Uri.QueryData.prototype.invalidateCache_ = function() {\n  'use strict';\n  this.encodedQuery_ = null;\n};\n\n\n/**\n * Removes all keys that are not in the provided list. (Modifies this object.)\n * @param {Array<string>} keys The desired keys.\n * @return {!goog.Uri.QueryData} a reference to this object.\n */\ngoog.Uri.QueryData.prototype.filterKeys = function(keys) {\n  'use strict';\n  this.ensureKeyMapInitialized_();\n  this.keyMap_.forEach(function(value, key) {\n    'use strict';\n    if (!goog.array.contains(keys, key)) {\n      this.remove(key);\n    }\n  }, this);\n  return this;\n};\n\n\n/**\n * Clone the query data instance.\n * @return {!goog.Uri.QueryData} New instance of the QueryData object.\n */\ngoog.Uri.QueryData.prototype.clone = function() {\n  'use strict';\n  var rv = new goog.Uri.QueryData();\n  rv.encodedQuery_ = this.encodedQuery_;\n  if (this.keyMap_) {\n    rv.keyMap_ = /** @type {!Map<string, !Array<*>>} */ (new Map(this.keyMap_));\n    rv.count_ = this.count_;\n  }\n  return rv;\n};\n\n\n/**\n * Helper function to get the key name from a JavaScript object. Converts\n * the object to a string, and to lower case if necessary.\n * @private\n * @param {*} arg The object to get a key name from.\n * @return {string} valid key name which can be looked up in #keyMap_.\n */\ngoog.Uri.QueryData.prototype.getKeyName_ = function(arg) {\n  'use strict';\n  var keyName = String(arg);\n  if (this.ignoreCase_) {\n    keyName = keyName.toLowerCase();\n  }\n  return keyName;\n};\n\n\n/**\n * Ignore case in parameter names.\n * NOTE: If there are already key/value pairs in the QueryData, and\n * ignoreCase_ is set to false, the keys will all be lower-cased.\n * @param {boolean} ignoreCase whether this goog.Uri should ignore case.\n */\ngoog.Uri.QueryData.prototype.setIgnoreCase = function(ignoreCase) {\n  'use strict';\n  var resetKeys = ignoreCase && !this.ignoreCase_;\n  if (resetKeys) {\n    this.ensureKeyMapInitialized_();\n    this.invalidateCache_();\n    this.keyMap_.forEach(function(value, key) {\n      'use strict';\n      var lowerCase = key.toLowerCase();\n      if (key != lowerCase) {\n        this.remove(key);\n        this.setValues(lowerCase, value);\n      }\n    }, this);\n  }\n  this.ignoreCase_ = ignoreCase;\n};\n\n\n/**\n * Extends a query data object with another query data or map like object. This\n * operates 'in-place', it does not create a new QueryData object.\n *\n * @param {...(?goog.Uri.QueryData|?goog.collections.maps.MapLike<?,\n *     ?>|?Object)} var_args The object from which key value pairs will be\n *     copied. Note: does not accept null.\n * @suppress {deprecated} Use deprecated goog.structs.forEach to allow different\n * types of parameters.\n */\ngoog.Uri.QueryData.prototype.extend = function(var_args) {\n  'use strict';\n  for (var i = 0; i < arguments.length; i++) {\n    var data = arguments[i];\n    goog.structs.forEach(data, function(value, key) {\n      'use strict';\n      this.add(key, value);\n    }, this);\n  }\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Utilities for string manipulation.\n */\n\n\n/**\n * Namespace for string utilities\n */\ngoog.provide('goog.string');\ngoog.provide('goog.string.Unicode');\n\ngoog.require('goog.dom.safe');\ngoog.require('goog.html.uncheckedconversions');\ngoog.require('goog.string.Const');\ngoog.require('goog.string.internal');\n\n\n/**\n * @define {boolean} Enables HTML escaping of lowercase letter \"e\" which helps\n * with detection of double-escaping as this letter is frequently used.\n */\ngoog.string.DETECT_DOUBLE_ESCAPING =\n    goog.define('goog.string.DETECT_DOUBLE_ESCAPING', false);\n\n\n/**\n * @define {boolean} Whether to force non-dom html unescaping.\n */\ngoog.string.FORCE_NON_DOM_HTML_UNESCAPING =\n    goog.define('goog.string.FORCE_NON_DOM_HTML_UNESCAPING', false);\n\n\n/**\n * Common Unicode string characters.\n * @enum {string}\n */\ngoog.string.Unicode = {\n  NBSP: '\\xa0'\n};\n\n\n/**\n * Fast prefix-checker.\n * @param {string} str The string to check.\n * @param {string} prefix A string to look for at the start of `str`.\n * @return {boolean} True if `str` begins with `prefix`.\n */\ngoog.string.startsWith = goog.string.internal.startsWith;\n\n\n/**\n * Fast suffix-checker.\n * @param {string} str The string to check.\n * @param {string} suffix A string to look for at the end of `str`.\n * @return {boolean} True if `str` ends with `suffix`.\n */\ngoog.string.endsWith = goog.string.internal.endsWith;\n\n\n/**\n * Case-insensitive prefix-checker.\n * @param {string} str The string to check.\n * @param {string} prefix  A string to look for at the end of `str`.\n * @return {boolean} True if `str` begins with `prefix` (ignoring\n *     case).\n */\ngoog.string.caseInsensitiveStartsWith =\n    goog.string.internal.caseInsensitiveStartsWith;\n\n\n/**\n * Case-insensitive suffix-checker.\n * @param {string} str The string to check.\n * @param {string} suffix A string to look for at the end of `str`.\n * @return {boolean} True if `str` ends with `suffix` (ignoring\n *     case).\n */\ngoog.string.caseInsensitiveEndsWith =\n    goog.string.internal.caseInsensitiveEndsWith;\n\n\n/**\n * Case-insensitive equality checker.\n * @param {string} str1 First string to check.\n * @param {string} str2 Second string to check.\n * @return {boolean} True if `str1` and `str2` are the same string,\n *     ignoring case.\n */\ngoog.string.caseInsensitiveEquals = goog.string.internal.caseInsensitiveEquals;\n\n\n/**\n * Does simple python-style string substitution.\n * subs(\"foo%s hot%s\", \"bar\", \"dog\") becomes \"foobar hotdog\".\n * @param {string} str The string containing the pattern.\n * @param {...*} var_args The items to substitute into the pattern.\n * @return {string} A copy of `str` in which each occurrence of\n *     {@code %s} has been replaced an argument from `var_args`.\n */\ngoog.string.subs = function(str, var_args) {\n  'use strict';\n  const splitParts = str.split('%s');\n  let returnString = '';\n\n  const subsArguments = Array.prototype.slice.call(arguments, 1);\n  while (subsArguments.length &&\n         // Replace up to the last split part. We are inserting in the\n         // positions between split parts.\n         splitParts.length > 1) {\n    returnString += splitParts.shift() + subsArguments.shift();\n  }\n\n  return returnString + splitParts.join('%s');  // Join unused '%s'\n};\n\n\n/**\n * Converts multiple whitespace chars (spaces, non-breaking-spaces, new lines\n * and tabs) to a single space, and strips leading and trailing whitespace.\n * @param {string} str Input string.\n * @return {string} A copy of `str` with collapsed whitespace.\n */\ngoog.string.collapseWhitespace = function(str) {\n  'use strict';\n  // Since IE doesn't include non-breaking-space (0xa0) in their \\s character\n  // class (as required by section 7.2 of the ECMAScript spec), we explicitly\n  // include it in the regexp to enforce consistent cross-browser behavior.\n  return str.replace(/[\\s\\xa0]+/g, ' ').replace(/^\\s+|\\s+$/g, '');\n};\n\n\n/**\n * Checks if a string is empty or contains only whitespaces.\n * @param {string} str The string to check.\n * @return {boolean} Whether `str` is empty or whitespace only.\n */\ngoog.string.isEmptyOrWhitespace = goog.string.internal.isEmptyOrWhitespace;\n\n\n/**\n * Checks if a string is empty.\n * @param {string} str The string to check.\n * @return {boolean} Whether `str` is empty.\n */\ngoog.string.isEmptyString = function(str) {\n  'use strict';\n  return str.length == 0;\n};\n\n\n/**\n * Checks if a string is empty or contains only whitespaces.\n *\n * @param {string} str The string to check.\n * @return {boolean} Whether `str` is empty or whitespace only.\n * @deprecated Use goog.string.isEmptyOrWhitespace instead.\n */\ngoog.string.isEmpty = goog.string.isEmptyOrWhitespace;\n\n\n/**\n * Checks if a string is null, undefined, empty or contains only whitespaces.\n * @param {*} str The string to check.\n * @return {boolean} Whether `str` is null, undefined, empty, or\n *     whitespace only.\n * @deprecated Use goog.string.isEmptyOrWhitespace(goog.string.makeSafe(str))\n *     instead.\n */\ngoog.string.isEmptyOrWhitespaceSafe = function(str) {\n  'use strict';\n  return goog.string.isEmptyOrWhitespace(goog.string.makeSafe(str));\n};\n\n\n/**\n * Checks if a string is null, undefined, empty or contains only whitespaces.\n *\n * @param {*} str The string to check.\n * @return {boolean} Whether `str` is null, undefined, empty, or\n *     whitespace only.\n * @deprecated Use goog.string.isEmptyOrWhitespace instead.\n */\ngoog.string.isEmptySafe = goog.string.isEmptyOrWhitespaceSafe;\n\n\n/**\n * Checks if a string is all breaking whitespace.\n * @param {string} str The string to check.\n * @return {boolean} Whether the string is all breaking whitespace.\n */\ngoog.string.isBreakingWhitespace = function(str) {\n  'use strict';\n  return !/[^\\t\\n\\r ]/.test(str);\n};\n\n\n/**\n * Checks if a string contains all letters.\n * @param {string} str string to check.\n * @return {boolean} True if `str` consists entirely of letters.\n */\ngoog.string.isAlpha = function(str) {\n  'use strict';\n  return !/[^a-zA-Z]/.test(str);\n};\n\n\n/**\n * Checks if a string contains only numbers.\n * @param {*} str string to check. If not a string, it will be\n *     casted to one.\n * @return {boolean} True if `str` is numeric.\n */\ngoog.string.isNumeric = function(str) {\n  'use strict';\n  return !/[^0-9]/.test(str);\n};\n\n\n/**\n * Checks if a string contains only numbers or letters.\n * @param {string} str string to check.\n * @return {boolean} True if `str` is alphanumeric.\n */\ngoog.string.isAlphaNumeric = function(str) {\n  'use strict';\n  return !/[^a-zA-Z0-9]/.test(str);\n};\n\n\n/**\n * Checks if a character is a space character.\n * @param {string} ch Character to check.\n * @return {boolean} True if `ch` is a space.\n */\ngoog.string.isSpace = function(ch) {\n  'use strict';\n  return ch == ' ';\n};\n\n\n/**\n * Checks if a character is a valid unicode character.\n * @param {string} ch Character to check.\n * @return {boolean} True if `ch` is a valid unicode character.\n */\ngoog.string.isUnicodeChar = function(ch) {\n  'use strict';\n  return ch.length == 1 && ch >= ' ' && ch <= '~' ||\n      ch >= '\\u0080' && ch <= '\\uFFFD';\n};\n\n\n/**\n * Takes a string and replaces newlines with a space. Multiple lines are\n * replaced with a single space.\n * @param {string} str The string from which to strip newlines.\n * @return {string} A copy of `str` stripped of newlines.\n */\ngoog.string.stripNewlines = function(str) {\n  'use strict';\n  return str.replace(/(\\r\\n|\\r|\\n)+/g, ' ');\n};\n\n\n/**\n * Replaces Windows and Mac new lines with unix style: \\r or \\r\\n with \\n.\n * @param {string} str The string to in which to canonicalize newlines.\n * @return {string} `str` A copy of {@code} with canonicalized newlines.\n */\ngoog.string.canonicalizeNewlines = function(str) {\n  'use strict';\n  return str.replace(/(\\r\\n|\\r|\\n)/g, '\\n');\n};\n\n\n/**\n * Normalizes whitespace in a string, replacing all whitespace chars with\n * a space.\n * @param {string} str The string in which to normalize whitespace.\n * @return {string} A copy of `str` with all whitespace normalized.\n */\ngoog.string.normalizeWhitespace = function(str) {\n  'use strict';\n  return str.replace(/\\xa0|\\s/g, ' ');\n};\n\n\n/**\n * Normalizes spaces in a string, replacing all consecutive spaces and tabs\n * with a single space. Replaces non-breaking space with a space.\n * @param {string} str The string in which to normalize spaces.\n * @return {string} A copy of `str` with all consecutive spaces and tabs\n *    replaced with a single space.\n */\ngoog.string.normalizeSpaces = function(str) {\n  'use strict';\n  return str.replace(/\\xa0|[ \\t]+/g, ' ');\n};\n\n\n/**\n * Removes the breaking spaces from the left and right of the string and\n * collapses the sequences of breaking spaces in the middle into single spaces.\n * The original and the result strings render the same way in HTML.\n * @param {string} str A string in which to collapse spaces.\n * @return {string} Copy of the string with normalized breaking spaces.\n */\ngoog.string.collapseBreakingSpaces = function(str) {\n  'use strict';\n  return str.replace(/[\\t\\r\\n ]+/g, ' ')\n      .replace(/^[\\t\\r\\n ]+|[\\t\\r\\n ]+$/g, '');\n};\n\n\n/**\n * Trims white spaces to the left and right of a string.\n * @param {string} str The string to trim.\n * @return {string} A trimmed copy of `str`.\n */\ngoog.string.trim = goog.string.internal.trim;\n\n\n/**\n * Trims whitespaces at the left end of a string.\n * @param {string} str The string to left trim.\n * @return {string} A trimmed copy of `str`.\n */\ngoog.string.trimLeft = function(str) {\n  'use strict';\n  // Since IE doesn't include non-breaking-space (0xa0) in their \\s character\n  // class (as required by section 7.2 of the ECMAScript spec), we explicitly\n  // include it in the regexp to enforce consistent cross-browser behavior.\n  return str.replace(/^[\\s\\xa0]+/, '');\n};\n\n\n/**\n * Trims whitespaces at the right end of a string.\n * @param {string} str The string to right trim.\n * @return {string} A trimmed copy of `str`.\n */\ngoog.string.trimRight = function(str) {\n  'use strict';\n  // Since IE doesn't include non-breaking-space (0xa0) in their \\s character\n  // class (as required by section 7.2 of the ECMAScript spec), we explicitly\n  // include it in the regexp to enforce consistent cross-browser behavior.\n  return str.replace(/[\\s\\xa0]+$/, '');\n};\n\n\n/**\n * A string comparator that ignores case.\n * -1 = str1 less than str2\n *  0 = str1 equals str2\n *  1 = str1 greater than str2\n *\n * @param {string} str1 The string to compare.\n * @param {string} str2 The string to compare `str1` to.\n * @return {number} The comparator result, as described above.\n */\ngoog.string.caseInsensitiveCompare =\n    goog.string.internal.caseInsensitiveCompare;\n\n\n/**\n * Compares two strings interpreting their numeric substrings as numbers.\n *\n * @param {string} str1 First string.\n * @param {string} str2 Second string.\n * @param {!RegExp} tokenizerRegExp Splits a string into substrings of\n *     non-negative integers, non-numeric characters and optionally fractional\n *     numbers starting with a decimal point.\n * @return {number} Negative if str1 < str2, 0 is str1 == str2, positive if\n *     str1 > str2.\n * @private\n */\ngoog.string.numberAwareCompare_ = function(str1, str2, tokenizerRegExp) {\n  'use strict';\n  if (str1 == str2) {\n    return 0;\n  }\n  if (!str1) {\n    return -1;\n  }\n  if (!str2) {\n    return 1;\n  }\n\n  // Using match to split the entire string ahead of time turns out to be faster\n  // for most inputs than using RegExp.exec or iterating over each character.\n  const tokens1 = str1.toLowerCase().match(tokenizerRegExp);\n  const tokens2 = str2.toLowerCase().match(tokenizerRegExp);\n\n  const count = Math.min(tokens1.length, tokens2.length);\n\n  for (let i = 0; i < count; i++) {\n    const a = tokens1[i];\n    const b = tokens2[i];\n\n    // Compare pairs of tokens, returning if one token sorts before the other.\n    if (a != b) {\n      // Only if both tokens are integers is a special comparison required.\n      // Decimal numbers are sorted as strings (e.g., '.09' < '.1').\n      const num1 = parseInt(a, 10);\n      if (!isNaN(num1)) {\n        const num2 = parseInt(b, 10);\n        if (!isNaN(num2) && num1 - num2) {\n          return num1 - num2;\n        }\n      }\n      return a < b ? -1 : 1;\n    }\n  }\n\n  // If one string is a substring of the other, the shorter string sorts first.\n  if (tokens1.length != tokens2.length) {\n    return tokens1.length - tokens2.length;\n  }\n\n  // The two strings must be equivalent except for case (perfect equality is\n  // tested at the head of the function.) Revert to default ASCII string\n  // comparison to stabilize the sort.\n  return str1 < str2 ? -1 : 1;\n};\n\n\n/**\n * String comparison function that handles non-negative integer numbers in a\n * way humans might expect. Using this function, the string 'File 2.jpg' sorts\n * before 'File 10.jpg', and 'Version 1.9' before 'Version 1.10'. The comparison\n * is mostly case-insensitive, though strings that are identical except for case\n * are sorted with the upper-case strings before lower-case.\n *\n * This comparison function is up to 50x slower than either the default or the\n * case-insensitive compare. It should not be used in time-critical code, but\n * should be fast enough to sort several hundred short strings (like filenames)\n * with a reasonable delay.\n *\n * @param {string} str1 The string to compare in a numerically sensitive way.\n * @param {string} str2 The string to compare `str1` to.\n * @return {number} less than 0 if str1 < str2, 0 if str1 == str2, greater than\n *     0 if str1 > str2.\n */\ngoog.string.intAwareCompare = function(str1, str2) {\n  'use strict';\n  return goog.string.numberAwareCompare_(str1, str2, /\\d+|\\D+/g);\n};\n\n\n/**\n * String comparison function that handles non-negative integer and fractional\n * numbers in a way humans might expect. Using this function, the string\n * 'File 2.jpg' sorts before 'File 10.jpg', and '3.14' before '3.2'. Equivalent\n * to {@link goog.string.intAwareCompare} apart from the way how it interprets\n * dots.\n *\n * @param {string} str1 The string to compare in a numerically sensitive way.\n * @param {string} str2 The string to compare `str1` to.\n * @return {number} less than 0 if str1 < str2, 0 if str1 == str2, greater than\n *     0 if str1 > str2.\n */\ngoog.string.floatAwareCompare = function(str1, str2) {\n  'use strict';\n  return goog.string.numberAwareCompare_(str1, str2, /\\d+|\\.\\d+|\\D+/g);\n};\n\n\n/**\n * Alias for {@link goog.string.floatAwareCompare}.\n *\n * @param {string} str1\n * @param {string} str2\n * @return {number}\n */\ngoog.string.numerateCompare = goog.string.floatAwareCompare;\n\n\n/**\n * URL-encodes a string\n * @param {*} str The string to url-encode.\n * @return {string} An encoded copy of `str` that is safe for urls.\n *     Note that '#', ':', and other characters used to delimit portions\n *     of URLs *will* be encoded.\n */\ngoog.string.urlEncode = function(str) {\n  'use strict';\n  return encodeURIComponent(String(str));\n};\n\n\n/**\n * URL-decodes the string. We need to specially handle '+'s because\n * the javascript library doesn't convert them to spaces.\n * @param {string} str The string to url decode.\n * @return {string} The decoded `str`.\n */\ngoog.string.urlDecode = function(str) {\n  'use strict';\n  return decodeURIComponent(str.replace(/\\+/g, ' '));\n};\n\n\n/**\n * Converts \\n to <br>s or <br />s.\n * @param {string} str The string in which to convert newlines.\n * @param {boolean=} opt_xml Whether to use XML compatible tags.\n * @return {string} A copy of `str` with converted newlines.\n */\ngoog.string.newLineToBr = goog.string.internal.newLineToBr;\n\n\n/**\n * Escapes double quote '\"' and single quote '\\'' characters in addition to\n * '&', '<', and '>' so that a string can be included in an HTML tag attribute\n * value within double or single quotes.\n *\n * It should be noted that > doesn't need to be escaped for the HTML or XML to\n * be valid, but it has been decided to escape it for consistency with other\n * implementations.\n *\n * With goog.string.DETECT_DOUBLE_ESCAPING, this function escapes also the\n * lowercase letter \"e\".\n *\n * NOTE(user):\n * HtmlEscape is often called during the generation of large blocks of HTML.\n * Using statics for the regular expressions and strings is an optimization\n * that can more than half the amount of time IE spends in this function for\n * large apps, since strings and regexes both contribute to GC allocations.\n *\n * Testing for the presence of a character before escaping increases the number\n * of function calls, but actually provides a speed increase for the average\n * case -- since the average case often doesn't require the escaping of all 4\n * characters and indexOf() is much cheaper than replace().\n * The worst case does suffer slightly from the additional calls, therefore the\n * opt_isLikelyToContainHtmlChars option has been included for situations\n * where all 4 HTML entities are very likely to be present and need escaping.\n *\n * Some benchmarks (times tended to fluctuate +-0.05ms):\n *                                     FireFox                     IE6\n * (no chars / average (mix of cases) / all 4 chars)\n * no checks                     0.13 / 0.22 / 0.22         0.23 / 0.53 / 0.80\n * indexOf                       0.08 / 0.17 / 0.26         0.22 / 0.54 / 0.84\n * indexOf + re test             0.07 / 0.17 / 0.28         0.19 / 0.50 / 0.85\n *\n * An additional advantage of checking if replace actually needs to be called\n * is a reduction in the number of object allocations, so as the size of the\n * application grows the difference between the various methods would increase.\n *\n * @param {string} str string to be escaped.\n * @param {boolean=} opt_isLikelyToContainHtmlChars Don't perform a check to see\n *     if the character needs replacing - use this option if you expect each of\n *     the characters to appear often. Leave false if you expect few html\n *     characters to occur in your strings, such as if you are escaping HTML.\n * @return {string} An escaped copy of `str`.\n */\ngoog.string.htmlEscape = function(str, opt_isLikelyToContainHtmlChars) {\n  'use strict';\n  str = goog.string.internal.htmlEscape(str, opt_isLikelyToContainHtmlChars);\n  if (goog.string.DETECT_DOUBLE_ESCAPING) {\n    str = str.replace(goog.string.E_RE_, '&#101;');\n  }\n  return str;\n};\n\n\n/**\n * Regular expression that matches a lowercase letter \"e\", for use in escaping.\n * @const {!RegExp}\n * @private\n */\ngoog.string.E_RE_ = /e/g;\n\n\n/**\n * Unescapes an HTML string.\n *\n * @param {string} str The string to unescape.\n * @return {string} An unescaped copy of `str`.\n */\ngoog.string.unescapeEntities = function(str) {\n  'use strict';\n  if (goog.string.contains(str, '&')) {\n    // We are careful not to use a DOM if we do not have one or we explicitly\n    // requested non-DOM html unescaping.\n    if (!goog.string.FORCE_NON_DOM_HTML_UNESCAPING &&\n        'document' in goog.global) {\n      return goog.string.unescapeEntitiesUsingDom_(str);\n    } else {\n      // Fall back on pure XML entities\n      return goog.string.unescapePureXmlEntities_(str);\n    }\n  }\n  return str;\n};\n\n\n/**\n * Unescapes a HTML string using the provided document.\n *\n * @param {string} str The string to unescape.\n * @param {!Document} document A document to use in escaping the string.\n * @return {string} An unescaped copy of `str`.\n */\ngoog.string.unescapeEntitiesWithDocument = function(str, document) {\n  'use strict';\n  if (goog.string.contains(str, '&')) {\n    return goog.string.unescapeEntitiesUsingDom_(str, document);\n  }\n  return str;\n};\n\n\n/**\n * Unescapes an HTML string using a DOM to resolve non-XML, non-numeric\n * entities. This function is XSS-safe and whitespace-preserving.\n * @private\n * @param {string} str The string to unescape.\n * @param {Document=} opt_document An optional document to use for creating\n *     elements. If this is not specified then the default window.document\n *     will be used.\n * @return {string} The unescaped `str` string.\n */\ngoog.string.unescapeEntitiesUsingDom_ = function(str, opt_document) {\n  'use strict';\n  /** @type {!Object<string, string>} */\n  const seen = {'&amp;': '&', '&lt;': '<', '&gt;': '>', '&quot;': '\"'};\n  /** @type {!Element} */\n  let div;\n  if (opt_document) {\n    div = opt_document.createElement('div');\n  } else {\n    div = goog.global.document.createElement('div');\n  }\n  // Match as many valid entity characters as possible. If the actual entity\n  // happens to be shorter, it will still work as innerHTML will return the\n  // trailing characters unchanged. Since the entity characters do not include\n  // open angle bracket, there is no chance of XSS from the innerHTML use.\n  // Since no whitespace is passed to innerHTML, whitespace is preserved.\n  return str.replace(goog.string.HTML_ENTITY_PATTERN_, function(s, entity) {\n    'use strict';\n    // Check for cached entity.\n    let value = seen[s];\n    if (value) {\n      return value;\n    }\n    // Check for numeric entity.\n    if (entity.charAt(0) == '#') {\n      // Prefix with 0 so that hex entities (e.g. &#x10) parse as hex numbers.\n      const n = Number('0' + entity.substr(1));\n      if (!isNaN(n)) {\n        value = String.fromCharCode(n);\n      }\n    }\n    // Fall back to innerHTML otherwise.\n    if (!value) {\n      // Append a non-entity character to avoid a bug in Webkit that parses\n      // an invalid entity at the end of innerHTML text as the empty string.\n      goog.dom.safe.setInnerHtml(\n          div,\n          goog.html.uncheckedconversions\n              .safeHtmlFromStringKnownToSatisfyTypeContract(\n                  goog.string.Const.from('Single HTML entity.'), s + ' '));\n      // Then remove the trailing character from the result.\n      value = div.firstChild.nodeValue.slice(0, -1);\n    }\n    // Cache and return.\n    return seen[s] = value;\n  });\n};\n\n\n/**\n * Unescapes XML entities.\n * @private\n * @param {string} str The string to unescape.\n * @return {string} An unescaped copy of `str`.\n */\ngoog.string.unescapePureXmlEntities_ = function(str) {\n  'use strict';\n  return str.replace(/&([^;]+);/g, function(s, entity) {\n    'use strict';\n    switch (entity) {\n      case 'amp':\n        return '&';\n      case 'lt':\n        return '<';\n      case 'gt':\n        return '>';\n      case 'quot':\n        return '\"';\n      default:\n        if (entity.charAt(0) == '#') {\n          // Prefix with 0 so that hex entities (e.g. &#x10) parse as hex.\n          const n = Number('0' + entity.substr(1));\n          if (!isNaN(n)) {\n            return String.fromCharCode(n);\n          }\n        }\n        // For invalid entities we just return the entity\n        return s;\n    }\n  });\n};\n\n\n/**\n * Regular expression that matches an HTML entity.\n * See also HTML5: Tokenization / Tokenizing character references.\n * @private\n * @type {!RegExp}\n */\ngoog.string.HTML_ENTITY_PATTERN_ = /&([^;\\s<&]+);?/g;\n\n\n/**\n * Do escaping of whitespace to preserve spatial formatting. We use character\n * entity #160 to make it safer for xml.\n * @param {string} str The string in which to escape whitespace.\n * @param {boolean=} opt_xml Whether to use XML compatible tags.\n * @return {string} An escaped copy of `str`.\n */\ngoog.string.whitespaceEscape = function(str, opt_xml) {\n  'use strict';\n  // This doesn't use goog.string.preserveSpaces for backwards compatibility.\n  return goog.string.newLineToBr(str.replace(/  /g, ' &#160;'), opt_xml);\n};\n\n\n/**\n * Preserve spaces that would be otherwise collapsed in HTML by replacing them\n * with non-breaking space Unicode characters.\n * @param {string} str The string in which to preserve whitespace.\n * @return {string} A copy of `str` with preserved whitespace.\n */\ngoog.string.preserveSpaces = function(str) {\n  'use strict';\n  return str.replace(/(^|[\\n ]) /g, '$1' + goog.string.Unicode.NBSP);\n};\n\n\n/**\n * Strip quote characters around a string.  The second argument is a string of\n * characters to treat as quotes.  This can be a single character or a string of\n * multiple character and in that case each of those are treated as possible\n * quote characters. For example:\n *\n * <pre>\n * goog.string.stripQuotes('\"abc\"', '\"`') --> 'abc'\n * goog.string.stripQuotes('`abc`', '\"`') --> 'abc'\n * </pre>\n *\n * @param {string} str The string to strip.\n * @param {string} quoteChars The quote characters to strip.\n * @return {string} A copy of `str` without the quotes.\n */\ngoog.string.stripQuotes = function(str, quoteChars) {\n  'use strict';\n  const length = quoteChars.length;\n  for (let i = 0; i < length; i++) {\n    const quoteChar = length == 1 ? quoteChars : quoteChars.charAt(i);\n    if (str.charAt(0) == quoteChar && str.charAt(str.length - 1) == quoteChar) {\n      return str.substring(1, str.length - 1);\n    }\n  }\n  return str;\n};\n\n\n/**\n * Truncates a string to a certain length and adds '...' if necessary.  The\n * length also accounts for the ellipsis, so a maximum length of 10 and a string\n * 'Hello World!' produces 'Hello W...'.\n * @param {string} str The string to truncate.\n * @param {number} chars Max number of characters.\n * @param {boolean=} opt_protectEscapedCharacters Whether to protect escaped\n *     characters from being cut off in the middle.\n * @return {string} The truncated `str` string.\n */\ngoog.string.truncate = function(str, chars, opt_protectEscapedCharacters) {\n  'use strict';\n  if (opt_protectEscapedCharacters) {\n    str = goog.string.unescapeEntities(str);\n  }\n\n  if (str.length > chars) {\n    str = str.substring(0, chars - 3) + '...';\n  }\n\n  if (opt_protectEscapedCharacters) {\n    str = goog.string.htmlEscape(str);\n  }\n\n  return str;\n};\n\n\n/**\n * Truncate a string in the middle, adding \"...\" if necessary,\n * and favoring the beginning of the string.\n * @param {string} str The string to truncate the middle of.\n * @param {number} chars Max number of characters.\n * @param {boolean=} opt_protectEscapedCharacters Whether to protect escaped\n *     characters from being cutoff in the middle.\n * @param {number=} opt_trailingChars Optional number of trailing characters to\n *     leave at the end of the string, instead of truncating as close to the\n *     middle as possible.\n * @return {string} A truncated copy of `str`.\n */\ngoog.string.truncateMiddle = function(\n    str, chars, opt_protectEscapedCharacters, opt_trailingChars) {\n  'use strict';\n  if (opt_protectEscapedCharacters) {\n    str = goog.string.unescapeEntities(str);\n  }\n\n  if (opt_trailingChars && str.length > chars) {\n    if (opt_trailingChars > chars) {\n      opt_trailingChars = chars;\n    }\n    const endPoint = str.length - opt_trailingChars;\n    const startPoint = chars - opt_trailingChars;\n    str = str.substring(0, startPoint) + '...' + str.substring(endPoint);\n  } else if (str.length > chars) {\n    // Favor the beginning of the string:\n    let half = Math.floor(chars / 2);\n    const endPos = str.length - half;\n    half += chars % 2;\n    str = str.substring(0, half) + '...' + str.substring(endPos);\n  }\n\n  if (opt_protectEscapedCharacters) {\n    str = goog.string.htmlEscape(str);\n  }\n\n  return str;\n};\n\n\n/**\n * Special chars that need to be escaped for goog.string.quote.\n * @private {!Object<string, string>}\n */\ngoog.string.specialEscapeChars_ = {\n  '\\0': '\\\\0',\n  '\\b': '\\\\b',\n  '\\f': '\\\\f',\n  '\\n': '\\\\n',\n  '\\r': '\\\\r',\n  '\\t': '\\\\t',\n  '\\x0B': '\\\\x0B',  // '\\v' is not supported in JScript\n  '\"': '\\\\\"',\n  '\\\\': '\\\\\\\\',\n  // To support the use case of embedding quoted strings inside of script\n  // tags, we have to make sure HTML comments and opening/closing script tags do\n  // not appear in the resulting string. The specific strings that must be\n  // escaped are documented at:\n  // https://html.spec.whatwg.org/multipage/scripting.html#restrictions-for-contents-of-script-elements\n  '<': '\\\\u003C'  // NOTE: JSON.parse crashes on '\\\\x3c'.\n};\n\n\n/**\n * Character mappings used internally for goog.string.escapeChar.\n * @private {!Object<string, string>}\n */\ngoog.string.jsEscapeCache_ = {\n  '\\'': '\\\\\\''\n};\n\n\n/**\n * Encloses a string in double quotes and escapes characters so that the\n * string is a valid JS string. The resulting string is safe to embed in\n * `<script>` tags as \"<\" is escaped.\n * @param {string} s The string to quote.\n * @return {string} A copy of `s` surrounded by double quotes.\n */\ngoog.string.quote = function(s) {\n  'use strict';\n  s = String(s);\n  const sb = ['\"'];\n  for (let i = 0; i < s.length; i++) {\n    const ch = s.charAt(i);\n    const cc = ch.charCodeAt(0);\n    sb[i + 1] = goog.string.specialEscapeChars_[ch] ||\n        ((cc > 31 && cc < 127) ? ch : goog.string.escapeChar(ch));\n  }\n  sb.push('\"');\n  return sb.join('');\n};\n\n\n/**\n * Takes a string and returns the escaped string for that input string.\n * @param {string} str The string to escape.\n * @return {string} An escaped string representing `str`.\n */\ngoog.string.escapeString = function(str) {\n  'use strict';\n  const sb = [];\n  for (let i = 0; i < str.length; i++) {\n    sb[i] = goog.string.escapeChar(str.charAt(i));\n  }\n  return sb.join('');\n};\n\n\n/**\n * Takes a character and returns the escaped string for that character. For\n * example escapeChar(String.fromCharCode(15)) -> \"\\\\x0E\".\n * @param {string} c The character to escape.\n * @return {string} An escaped string representing `c`.\n */\ngoog.string.escapeChar = function(c) {\n  'use strict';\n  if (c in goog.string.jsEscapeCache_) {\n    return goog.string.jsEscapeCache_[c];\n  }\n\n  if (c in goog.string.specialEscapeChars_) {\n    return goog.string.jsEscapeCache_[c] = goog.string.specialEscapeChars_[c];\n  }\n\n  let rv = c;\n  const cc = c.charCodeAt(0);\n  if (cc > 31 && cc < 127) {\n    rv = c;\n  } else {\n    // tab is 9 but handled above\n    if (cc < 256) {\n      rv = '\\\\x';\n      if (cc < 16 || cc > 256) {\n        rv += '0';\n      }\n    } else {\n      rv = '\\\\u';\n      if (cc < 4096) {  // \\u1000\n        rv += '0';\n      }\n    }\n    rv += cc.toString(16).toUpperCase();\n  }\n\n  return goog.string.jsEscapeCache_[c] = rv;\n};\n\n\n/**\n * Determines whether a string contains a substring.\n * @param {string} str The string to search.\n * @param {string} subString The substring to search for.\n * @return {boolean} Whether `str` contains `subString`.\n */\ngoog.string.contains = goog.string.internal.contains;\n\n\n/**\n * Determines whether a string contains a substring, ignoring case.\n * @param {string} str The string to search.\n * @param {string} subString The substring to search for.\n * @return {boolean} Whether `str` contains `subString`.\n */\ngoog.string.caseInsensitiveContains =\n    goog.string.internal.caseInsensitiveContains;\n\n\n/**\n * Returns the non-overlapping occurrences of ss in s.\n * If either s or ss evalutes to false, then returns zero.\n * @param {string} s The string to look in.\n * @param {string} ss The string to look for.\n * @return {number} Number of occurrences of ss in s.\n */\ngoog.string.countOf = function(s, ss) {\n  'use strict';\n  return s && ss ? s.split(ss).length - 1 : 0;\n};\n\n\n/**\n * Removes a substring of a specified length at a specific\n * index in a string.\n * @param {string} s The base string from which to remove.\n * @param {number} index The index at which to remove the substring.\n * @param {number} stringLength The length of the substring to remove.\n * @return {string} A copy of `s` with the substring removed or the full\n *     string if nothing is removed or the input is invalid.\n */\ngoog.string.removeAt = function(s, index, stringLength) {\n  'use strict';\n  let resultStr = s;\n  // If the index is greater or equal to 0 then remove substring\n  if (index >= 0 && index < s.length && stringLength > 0) {\n    resultStr = s.substr(0, index) +\n        s.substr(index + stringLength, s.length - index - stringLength);\n  }\n  return resultStr;\n};\n\n\n/**\n * Removes the first occurrence of a substring from a string.\n * @param {string} str The base string from which to remove.\n * @param {string} substr The string to remove.\n * @return {string} A copy of `str` with `substr` removed or the\n *     full string if nothing is removed.\n */\ngoog.string.remove = function(str, substr) {\n  'use strict';\n  return str.replace(substr, '');\n};\n\n\n/**\n *  Removes all occurrences of a substring from a string.\n *  @param {string} s The base string from which to remove.\n *  @param {string} ss The string to remove.\n *  @return {string} A copy of `s` with `ss` removed or the full\n *      string if nothing is removed.\n */\ngoog.string.removeAll = function(s, ss) {\n  'use strict';\n  const re = new RegExp(goog.string.regExpEscape(ss), 'g');\n  return s.replace(re, '');\n};\n\n\n/**\n *  Replaces all occurrences of a substring of a string with a new substring.\n *  @param {string} s The base string from which to remove.\n *  @param {string} ss The string to replace.\n *  @param {string} replacement The replacement string.\n *  @return {string} A copy of `s` with `ss` replaced by\n *      `replacement` or the original string if nothing is replaced.\n */\ngoog.string.replaceAll = function(s, ss, replacement) {\n  'use strict';\n  const re = new RegExp(goog.string.regExpEscape(ss), 'g');\n  return s.replace(re, replacement.replace(/\\$/g, '$$$$'));\n};\n\n\n/**\n * Escapes characters in the string that are not safe to use in a RegExp.\n * @param {*} s The string to escape. If not a string, it will be casted\n *     to one.\n * @return {string} A RegExp safe, escaped copy of `s`.\n */\ngoog.string.regExpEscape = function(s) {\n  'use strict';\n  return String(s)\n      .replace(/([-()\\[\\]{}+?*.$\\^|,:#<!\\\\])/g, '\\\\$1')\n      .replace(/\\x08/g, '\\\\x08');\n};\n\n\n/**\n * Repeats a string n times.\n * @param {string} string The string to repeat.\n * @param {number} length The number of times to repeat.\n * @return {string} A string containing `length` repetitions of\n *     `string`.\n */\ngoog.string.repeat = (String.prototype.repeat) ? function(string, length) {\n  'use strict';\n  // The native method is over 100 times faster than the alternative.\n  return string.repeat(length);\n} : function(string, length) {\n  'use strict';\n  return new Array(length + 1).join(string);\n};\n\n\n/**\n * Pads number to given length and optionally rounds it to a given precision.\n * For example:\n * <pre>padNumber(1.25, 2, 3) -> '01.250'\n * padNumber(1.25, 2) -> '01.25'\n * padNumber(1.25, 2, 1) -> '01.3'\n * padNumber(1.25, 0) -> '1.25'</pre>\n *\n * @param {number} num The number to pad.\n * @param {number} length The desired length.\n * @param {number=} opt_precision The desired precision.\n * @return {string} `num` as a string with the given options.\n */\ngoog.string.padNumber = function(num, length, opt_precision) {\n  'use strict';\n  if (!Number.isFinite(num)) return String(num);\n  let s =\n      (opt_precision !== undefined) ? num.toFixed(opt_precision) : String(num);\n  let index = s.indexOf('.');\n  if (index === -1) {\n    index = s.length;\n  }\n  const sign = s[0] === '-' ? '-' : '';\n  if (sign) {\n    s = s.substring(1);\n  }\n  return sign + goog.string.repeat('0', Math.max(0, length - index)) + s;\n};\n\n\n/**\n * Returns a string representation of the given object, with\n * null and undefined being returned as the empty string.\n *\n * @param {*} obj The object to convert.\n * @return {string} A string representation of the `obj`.\n */\ngoog.string.makeSafe = function(obj) {\n  'use strict';\n  return obj == null ? '' : String(obj);\n};\n\n/**\n * Returns a string with at least 64-bits of randomness.\n *\n * Doesn't trust JavaScript's random function entirely. Uses a combination of\n * random and current timestamp, and then encodes the string in base-36 to\n * make it shorter.\n *\n * @return {string} A random string, e.g. sn1s7vb4gcic.\n */\ngoog.string.getRandomString = function() {\n  'use strict';\n  const x = 2147483648;\n  return Math.floor(Math.random() * x).toString(36) +\n      Math.abs(Math.floor(Math.random() * x) ^ goog.now()).toString(36);\n};\n\n\n/**\n * Compares two version numbers.\n *\n * @param {string|number} version1 Version of first item.\n * @param {string|number} version2 Version of second item.\n *\n * @return {number}  1 if `version1` is higher.\n *                   0 if arguments are equal.\n *                  -1 if `version2` is higher.\n */\ngoog.string.compareVersions = goog.string.internal.compareVersions;\n\n\n/**\n * String hash function similar to java.lang.String.hashCode().\n * The hash code for a string is computed as\n * s[0] * 31 ^ (n - 1) + s[1] * 31 ^ (n - 2) + ... + s[n - 1],\n * where s[i] is the ith character of the string and n is the length of\n * the string. We mod the result to make it between 0 (inclusive) and 2^32\n * (exclusive).\n * @param {string} str A string.\n * @return {number} Hash value for `str`, between 0 (inclusive) and 2^32\n *  (exclusive). The empty string returns 0.\n */\ngoog.string.hashCode = function(str) {\n  'use strict';\n  let result = 0;\n  for (let i = 0; i < str.length; ++i) {\n    // Normalize to 4 byte range, 0 ... 2^32.\n    result = (31 * result + str.charCodeAt(i)) >>> 0;\n  }\n  return result;\n};\n\n\n/**\n * The most recent unique ID. |0 is equivalent to Math.floor in this case.\n * @type {number}\n * @private\n */\ngoog.string.uniqueStringCounter_ = Math.random() * 0x80000000 | 0;\n\n\n/**\n * Generates and returns a string which is unique in the current document.\n * This is useful, for example, to create unique IDs for DOM elements.\n * @return {string} A unique id.\n */\ngoog.string.createUniqueString = function() {\n  'use strict';\n  return 'goog_' + goog.string.uniqueStringCounter_++;\n};\n\n\n/**\n * Converts the supplied string to a number, which may be Infinity or NaN.\n * This function strips whitespace: (toNumber(' 123') === 123)\n * This function accepts scientific notation: (toNumber('1e1') === 10)\n *\n * This is better than JavaScript's built-in conversions because, sadly:\n *     (Number(' ') === 0) and (parseFloat('123a') === 123)\n *\n * @param {string} str The string to convert.\n * @return {number} The number the supplied string represents, or NaN.\n */\ngoog.string.toNumber = function(str) {\n  'use strict';\n  const num = Number(str);\n  if (num == 0 && goog.string.isEmptyOrWhitespace(str)) {\n    return NaN;\n  }\n  return num;\n};\n\n\n/**\n * Returns whether the given string is lower camel case (e.g. \"isFooBar\").\n *\n * Note that this assumes the string is entirely letters.\n * @see http://en.wikipedia.org/wiki/CamelCase#Variations_and_synonyms\n *\n * @param {string} str String to test.\n * @return {boolean} Whether the string is lower camel case.\n */\ngoog.string.isLowerCamelCase = function(str) {\n  'use strict';\n  return /^[a-z]+([A-Z][a-z]*)*$/.test(str);\n};\n\n\n/**\n * Returns whether the given string is upper camel case (e.g. \"FooBarBaz\").\n *\n * Note that this assumes the string is entirely letters.\n * @see http://en.wikipedia.org/wiki/CamelCase#Variations_and_synonyms\n *\n * @param {string} str String to test.\n * @return {boolean} Whether the string is upper camel case.\n */\ngoog.string.isUpperCamelCase = function(str) {\n  'use strict';\n  return /^([A-Z][a-z]*)+$/.test(str);\n};\n\n\n/**\n * Converts a string from selector-case to camelCase (e.g. from\n * \"multi-part-string\" to \"multiPartString\"), useful for converting\n * CSS selectors and HTML dataset keys to their equivalent JS properties.\n * @param {string} str The string in selector-case form.\n * @return {string} The string in camelCase form.\n */\ngoog.string.toCamelCase = function(str) {\n  'use strict';\n  return String(str).replace(/\\-([a-z])/g, function(all, match) {\n    'use strict';\n    return match.toUpperCase();\n  });\n};\n\n\n/**\n * Converts a string from camelCase to selector-case (e.g. from\n * \"multiPartString\" to \"multi-part-string\"), useful for converting JS\n * style and dataset properties to equivalent CSS selectors and HTML keys.\n * @param {string} str The string in camelCase form.\n * @return {string} The string in selector-case form.\n */\ngoog.string.toSelectorCase = function(str) {\n  'use strict';\n  return String(str).replace(/([A-Z])/g, '-$1').toLowerCase();\n};\n\n\n/**\n * Converts a string into TitleCase. First character of the string is always\n * capitalized in addition to the first letter of every subsequent word.\n * Words are delimited by one or more whitespaces by default. Custom delimiters\n * can optionally be specified to replace the default, which doesn't preserve\n * whitespace delimiters and instead must be explicitly included if needed.\n *\n * Default delimiter => \" \":\n *    goog.string.toTitleCase('oneTwoThree')    => 'OneTwoThree'\n *    goog.string.toTitleCase('one two three')  => 'One Two Three'\n *    goog.string.toTitleCase('  one   two   ') => '  One   Two   '\n *    goog.string.toTitleCase('one_two_three')  => 'One_two_three'\n *    goog.string.toTitleCase('one-two-three')  => 'One-two-three'\n *\n * Custom delimiter => \"_-.\":\n *    goog.string.toTitleCase('oneTwoThree', '_-.')       => 'OneTwoThree'\n *    goog.string.toTitleCase('one two three', '_-.')     => 'One two three'\n *    goog.string.toTitleCase('  one   two   ', '_-.')    => '  one   two   '\n *    goog.string.toTitleCase('one_two_three', '_-.')     => 'One_Two_Three'\n *    goog.string.toTitleCase('one-two-three', '_-.')     => 'One-Two-Three'\n *    goog.string.toTitleCase('one...two...three', '_-.') => 'One...Two...Three'\n *    goog.string.toTitleCase('one. two. three', '_-.')   => 'One. two. three'\n *    goog.string.toTitleCase('one-two.three', '_-.')     => 'One-Two.Three'\n *\n * @param {string} str String value in camelCase form.\n * @param {string=} opt_delimiters Custom delimiter character set used to\n *      distinguish words in the string value. Each character represents a\n *      single delimiter. When provided, default whitespace delimiter is\n *      overridden and must be explicitly included if needed.\n * @return {string} String value in TitleCase form.\n */\ngoog.string.toTitleCase = function(str, opt_delimiters) {\n  'use strict';\n  let delimiters = (typeof opt_delimiters === 'string') ?\n      goog.string.regExpEscape(opt_delimiters) :\n      '\\\\s';\n\n  // For IE8, we need to prevent using an empty character set. Otherwise,\n  // incorrect matching will occur.\n  delimiters = delimiters ? '|[' + delimiters + ']+' : '';\n\n  const regexp = new RegExp('(^' + delimiters + ')([a-z])', 'g');\n  return str.replace(regexp, function(all, p1, p2) {\n    'use strict';\n    return p1 + p2.toUpperCase();\n  });\n};\n\n\n/**\n * Capitalizes a string, i.e. converts the first letter to uppercase\n * and all other letters to lowercase, e.g.:\n *\n * goog.string.capitalize('one')     => 'One'\n * goog.string.capitalize('ONE')     => 'One'\n * goog.string.capitalize('one two') => 'One two'\n *\n * Note that this function does not trim initial whitespace.\n *\n * @param {string} str String value to capitalize.\n * @return {string} String value with first letter in uppercase.\n */\ngoog.string.capitalize = function(str) {\n  'use strict';\n  return String(str.charAt(0)).toUpperCase() +\n      String(str.substr(1)).toLowerCase();\n};\n\n\n/**\n * Parse a string in decimal or hexidecimal ('0xFFFF') form.\n *\n * To parse a particular radix, please use parseInt(string, radix) directly. See\n * https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/parseInt\n *\n * This is a wrapper for the built-in parseInt function that will only parse\n * numbers as base 10 or base 16.  Some JS implementations assume strings\n * starting with \"0\" are intended to be octal. ES3 allowed but discouraged\n * this behavior. ES5 forbids it.  This function emulates the ES5 behavior.\n *\n * For more information, see Mozilla JS Reference: http://goo.gl/8RiFj\n *\n * @param {string|number|null|undefined} value The value to be parsed.\n * @return {number} The number, parsed. If the string failed to parse, this\n *     will be NaN.\n */\ngoog.string.parseInt = function(value) {\n  'use strict';\n  // Force finite numbers to strings.\n  if (isFinite(value)) {\n    value = String(value);\n  }\n\n  if (typeof value === 'string') {\n    // If the string starts with '0x' or '-0x', parse as hex.\n    return /^\\s*-?0x/i.test(value) ? parseInt(value, 16) : parseInt(value, 10);\n  }\n\n  return NaN;\n};\n\n\n/**\n * Splits a string on a separator a limited number of times.\n *\n * This implementation is more similar to Python or Java, where the limit\n * parameter specifies the maximum number of splits rather than truncating\n * the number of results.\n *\n * See http://docs.python.org/2/library/stdtypes.html#str.split\n * See JavaDoc: http://goo.gl/F2AsY\n * See Mozilla reference: http://goo.gl/dZdZs\n *\n * @param {string} str String to split.\n * @param {string} separator The separator.\n * @param {number} limit The limit to the number of splits. The resulting array\n *     will have a maximum length of limit+1.  Negative numbers are the same\n *     as zero.\n * @return {!Array<string>} The string, split.\n */\ngoog.string.splitLimit = function(str, separator, limit) {\n  'use strict';\n  const parts = str.split(separator);\n  const returnVal = [];\n\n  // Only continue doing this while we haven't hit the limit and we have\n  // parts left.\n  while (limit > 0 && parts.length) {\n    returnVal.push(parts.shift());\n    limit--;\n  }\n\n  // If there are remaining parts, append them to the end.\n  if (parts.length) {\n    returnVal.push(parts.join(separator));\n  }\n\n  return returnVal;\n};\n\n\n/**\n * Finds the characters to the right of the last instance of any separator\n *\n * This function is similar to goog.string.path.baseName, except it can take a\n * list of characters to split the string on. It will return the rightmost\n * grouping of characters to the right of any separator as a left-to-right\n * oriented string.\n *\n * @see goog.string.path.baseName\n * @param {string} str The string\n * @param {string|!Array<string>} separators A list of separator characters\n * @return {string} The last part of the string with respect to the separators\n */\ngoog.string.lastComponent = function(str, separators) {\n  'use strict';\n  if (!separators) {\n    return str;\n  } else if (typeof separators == 'string') {\n    separators = [separators];\n  }\n\n  let lastSeparatorIndex = -1;\n  for (let i = 0; i < separators.length; i++) {\n    if (separators[i] == '') {\n      continue;\n    }\n    const currentSeparatorIndex = str.lastIndexOf(separators[i]);\n    if (currentSeparatorIndex > lastSeparatorIndex) {\n      lastSeparatorIndex = currentSeparatorIndex;\n    }\n  }\n  if (lastSeparatorIndex == -1) {\n    return str;\n  }\n  return str.slice(lastSeparatorIndex + 1);\n};\n\n\n/**\n * Computes the Levenshtein edit distance between two strings.\n * @param {string} a\n * @param {string} b\n * @return {number} The edit distance between the two strings.\n */\ngoog.string.editDistance = function(a, b) {\n  'use strict';\n  const v0 = [];\n  const v1 = [];\n\n  if (a == b) {\n    return 0;\n  }\n\n  if (!a.length || !b.length) {\n    return Math.max(a.length, b.length);\n  }\n\n  for (let i = 0; i < b.length + 1; i++) {\n    v0[i] = i;\n  }\n\n  for (let i = 0; i < a.length; i++) {\n    v1[0] = i + 1;\n\n    for (let j = 0; j < b.length; j++) {\n      const cost = Number(a[i] != b[j]);\n      // Cost for the substring is the minimum of adding one character, removing\n      // one character, or a swap.\n      v1[j + 1] = Math.min(v1[j] + 1, v0[j + 1] + 1, v0[j] + cost);\n    }\n\n    for (let j = 0; j < v0.length; j++) {\n      v0[j] = v1[j];\n    }\n  }\n\n  return v1[b.length];\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview The dispose method is used to clean up references and\n * resources.\n */\n\ngoog.module('goog.dispose');\ngoog.module.declareLegacyNamespace();\n\n/**\n * Calls `dispose` on the argument if it supports it. If obj is not an\n *     object with a dispose() method, this is a no-op.\n * @param {*} obj The object to dispose of.\n */\nfunction dispose(obj) {\n  if (obj && typeof obj.dispose == 'function') {\n    obj.dispose();\n  }\n}\nexports = dispose;\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Codec functions of the v8 wire protocol. Eventually we'd want\n * to support pluggable wire-format to improve wire efficiency and to enable\n * binary encoding. Such support will require an interface class, which\n * will be added later.\n *\n */\n\n\ngoog.provide('goog.labs.net.webChannel.WireV8');\n\ngoog.require('goog.asserts');\ngoog.require('goog.collections.maps');\ngoog.require('goog.json');\ngoog.require('goog.json.NativeJsonProcessor');\ngoog.require('goog.labs.net.webChannel.Wire');\ngoog.require('goog.structs');\ngoog.requireType('goog.string.Parser');\n\n\n\n/**\n * The v8 codec class.\n *\n * @constructor\n * @struct\n */\ngoog.labs.net.webChannel.WireV8 = function() {\n  'use strict';\n  /**\n   * Parser for a response payload. The parser should return an array.\n   * @private {!goog.string.Parser}\n   */\n  this.parser_ = new goog.json.NativeJsonProcessor();\n};\n\n\ngoog.scope(function() {\n'use strict';\nconst WireV8 = goog.labs.net.webChannel.WireV8;\nconst Wire = goog.labs.net.webChannel.Wire;\n\n\n/**\n * Encodes a standalone message into the wire format.\n *\n * May throw exception if the message object contains any invalid elements.\n *\n * @param {!Object|!goog.collections.maps.MapLike} message The message data.\n *     V8 only support JS objects (or Map).\n * @param {!Array<string>} buffer The text buffer to write the message to.\n * @param {string=} opt_prefix The prefix for each field of the object.\n */\nWireV8.prototype.encodeMessage = function(message, buffer, opt_prefix) {\n  'use strict';\n  const prefix = opt_prefix || '';\n  try {\n    goog.structs.forEach(message, function(value, key) {\n      'use strict';\n      let encodedValue = value;\n      if (goog.isObject(value)) {\n        encodedValue = goog.json.serialize(value);\n      }  // keep the fast-path for primitive types\n      buffer.push(prefix + key + '=' + encodeURIComponent(encodedValue));\n    });\n  } catch (ex) {\n    // We send a map here because lots of the retry logic relies on map IDs,\n    // so we have to send something (possibly redundant).\n    buffer.push(\n        prefix + 'type' +\n        '=' + encodeURIComponent('_badmap'));\n    throw ex;\n  }\n};\n\n\n/**\n * Encodes all the buffered messages of the forward channel.\n *\n * @param {!Array<Wire.QueuedMap>} messageQueue The message data.\n *     V8 only support JS objects.\n * @param {number} count The number of messages to be encoded.\n * @param {?function(!Object)} badMapHandler Callback for bad messages.\n * @return {string} the encoded messages\n */\nWireV8.prototype.encodeMessageQueue = function(\n    messageQueue, count, badMapHandler) {\n  'use strict';\n  let offset = -1;\n  while (true) {\n    const sb = ['count=' + count];\n    // To save a bit of bandwidth, specify the base mapId and the rest as\n    // offsets from it.\n    if (offset == -1) {\n      if (count > 0) {\n        offset = messageQueue[0].mapId;\n        sb.push('ofs=' + offset);\n      } else {\n        offset = 0;\n      }\n    } else {\n      sb.push('ofs=' + offset);\n    }\n    let done = true;\n    for (let i = 0; i < count; i++) {\n      let mapId = messageQueue[i].mapId;\n      const map = messageQueue[i].map;\n      mapId -= offset;\n      if (mapId < 0) {\n        // redo the encoding in case of retry/reordering, plus extra space\n        offset = Math.max(0, messageQueue[i].mapId - 100);\n        done = false;\n        continue;\n      }\n      try {\n        this.encodeMessage(map, sb, 'req' + mapId + '_');\n      } catch (ex) {\n        if (badMapHandler) {\n          badMapHandler(map);\n        }\n      }\n    }\n    if (done) {\n      return sb.join('&');\n    }\n  }\n};\n\n\n/**\n * Decodes a standalone message received from the wire. May throw exception\n * if text is ill-formatted.\n *\n * Must be valid JSON as it is insecure to use eval() to decode JS literals;\n * and eval() is disallowed in Chrome apps too.\n *\n * Invalid JS literals include null array elements, quotas etc.\n *\n * @param {string} messageText The string content as received from the wire.\n * @return {*} The decoded message object.\n */\nWireV8.prototype.decodeMessage = function(messageText) {\n  'use strict';\n  const response = this.parser_.parse(messageText);\n  goog.asserts.assert(Array.isArray(response));  // throw exception\n  return response;\n};\n});  // goog.scope\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview A pool of forward channel requests to enable real-time\n * messaging from the client to server.\n *\n */\n\ngoog.module('goog.labs.net.webChannel.ForwardChannelRequestPool');\n\ngoog.module.declareLegacyNamespace();\n\nconst ChannelRequest = goog.require('goog.labs.net.webChannel.ChannelRequest');\nconst Wire = goog.require('goog.labs.net.webChannel.Wire');\nconst array = goog.require('goog.array');\nconst googString = goog.require('goog.string');\n\n\n/**\n * This class represents the state of all forward channel requests.\n *\n * @param {number=} opt_maxPoolSize The maximum pool size.\n *\n * @struct @constructor @final\n */\nconst ForwardChannelRequestPool = function(opt_maxPoolSize) {\n  /**\n   * The max pool size as configured.\n   *\n   * @private {number}\n   */\n  this.maxPoolSizeConfigured_ =\n      opt_maxPoolSize || ForwardChannelRequestPool.MAX_POOL_SIZE_;\n\n  /**\n   * The current size limit of the request pool. This limit is meant to be\n   * read-only after the channel is fully opened.\n   *\n   * If SPDY or HTTP2 is enabled, set it to the max pool size, which is also\n   * configurable.\n   *\n   * @private {number}\n   */\n  this.maxSize_ = ForwardChannelRequestPool.isSpdyOrHttp2Enabled_() ?\n      this.maxPoolSizeConfigured_ :\n      1;\n\n  /**\n   * The container for all the pending request objects.\n   *\n   * @private {?Set<?ChannelRequest>}\n   */\n  this.requestPool_ = null;\n\n  if (this.maxSize_ > 1) {\n    this.requestPool_ = new Set();\n  }\n\n  /**\n   * The single request object when the pool size is limited to one.\n   *\n   * @private {?ChannelRequest}\n   */\n  this.request_ = null;\n\n  /**\n   * Saved pending messages when the pool is cancelled.\n   *\n   * @private {!Array<Wire.QueuedMap>}\n   */\n  this.pendingMessages_ = [];\n};\n\n\n/**\n * The default size limit of the request pool.\n *\n * @private {number}\n */\nForwardChannelRequestPool.MAX_POOL_SIZE_ = 10;\n\n\n/**\n * @return {boolean} True if SPDY or HTTP2 is enabled. Uses chrome-specific APIs\n *     as a fallback and will always return false for other browsers where\n *     PerformanceNavigationTiming is not available.\n * @private\n */\nForwardChannelRequestPool.isSpdyOrHttp2Enabled_ = function() {\n  if (goog.global.PerformanceNavigationTiming) {\n    const entrys = /** @type {!Array<!PerformanceNavigationTiming>} */ (\n        goog.global.performance.getEntriesByType('navigation'));\n    return entrys.length > 0 &&\n        (entrys[0].nextHopProtocol == 'hq' ||\n         entrys[0].nextHopProtocol == 'h2');\n  }\n  return !!(\n      goog.global.chrome && goog.global.chrome.loadTimes &&\n      goog.global.chrome.loadTimes() &&\n      goog.global.chrome.loadTimes().wasFetchedViaSpdy);\n};\n\n\n/**\n * Once we know the client protocol (from the handshake), check if we need\n * enable the request pool accordingly. This is more robust than using\n * browser-internal APIs (specific to Chrome).\n *\n * @param {string} clientProtocol The client protocol\n */\nForwardChannelRequestPool.prototype.applyClientProtocol = function(\n    clientProtocol) {\n  if (this.requestPool_) {\n    return;\n  }\n\n  if (googString.contains(clientProtocol, 'spdy') ||\n      googString.contains(clientProtocol, 'quic') ||\n      googString.contains(clientProtocol, 'h2')) {\n    this.maxSize_ = this.maxPoolSizeConfigured_;\n    this.requestPool_ = new Set();\n    if (this.request_) {\n      this.addRequest(this.request_);\n      this.request_ = null;\n    }\n  }\n};\n\n\n/**\n * @return {boolean} True if the pool is full.\n */\nForwardChannelRequestPool.prototype.isFull = function() {\n  if (this.request_) {\n    return true;\n  }\n\n  if (this.requestPool_) {\n    return this.requestPool_.size >= this.maxSize_;\n  }\n\n  return false;\n};\n\n\n/**\n * @return {number} The current size limit.\n */\nForwardChannelRequestPool.prototype.getMaxSize = function() {\n  return this.maxSize_;\n};\n\n\n/**\n * @return {number} The number of pending requests in the pool.\n */\nForwardChannelRequestPool.prototype.getRequestCount = function() {\n  if (this.request_) {\n    return 1;\n  }\n\n  if (this.requestPool_) {\n    return this.requestPool_.size;\n  }\n\n  return 0;\n};\n\n\n/**\n * @param {ChannelRequest} req The channel request.\n * @return {boolean} True if the request is a included inside the pool.\n */\nForwardChannelRequestPool.prototype.hasRequest = function(req) {\n  if (this.request_) {\n    return this.request_ == req;\n  }\n\n  if (this.requestPool_) {\n    return this.requestPool_.has(req);\n  }\n\n  return false;\n};\n\n\n/**\n * Adds a new request to the pool.\n *\n * @param {!ChannelRequest} req The new channel request.\n */\nForwardChannelRequestPool.prototype.addRequest = function(req) {\n  if (this.requestPool_) {\n    this.requestPool_.add(req);\n  } else {\n    this.request_ = req;\n  }\n};\n\n\n/**\n * Removes the given request from the pool.\n *\n * @param {ChannelRequest} req The channel request.\n * @return {boolean} Whether the request has been removed from the pool.\n */\nForwardChannelRequestPool.prototype.removeRequest = function(req) {\n  if (this.request_ && this.request_ == req) {\n    this.request_ = null;\n    return true;\n  }\n\n  if (this.requestPool_ && this.requestPool_.has(req)) {\n    this.requestPool_.delete(req);\n    return true;\n  }\n\n  return false;\n};\n\n\n/**\n * Clears the pool and cancel all the pending requests.\n */\nForwardChannelRequestPool.prototype.cancel = function() {\n  // save any pending messages\n  this.pendingMessages_ = this.getPendingMessages();\n\n  if (this.request_) {\n    this.request_.cancel();\n    this.request_ = null;\n    return;\n  }\n\n  if (this.requestPool_ && this.requestPool_.size !== 0) {\n    for (const val of this.requestPool_.values()) {\n      val.cancel();\n    }\n    this.requestPool_.clear();\n  }\n};\n\n\n/**\n * @return {boolean} Whether there are any pending requests.\n */\nForwardChannelRequestPool.prototype.hasPendingRequest = function() {\n  return (this.request_ != null) ||\n      (this.requestPool_ != null && this.requestPool_.size !== 0);\n};\n\n\n/**\n * @return {!Array<Wire.QueuedMap>} All the pending messages from the pool,\n *     as a new array.\n */\nForwardChannelRequestPool.prototype.getPendingMessages = function() {\n  if (this.request_ != null) {\n    return this.pendingMessages_.concat(this.request_.getPendingMessages());\n  }\n\n  if (this.requestPool_ != null && this.requestPool_.size !== 0) {\n    let result = this.pendingMessages_;\n    for (const val of this.requestPool_.values()) {\n      result = result.concat(val.getPendingMessages());\n    }\n    return result;\n  }\n\n  return array.clone(this.pendingMessages_);\n};\n\n\n/**\n * Records pending messages, e.g. when a request receives a failed response.\n *\n * @param {!Array<Wire.QueuedMap>} messages Pending messages.\n */\nForwardChannelRequestPool.prototype.addPendingMessages = function(messages) {\n  this.pendingMessages_ = this.pendingMessages_.concat(messages);\n};\n\n\n/**\n * Clears any recorded pending messages.\n */\nForwardChannelRequestPool.prototype.clearPendingMessages = function() {\n  this.pendingMessages_.length = 0;\n};\n\n\n/**\n * Cancels all pending requests and force the completion of channel requests.\n *\n * Need go through the standard onRequestComplete logic to expose the max-retry\n * failure in the standard way.\n *\n * @param {function(!ChannelRequest)} onComplete The completion callback.\n * @return {boolean} true if any request has been forced to complete.\n */\nForwardChannelRequestPool.prototype.forceComplete = function(onComplete) {\n  if (this.request_ != null) {\n    this.request_.cancel();\n    onComplete(this.request_);\n    return true;\n  }\n\n  if (this.requestPool_ && this.requestPool_.size !== 0) {\n    for (const val of this.requestPool_.values()) {\n      val.cancel();\n      onComplete(val);\n    }\n    return true;\n  }\n\n  return false;\n};\n\nexports = ForwardChannelRequestPool;\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Generics method for collection-like classes and objects.\n *\n *\n * This file contains functions to work with collections. It supports using\n * Map, Set, Array and Object and other classes that implement collection-like\n * methods.\n * @suppress {strictMissingProperties}\n */\n\n\ngoog.provide('goog.structs');\n\ngoog.require('goog.array');\ngoog.require('goog.object');\n\n\n// We treat an object as a dictionary if it has getKeys or it is an object that\n// isn't arrayLike.\n\n\n/**\n * Returns the number of values in the collection-like object.\n * @param {Object} col The collection-like object.\n * @return {number} The number of values in the collection-like object.\n */\ngoog.structs.getCount = function(col) {\n  'use strict';\n  if (col.getCount && typeof col.getCount == 'function') {\n    return col.getCount();\n  }\n  if (goog.isArrayLike(col) || typeof col === 'string') {\n    return col.length;\n  }\n  return goog.object.getCount(col);\n};\n\n\n/**\n * Returns the values of the collection-like object.\n * @param {Object} col The collection-like object.\n * @return {!Array<?>} The values in the collection-like object.\n */\ngoog.structs.getValues = function(col) {\n  'use strict';\n  if (col.getValues && typeof col.getValues == 'function') {\n    return col.getValues();\n  }\n  // ES6 Map and Set both define a values function that returns an iterator.\n  // The typeof check allows the compiler to remove the Map and Set polyfills\n  // if they are otherwise unused throughout the entire binary.\n  if ((typeof Map !== 'undefined' && col instanceof Map) ||\n      (typeof Set !== 'undefined' && col instanceof Set)) {\n    return Array.from(col.values());\n  }\n  if (typeof col === 'string') {\n    return col.split('');\n  }\n  if (goog.isArrayLike(col)) {\n    var rv = [];\n    var l = col.length;\n    for (var i = 0; i < l; i++) {\n      rv.push(col[i]);\n    }\n    return rv;\n  }\n  return goog.object.getValues(col);\n};\n\n\n/**\n * Returns the keys of the collection. Some collections have no notion of\n * keys/indexes and this function will return undefined in those cases.\n * @param {Object} col The collection-like object.\n * @return {!Array|undefined} The keys in the collection.\n */\ngoog.structs.getKeys = function(col) {\n  'use strict';\n  if (col.getKeys && typeof col.getKeys == 'function') {\n    return col.getKeys();\n  }\n  // if we have getValues but no getKeys we know this is a key-less collection\n  if (col.getValues && typeof col.getValues == 'function') {\n    return undefined;\n  }\n  // ES6 Map and Set both define a keys function that returns an iterator. For\n  // Sets this iterates over the same values as the values iterator.\n  // The typeof check allows the compiler to remove the Map and Set polyfills\n  // if they are otherwise unused throughout the entire binary.\n  if (typeof Map !== 'undefined' && col instanceof Map) {\n    return Array.from(col.keys());\n  }\n  // Unlike the native Set, goog.structs.Set does not expose keys as the values.\n  if (typeof Set !== 'undefined' && col instanceof Set) {\n    return undefined;\n  }\n  if (goog.isArrayLike(col) || typeof col === 'string') {\n    var rv = [];\n    var l = col.length;\n    for (var i = 0; i < l; i++) {\n      rv.push(i);\n    }\n    return rv;\n  }\n\n  return goog.object.getKeys(col);\n};\n\n\n/**\n * Whether the collection contains the given value. This is O(n) and uses\n * equals (==) to test the existence.\n * @param {Object} col The collection-like object.\n * @param {*} val The value to check for.\n * @return {boolean} True if the map contains the value.\n */\ngoog.structs.contains = function(col, val) {\n  'use strict';\n  if (col.contains && typeof col.contains == 'function') {\n    return col.contains(val);\n  }\n  if (col.containsValue && typeof col.containsValue == 'function') {\n    return col.containsValue(val);\n  }\n  if (goog.isArrayLike(col) || typeof col === 'string') {\n    return goog.array.contains(/** @type {!Array<?>} */ (col), val);\n  }\n  return goog.object.containsValue(col, val);\n};\n\n\n/**\n * Whether the collection is empty.\n * @param {Object} col The collection-like object.\n * @return {boolean} True if empty.\n */\ngoog.structs.isEmpty = function(col) {\n  'use strict';\n  if (col.isEmpty && typeof col.isEmpty == 'function') {\n    return col.isEmpty();\n  }\n\n  // We do not use goog.string.isEmptyOrWhitespace because here we treat the\n  // string as\n  // collection and as such even whitespace matters\n\n  if (goog.isArrayLike(col) || typeof col === 'string') {\n    return /** @type {!Array<?>} */ (col).length === 0;\n  }\n  return goog.object.isEmpty(col);\n};\n\n\n/**\n * Removes all the elements from the collection.\n * @param {Object} col The collection-like object.\n * @return {void}\n */\ngoog.structs.clear = function(col) {\n  'use strict';\n  // NOTE(arv): This should not contain strings because strings are immutable\n  if (col.clear && typeof col.clear == 'function') {\n    col.clear();\n  } else if (goog.isArrayLike(col)) {\n    goog.array.clear(/** @type {IArrayLike<?>} */ (col));\n  } else {\n    goog.object.clear(col);\n  }\n};\n\n\n/**\n * Calls a function for each value in a collection. The function takes\n * three arguments; the value, the key and the collection.\n *\n * @param {S} col The collection-like object.\n * @param {function(this:T,?,?,S):?} f The function to call for every value.\n *     This function takes\n *     3 arguments (the value, the key or undefined if the collection has no\n *     notion of keys, and the collection) and the return value is irrelevant.\n * @param {T=} opt_obj The object to be used as the value of 'this'\n *     within `f`.\n * @return {void}\n * @template T,S\n * @deprecated Use a more specific method, e.g. native Array.prototype.forEach,\n *     or for-of.\n */\ngoog.structs.forEach = function(col, f, opt_obj) {\n  'use strict';\n  if (col.forEach && typeof col.forEach == 'function') {\n    col.forEach(f, opt_obj);\n  } else if (goog.isArrayLike(col) || typeof col === 'string') {\n    Array.prototype.forEach.call(/** @type {!Array<?>} */ (col), f, opt_obj);\n  } else {\n    var keys = goog.structs.getKeys(col);\n    var values = goog.structs.getValues(col);\n    var l = values.length;\n    for (var i = 0; i < l; i++) {\n      f.call(/** @type {?} */ (opt_obj), values[i], keys && keys[i], col);\n    }\n  }\n};\n\n\n/**\n * Calls a function for every value in the collection. When a call returns true,\n * adds the value to a new collection (Array is returned by default).\n *\n * @param {S} col The collection-like object.\n * @param {function(this:T,?,?,S):boolean} f The function to call for every\n *     value. This function takes\n *     3 arguments (the value, the key or undefined if the collection has no\n *     notion of keys, and the collection) and should return a Boolean. If the\n *     return value is true the value is added to the result collection. If it\n *     is false the value is not included.\n * @param {T=} opt_obj The object to be used as the value of 'this'\n *     within `f`.\n * @return {!Object|!Array<?>} A new collection where the passed values are\n *     present. If col is a key-less collection an array is returned.  If col\n *     has keys and values a plain old JS object is returned.\n * @template T,S\n */\ngoog.structs.filter = function(col, f, opt_obj) {\n  'use strict';\n  if (typeof col.filter == 'function') {\n    return col.filter(f, opt_obj);\n  }\n  if (goog.isArrayLike(col) || typeof col === 'string') {\n    return Array.prototype.filter.call(\n        /** @type {!Array<?>} */ (col), f, opt_obj);\n  }\n\n  var rv;\n  var keys = goog.structs.getKeys(col);\n  var values = goog.structs.getValues(col);\n  var l = values.length;\n  if (keys) {\n    rv = {};\n    for (var i = 0; i < l; i++) {\n      if (f.call(/** @type {?} */ (opt_obj), values[i], keys[i], col)) {\n        rv[keys[i]] = values[i];\n      }\n    }\n  } else {\n    // We should not use Array#filter here since we want to make sure that\n    // the index is undefined as well as make sure that col is passed to the\n    // function.\n    rv = [];\n    for (var i = 0; i < l; i++) {\n      if (f.call(opt_obj, values[i], undefined, col)) {\n        rv.push(values[i]);\n      }\n    }\n  }\n  return rv;\n};\n\n\n/**\n * Calls a function for every value in the collection and adds the result into a\n * new collection (defaults to creating a new Array).\n *\n * @param {S} col The collection-like object.\n * @param {function(this:T,?,?,S):V} f The function to call for every value.\n *     This function takes 3 arguments (the value, the key or undefined if the\n *     collection has no notion of keys, and the collection) and should return\n *     something. The result will be used as the value in the new collection.\n * @param {T=} opt_obj  The object to be used as the value of 'this'\n *     within `f`.\n * @return {!Object<V>|!Array<V>} A new collection with the new values.  If\n *     col is a key-less collection an array is returned.  If col has keys and\n *     values a plain old JS object is returned.\n * @template T,S,V\n */\ngoog.structs.map = function(col, f, opt_obj) {\n  'use strict';\n  if (typeof col.map == 'function') {\n    return col.map(f, opt_obj);\n  }\n  if (goog.isArrayLike(col) || typeof col === 'string') {\n    return Array.prototype.map.call(/** @type {!Array<?>} */ (col), f, opt_obj);\n  }\n\n  var rv;\n  var keys = goog.structs.getKeys(col);\n  var values = goog.structs.getValues(col);\n  var l = values.length;\n  if (keys) {\n    rv = {};\n    for (var i = 0; i < l; i++) {\n      rv[keys[i]] = f.call(/** @type {?} */ (opt_obj), values[i], keys[i], col);\n    }\n  } else {\n    // We should not use Array#map here since we want to make sure that\n    // the index is undefined as well as make sure that col is passed to the\n    // function.\n    rv = [];\n    for (var i = 0; i < l; i++) {\n      rv[i] = f.call(/** @type {?} */ (opt_obj), values[i], undefined, col);\n    }\n  }\n  return rv;\n};\n\n\n/**\n * Calls f for each value in a collection. If any call returns true this returns\n * true (without checking the rest). If all returns false this returns false.\n *\n * @param {S} col The collection-like object.\n * @param {function(this:T,?,?,S):boolean} f The function to call for every\n *     value. This function takes 3 arguments (the value, the key or undefined\n *     if the collection has no notion of keys, and the collection) and should\n *     return a boolean.\n * @param {T=} opt_obj  The object to be used as the value of 'this'\n *     within `f`.\n * @return {boolean} True if any value passes the test.\n * @template T,S\n */\ngoog.structs.some = function(col, f, opt_obj) {\n  'use strict';\n  if (typeof col.some == 'function') {\n    return col.some(f, opt_obj);\n  }\n  if (goog.isArrayLike(col) || typeof col === 'string') {\n    return Array.prototype.some.call(\n        /** @type {!Array<?>} */ (col), f, opt_obj);\n  }\n  var keys = goog.structs.getKeys(col);\n  var values = goog.structs.getValues(col);\n  var l = values.length;\n  for (var i = 0; i < l; i++) {\n    if (f.call(/** @type {?} */ (opt_obj), values[i], keys && keys[i], col)) {\n      return true;\n    }\n  }\n  return false;\n};\n\n\n/**\n * Calls f for each value in a collection. If all calls return true this return\n * true this returns true. If any returns false this returns false at this point\n *  and does not continue to check the remaining values.\n *\n * @param {S} col The collection-like object.\n * @param {function(this:T,?,?,S):boolean} f The function to call for every\n *     value. This function takes 3 arguments (the value, the key or\n *     undefined if the collection has no notion of keys, and the collection)\n *     and should return a boolean.\n * @param {T=} opt_obj  The object to be used as the value of 'this'\n *     within `f`.\n * @return {boolean} True if all key-value pairs pass the test.\n * @template T,S\n */\ngoog.structs.every = function(col, f, opt_obj) {\n  'use strict';\n  if (typeof col.every == 'function') {\n    return col.every(f, opt_obj);\n  }\n  if (goog.isArrayLike(col) || typeof col === 'string') {\n    return Array.prototype.every.call(\n        /** @type {!Array<?>} */ (col), f, opt_obj);\n  }\n  var keys = goog.structs.getKeys(col);\n  var values = goog.structs.getValues(col);\n  var l = values.length;\n  for (var i = 0; i < l; i++) {\n    if (!f.call(/** @type {?} */ (opt_obj), values[i], keys && keys[i], col)) {\n      return false;\n    }\n  }\n  return true;\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Simple utilities for dealing with URI strings.\n *\n * This package is deprecated in favour of the Closure URL package (goog.url)\n * when manipulating URIs for use by a browser. This package uses regular\n * expressions to parse a potential URI which can fall out of sync with how a\n * browser will actually interpret the URI. See\n * `goog.uri.utils.setUrlPackageSupportLoggingHandler` for one way to identify\n * URIs that should instead be parsed using the URL package.\n *\n * This is intended to be a lightweight alternative to constructing goog.Uri\n * objects.  Whereas goog.Uri adds several kilobytes to the binary regardless\n * of how much of its functionality you use, this is designed to be a set of\n * mostly-independent utilities so that the compiler includes only what is\n * necessary for the task.  Estimated savings of porting is 5k pre-gzip and\n * 1.5k post-gzip.  To ensure the savings remain, future developers should\n * avoid adding new functionality to existing functions, but instead create\n * new ones and factor out shared code.\n *\n * Many of these utilities have limited functionality, tailored to common\n * cases.  The query parameter utilities assume that the parameter keys are\n * already encoded, since most keys are compile-time alphanumeric strings.  The\n * query parameter mutation utilities also do not tolerate fragment identifiers.\n *\n * By design, these functions can be slower than goog.Uri equivalents.\n * Repeated calls to some of functions may be quadratic in behavior for IE,\n * although the effect is somewhat limited given the 2kb limit.\n *\n * One advantage of the limited functionality here is that this approach is\n * less sensitive to differences in URI encodings than goog.Uri, since these\n * functions operate on strings directly, rather than decoding them and\n * then re-encoding.\n *\n * Uses features of RFC 3986 for parsing/formatting URIs:\n *   http://www.ietf.org/rfc/rfc3986.txt\n */\n\ngoog.provide('goog.uri.utils');\ngoog.provide('goog.uri.utils.ComponentIndex');\ngoog.provide('goog.uri.utils.QueryArray');\ngoog.provide('goog.uri.utils.QueryValue');\ngoog.provide('goog.uri.utils.StandardQueryParam');\n\ngoog.require('goog.asserts');\ngoog.require('goog.string');\n\n\n/**\n * Character codes inlined to avoid object allocations due to charCode.\n * @enum {number}\n * @private\n */\ngoog.uri.utils.CharCode_ = {\n  AMPERSAND: 38,\n  EQUAL: 61,\n  HASH: 35,\n  QUESTION: 63\n};\n\n\n/**\n * Builds a URI string from already-encoded parts.\n *\n * No encoding is performed.  Any component may be omitted as either null or\n * undefined.\n *\n * @param {?string=} opt_scheme The scheme such as 'http'.\n * @param {?string=} opt_userInfo The user name before the '@'.\n * @param {?string=} opt_domain The domain such as 'www.google.com', already\n *     URI-encoded.\n * @param {(string|number|null)=} opt_port The port number.\n * @param {?string=} opt_path The path, already URI-encoded.  If it is not\n *     empty, it must begin with a slash.\n * @param {?string=} opt_queryData The URI-encoded query data.\n * @param {?string=} opt_fragment The URI-encoded fragment identifier.\n * @return {string} The fully combined URI.\n */\ngoog.uri.utils.buildFromEncodedParts = function(\n    opt_scheme, opt_userInfo, opt_domain, opt_port, opt_path, opt_queryData,\n    opt_fragment) {\n  'use strict';\n  var out = '';\n\n  if (opt_scheme) {\n    out += opt_scheme + ':';\n  }\n\n  if (opt_domain) {\n    out += '//';\n\n    if (opt_userInfo) {\n      out += opt_userInfo + '@';\n    }\n\n    out += opt_domain;\n\n    if (opt_port) {\n      out += ':' + opt_port;\n    }\n  }\n\n  if (opt_path) {\n    out += opt_path;\n  }\n\n  if (opt_queryData) {\n    out += '?' + opt_queryData;\n  }\n\n  if (opt_fragment) {\n    out += '#' + opt_fragment;\n  }\n\n  return out;\n};\n\n\n/**\n * A regular expression for breaking a URI into its component parts.\n *\n * {@link http://www.ietf.org/rfc/rfc3986.txt} says in Appendix B\n * As the \"first-match-wins\" algorithm is identical to the \"greedy\"\n * disambiguation method used by POSIX regular expressions, it is natural and\n * commonplace to use a regular expression for parsing the potential five\n * components of a URI reference.\n *\n * The following line is the regular expression for breaking-down a\n * well-formed URI reference into its components.\n *\n * <pre>\n * ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?\n *  12            3  4          5       6  7        8 9\n * </pre>\n *\n * The numbers in the second line above are only to assist readability; they\n * indicate the reference points for each subexpression (i.e., each paired\n * parenthesis). We refer to the value matched for subexpression <n> as $<n>.\n * For example, matching the above expression to\n * <pre>\n *     http://www.ics.uci.edu/pub/ietf/uri/#Related\n * </pre>\n * results in the following subexpression matches:\n * <pre>\n *    $1 = http:\n *    $2 = http\n *    $3 = //www.ics.uci.edu\n *    $4 = www.ics.uci.edu\n *    $5 = /pub/ietf/uri/\n *    $6 = <undefined>\n *    $7 = <undefined>\n *    $8 = #Related\n *    $9 = Related\n * </pre>\n * where <undefined> indicates that the component is not present, as is the\n * case for the query component in the above example. Therefore, we can\n * determine the value of the five components as\n * <pre>\n *    scheme    = $2\n *    authority = $4\n *    path      = $5\n *    query     = $7\n *    fragment  = $9\n * </pre>\n *\n * The regular expression has been modified slightly to expose the\n * userInfo, domain, and port separately from the authority.\n * The modified version yields\n * <pre>\n *    $1 = http              scheme\n *    $2 = <undefined>       userInfo -\\\n *    $3 = www.ics.uci.edu   domain     | authority\n *    $4 = <undefined>       port     -/\n *    $5 = /pub/ietf/uri/    path\n *    $6 = <undefined>       query without ?\n *    $7 = Related           fragment without #\n * </pre>\n *\n * TODO(user): separate out the authority terminating characters once this\n * file is moved to ES6.\n * @type {!RegExp}\n * @private\n */\ngoog.uri.utils.splitRe_ = new RegExp(\n    '^' +  // Anchor against the entire string.\n    '(?:' +\n    '([^:/?#.]+)' +  // scheme - ignore special characters\n                     // used by other URL parts such as :,\n                     // ?, /, #, and .\n    ':)?' +\n    '(?://' +\n    '(?:([^\\\\\\\\/?#]*)@)?' +  // userInfo\n    '([^\\\\\\\\/?#]*?)' +       // domain\n    '(?::([0-9]+))?' +       // port\n    '(?=[\\\\\\\\/?#]|$)' +      // authority-terminating character.\n    ')?' +\n    '([^?#]+)?' +          // path\n    '(?:\\\\?([^#]*))?' +    // query\n    '(?:#([\\\\s\\\\S]*))?' +  // fragment. Can't use '.*' with 's' flag as Firefox\n                           // doesn't support the flag, and can't use an\n                           // \"everything set\" ([^]) as IE10 doesn't match any\n                           // characters with it.\n    '$');\n\n\n/**\n * The index of each URI component in the return value of goog.uri.utils.split.\n * @enum {number}\n */\ngoog.uri.utils.ComponentIndex = {\n  SCHEME: 1,\n  USER_INFO: 2,\n  DOMAIN: 3,\n  PORT: 4,\n  PATH: 5,\n  QUERY_DATA: 6,\n  FRAGMENT: 7\n};\n\n/**\n * @type {?function(string)}\n * @private\n */\ngoog.uri.utils.urlPackageSupportLoggingHandler_ = null;\n\n/**\n * @param {?function(string)} handler The handler function to call when a URI\n *     with a protocol that is better supported by the Closure URL package is\n *     detected.\n */\ngoog.uri.utils.setUrlPackageSupportLoggingHandler = function(handler) {\n  'use strict';\n  goog.uri.utils.urlPackageSupportLoggingHandler_ = handler;\n};\n\n/**\n * Splits a URI into its component parts.\n *\n * Each component can be accessed via the component indices; for example:\n * <pre>\n * goog.uri.utils.split(someStr)[goog.uri.utils.ComponentIndex.QUERY_DATA];\n * </pre>\n *\n * @param {string} uri The URI string to examine.\n * @return {!Array<string|undefined>} Each component still URI-encoded.\n *     Each component that is present will contain the encoded value, whereas\n *     components that are not present will be undefined or empty, depending\n *     on the browser's regular expression implementation.  Never null, since\n *     arbitrary strings may still look like path names.\n */\ngoog.uri.utils.split = function(uri) {\n  'use strict';\n  // See @return comment -- never null.\n  var result = /** @type {!Array<string|undefined>} */ (\n      uri.match(goog.uri.utils.splitRe_));\n  if (goog.uri.utils.urlPackageSupportLoggingHandler_ &&\n      ['http', 'https', 'ws', 'wss',\n       'ftp'].indexOf(result[goog.uri.utils.ComponentIndex.SCHEME]) >= 0) {\n    goog.uri.utils.urlPackageSupportLoggingHandler_(uri);\n  }\n  return result;\n};\n\n\n/**\n * @param {?string} uri A possibly null string.\n * @param {boolean=} opt_preserveReserved If true, percent-encoding of RFC-3986\n *     reserved characters will not be removed.\n * @return {?string} The string URI-decoded, or null if uri is null.\n * @private\n */\ngoog.uri.utils.decodeIfPossible_ = function(uri, opt_preserveReserved) {\n  'use strict';\n  if (!uri) {\n    return uri;\n  }\n\n  return opt_preserveReserved ? decodeURI(uri) : decodeURIComponent(uri);\n};\n\n\n/**\n * Gets a URI component by index.\n *\n * It is preferred to use the getPathEncoded() variety of functions ahead,\n * since they are more readable.\n *\n * @param {goog.uri.utils.ComponentIndex} componentIndex The component index.\n * @param {string} uri The URI to examine.\n * @return {?string} The still-encoded component, or null if the component\n *     is not present.\n * @private\n */\ngoog.uri.utils.getComponentByIndex_ = function(componentIndex, uri) {\n  'use strict';\n  // Convert undefined, null, and empty string into null.\n  return goog.uri.utils.split(uri)[componentIndex] || null;\n};\n\n\n/**\n * @param {string} uri The URI to examine.\n * @return {?string} The protocol or scheme, or null if none.  Does not\n *     include trailing colons or slashes.\n */\ngoog.uri.utils.getScheme = function(uri) {\n  'use strict';\n  return goog.uri.utils.getComponentByIndex_(\n      goog.uri.utils.ComponentIndex.SCHEME, uri);\n};\n\n\n/**\n * Gets the effective scheme for the URL.  If the URL is relative then the\n * scheme is derived from the page's location.\n * @param {string} uri The URI to examine.\n * @return {string} The protocol or scheme, always lower case.\n */\ngoog.uri.utils.getEffectiveScheme = function(uri) {\n  'use strict';\n  var scheme = goog.uri.utils.getScheme(uri);\n  if (!scheme && goog.global.self && goog.global.self.location) {\n    var protocol = goog.global.self.location.protocol;\n    scheme = protocol.substr(0, protocol.length - 1);\n  }\n  // NOTE: When called from a web worker in Firefox 3.5, location may be null.\n  // All other browsers with web workers support self.location from the worker.\n  return scheme ? scheme.toLowerCase() : '';\n};\n\n\n/**\n * @param {string} uri The URI to examine.\n * @return {?string} The user name still encoded, or null if none.\n */\ngoog.uri.utils.getUserInfoEncoded = function(uri) {\n  'use strict';\n  return goog.uri.utils.getComponentByIndex_(\n      goog.uri.utils.ComponentIndex.USER_INFO, uri);\n};\n\n\n/**\n * @param {string} uri The URI to examine.\n * @return {?string} The decoded user info, or null if none.\n */\ngoog.uri.utils.getUserInfo = function(uri) {\n  'use strict';\n  return goog.uri.utils.decodeIfPossible_(\n      goog.uri.utils.getUserInfoEncoded(uri));\n};\n\n\n/**\n * @param {string} uri The URI to examine.\n * @return {?string} The domain name still encoded, or null if none.\n */\ngoog.uri.utils.getDomainEncoded = function(uri) {\n  'use strict';\n  return goog.uri.utils.getComponentByIndex_(\n      goog.uri.utils.ComponentIndex.DOMAIN, uri);\n};\n\n\n/**\n * @param {string} uri The URI to examine.\n * @return {?string} The decoded domain, or null if none.\n */\ngoog.uri.utils.getDomain = function(uri) {\n  'use strict';\n  return goog.uri.utils.decodeIfPossible_(\n      goog.uri.utils.getDomainEncoded(uri), true /* opt_preserveReserved */);\n};\n\n\n/**\n * @param {string} uri The URI to examine.\n * @return {?number} The port number, or null if none.\n */\ngoog.uri.utils.getPort = function(uri) {\n  'use strict';\n  // Coerce to a number.  If the result of getComponentByIndex_ is null or\n  // non-numeric, the number coersion yields NaN.  This will then return\n  // null for all non-numeric cases (though also zero, which isn't a relevant\n  // port number).\n  return Number(\n             goog.uri.utils.getComponentByIndex_(\n                 goog.uri.utils.ComponentIndex.PORT, uri)) ||\n      null;\n};\n\n\n/**\n * @param {string} uri The URI to examine.\n * @return {?string} The path still encoded, or null if none. Includes the\n *     leading slash, if any.\n */\ngoog.uri.utils.getPathEncoded = function(uri) {\n  'use strict';\n  return goog.uri.utils.getComponentByIndex_(\n      goog.uri.utils.ComponentIndex.PATH, uri);\n};\n\n\n/**\n * @param {string} uri The URI to examine.\n * @return {?string} The decoded path, or null if none.  Includes the leading\n *     slash, if any.\n */\ngoog.uri.utils.getPath = function(uri) {\n  'use strict';\n  return goog.uri.utils.decodeIfPossible_(\n      goog.uri.utils.getPathEncoded(uri), true /* opt_preserveReserved */);\n};\n\n\n/**\n * @param {string} uri The URI to examine.\n * @return {?string} The query data still encoded, or null if none.  Does not\n *     include the question mark itself.\n */\ngoog.uri.utils.getQueryData = function(uri) {\n  'use strict';\n  return goog.uri.utils.getComponentByIndex_(\n      goog.uri.utils.ComponentIndex.QUERY_DATA, uri);\n};\n\n\n/**\n * @param {string} uri The URI to examine.\n * @return {?string} The fragment identifier, or null if none.  Does not\n *     include the hash mark itself.\n */\ngoog.uri.utils.getFragmentEncoded = function(uri) {\n  'use strict';\n  // The hash mark may not appear in any other part of the URL.\n  var hashIndex = uri.indexOf('#');\n  return hashIndex < 0 ? null : uri.substr(hashIndex + 1);\n};\n\n\n/**\n * @param {string} uri The URI to examine.\n * @param {?string} fragment The encoded fragment identifier, or null if none.\n *     Does not include the hash mark itself.\n * @return {string} The URI with the fragment set.\n */\ngoog.uri.utils.setFragmentEncoded = function(uri, fragment) {\n  'use strict';\n  return goog.uri.utils.removeFragment(uri) + (fragment ? '#' + fragment : '');\n};\n\n\n/**\n * @param {string} uri The URI to examine.\n * @return {?string} The decoded fragment identifier, or null if none.  Does\n *     not include the hash mark.\n */\ngoog.uri.utils.getFragment = function(uri) {\n  'use strict';\n  return goog.uri.utils.decodeIfPossible_(\n      goog.uri.utils.getFragmentEncoded(uri));\n};\n\n\n/**\n * Extracts everything up to the port of the URI.\n * @param {string} uri The URI string.\n * @return {string} Everything up to and including the port.\n */\ngoog.uri.utils.getHost = function(uri) {\n  'use strict';\n  var pieces = goog.uri.utils.split(uri);\n  return goog.uri.utils.buildFromEncodedParts(\n      pieces[goog.uri.utils.ComponentIndex.SCHEME],\n      pieces[goog.uri.utils.ComponentIndex.USER_INFO],\n      pieces[goog.uri.utils.ComponentIndex.DOMAIN],\n      pieces[goog.uri.utils.ComponentIndex.PORT]);\n};\n\n\n/**\n * Returns the origin for a given URL.\n * @param {string} uri The URI string.\n * @return {string} Everything up to and including the port.\n */\ngoog.uri.utils.getOrigin = function(uri) {\n  'use strict';\n  var pieces = goog.uri.utils.split(uri);\n  return goog.uri.utils.buildFromEncodedParts(\n      pieces[goog.uri.utils.ComponentIndex.SCHEME], null /* opt_userInfo */,\n      pieces[goog.uri.utils.ComponentIndex.DOMAIN],\n      pieces[goog.uri.utils.ComponentIndex.PORT]);\n};\n\n\n/**\n * Extracts the path of the URL and everything after.\n * @param {string} uri The URI string.\n * @return {string} The URI, starting at the path and including the query\n *     parameters and fragment identifier.\n */\ngoog.uri.utils.getPathAndAfter = function(uri) {\n  'use strict';\n  var pieces = goog.uri.utils.split(uri);\n  return goog.uri.utils.buildFromEncodedParts(\n      null, null, null, null, pieces[goog.uri.utils.ComponentIndex.PATH],\n      pieces[goog.uri.utils.ComponentIndex.QUERY_DATA],\n      pieces[goog.uri.utils.ComponentIndex.FRAGMENT]);\n};\n\n\n/**\n * Gets the URI with the fragment identifier removed.\n * @param {string} uri The URI to examine.\n * @return {string} Everything preceding the hash mark.\n */\ngoog.uri.utils.removeFragment = function(uri) {\n  'use strict';\n  // The hash mark may not appear in any other part of the URL.\n  var hashIndex = uri.indexOf('#');\n  return hashIndex < 0 ? uri : uri.substr(0, hashIndex);\n};\n\n\n/**\n * Ensures that two URI's have the exact same domain, scheme, and port.\n *\n * Unlike the version in goog.Uri, this checks protocol, and therefore is\n * suitable for checking against the browser's same-origin policy.\n *\n * @param {string} uri1 The first URI.\n * @param {string} uri2 The second URI.\n * @return {boolean} Whether they have the same scheme, domain and port.\n */\ngoog.uri.utils.haveSameDomain = function(uri1, uri2) {\n  'use strict';\n  var pieces1 = goog.uri.utils.split(uri1);\n  var pieces2 = goog.uri.utils.split(uri2);\n  return pieces1[goog.uri.utils.ComponentIndex.DOMAIN] ==\n      pieces2[goog.uri.utils.ComponentIndex.DOMAIN] &&\n      pieces1[goog.uri.utils.ComponentIndex.SCHEME] ==\n      pieces2[goog.uri.utils.ComponentIndex.SCHEME] &&\n      pieces1[goog.uri.utils.ComponentIndex.PORT] ==\n      pieces2[goog.uri.utils.ComponentIndex.PORT];\n};\n\n\n/**\n * Asserts that there are no fragment or query identifiers, only in uncompiled\n * mode.\n * @param {string} uri The URI to examine.\n * @private\n */\ngoog.uri.utils.assertNoFragmentsOrQueries_ = function(uri) {\n  'use strict';\n  goog.asserts.assert(\n      uri.indexOf('#') < 0 && uri.indexOf('?') < 0,\n      'goog.uri.utils: Fragment or query identifiers are not supported: [%s]',\n      uri);\n};\n\n\n/**\n * Supported query parameter values by the parameter serializing utilities.\n *\n * If a value is null or undefined, the key-value pair is skipped, as an easy\n * way to omit parameters conditionally.  Non-array parameters are converted\n * to a string and URI encoded.  Array values are expanded into multiple\n * &key=value pairs, with each element stringized and URI-encoded.\n *\n * @typedef {*}\n */\ngoog.uri.utils.QueryValue;\n\n\n/**\n * An array representing a set of query parameters with alternating keys\n * and values.\n *\n * Keys are assumed to be URI encoded already and live at even indices.  See\n * goog.uri.utils.QueryValue for details on how parameter values are encoded.\n *\n * Example:\n * <pre>\n * var data = [\n *   // Simple param: ?name=BobBarker\n *   'name', 'BobBarker',\n *   // Conditional param -- may be omitted entirely.\n *   'specialDietaryNeeds', hasDietaryNeeds() ? getDietaryNeeds() : null,\n *   // Multi-valued param: &house=LosAngeles&house=NewYork&house=null\n *   'house', ['LosAngeles', 'NewYork', null]\n * ];\n * </pre>\n *\n * @typedef {!Array<string|goog.uri.utils.QueryValue>}\n */\ngoog.uri.utils.QueryArray;\n\n\n/**\n * Parses encoded query parameters and calls callback function for every\n * parameter found in the string.\n *\n * Missing value of parameter (e.g. “…&key&…”) is treated as if the value was an\n * empty string.  Keys may be empty strings (e.g. “…&=value&…”) which also means\n * that “…&=&…” and “…&&…” will result in an empty key and value.\n *\n * @param {string} encodedQuery Encoded query string excluding question mark at\n *     the beginning.\n * @param {function(string, string)} callback Function called for every\n *     parameter found in query string.  The first argument (name) will not be\n *     urldecoded (so the function is consistent with buildQueryData), but the\n *     second will.  If the parameter has no value (i.e. “=” was not present)\n *     the second argument (value) will be an empty string.\n */\ngoog.uri.utils.parseQueryData = function(encodedQuery, callback) {\n  'use strict';\n  if (!encodedQuery) {\n    return;\n  }\n  var pairs = encodedQuery.split('&');\n  for (var i = 0; i < pairs.length; i++) {\n    var indexOfEquals = pairs[i].indexOf('=');\n    var name = null;\n    var value = null;\n    if (indexOfEquals >= 0) {\n      name = pairs[i].substring(0, indexOfEquals);\n      value = pairs[i].substring(indexOfEquals + 1);\n    } else {\n      name = pairs[i];\n    }\n    callback(name, value ? goog.string.urlDecode(value) : '');\n  }\n};\n\n\n/**\n * Split the URI into 3 parts where the [1] is the queryData without a leading\n * '?'. For example, the URI http://foo.com/bar?a=b#abc returns\n * ['http://foo.com/bar','a=b','#abc'].\n * @param {string} uri The URI to parse.\n * @return {!Array<string>} An array representation of uri of length 3 where the\n *     middle value is the queryData without a leading '?'.\n * @private\n */\ngoog.uri.utils.splitQueryData_ = function(uri) {\n  'use strict';\n  // Find the query data and hash.\n  var hashIndex = uri.indexOf('#');\n  if (hashIndex < 0) {\n    hashIndex = uri.length;\n  }\n  var questionIndex = uri.indexOf('?');\n  var queryData;\n  if (questionIndex < 0 || questionIndex > hashIndex) {\n    questionIndex = hashIndex;\n    queryData = '';\n  } else {\n    queryData = uri.substring(questionIndex + 1, hashIndex);\n  }\n  return [uri.substr(0, questionIndex), queryData, uri.substr(hashIndex)];\n};\n\n\n/**\n * Join an array created by splitQueryData_ back into a URI.\n * @param {!Array<string>} parts A URI in the form generated by splitQueryData_.\n * @return {string} The joined URI.\n * @private\n */\ngoog.uri.utils.joinQueryData_ = function(parts) {\n  'use strict';\n  return parts[0] + (parts[1] ? '?' + parts[1] : '') + parts[2];\n};\n\n\n/**\n * @param {string} queryData\n * @param {string} newData\n * @return {string}\n * @private\n */\ngoog.uri.utils.appendQueryData_ = function(queryData, newData) {\n  'use strict';\n  if (!newData) {\n    return queryData;\n  }\n  return queryData ? queryData + '&' + newData : newData;\n};\n\n\n/**\n * @param {string} uri\n * @param {string} queryData\n * @return {string}\n * @private\n */\ngoog.uri.utils.appendQueryDataToUri_ = function(uri, queryData) {\n  'use strict';\n  if (!queryData) {\n    return uri;\n  }\n  var parts = goog.uri.utils.splitQueryData_(uri);\n  parts[1] = goog.uri.utils.appendQueryData_(parts[1], queryData);\n  return goog.uri.utils.joinQueryData_(parts);\n};\n\n\n/**\n * Appends key=value pairs to an array, supporting multi-valued objects.\n * @param {*} key The key prefix.\n * @param {goog.uri.utils.QueryValue} value The value to serialize.\n * @param {!Array<string>} pairs The array to which the 'key=value' strings\n *     should be appended.\n * @private\n */\ngoog.uri.utils.appendKeyValuePairs_ = function(key, value, pairs) {\n  'use strict';\n  goog.asserts.assertString(key);\n  if (Array.isArray(value)) {\n    // Convince the compiler it's an array.\n    goog.asserts.assertArray(value);\n    for (var j = 0; j < value.length; j++) {\n      // Convert to string explicitly, to short circuit the null and array\n      // logic in this function -- this ensures that null and undefined get\n      // written as literal 'null' and 'undefined', and arrays don't get\n      // expanded out but instead encoded in the default way.\n      goog.uri.utils.appendKeyValuePairs_(key, String(value[j]), pairs);\n    }\n  } else if (value != null) {\n    // Skip a top-level null or undefined entirely.\n    pairs.push(\n        key +\n        // Check for empty string. Zero gets encoded into the url as literal\n        // strings.  For empty string, skip the equal sign, to be consistent\n        // with UriBuilder.java.\n        (value === '' ? '' : '=' + goog.string.urlEncode(value)));\n  }\n};\n\n\n/**\n * Builds a query data string from a sequence of alternating keys and values.\n * Currently generates \"&key&\" for empty args.\n *\n * @param {!IArrayLike<string|goog.uri.utils.QueryValue>} keysAndValues\n *     Alternating keys and values. See the QueryArray typedef.\n * @param {number=} opt_startIndex A start offset into the arary, defaults to 0.\n * @return {string} The encoded query string, in the form 'a=1&b=2'.\n */\ngoog.uri.utils.buildQueryData = function(keysAndValues, opt_startIndex) {\n  'use strict';\n  goog.asserts.assert(\n      Math.max(keysAndValues.length - (opt_startIndex || 0), 0) % 2 == 0,\n      'goog.uri.utils: Key/value lists must be even in length.');\n\n  var params = [];\n  for (var i = opt_startIndex || 0; i < keysAndValues.length; i += 2) {\n    var key = /** @type {string} */ (keysAndValues[i]);\n    goog.uri.utils.appendKeyValuePairs_(key, keysAndValues[i + 1], params);\n  }\n  return params.join('&');\n};\n\n\n/**\n * Builds a query data string from a map.\n * Currently generates \"&key&\" for empty args.\n *\n * @param {!Object<string, goog.uri.utils.QueryValue>} map An object where keys\n *     are URI-encoded parameter keys, and the values are arbitrary types\n *     or arrays. Keys with a null value are dropped.\n * @return {string} The encoded query string, in the form 'a=1&b=2'.\n */\ngoog.uri.utils.buildQueryDataFromMap = function(map) {\n  'use strict';\n  var params = [];\n  for (var key in map) {\n    goog.uri.utils.appendKeyValuePairs_(key, map[key], params);\n  }\n  return params.join('&');\n};\n\n\n/**\n * Appends URI parameters to an existing URI.\n *\n * The variable arguments may contain alternating keys and values.  Keys are\n * assumed to be already URI encoded.  The values should not be URI-encoded,\n * and will instead be encoded by this function.\n * <pre>\n * appendParams('http://www.foo.com?existing=true',\n *     'key1', 'value1',\n *     'key2', 'value?willBeEncoded',\n *     'key3', ['valueA', 'valueB', 'valueC'],\n *     'key4', null);\n * result: 'http://www.foo.com?existing=true&' +\n *     'key1=value1&' +\n *     'key2=value%3FwillBeEncoded&' +\n *     'key3=valueA&key3=valueB&key3=valueC'\n * </pre>\n *\n * A single call to this function will not exhibit quadratic behavior in IE,\n * whereas multiple repeated calls may, although the effect is limited by\n * fact that URL's generally can't exceed 2kb.\n *\n * @param {string} uri The original URI, which may already have query data.\n * @param {...(goog.uri.utils.QueryArray|goog.uri.utils.QueryValue)}\n * var_args\n *     An array or argument list conforming to goog.uri.utils.QueryArray.\n * @return {string} The URI with all query parameters added.\n */\ngoog.uri.utils.appendParams = function(uri, var_args) {\n  'use strict';\n  var queryData = arguments.length == 2 ?\n      goog.uri.utils.buildQueryData(arguments[1], 0) :\n      goog.uri.utils.buildQueryData(arguments, 1);\n  return goog.uri.utils.appendQueryDataToUri_(uri, queryData);\n};\n\n\n/**\n * Appends query parameters from a map.\n *\n * @param {string} uri The original URI, which may already have query data.\n * @param {!Object<goog.uri.utils.QueryValue>} map An object where keys are\n *     URI-encoded parameter keys, and the values are arbitrary types or arrays.\n *     Keys with a null value are dropped.\n * @return {string} The new parameters.\n */\ngoog.uri.utils.appendParamsFromMap = function(uri, map) {\n  'use strict';\n  var queryData = goog.uri.utils.buildQueryDataFromMap(map);\n  return goog.uri.utils.appendQueryDataToUri_(uri, queryData);\n};\n\n\n/**\n * Appends a single URI parameter.\n *\n * Repeated calls to this can exhibit quadratic behavior in IE6 due to the\n * way string append works, though it should be limited given the 2kb limit.\n *\n * @param {string} uri The original URI, which may already have query data.\n * @param {string} key The key, which must already be URI encoded.\n * @param {*=} opt_value The value, which will be stringized and encoded\n *     (assumed not already to be encoded).  If omitted, undefined, or null, the\n *     key will be added as a valueless parameter.\n * @return {string} The URI with the query parameter added.\n */\ngoog.uri.utils.appendParam = function(uri, key, opt_value) {\n  'use strict';\n  var value = (opt_value != null) ? '=' + goog.string.urlEncode(opt_value) : '';\n  return goog.uri.utils.appendQueryDataToUri_(uri, key + value);\n};\n\n\n/**\n * Finds the next instance of a query parameter with the specified name.\n *\n * Does not instantiate any objects.\n *\n * @param {string} uri The URI to search.  May contain a fragment identifier\n *     if opt_hashIndex is specified.\n * @param {number} startIndex The index to begin searching for the key at.  A\n *     match may be found even if this is one character after the ampersand.\n * @param {string} keyEncoded The URI-encoded key.\n * @param {number} hashOrEndIndex Index to stop looking at.  If a hash\n *     mark is present, it should be its index, otherwise it should be the\n *     length of the string.\n * @return {number} The position of the first character in the key's name,\n *     immediately after either a question mark or a dot.\n * @private\n */\ngoog.uri.utils.findParam_ = function(\n    uri, startIndex, keyEncoded, hashOrEndIndex) {\n  'use strict';\n  var index = startIndex;\n  var keyLength = keyEncoded.length;\n\n  // Search for the key itself and post-filter for surronuding punctuation,\n  // rather than expensively building a regexp.\n  while ((index = uri.indexOf(keyEncoded, index)) >= 0 &&\n         index < hashOrEndIndex) {\n    var precedingChar = uri.charCodeAt(index - 1);\n    // Ensure that the preceding character is '&' or '?'.\n    if (precedingChar == goog.uri.utils.CharCode_.AMPERSAND ||\n        precedingChar == goog.uri.utils.CharCode_.QUESTION) {\n      // Ensure the following character is '&', '=', '#', or NaN\n      // (end of string).\n      var followingChar = uri.charCodeAt(index + keyLength);\n      if (!followingChar || followingChar == goog.uri.utils.CharCode_.EQUAL ||\n          followingChar == goog.uri.utils.CharCode_.AMPERSAND ||\n          followingChar == goog.uri.utils.CharCode_.HASH) {\n        return index;\n      }\n    }\n    index += keyLength + 1;\n  }\n\n  return -1;\n};\n\n\n/**\n * Regular expression for finding a hash mark or end of string.\n * @type {RegExp}\n * @private\n */\ngoog.uri.utils.hashOrEndRe_ = /#|$/;\n\n\n/**\n * Determines if the URI contains a specific key.\n *\n * Performs no object instantiations.\n *\n * @param {string} uri The URI to process.  May contain a fragment\n *     identifier.\n * @param {string} keyEncoded The URI-encoded key.  Case-sensitive.\n * @return {boolean} Whether the key is present.\n */\ngoog.uri.utils.hasParam = function(uri, keyEncoded) {\n  'use strict';\n  return goog.uri.utils.findParam_(\n             uri, 0, keyEncoded, uri.search(goog.uri.utils.hashOrEndRe_)) >= 0;\n};\n\n\n/**\n * Gets the first value of a query parameter.\n * @param {string} uri The URI to process.  May contain a fragment.\n * @param {string} keyEncoded The URI-encoded key.  Case-sensitive.\n * @return {?string} The first value of the parameter (URI-decoded), or null\n *     if the parameter is not found.\n */\ngoog.uri.utils.getParamValue = function(uri, keyEncoded) {\n  'use strict';\n  var hashOrEndIndex = uri.search(goog.uri.utils.hashOrEndRe_);\n  var foundIndex =\n      goog.uri.utils.findParam_(uri, 0, keyEncoded, hashOrEndIndex);\n\n  if (foundIndex < 0) {\n    return null;\n  } else {\n    var endPosition = uri.indexOf('&', foundIndex);\n    if (endPosition < 0 || endPosition > hashOrEndIndex) {\n      endPosition = hashOrEndIndex;\n    }\n    // Progress forth to the end of the \"key=\" or \"key&\" substring.\n    foundIndex += keyEncoded.length + 1;\n    // Use substr, because it (unlike substring) will return empty string\n    // if foundIndex > endPosition.\n    return goog.string.urlDecode(\n        uri.substr(foundIndex, endPosition - foundIndex));\n  }\n};\n\n\n/**\n * Gets all values of a query parameter.\n * @param {string} uri The URI to process.  May contain a fragment.\n * @param {string} keyEncoded The URI-encoded key.  Case-sensitive.\n * @return {!Array<string>} All URI-decoded values with the given key.\n *     If the key is not found, this will have length 0, but never be null.\n */\ngoog.uri.utils.getParamValues = function(uri, keyEncoded) {\n  'use strict';\n  var hashOrEndIndex = uri.search(goog.uri.utils.hashOrEndRe_);\n  var position = 0;\n  var foundIndex;\n  var result = [];\n\n  while ((foundIndex = goog.uri.utils.findParam_(\n              uri, position, keyEncoded, hashOrEndIndex)) >= 0) {\n    // Find where this parameter ends, either the '&' or the end of the\n    // query parameters.\n    position = uri.indexOf('&', foundIndex);\n    if (position < 0 || position > hashOrEndIndex) {\n      position = hashOrEndIndex;\n    }\n\n    // Progress forth to the end of the \"key=\" or \"key&\" substring.\n    foundIndex += keyEncoded.length + 1;\n    // Use substr, because it (unlike substring) will return empty string\n    // if foundIndex > position.\n    result.push(\n        goog.string.urlDecode(uri.substr(foundIndex, position - foundIndex)));\n  }\n\n  return result;\n};\n\n\n/**\n * Regexp to find trailing question marks and ampersands.\n * @type {RegExp}\n * @private\n */\ngoog.uri.utils.trailingQueryPunctuationRe_ = /[?&]($|#)/;\n\n\n/**\n * Removes all instances of a query parameter.\n * @param {string} uri The URI to process.  Must not contain a fragment.\n * @param {string} keyEncoded The URI-encoded key.\n * @return {string} The URI with all instances of the parameter removed.\n */\ngoog.uri.utils.removeParam = function(uri, keyEncoded) {\n  'use strict';\n  var hashOrEndIndex = uri.search(goog.uri.utils.hashOrEndRe_);\n  var position = 0;\n  var foundIndex;\n  var buffer = [];\n\n  // Look for a query parameter.\n  while ((foundIndex = goog.uri.utils.findParam_(\n              uri, position, keyEncoded, hashOrEndIndex)) >= 0) {\n    // Get the portion of the query string up to, but not including, the ?\n    // or & starting the parameter.\n    buffer.push(uri.substring(position, foundIndex));\n    // Progress to immediately after the '&'.  If not found, go to the end.\n    // Avoid including the hash mark.\n    position = Math.min(\n        (uri.indexOf('&', foundIndex) + 1) || hashOrEndIndex, hashOrEndIndex);\n  }\n\n  // Append everything that is remaining.\n  buffer.push(uri.substr(position));\n\n  // Join the buffer, and remove trailing punctuation that remains.\n  return buffer.join('').replace(\n      goog.uri.utils.trailingQueryPunctuationRe_, '$1');\n};\n\n\n/**\n * Replaces all existing definitions of a parameter with a single definition.\n *\n * Repeated calls to this can exhibit quadratic behavior due to the need to\n * find existing instances and reconstruct the string, though it should be\n * limited given the 2kb limit.  Consider using appendParams or setParamsFromMap\n * to update multiple parameters in bulk.\n *\n * @param {string} uri The original URI, which may already have query data.\n * @param {string} keyEncoded The key, which must already be URI encoded.\n * @param {*} value The value, which will be stringized and encoded (assumed\n *     not already to be encoded).\n * @return {string} The URI with the query parameter added.\n */\ngoog.uri.utils.setParam = function(uri, keyEncoded, value) {\n  'use strict';\n  return goog.uri.utils.appendParam(\n      goog.uri.utils.removeParam(uri, keyEncoded), keyEncoded, value);\n};\n\n\n/**\n * Effeciently set or remove multiple query parameters in a URI. Order of\n * unchanged parameters will not be modified, all updated parameters will be\n * appended to the end of the query. Params with values of null or undefined are\n * removed.\n *\n * @param {string} uri The URI to process.\n * @param {!Object<string, goog.uri.utils.QueryValue>} params A list of\n *     parameters to update. If null or undefined, the param will be removed.\n * @return {string} An updated URI where the query data has been updated with\n *     the params.\n */\ngoog.uri.utils.setParamsFromMap = function(uri, params) {\n  'use strict';\n  var parts = goog.uri.utils.splitQueryData_(uri);\n  var queryData = parts[1];\n  var buffer = [];\n  if (queryData) {\n    queryData.split('&').forEach(function(pair) {\n      'use strict';\n      var indexOfEquals = pair.indexOf('=');\n      var name = indexOfEquals >= 0 ? pair.substr(0, indexOfEquals) : pair;\n      if (!params.hasOwnProperty(name)) {\n        buffer.push(pair);\n      }\n    });\n  }\n  parts[1] = goog.uri.utils.appendQueryData_(\n      buffer.join('&'), goog.uri.utils.buildQueryDataFromMap(params));\n  return goog.uri.utils.joinQueryData_(parts);\n};\n\n\n/**\n * Generates a URI path using a given URI and a path with checks to\n * prevent consecutive \"//\". The baseUri passed in must not contain\n * query or fragment identifiers. The path to append may not contain query or\n * fragment identifiers.\n *\n * @param {string} baseUri URI to use as the base.\n * @param {string} path Path to append.\n * @return {string} Updated URI.\n */\ngoog.uri.utils.appendPath = function(baseUri, path) {\n  'use strict';\n  goog.uri.utils.assertNoFragmentsOrQueries_(baseUri);\n\n  // Remove any trailing '/'\n  if (goog.string.endsWith(baseUri, '/')) {\n    baseUri = baseUri.substr(0, baseUri.length - 1);\n  }\n  // Remove any leading '/'\n  if (goog.string.startsWith(path, '/')) {\n    path = path.substr(1);\n  }\n  return '' + baseUri + '/' + path;\n};\n\n\n/**\n * Replaces the path.\n * @param {string} uri URI to use as the base.\n * @param {string} path New path.\n * @return {string} Updated URI.\n */\ngoog.uri.utils.setPath = function(uri, path) {\n  'use strict';\n  // Add any missing '/'.\n  if (!goog.string.startsWith(path, '/')) {\n    path = '/' + path;\n  }\n  var parts = goog.uri.utils.split(uri);\n  return goog.uri.utils.buildFromEncodedParts(\n      parts[goog.uri.utils.ComponentIndex.SCHEME],\n      parts[goog.uri.utils.ComponentIndex.USER_INFO],\n      parts[goog.uri.utils.ComponentIndex.DOMAIN],\n      parts[goog.uri.utils.ComponentIndex.PORT], path,\n      parts[goog.uri.utils.ComponentIndex.QUERY_DATA],\n      parts[goog.uri.utils.ComponentIndex.FRAGMENT]);\n};\n\n\n/**\n * Standard supported query parameters.\n * @enum {string}\n */\ngoog.uri.utils.StandardQueryParam = {\n\n  /** Unused parameter for unique-ifying. */\n  RANDOM: 'zx'\n};\n\n\n/**\n * Sets the zx parameter of a URI to a random value.\n * @param {string} uri Any URI.\n * @return {string} That URI with the \"zx\" parameter added or replaced to\n *     contain a random string.\n */\ngoog.uri.utils.makeUnique = function(uri) {\n  'use strict';\n  return goog.uri.utils.setParam(\n      uri, goog.uri.utils.StandardQueryParam.RANDOM,\n      goog.string.getRandomString());\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Interface and shared data structures for implementing\n * different wire protocol versions.\n */\ngoog.provide('goog.labs.net.webChannel.Wire');\ngoog.provide('goog.labs.net.webChannel.Wire.QueuedMap');\n\n\n\ngoog.require('goog.collections.maps');\n\n\n\n/**\n * The interface class.\n * @interface\n */\ngoog.labs.net.webChannel.Wire = class {\n  constructor() {}\n};\n\n\n/**\n * The latest protocol version that this class supports. We request this version\n * from the server when opening the connection. Should match\n * LATEST_CHANNEL_VERSION on the server code.\n * @type {number}\n */\ngoog.labs.net.webChannel.Wire.LATEST_CHANNEL_VERSION = 8;\n\n\n/**\n * The JSON field key for the raw data wrapper object.\n * @type {string}\n */\ngoog.labs.net.webChannel.Wire.RAW_DATA_KEY = '__data__';\n\n\n\n/**\n * Simple container class for a (mapId, map) pair.\n */\ngoog.labs.net.webChannel.Wire.QueuedMap = class {\n  /**\n   * @param {number} mapId The id for this map.\n   * @param {!Object|!goog.collections.maps.MapLike} map The map itself.\n   * @param {!Object=} opt_context The context associated with the map.\n   */\n  constructor(mapId, map, opt_context) {\n    'use strict';\n    /**\n     * The id for this map.\n     * @type {number}\n     */\n    this.mapId = mapId;\n\n    /**\n     * The map itself.\n     * @type {!Object|!goog.collections.maps.MapLike}\n     */\n    this.map = map;\n\n    /**\n     * The context for the map.\n     * @type {Object}\n     */\n    this.context = opt_context || null;\n  }\n\n  /**\n   * @return {number|undefined} the size of the raw JSON message or\n   * undefined if the message is not encoded as a raw JSON message\n   */\n  getRawDataSize() {\n    'use strict';\n    if (goog.labs.net.webChannel.Wire.RAW_DATA_KEY in this.map) {\n      const data = this.map[goog.labs.net.webChannel.Wire.RAW_DATA_KEY];\n      if (typeof data === 'string') {\n        return data.length;\n      }\n    }\n\n    return undefined;\n  }\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n\n/**\n * @fileoverview Defines a class for parsing JSON using the browser's built in\n * JSON library.\n */\n\ngoog.provide('goog.json.NativeJsonProcessor');\n\ngoog.require('goog.asserts');\ngoog.require('goog.json.Processor');\n\n\n\n/**\n * A class that parses and stringifies JSON using the browser's built-in JSON\n * library, if it is available.\n *\n * Note that the native JSON api has subtle differences across browsers, so\n * use this implementation with care.  See json_test#assertSerialize\n * for details on the differences from goog.json.\n *\n * This implementation is signficantly faster than goog.json, at least on\n * Chrome.  See json_perf.html for a perf test showing the difference.\n *\n * @param {?goog.json.Replacer=} opt_replacer An optional replacer to use during\n *     serialization.\n * @param {?goog.json.Reviver=} opt_reviver An optional reviver to use during\n *     parsing.\n * @constructor\n * @implements {goog.json.Processor}\n * @final\n */\ngoog.json.NativeJsonProcessor = function(opt_replacer, opt_reviver) {\n  'use strict';\n  goog.asserts.assert(goog.global['JSON'] !== undefined, 'JSON not defined');\n\n  /**\n   * @type {goog.json.Replacer|null|undefined}\n   * @private\n   */\n  this.replacer_ = opt_replacer;\n\n  /**\n   * @type {goog.json.Reviver|null|undefined}\n   * @private\n   */\n  this.reviver_ = opt_reviver;\n};\n\n\n/** @override */\ngoog.json.NativeJsonProcessor.prototype.stringify = function(object) {\n  'use strict';\n  return goog.global['JSON'].stringify(object, this.replacer_);\n};\n\n\n/** @override */\ngoog.json.NativeJsonProcessor.prototype.parse = function(s) {\n  'use strict';\n  return goog.global['JSON'].parse(s, this.reviver_);\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Utility functions for managing networking, such as\n * testing network connectivity.\n *\n */\n\n\ngoog.provide('goog.labs.net.webChannel.netUtils');\n\ngoog.require('goog.Uri');\ngoog.require('goog.labs.net.webChannel.WebChannelDebug');\n\ngoog.scope(function() {\n'use strict';\nconst netUtils = goog.labs.net.webChannel.netUtils;\nconst WebChannelDebug = goog.labs.net.webChannel.WebChannelDebug;\n\n\n/**\n * Default timeout to allow for URI pings.\n * @type {number}\n */\nnetUtils.NETWORK_TIMEOUT = 10000;\n\n\n/**\n * Pings the network with an image URI to check if an error is a server error\n * or user's network error.\n *\n * The caller needs to add a 'rand' parameter to make sure the response is\n * not fulfilled by browser cache.\n *\n * @param {function(boolean)} callback The function to call back with results.\n * @param {goog.Uri=} opt_imageUri The URI (of an image) to use for the network\n *     test.\n */\nnetUtils.testNetwork = function(callback, opt_imageUri) {\n  'use strict';\n  let uri = opt_imageUri;\n  if (!uri) {\n    // default google.com image\n    uri = new goog.Uri('//www.google.com/images/cleardot.gif');\n\n    if (!(goog.global.location && goog.global.location.protocol == 'http')) {\n      uri.setScheme('https');  // e.g. chrome-extension\n    }\n    uri.makeUnique();\n  }\n\n  netUtils.testLoadImage(uri.toString(), netUtils.NETWORK_TIMEOUT, callback);\n};\n\n\n/**\n * Test loading the given image, retrying if necessary.\n * @param {string} url URL to the image.\n * @param {number} timeout Milliseconds before giving up.\n * @param {function(boolean)} callback Function to call with results.\n * @param {number} retries The number of times to retry.\n * @param {!WebChannelDebug} channelDebug The debug object\n * @param {number=} opt_pauseBetweenRetriesMS Optional number of milliseconds\n *     between retries - defaults to 0.\n */\nnetUtils.testLoadImageWithRetries = function(\n    url, timeout, callback, retries, channelDebug, opt_pauseBetweenRetriesMS) {\n  'use strict';\n  channelDebug.debug('TestLoadImageWithRetries: ' + opt_pauseBetweenRetriesMS);\n  if (retries == 0) {\n    // no more retries, give up\n    callback(false);\n    return;\n  }\n\n  const pauseBetweenRetries = opt_pauseBetweenRetriesMS || 0;\n  retries--;\n  netUtils.testLoadImage(url, timeout, function(succeeded) {\n    'use strict';\n    if (succeeded) {\n      callback(true);\n    } else {\n      // try again\n      goog.global.setTimeout(function() {\n        'use strict';\n        netUtils.testLoadImageWithRetries(\n            url, timeout, callback, retries, channelDebug, pauseBetweenRetries);\n      }, pauseBetweenRetries);\n    }\n  });\n};\n\n\n/**\n * Test loading the given image.\n * @param {string} url URL to the image.\n * @param {number} timeout Milliseconds before giving up.\n * @param {function(boolean)} callback Function to call with results.\n * @suppress {strictMissingProperties} Part of the go/strict_warnings_migration\n */\nnetUtils.testLoadImage = function(url, timeout, callback) {\n  'use strict';\n  const channelDebug = new WebChannelDebug();\n  channelDebug.debug('TestLoadImage: loading ' + url);\n  if (goog.global.Image) {\n    const img = new Image();\n    img.onload = goog.partial(\n        netUtils.imageCallback_, channelDebug, img, 'TestLoadImage: loaded',\n        true, callback);\n    img.onerror = goog.partial(\n        netUtils.imageCallback_, channelDebug, img, 'TestLoadImage: error',\n        false, callback);\n    img.onabort = goog.partial(\n        netUtils.imageCallback_, channelDebug, img, 'TestLoadImage: abort',\n        false, callback);\n    img.ontimeout = goog.partial(\n        netUtils.imageCallback_, channelDebug, img, 'TestLoadImage: timeout',\n        false, callback);\n\n    goog.global.setTimeout(function() {\n      'use strict';\n      if (img.ontimeout) {\n        img.ontimeout();\n      }\n    }, timeout);\n    img.src = url;\n  } else {\n    // log ERROR_OTHER from environements where Image is not supported\n    callback(false);\n  }\n};\n\n\n/**\n * Wrap the image callback with debug and cleanup logic.\n * @param {!WebChannelDebug} channelDebug The WebChannelDebug object.\n * @param {!Image} img The image element.\n * @param {string} debugText The debug text.\n * @param {boolean} result The result of image loading.\n * @param {function(boolean)} callback The image callback.\n * @private\n */\nnetUtils.imageCallback_ = function(\n    channelDebug, img, debugText, result, callback) {\n  'use strict';\n  try {\n    channelDebug.debug(debugText);\n    netUtils.clearImageCallbacks_(img);\n    callback(result);\n  } catch (e) {\n    channelDebug.dumpException(e);\n  }\n};\n\n\n/**\n * Clears handlers to avoid memory leaks.\n * @param {Image} img The image to clear handlers from.\n * @private\n * @suppress {strictMissingProperties} Part of the go/strict_warnings_migration\n */\nnetUtils.clearImageCallbacks_ = function(img) {\n  'use strict';\n  img.onload = null;\n  img.onerror = null;\n  img.onabort = null;\n  img.ontimeout = null;\n};\n});  // goog.scope\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\ngoog.provide('goog.net.FetchXmlHttp');\ngoog.provide('goog.net.FetchXmlHttpFactory');\n\ngoog.require('goog.asserts');\ngoog.require('goog.events.EventTarget');\ngoog.require('goog.functions');\ngoog.require('goog.log');\ngoog.require('goog.net.XhrLike');\ngoog.require('goog.net.XmlHttpFactory');\n\n\n\n/**\n * @record\n */\ngoog.net.FetchXmlHttpFactoryOptions = function() {\n  /**\n   * @type {!WorkerGlobalScope|undefined} The Service Worker global scope.\n   */\n  this.worker;\n\n  /**\n   * @type {boolean|undefined} Whether to store the FetchXmlHttp response as an\n   * array of Uint8Arrays.  If this is true then the 'responseType' attribute\n   * must be empty.\n   */\n  this.streamBinaryChunks;\n};\n\n\n\n/**\n * Factory for creating Xhr objects that uses the native fetch() method.\n * https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\n * @param {!goog.net.FetchXmlHttpFactoryOptions} opts\n * @extends {goog.net.XmlHttpFactory}\n * @struct\n * @constructor\n */\ngoog.net.FetchXmlHttpFactory = function(opts) {\n  'use strict';\n  goog.net.FetchXmlHttpFactory.base(this, 'constructor');\n\n  /** @private @final {?WorkerGlobalScope} */\n  this.worker_ = opts.worker || null;\n\n  /** @private @final {boolean} */\n  this.streamBinaryChunks_ = opts.streamBinaryChunks || false;\n\n  /** @private {!RequestCredentials|undefined} */\n  this.credentialsMode_ = undefined;\n\n  /** @private {!RequestCache|undefined} */\n  this.cacheMode_ = undefined;\n};\ngoog.inherits(goog.net.FetchXmlHttpFactory, goog.net.XmlHttpFactory);\n\n\n/** @override */\ngoog.net.FetchXmlHttpFactory.prototype.createInstance = function() {\n  'use strict';\n  const instance =\n      new goog.net.FetchXmlHttp(this.worker_, this.streamBinaryChunks_);\n  if (this.credentialsMode_) {\n    instance.setCredentialsMode(this.credentialsMode_);\n  }\n  if (this.cacheMode_) {\n    instance.setCacheMode(this.cacheMode_);\n  }\n  return instance;\n};\n\n\n/** @override */\ngoog.net.FetchXmlHttpFactory.prototype.internalGetOptions =\n    goog.functions.constant({});\n\n\n/**\n * @param {!RequestCredentials} credentialsMode The credentials mode of the\n *     Service Worker fetch.\n */\ngoog.net.FetchXmlHttpFactory.prototype.setCredentialsMode = function(\n    credentialsMode) {\n  'use strict';\n  this.credentialsMode_ = credentialsMode;\n};\n\n\n/**\n * @param {!RequestCache} cacheMode The cache mode of the Service Worker fetch.\n */\ngoog.net.FetchXmlHttpFactory.prototype.setCacheMode = function(cacheMode) {\n  'use strict';\n  this.cacheMode_ = cacheMode;\n};\n\n\n\n/**\n * FetchXmlHttp object constructor.\n * @param {?WorkerGlobalScope} worker\n * @param {boolean} streamBinaryChunks\n * @extends {goog.events.EventTarget}\n * @implements {goog.net.XhrLike}\n * @constructor\n * @struct\n */\ngoog.net.FetchXmlHttp = function(worker, streamBinaryChunks) {\n  'use strict';\n  goog.net.FetchXmlHttp.base(this, 'constructor');\n\n  /** @private @final {?WorkerGlobalScope} */\n  this.worker_ = worker;\n\n  /** @private @final {boolean} */\n  this.streamBinaryChunks_ = streamBinaryChunks;\n\n  /** @private {RequestCredentials|undefined} */\n  this.credentialsMode_ = undefined;\n\n  /** @private {RequestCache|undefined} */\n  this.cacheMode_ = undefined;\n\n  /**\n   * Request state.\n   * @type {goog.net.FetchXmlHttp.RequestState}\n   */\n  this.readyState = goog.net.FetchXmlHttp.RequestState.UNSENT;\n\n  /**\n   * HTTP status.\n   * @type {number}\n   */\n  this.status = 0;\n\n  /**\n   * HTTP status string.\n   * @type {string}\n   */\n  this.statusText = '';\n\n  /**\n   * Content of the response.\n   * @type {string|!ArrayBuffer|!Array<!Uint8Array>}\n   */\n  this.response = '';\n\n  /**\n   * Content of the response.\n   * @type {string}\n   */\n  this.responseText = '';\n\n  /**\n   * The type of the response.  If this is set to 'arraybuffer' the request will\n   * be discrete, streaming is only supported for text encoded requests.\n   * @type {string}\n   */\n  this.responseType = '';\n\n  /**\n   * Document response entity body.\n   * NOTE: This is always null and not supported by this class.\n   * @final {null}\n   */\n  this.responseXML = null;\n\n  /**\n   * Method to call when the state changes.\n   * @type {?function()}\n   */\n  this.onreadystatechange = null;\n\n  /** @private {!Headers} */\n  this.requestHeaders_ = new Headers();\n\n  /** @private {?Headers} */\n  this.responseHeaders_ = null;\n\n  /**\n   * Request method (GET or POST).\n   * @private {string}\n   */\n  this.method_ = 'GET';\n\n  /**\n   * Request URL.\n   * @private {string}\n   */\n  this.url_ = '';\n\n  /**\n   * Whether the request is in progress.\n   * @private {boolean}\n   */\n  this.inProgress_ = false;\n\n  /** @private @final {?goog.log.Logger} */\n  this.logger_ = goog.log.getLogger('goog.net.FetchXmlHttp');\n\n  /** @private {?Response} */\n  this.fetchResponse_ = null;\n\n  /** @private {!ReadableStreamDefaultReader|null} */\n  this.currentReader_ = null;\n\n  /** @private {?TextDecoder} */\n  this.textDecoder_ = null;\n};\ngoog.inherits(goog.net.FetchXmlHttp, goog.events.EventTarget);\n\n\n/**\n * State of the requests.\n * @enum {number}\n */\ngoog.net.FetchXmlHttp.RequestState = {\n  UNSENT: 0,\n  OPENED: 1,\n  HEADER_RECEIVED: 2,\n  LOADING: 3,\n  DONE: 4,\n};\n\n\n/** @override */\ngoog.net.FetchXmlHttp.prototype.open = function(method, url, opt_async) {\n  'use strict';\n  goog.asserts.assert(!!opt_async, 'Only async requests are supported.');\n  if (this.readyState != goog.net.FetchXmlHttp.RequestState.UNSENT) {\n    this.abort();\n    throw new Error('Error reopening a connection');\n  }\n\n  this.method_ = method;\n  this.url_ = url;\n\n  this.readyState = goog.net.FetchXmlHttp.RequestState.OPENED;\n  this.dispatchCallback_();\n};\n\n\n/** @override */\ngoog.net.FetchXmlHttp.prototype.send = function(opt_data) {\n  'use strict';\n  if (this.readyState != goog.net.FetchXmlHttp.RequestState.OPENED) {\n    this.abort();\n    throw new Error('need to call open() first. ');\n  }\n\n  this.inProgress_ = true;\n  const requestInit = {\n    headers: this.requestHeaders_,\n    method: this.method_,\n    credentials: this.credentialsMode_,\n    cache: this.cacheMode_,\n  };\n  if (opt_data) {\n    requestInit['body'] = opt_data;\n  }\n\n  (this.worker_ || goog.global)\n      .fetch(new Request(this.url_, /** @type {!RequestInit} */ (requestInit)))\n      .then(\n          this.handleResponse_.bind(this), this.handleSendFailure_.bind(this));\n};\n\n\n/** @override */\ngoog.net.FetchXmlHttp.prototype.abort = function() {\n  'use strict';\n  this.response = this.responseText = '';\n  this.requestHeaders_ = new Headers();\n  this.status = 0;\n\n  if (!!this.currentReader_) {\n    this.currentReader_.cancel('Request was aborted.')\n        .catch(\n            e => goog.log.warning(\n                this.logger_, 'Fetch reader cancellation error.', e));\n  }\n\n  if (((this.readyState >= goog.net.FetchXmlHttp.RequestState.OPENED) &&\n       this.inProgress_) &&\n      (this.readyState != goog.net.FetchXmlHttp.RequestState.DONE)) {\n    this.inProgress_ = false;\n    this.requestDone_();\n  }\n\n  this.readyState = goog.net.FetchXmlHttp.RequestState.UNSENT;\n};\n\n\n/**\n * Handles the fetch response.\n * @param {!Response} response\n * @private\n */\ngoog.net.FetchXmlHttp.prototype.handleResponse_ = function(response) {\n  'use strict';\n  if (!this.inProgress_) {\n    // The request was aborted, ignore.\n    return;\n  }\n\n  this.fetchResponse_ = response;\n\n  if (!this.responseHeaders_) {\n    this.status = this.fetchResponse_.status;\n    this.statusText = this.fetchResponse_.statusText;\n    this.responseHeaders_ = response.headers;\n    this.readyState = goog.net.FetchXmlHttp.RequestState.HEADER_RECEIVED;\n    this.dispatchCallback_();\n  }\n  // A callback may abort the request.\n  if (!this.inProgress_) {\n    // The request was aborted, ignore.\n    return;\n  }\n\n  this.readyState = goog.net.FetchXmlHttp.RequestState.LOADING;\n  this.dispatchCallback_();\n  // A callback may abort the request.\n  if (!this.inProgress_) {\n    // The request was aborted, ignore.\n    return;\n  }\n\n  if (this.responseType === 'arraybuffer') {\n    response.arrayBuffer().then(\n        this.handleResponseArrayBuffer_.bind(this),\n        this.handleSendFailure_.bind(this));\n  } else if (\n      typeof (goog.global.ReadableStream) !== 'undefined' &&\n      'body' in response) {\n    this.currentReader_ =\n        /** @type {!ReadableStreamDefaultReader} */ (response.body.getReader());\n    if (this.streamBinaryChunks_) {\n      if (this.responseType) {\n        throw new Error(\n            'responseType must be empty for \"streamBinaryChunks\" mode responses.');\n      }\n      this.response = [];\n    } else {\n      this.response = this.responseText = '';\n      this.textDecoder_ = new TextDecoder();\n    }\n    this.readInputFromFetch_();\n  } else {\n    response.text().then(\n        this.handleResponseText_.bind(this),\n        this.handleSendFailure_.bind(this));\n  }\n};\n\n\n/**\n * Reads the next chunk of data from the fetch response.\n * @private\n */\ngoog.net.FetchXmlHttp.prototype.readInputFromFetch_ = function() {\n  'use strict';\n  this.currentReader_.read()\n      .then(this.handleDataFromStream_.bind(this))\n      .catch(this.handleSendFailure_.bind(this));\n};\n\n\n/**\n * Handles a chunk of data from the fetch response stream reader.\n * @param {!IIterableResult} result\n * @private\n */\ngoog.net.FetchXmlHttp.prototype.handleDataFromStream_ = function(result) {\n  'use strict';\n  if (!this.inProgress_) {\n    // The request was aborted, ignore.\n    return;\n  }\n\n  if (this.streamBinaryChunks_ && result.value) {\n    // When streamBinaryChunks_ is enabled, \"response\" is an array\n    /** @type {!Array} */ (this.response)\n        .push(/** @type {!Uint8Array} */ (result.value));\n  } else if (!this.streamBinaryChunks_) {\n    const dataPacket = result.value ?\n        /** @type {!Uint8Array} */ (result.value) :\n        new Uint8Array(0);\n    const newText =\n        this.textDecoder_.decode(dataPacket, {stream: !result.done});\n    if (newText) {\n      this.responseText += newText;\n      this.response = this.responseText;\n    }\n  }\n  if (result.done) {\n    this.requestDone_();\n  } else {\n    this.dispatchCallback_();\n  }\n\n  if (this.readyState == goog.net.FetchXmlHttp.RequestState.LOADING) {\n    this.readInputFromFetch_();\n  }\n};\n\n/**\n * Handles the response text.\n * @param {string} responseText\n * @private\n */\ngoog.net.FetchXmlHttp.prototype.handleResponseText_ = function(responseText) {\n  'use strict';\n  if (!this.inProgress_) {\n    // The request was aborted, ignore.\n    return;\n  }\n  this.response = this.responseText = responseText;\n  this.requestDone_();\n};\n\n\n/**\n * Handles the response text.\n * @param {!ArrayBuffer} responseArrayBuffer\n * @private\n */\ngoog.net.FetchXmlHttp.prototype.handleResponseArrayBuffer_ = function(\n    responseArrayBuffer) {\n  'use strict';\n  if (!this.inProgress_) {\n    // The request was aborted, ignore.\n    return;\n  }\n  this.response = responseArrayBuffer;\n  this.requestDone_();\n};\n\n\n/**\n * Handles the send failure.\n * @param {*} error\n * @private\n */\ngoog.net.FetchXmlHttp.prototype.handleSendFailure_ = function(error) {\n  'use strict';\n  const e = error instanceof Error ? error : Error(error);\n  goog.log.warning(this.logger_, 'Failed to fetch url ' + this.url_, e);\n  if (!this.inProgress_) {\n    // The request was aborted, ignore.\n    return;\n  }\n  this.requestDone_();\n};\n\n\n/**\n * Sets the request state to DONE and performs cleanup.\n * @private\n */\ngoog.net.FetchXmlHttp.prototype.requestDone_ = function() {\n  'use strict';\n  this.readyState = goog.net.FetchXmlHttp.RequestState.DONE;\n\n  this.fetchResponse_ = null;\n  this.currentReader_ = null;\n  this.textDecoder_ = null;\n\n  this.dispatchCallback_();\n};\n\n\n/** @override */\ngoog.net.FetchXmlHttp.prototype.setRequestHeader = function(header, value) {\n  'use strict';\n  this.requestHeaders_.append(header, value);\n};\n\n\n/** @override */\ngoog.net.FetchXmlHttp.prototype.getResponseHeader = function(header) {\n  'use strict';\n  // TODO(user): This method should return null when the headers are not\n  // present or the specified header is missing. The externs need to be fixed.\n  if (!this.responseHeaders_) {\n    goog.log.warning(\n        this.logger_,\n        'Attempting to get response header but no headers have been received ' +\n            'for url: ' + this.url_);\n    return '';\n  }\n  return this.responseHeaders_.get(header.toLowerCase()) || '';\n};\n\n\n/** @override */\ngoog.net.FetchXmlHttp.prototype.getAllResponseHeaders = function() {\n  'use strict';\n  if (!this.responseHeaders_) {\n    goog.log.warning(\n        this.logger_,\n        'Attempting to get all response headers but no headers have been ' +\n            'received for url: ' + this.url_);\n    return '';\n  }\n  const lines = [];\n  const iter = this.responseHeaders_.entries();\n  let entry = iter.next();\n  while (!entry.done) {\n    const pair = entry.value;\n    lines.push(pair[0] + ': ' + pair[1]);\n    entry = iter.next();\n  }\n  return lines.join('\\r\\n');\n};\n\n\n/**\n * @param {!RequestCredentials} credentialsMode The credentials mode of the\n *     Service Worker fetch.\n */\ngoog.net.FetchXmlHttp.prototype.setCredentialsMode = function(credentialsMode) {\n  'use strict';\n  this.credentialsMode_ = credentialsMode;\n};\n\n/**\n * @return {!RequestCredentials|undefined} The credentials mode of the\n *     Service Worker fetch.\n */\ngoog.net.FetchXmlHttp.prototype.getCredentialsMode = function() {\n  'use strict';\n  return this.credentialsMode_;\n};\n\n/**\n * @param {!RequestCache} cacheMode The cache mode of the Service Worker fetch.\n */\ngoog.net.FetchXmlHttp.prototype.setCacheMode = function(cacheMode) {\n  'use strict';\n  this.cacheMode_ = cacheMode;\n};\n\n\n/**\n * Dispatches the callback, if the callback attribute is defined.\n * @private\n */\ngoog.net.FetchXmlHttp.prototype.dispatchCallback_ = function() {\n  'use strict';\n  if (this.onreadystatechange) {\n    this.onreadystatechange.call(this);\n  }\n};\n\n// Polyfill XmlHttpRequest's withCredentials property for specifying whether to\n// include credentials on cross domain requests.\nObject.defineProperty(goog.net.FetchXmlHttp.prototype, 'withCredentials', {\n  get:\n      /**\n       * @this {goog.net.FetchXmlHttp}\n       * @return {boolean} Whether to include credentials in cross domain\n       *     requests.\n       */\n      function() {\n        'use strict';\n        return this.getCredentialsMode() === 'include';\n      },\n\n  set:\n      /**\n       * @param {boolean} value Whether to include credentials in cross domain\n       *     requests.\n       * @this {goog.net.FetchXmlHttp}\n       **/\n      function(value) {\n        'use strict';\n        this.setCredentialsMode(value ? 'include' : 'same-origin');\n      }\n});\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Utilities for creating functions. Loosely inspired by these\n * java classes from the Guava library:\n * com.google.common.base.Functions\n * https://google.github.io/guava/releases/snapshot-jre/api/docs/index.html?com/google/common/base/Functions.html\n *\n * com.google.common.base.Predicates\n * https://google.github.io/guava/releases/snapshot-jre/api/docs/index.html?com/google/common/base/Predicates.html\n *\n * More about these can be found at\n * https://github.com/google/guava/wiki/FunctionalExplained\n */\n\n\ngoog.provide('goog.functions');\n\n\n/**\n * Creates a function that always returns the same value.\n * @param {T} retValue The value to return.\n * @return {function():T} The new function.\n * @template T\n */\ngoog.functions.constant = function(retValue) {\n  'use strict';\n  return function() {\n    'use strict';\n    return retValue;\n  };\n};\n\n\n/**\n * Always returns false.\n * @type {function(...): boolean}\n */\ngoog.functions.FALSE = function() {\n  'use strict';\n  return false;\n};\n\n\n/**\n * Always returns true.\n * @type {function(...): boolean}\n */\ngoog.functions.TRUE = function() {\n  'use strict';\n  return true;\n};\n\n\n/**\n * Always returns `null`.\n * @type {function(...): null}\n */\ngoog.functions.NULL = function() {\n  'use strict';\n  return null;\n};\n\n\n/**\n * Always returns `undefined`.\n * @type {function(...): undefined}\n */\ngoog.functions.UNDEFINED = function() {\n  return undefined;\n};\n\n/**\n * Always returns `undefined` (loosely-typed version).\n * @type {!Function}\n */\ngoog.functions.EMPTY = /** @type {?} */ (goog.functions.UNDEFINED);\n\n\n/**\n * A simple function that returns the first argument of whatever is passed\n * into it.\n * @param {T=} opt_returnValue The single value that will be returned.\n * @param {...*} var_args Optional trailing arguments. These are ignored.\n * @return {T} The first argument passed in, or undefined if nothing was passed.\n * @template T\n */\ngoog.functions.identity = function(opt_returnValue, var_args) {\n  'use strict';\n  return opt_returnValue;\n};\n\n\n/**\n * Creates a function that always throws an error with the given message.\n * @param {string} message The error message.\n * @return {!Function} The error-throwing function.\n */\ngoog.functions.error = function(message) {\n  'use strict';\n  return function() {\n    'use strict';\n    throw new Error(message);\n  };\n};\n\n\n/**\n * Creates a function that throws the given object.\n * @param {*} err An object to be thrown.\n * @return {!Function} The error-throwing function.\n */\ngoog.functions.fail = function(err) {\n  'use strict';\n  return function() {\n    'use strict';\n    throw err;\n  };\n};\n\n\n/**\n * Given a function, create a function that keeps opt_numArgs arguments and\n * silently discards all additional arguments.\n * @param {Function} f The original function.\n * @param {number=} opt_numArgs The number of arguments to keep. Defaults to 0.\n * @return {!Function} A version of f that only keeps the first opt_numArgs\n *     arguments.\n */\ngoog.functions.lock = function(f, opt_numArgs) {\n  'use strict';\n  opt_numArgs = opt_numArgs || 0;\n  return function() {\n    'use strict';\n    const self = /** @type {*} */ (this);\n    return f.apply(self, Array.prototype.slice.call(arguments, 0, opt_numArgs));\n  };\n};\n\n\n/**\n * Creates a function that returns its nth argument.\n * @param {number} n The position of the return argument.\n * @return {!Function} A new function.\n */\ngoog.functions.nth = function(n) {\n  'use strict';\n  return function() {\n    'use strict';\n    return arguments[n];\n  };\n};\n\n\n/**\n * Like goog.partial(), except that arguments are added after arguments to the\n * returned function.\n *\n * Usage:\n * function f(arg1, arg2, arg3, arg4) { ... }\n * var g = goog.functions.partialRight(f, arg3, arg4);\n * g(arg1, arg2);\n *\n * @param {!Function} fn A function to partially apply.\n * @param {...*} var_args Additional arguments that are partially applied to fn\n *     at the end.\n * @return {!Function} A partially-applied form of the function goog.partial()\n *     was invoked as a method of.\n */\ngoog.functions.partialRight = function(fn, var_args) {\n  'use strict';\n  const rightArgs = Array.prototype.slice.call(arguments, 1);\n  return function() {\n    'use strict';\n    // Even in strict mode, IE10/11 and Edge (non-Chromium) use global context\n    // when free-calling functions. To catch cases where people were using this\n    // erroneously, we explicitly change the context to undefined to match\n    // strict mode specifications.\n    let self = /** @type {*} */ (this);\n    if (self === goog.global) {\n      self = undefined;\n    }\n    const newArgs = Array.prototype.slice.call(arguments);\n    newArgs.push.apply(newArgs, rightArgs);\n    return fn.apply(self, newArgs);\n  };\n};\n\n\n/**\n * Given a function, create a new function that swallows its return value\n * and replaces it with a new one.\n * @param {Function} f A function.\n * @param {T} retValue A new return value.\n * @return {function(...?):T} A new function.\n * @template T\n */\ngoog.functions.withReturnValue = function(f, retValue) {\n  'use strict';\n  return goog.functions.sequence(f, goog.functions.constant(retValue));\n};\n\n\n/**\n * Creates a function that returns whether its argument equals the given value.\n *\n * Example:\n * var key = goog.object.findKey(obj, goog.functions.equalTo('needle'));\n *\n * @param {*} value The value to compare to.\n * @param {boolean=} opt_useLooseComparison Whether to use a loose (==)\n *     comparison rather than a strict (===) one. Defaults to false.\n * @return {function(*):boolean} The new function.\n */\ngoog.functions.equalTo = function(value, opt_useLooseComparison) {\n  'use strict';\n  return function(other) {\n    'use strict';\n    return opt_useLooseComparison ? (value == other) : (value === other);\n  };\n};\n\n\n/**\n * Creates the composition of the functions passed in.\n * For example, (goog.functions.compose(f, g))(a) is equivalent to f(g(a)).\n * @param {function(...?):T} fn The final function.\n * @param {...Function} var_args A list of functions.\n * @return {function(...?):T} The composition of all inputs.\n * @template T\n */\ngoog.functions.compose = function(fn, var_args) {\n  'use strict';\n  const functions = arguments;\n  const length = functions.length;\n  return function() {\n    'use strict';\n    const self = /** @type {*} */ (this);\n    let result;\n    if (length) {\n      result = functions[length - 1].apply(self, arguments);\n    }\n\n    for (let i = length - 2; i >= 0; i--) {\n      result = functions[i].call(self, result);\n    }\n    return result;\n  };\n};\n\n\n/**\n * Creates a function that calls the functions passed in in sequence, and\n * returns the value of the last function. For example,\n * (goog.functions.sequence(f, g))(x) is equivalent to f(x),g(x).\n * @param {...Function} var_args A list of functions.\n * @return {!Function} A function that calls all inputs in sequence.\n */\ngoog.functions.sequence = function(var_args) {\n  'use strict';\n  const functions = arguments;\n  const length = functions.length;\n  return function() {\n    'use strict';\n    const self = /** @type {*} */ (this);\n    let result;\n    for (let i = 0; i < length; i++) {\n      result = functions[i].apply(self, arguments);\n    }\n    return result;\n  };\n};\n\n\n/**\n * Creates a function that returns true if each of its components evaluates\n * to true. The components are evaluated in order, and the evaluation will be\n * short-circuited as soon as a function returns false.\n * For example, (goog.functions.and(f, g))(x) is equivalent to f(x) && g(x).\n * @param {...Function} var_args A list of functions.\n * @return {function(...?):boolean} A function that ANDs its component\n *      functions.\n */\ngoog.functions.and = function(var_args) {\n  'use strict';\n  const functions = arguments;\n  const length = functions.length;\n  return function() {\n    'use strict';\n    const self = /** @type {*} */ (this);\n    for (let i = 0; i < length; i++) {\n      if (!functions[i].apply(self, arguments)) {\n        return false;\n      }\n    }\n    return true;\n  };\n};\n\n\n/**\n * Creates a function that returns true if any of its components evaluates\n * to true. The components are evaluated in order, and the evaluation will be\n * short-circuited as soon as a function returns true.\n * For example, (goog.functions.or(f, g))(x) is equivalent to f(x) || g(x).\n * @param {...Function} var_args A list of functions.\n * @return {function(...?):boolean} A function that ORs its component\n *    functions.\n */\ngoog.functions.or = function(var_args) {\n  'use strict';\n  const functions = arguments;\n  const length = functions.length;\n  return function() {\n    'use strict';\n    const self = /** @type {*} */ (this);\n    for (let i = 0; i < length; i++) {\n      if (functions[i].apply(self, arguments)) {\n        return true;\n      }\n    }\n    return false;\n  };\n};\n\n\n/**\n * Creates a function that returns the Boolean opposite of a provided function.\n * For example, (goog.functions.not(f))(x) is equivalent to !f(x).\n * @param {!Function} f The original function.\n * @return {function(...?):boolean} A function that delegates to f and returns\n * opposite.\n */\ngoog.functions.not = function(f) {\n  'use strict';\n  return function() {\n    'use strict';\n    const self = /** @type {*} */ (this);\n    return !f.apply(self, arguments);\n  };\n};\n\n\n/**\n * Generic factory function to construct an object given the constructor\n * and the arguments. Intended to be bound to create object factories.\n *\n * Example:\n *\n * var factory = goog.partial(goog.functions.create, Class);\n *\n * @param {function(new:T, ...)} constructor The constructor for the Object.\n * @param {...*} var_args The arguments to be passed to the constructor.\n * @return {T} A new instance of the class given in `constructor`.\n * @template T\n * @deprecated This function does not work with ES6 class constructors. Use\n *     arrow functions + spread args instead.\n */\ngoog.functions.create = function(constructor, var_args) {\n  'use strict';\n  /**\n   * @constructor\n   * @final\n   */\n  const temp = function() {};\n  temp.prototype = constructor.prototype;\n\n  // obj will have constructor's prototype in its chain and\n  // 'obj instanceof constructor' will be true.\n  const obj = new temp();\n\n  // obj is initialized by constructor.\n  // arguments is only array-like so lacks shift(), but can be used with\n  // the Array prototype function.\n  constructor.apply(obj, Array.prototype.slice.call(arguments, 1));\n  return obj;\n};\n\n\n/**\n * @define {boolean} Whether the return value cache should be used.\n *    This should only be used to disable caches when testing.\n */\ngoog.functions.CACHE_RETURN_VALUE =\n    goog.define('goog.functions.CACHE_RETURN_VALUE', true);\n\n\n/**\n * Gives a wrapper function that caches the return value of a parameterless\n * function when first called.\n *\n * When called for the first time, the given function is called and its\n * return value is cached (thus this is only appropriate for idempotent\n * functions).  Subsequent calls will return the cached return value. This\n * allows the evaluation of expensive functions to be delayed until first used.\n *\n * To cache the return values of functions with parameters, see goog.memoize.\n *\n * @param {function():T} fn A function to lazily evaluate.\n * @return {function():T} A wrapped version the function.\n * @template T\n */\ngoog.functions.cacheReturnValue = function(fn) {\n  'use strict';\n  let called = false;\n  let value;\n\n  return function() {\n    'use strict';\n    if (!goog.functions.CACHE_RETURN_VALUE) {\n      return fn();\n    }\n\n    if (!called) {\n      value = fn();\n      called = true;\n    }\n\n    return value;\n  };\n};\n\n\n/**\n * Wraps a function to allow it to be called, at most, once. All\n * additional calls are no-ops.\n *\n * This is particularly useful for initialization functions\n * that should be called, at most, once.\n *\n * @param {function():*} f Function to call.\n * @return {function():undefined} Wrapped function.\n */\ngoog.functions.once = function(f) {\n  'use strict';\n  // Keep a reference to the function that we null out when we're done with\n  // it -- that way, the function can be GC'd when we're done with it.\n  let inner = f;\n  return function() {\n    'use strict';\n    if (inner) {\n      const tmp = inner;\n      inner = null;\n      tmp();\n    }\n  };\n};\n\n\n/**\n * Wraps a function to allow it to be called, at most, once per interval\n * (specified in milliseconds). If the wrapper function is called N times within\n * that interval, only the Nth call will go through.\n *\n * This is particularly useful for batching up repeated actions where the\n * last action should win. This can be used, for example, for refreshing an\n * autocomplete pop-up every so often rather than updating with every keystroke,\n * since the final text typed by the user is the one that should produce the\n * final autocomplete results. For more stateful debouncing with support for\n * pausing, resuming, and canceling debounced actions, use\n * `goog.async.Debouncer`.\n *\n * @param {function(this:SCOPE, ...?)} f Function to call.\n * @param {number} interval Interval over which to debounce. The function will\n *     only be called after the full interval has elapsed since the last call.\n * @param {SCOPE=} opt_scope Object in whose scope to call the function.\n * @return {function(...?): undefined} Wrapped function.\n * @template SCOPE\n */\ngoog.functions.debounce = function(f, interval, opt_scope) {\n  'use strict';\n  let timeout = 0;\n  return /** @type {function(...?)} */ (function(var_args) {\n    'use strict';\n    goog.global.clearTimeout(timeout);\n    const args = arguments;\n    timeout = goog.global.setTimeout(function() {\n      'use strict';\n      f.apply(opt_scope, args);\n    }, interval);\n  });\n};\n\n\n/**\n * Wraps a function to allow it to be called, at most, once per interval\n * (specified in milliseconds). If the wrapper function is called N times in\n * that interval, both the 1st and the Nth calls will go through.\n *\n * This is particularly useful for limiting repeated user requests where the\n * the last action should win, but you also don't want to wait until the end of\n * the interval before sending a request out, as it leads to a perception of\n * slowness for the user.\n *\n * @param {function(this:SCOPE, ...?)} f Function to call.\n * @param {number} interval Interval over which to throttle. The function can\n *     only be called once per interval.\n * @param {SCOPE=} opt_scope Object in whose scope to call the function.\n * @return {function(...?): undefined} Wrapped function.\n * @template SCOPE\n */\ngoog.functions.throttle = function(f, interval, opt_scope) {\n  'use strict';\n  let timeout = 0;\n  let shouldFire = false;\n  let storedArgs = [];\n\n  const handleTimeout = function() {\n    'use strict';\n    timeout = 0;\n    if (shouldFire) {\n      shouldFire = false;\n      fire();\n    }\n  };\n\n  const fire = function() {\n    'use strict';\n    timeout = goog.global.setTimeout(handleTimeout, interval);\n    let args = storedArgs;\n    storedArgs = [];  // Avoid a space leak by clearing stored arguments.\n    f.apply(opt_scope, args);\n  };\n\n  return /** @type {function(...?)} */ (function(var_args) {\n    'use strict';\n    storedArgs = arguments;\n    if (!timeout) {\n      fire();\n    } else {\n      shouldFire = true;\n    }\n  });\n};\n\n\n/**\n * Wraps a function to allow it to be called, at most, once per interval\n * (specified in milliseconds). If the wrapper function is called N times within\n * that interval, only the 1st call will go through.\n *\n * This is particularly useful for limiting repeated user requests where the\n * first request is guaranteed to have all the data required to perform the\n * final action, so there's no need to wait until the end of the interval before\n * sending the request out.\n *\n * @param {function(this:SCOPE, ...?)} f Function to call.\n * @param {number} interval Interval over which to rate-limit. The function will\n *     only be called once per interval, and ignored for the remainer of the\n *     interval.\n * @param {SCOPE=} opt_scope Object in whose scope to call the function.\n * @return {function(...?): undefined} Wrapped function.\n * @template SCOPE\n */\ngoog.functions.rateLimit = function(f, interval, opt_scope) {\n  'use strict';\n  let timeout = 0;\n\n  const handleTimeout = function() {\n    'use strict';\n    timeout = 0;\n  };\n\n  return /** @type {function(...?)} */ (function(var_args) {\n    'use strict';\n    if (!timeout) {\n      timeout = goog.global.setTimeout(handleTimeout, interval);\n      f.apply(opt_scope, arguments);\n    }\n  });\n};\n\n/**\n * Returns true if the specified value is a function.\n * @param {*} val Variable to test.\n * @return {boolean} Whether variable is a function.\n */\ngoog.functions.isFunction = (val) => {\n  return typeof val === 'function';\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n\n/**\n * @fileoverview Utility to attempt native JSON processing, falling back to\n *     goog.json if not available.\n *\n *     This is intended as a drop-in for current users of goog.json who want\n *     to take advantage of native JSON if present.\n */\n\ngoog.provide('goog.json.hybrid');\n\ngoog.require('goog.asserts');\ngoog.require('goog.json');\n\n\n/**\n * Attempts to serialize the JSON string natively, falling back to\n * `goog.json.serialize` if unsuccessful.\n * @param {!Object} obj JavaScript object to serialize to JSON.\n * @return {string} Resulting JSON string.\n */\ngoog.json.hybrid.stringify = goog.json.USE_NATIVE_JSON ?\n    goog.global['JSON']['stringify'] :\n    function(obj) {\n      'use strict';\n      if (goog.global.JSON) {\n        try {\n          return goog.global.JSON.stringify(obj);\n        } catch (e) {\n          // Native serialization failed.  Fall through to retry with\n          // goog.json.serialize.\n        }\n      }\n\n      return goog.json.serialize(obj);\n    };\n\n\n/**\n * Attempts to parse the JSON string natively, falling back to\n * the supplied `fallbackParser` if unsuccessful.\n * @param {string} jsonString JSON string to parse.\n * @param {function(string):Object} fallbackParser Fallback JSON parser used\n *     if native\n * @return {?Object} Resulting JSON object.\n * @private\n */\ngoog.json.hybrid.parse_ = function(jsonString, fallbackParser) {\n  'use strict';\n  if (goog.global.JSON) {\n    try {\n      var obj = goog.global.JSON.parse(jsonString);\n      goog.asserts.assert(typeof obj == 'object');\n      return /** @type {?Object} */ (obj);\n    } catch (e) {\n      // Native parse failed.  Fall through to retry with goog.json.parse.\n    }\n  }\n\n  return fallbackParser(jsonString);\n};\n\n\n/**\n * Attempts to parse the JSON string natively, falling back to\n * `goog.json.parse` if unsuccessful.\n * @param {string} jsonString JSON string to parse.\n * @return {?Object} Resulting JSON object.\n */\ngoog.json.hybrid.parse = goog.json.USE_NATIVE_JSON ?\n    goog.global['JSON']['parse'] :\n    function(jsonString) {\n      'use strict';\n      return goog.json.hybrid.parse_(jsonString, goog.json.parse);\n    };\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Constants for HTTP status codes.\n */\n\ngoog.provide('goog.net.HttpStatus');\n\n\n/**\n * HTTP Status Codes defined in RFC 2616, RFC 6585, RFC 4918 and RFC 7538.\n * @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html\n * @see http://tools.ietf.org/html/rfc6585\n * @see https://tools.ietf.org/html/rfc4918\n * @see https://tools.ietf.org/html/rfc7538\n * @enum {number}\n */\ngoog.net.HttpStatus = {\n  // Informational 1xx\n  CONTINUE: 100,\n  SWITCHING_PROTOCOLS: 101,\n\n  // Successful 2xx\n  OK: 200,\n  CREATED: 201,\n  ACCEPTED: 202,\n  NON_AUTHORITATIVE_INFORMATION: 203,\n  NO_CONTENT: 204,\n  RESET_CONTENT: 205,\n  PARTIAL_CONTENT: 206,\n  MULTI_STATUS: 207,\n\n  // Redirection 3xx\n  MULTIPLE_CHOICES: 300,\n  MOVED_PERMANENTLY: 301,\n  FOUND: 302,\n  SEE_OTHER: 303,\n  NOT_MODIFIED: 304,\n  USE_PROXY: 305,\n  TEMPORARY_REDIRECT: 307,\n  PERMANENT_REDIRECT: 308,\n\n  // Client Error 4xx\n  BAD_REQUEST: 400,\n  UNAUTHORIZED: 401,\n  PAYMENT_REQUIRED: 402,\n  FORBIDDEN: 403,\n  NOT_FOUND: 404,\n  METHOD_NOT_ALLOWED: 405,\n  NOT_ACCEPTABLE: 406,\n  PROXY_AUTHENTICATION_REQUIRED: 407,\n  REQUEST_TIMEOUT: 408,\n  CONFLICT: 409,\n  GONE: 410,\n  LENGTH_REQUIRED: 411,\n  PRECONDITION_FAILED: 412,\n  REQUEST_ENTITY_TOO_LARGE: 413,\n  REQUEST_URI_TOO_LONG: 414,\n  UNSUPPORTED_MEDIA_TYPE: 415,\n  REQUEST_RANGE_NOT_SATISFIABLE: 416,\n  EXPECTATION_FAILED: 417,\n  UNPROCESSABLE_ENTITY: 422,\n  LOCKED: 423,\n  FAILED_DEPENDENCY: 424,\n  PRECONDITION_REQUIRED: 428,\n  TOO_MANY_REQUESTS: 429,\n  REQUEST_HEADER_FIELDS_TOO_LARGE: 431,\n  CLIENT_CLOSED_REQUEST: 499,  // Nonstandard, used by GRPC\n\n  // Server Error 5xx\n  INTERNAL_SERVER_ERROR: 500,\n  NOT_IMPLEMENTED: 501,\n  BAD_GATEWAY: 502,\n  SERVICE_UNAVAILABLE: 503,\n  GATEWAY_TIMEOUT: 504,\n  HTTP_VERSION_NOT_SUPPORTED: 505,\n  INSUFFICIENT_STORAGE: 507,\n  NETWORK_AUTHENTICATION_REQUIRED: 511,\n\n  /*\n   * IE returns this code for 204 due to its use of URLMon, which returns this\n   * code for 'Operation Aborted'. The status text is 'Unknown', the response\n   * headers are ''. Known to occur on IE 6 on XP through IE9 on Win7.\n   */\n  QUIRK_IE_NO_CONTENT: 1223,\n};\n\n\n/**\n * Returns whether the given status should be considered successful.\n *\n * Successful codes are OK (200), CREATED (201), ACCEPTED (202),\n * NO CONTENT (204), PARTIAL CONTENT (206), NOT MODIFIED (304),\n * and IE's no content code (1223).\n *\n * @param {number} status The status code to test.\n * @return {boolean} Whether the status code should be considered successful.\n */\ngoog.net.HttpStatus.isSuccess = function(status) {\n  'use strict';\n  switch (status) {\n    case goog.net.HttpStatus.OK:\n    case goog.net.HttpStatus.CREATED:\n    case goog.net.HttpStatus.ACCEPTED:\n    case goog.net.HttpStatus.NO_CONTENT:\n    case goog.net.HttpStatus.PARTIAL_CONTENT:\n    case goog.net.HttpStatus.NOT_MODIFIED:\n    case goog.net.HttpStatus.QUIRK_IE_NO_CONTENT:\n      return true;\n\n    default:\n      return false;\n  }\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Provides CORS support for HTTP based RPC requests.\n *\n * As part of net.rpc package, CORS features provided by this class\n * depend on the server support. Please check related specs to decide how\n * to enable any of the features provided by this class.\n */\n\ngoog.module('goog.net.rpc.HttpCors');\n\nconst GoogUri = goog.require('goog.Uri');\nconst googObject = goog.require('goog.object');\nconst googString = goog.require('goog.string');\nconst googUriUtils = goog.require('goog.uri.utils');\n\n\n/**\n * The default URL parameter name to overwrite http headers with a URL param\n * to avoid CORS preflight.\n *\n * See https://github.com/whatwg/fetch/issues/210#issue-129531743 for the spec.\n *\n * @type {string}\n */\nexports.HTTP_HEADERS_PARAM_NAME = '$httpHeaders';\n\n\n/**\n * The default URL parameter name to overwrite http method with a URL param\n * to avoid CORS preflight.\n *\n * See https://github.com/whatwg/fetch/issues/210#issue-129531743 for the spec.\n *\n * @type {string}\n */\nexports.HTTP_METHOD_PARAM_NAME = '$httpMethod';\n\n\n/**\n * Generates the URL parameter value with custom headers encoded as\n * HTTP/1.1 headers block.\n *\n * @param {!Object<string, string>} headers The custom headers.\n * @return {string} The URL param to overwrite custom HTTP headers.\n */\nexports.generateHttpHeadersOverwriteParam = function(headers) {\n  let result = '';\n  googObject.forEach(headers, function(value, key) {\n    result += key;\n    result += ':';\n    result += value;\n    result += '\\r\\n';\n  });\n  return result;\n};\n\n\n/**\n * Generates the URL-encoded URL parameter value with custom headers encoded as\n * HTTP/1.1 headers block.\n *\n * @param {!Object<string, string>} headers The custom headers.\n * @return {string} The URL param to overwrite custom HTTP headers.\n */\nexports.generateEncodedHttpHeadersOverwriteParam = function(headers) {\n  return googString.urlEncode(\n      exports.generateHttpHeadersOverwriteParam(headers));\n};\n\n\n/**\n * Sets custom HTTP headers via an overwrite URL param.\n *\n * @param {!GoogUri|string} url The URI object or a string path.\n * @param {string} urlParam The URL param name.\n * @param {!Object<string, string>} extraHeaders The HTTP headers.\n * @return {!GoogUri|string} The URI object or a string path with headers\n * encoded as a url param.\n */\nexports.setHttpHeadersWithOverwriteParam = function(\n    url, urlParam, extraHeaders) {\n  if (googObject.isEmpty(extraHeaders)) {\n    return url;\n  }\n  const httpHeaders = exports.generateHttpHeadersOverwriteParam(extraHeaders);\n  if (typeof url === 'string') {\n    return googUriUtils.appendParam(\n        url, googString.urlEncode(urlParam), httpHeaders);\n  } else {\n    url.setParameterValue(urlParam, httpHeaders);  // duplicate removed!\n    return url;\n  }\n};\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Transport support for WebChannel.\n *\n * The <code>WebChannelTransport</code> implementation serves as the factory\n * for <code>WebChannel</code>, which offers an abstraction for\n * point-to-point socket-like communication similar to what BrowserChannel\n * or HTML5 WebSocket offers.\n */\n\ngoog.provide('goog.net.WebChannelTransport');\n\ngoog.requireType('goog.net.WebChannel');\ngoog.requireType('goog.net.WebChannel.Options');\n\n\n\n/**\n * A WebChannelTransport instance represents a shared context of logical\n * connectivity between a browser client and a remote origin.\n *\n * Over a single WebChannelTransport instance, multiple WebChannels may be\n * created against different URLs, which may all share the same\n * underlying connectivity (i.e. TCP connection) whenever possible.\n *\n * When multi-domains are supported, such as CORS, multiple origins may be\n * supported over a single WebChannelTransport instance at the same time.\n *\n * Sharing between different window contexts such as tabs is not addressed\n * by WebChannelTransport. Applications may choose HTML5 shared workers\n * or other techniques to access the same transport instance\n * across different window contexts.\n *\n * @interface\n */\ngoog.net.WebChannelTransport = function() {};\n\n\n/**\n * The client version. This integer value will be passed to the server\n * when a channel is opened to inform the server the client \"capabilities\".\n *\n * Wire protocol version is a different concept and is internal to the\n * transport implementation.\n *\n * @const\n * @type {number}\n */\ngoog.net.WebChannelTransport.CLIENT_VERSION = 22;\n\n\n/**\n * Create a new WebChannel instance.\n *\n * The new WebChannel is to be opened against the server-side resource\n * as specified by the given URL. See {@link goog.net.WebChannel} for detailed\n * semantics.\n *\n * @param {string} url The URL path for the new WebChannel instance.\n * @param {!goog.net.WebChannel.Options=} opt_options Configuration for the\n *     new WebChannel instance. The configuration object is reusable after\n *     the new channel instance is created.\n * @return {!goog.net.WebChannel} the newly created WebChannel instance.\n */\ngoog.net.WebChannelTransport.prototype.createWebChannel = goog.abstractMethod;\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Implementation of a WebChannel transport using WebChannelBase.\n *\n * When WebChannelBase is used as the underlying transport, the capabilities\n * of the WebChannel are limited to what's supported by the implementation.\n * Particularly, multiplexing is not possible, and only strings are\n * supported as message types.\n */\n\ngoog.provide('goog.labs.net.webChannel.WebChannelBaseTransport');\n\ngoog.require('goog.asserts');\ngoog.require('goog.collections.maps');\ngoog.require('goog.events.EventTarget');\ngoog.require('goog.json');\ngoog.require('goog.labs.net.webChannel.ChannelRequest');\ngoog.require('goog.labs.net.webChannel.WebChannelBase');\ngoog.require('goog.labs.net.webChannel.Wire');\ngoog.require('goog.log');\ngoog.require('goog.net.WebChannel');\ngoog.require('goog.net.WebChannelTransport');\ngoog.require('goog.object');\ngoog.require('goog.string');\n\n\n\n/**\n * Implementation of {@link goog.net.WebChannelTransport} with\n * {@link goog.labs.net.webChannel.WebChannelBase} as the underlying channel\n * implementation.\n *\n * @constructor\n * @struct\n * @implements {goog.net.WebChannelTransport}\n * @final\n */\ngoog.labs.net.webChannel.WebChannelBaseTransport = function() {\n  'use strict';\n  if (!goog.labs.net.webChannel.ChannelRequest.supportsXhrStreaming()) {\n    throw new Error('Environmental error: no available transport.');\n  }\n};\n\n\ngoog.scope(function() {\n'use strict';\nconst WebChannelBaseTransport =\n    goog.labs.net.webChannel.WebChannelBaseTransport;\nconst WebChannelBase = goog.labs.net.webChannel.WebChannelBase;\nconst Wire = goog.labs.net.webChannel.Wire;\n\n\n/**\n * @override\n */\nWebChannelBaseTransport.prototype.createWebChannel = function(\n    url, opt_options) {\n  'use strict';\n  return new WebChannelBaseTransport.Channel(url, opt_options);\n};\n\n\n\n/**\n * Implementation of the {@link goog.net.WebChannel} interface.\n *\n * @param {string} url The URL path for the new WebChannel instance.\n * @param {!goog.net.WebChannel.Options=} opt_options Configuration for the\n *     new WebChannel instance.\n *\n * @constructor\n * @implements {goog.net.WebChannel}\n * @extends {goog.events.EventTarget}\n * @final\n */\nWebChannelBaseTransport.Channel = function(url, opt_options) {\n  'use strict';\n  WebChannelBaseTransport.Channel.base(this, 'constructor');\n\n  /**\n   * @private {!WebChannelBase} The underlying channel object.\n   */\n  this.channel_ = new WebChannelBase(\n      opt_options, goog.net.WebChannelTransport.CLIENT_VERSION);\n\n  /**\n   * @private {string} The URL of the target server end-point.\n   */\n  this.url_ = url;\n\n  /**\n   * @private {goog.log.Logger} The logger for this class.\n   */\n  this.logger_ =\n      goog.log.getLogger('goog.labs.net.webChannel.WebChannelBaseTransport');\n\n  /**\n   * @private {Object<string, string>} Extra URL parameters\n   * to be added to each HTTP request.\n   */\n  this.messageUrlParams_ =\n      (opt_options && opt_options.messageUrlParams) || null;\n\n  let messageHeaders = (opt_options && opt_options.messageHeaders) || null;\n\n  // default is false\n  if (opt_options && opt_options.clientProtocolHeaderRequired) {\n    if (messageHeaders) {\n      goog.object.set(\n          messageHeaders, goog.net.WebChannel.X_CLIENT_PROTOCOL,\n          goog.net.WebChannel.X_CLIENT_PROTOCOL_WEB_CHANNEL);\n    } else {\n      messageHeaders = goog.object.create(\n          goog.net.WebChannel.X_CLIENT_PROTOCOL,\n          goog.net.WebChannel.X_CLIENT_PROTOCOL_WEB_CHANNEL);\n    }\n  }\n\n  this.channel_.setExtraHeaders(messageHeaders);\n\n  let initHeaders = (opt_options && opt_options.initMessageHeaders) || null;\n\n  if (opt_options && opt_options.messageContentType) {\n    if (initHeaders) {\n      goog.object.set(\n          initHeaders, goog.net.WebChannel.X_WEBCHANNEL_CONTENT_TYPE,\n          opt_options.messageContentType);\n    } else {\n      initHeaders = goog.object.create(\n          goog.net.WebChannel.X_WEBCHANNEL_CONTENT_TYPE,\n          opt_options.messageContentType);\n    }\n  }\n\n  if (opt_options && opt_options.clientProfile) {\n    if (initHeaders) {\n      goog.object.set(\n          initHeaders, goog.net.WebChannel.X_WEBCHANNEL_CLIENT_PROFILE,\n          opt_options.clientProfile);\n    } else {\n      initHeaders = goog.object.create(\n          goog.net.WebChannel.X_WEBCHANNEL_CLIENT_PROFILE,\n          opt_options.clientProfile);\n    }\n  }\n\n  this.channel_.setInitHeaders(initHeaders);\n\n  const httpHeadersOverwriteParam =\n      opt_options && opt_options.httpHeadersOverwriteParam;\n  if (httpHeadersOverwriteParam &&\n      !goog.string.isEmptyOrWhitespace(httpHeadersOverwriteParam)) {\n    this.channel_.setHttpHeadersOverwriteParam(httpHeadersOverwriteParam);\n  }\n\n  /**\n   * @private {boolean} Whether to enable CORS.\n   */\n  this.supportsCrossDomainXhr_ =\n      (opt_options && opt_options.supportsCrossDomainXhr) || false;\n\n  /**\n   * @private {boolean} Whether to send raw Json and bypass v8 wire format.\n   */\n  this.sendRawJson_ = (opt_options && opt_options.sendRawJson) || false;\n\n  // Note that httpSessionIdParam will be ignored if the same parameter name\n  // has already been specified with messageUrlParams\n  const httpSessionIdParam = opt_options && opt_options.httpSessionIdParam;\n  if (httpSessionIdParam &&\n      !goog.string.isEmptyOrWhitespace(httpSessionIdParam)) {\n    this.channel_.setHttpSessionIdParam(httpSessionIdParam);\n    if (goog.object.containsKey(this.messageUrlParams_, httpSessionIdParam)) {\n      goog.object.remove(this.messageUrlParams_, httpSessionIdParam);\n      goog.log.warning(\n          this.logger_,\n          'Ignore httpSessionIdParam also specified with messageUrlParams: ' +\n              httpSessionIdParam);\n    }\n  }\n\n  /**\n   * The channel handler.\n   *\n   * @private {!WebChannelBaseTransport.Channel.Handler_}\n   */\n  this.channelHandler_ = new WebChannelBaseTransport.Channel.Handler_(this);\n};\ngoog.inherits(WebChannelBaseTransport.Channel, goog.events.EventTarget);\n\n\n/**\n * @override\n */\nWebChannelBaseTransport.Channel.prototype.open = function() {\n  'use strict';\n  this.channel_.setHandler(this.channelHandler_);\n  if (this.supportsCrossDomainXhr_) {\n    this.channel_.setSupportsCrossDomainXhrs(true);\n  }\n  this.channel_.connect(this.url_, (this.messageUrlParams_ || undefined));\n};\n\n\n/**\n * @override\n */\nWebChannelBaseTransport.Channel.prototype.close = function() {\n  'use strict';\n  this.channel_.disconnect();\n};\n\n\n/**\n * @override\n */\nWebChannelBaseTransport.Channel.prototype.halfClose = function() {\n  'use strict';\n  // to be implemented\n  throw new Error('Not implemented');\n};\n\n\n/**\n * The WebChannelBase only supports object types.\n *\n * @param {!goog.net.WebChannel.MessageData} message The message to send.\n *\n * @override\n */\nWebChannelBaseTransport.Channel.prototype.send = function(message) {\n  'use strict';\n  this.channel_.sendMap(this.messageToMapObject_(message));\n};\n\n\n/**\n * Converts a message to the map used by the underlying channel.\n *\n * @param {!goog.net.WebChannel.MessageData} message\n * @return {!Object|!goog.collections.maps.MapLike}\n */\nWebChannelBaseTransport.Channel.prototype.messageToMapObject_ = function(\n    message) {\n  'use strict';\n  goog.asserts.assert(\n      goog.isObject(message) || typeof message === 'string',\n      'only object type or raw string is supported');\n\n  if (typeof message === 'string') {\n    const rawJson = {};\n    rawJson[Wire.RAW_DATA_KEY] = message;\n    return rawJson;\n  }\n\n  if (this.sendRawJson_) {\n    const rawJson = {};\n    rawJson[Wire.RAW_DATA_KEY] = goog.json.serialize(message);\n    return rawJson;\n  }\n\n  return message;\n};\n\n\n/**\n * Converts the map used by the underlying channel to a message.\n *\n * NOTE: In the case of the message being JS Object or string, the exact same\n * object passed during `messageToMapObject_()` is returned. In the case of raw\n * JSON, an equal (but not the same) object is returned (due to serialization).\n *\n * @param {!Object|!goog.collections.maps.MapLike} map\n * @return {!goog.net.WebChannel.MessageData}\n */\nWebChannelBaseTransport.Channel.prototype.mapObjectToMessage_ = function(map) {\n  'use strict';\n  if (Wire.RAW_DATA_KEY in map) {\n    const rawMessage = map[Wire.RAW_DATA_KEY];\n\n    if (this.sendRawJson_) {\n      return /** @type {!goog.net.WebChannel.MessageData} */ (\n          goog.json.parse(rawMessage));\n    } else {  // string message\n      return rawMessage;\n    }\n  }\n\n  return map;\n};\n\n\n/**\n * @override\n */\nWebChannelBaseTransport.Channel.prototype.disposeInternal = function() {\n  'use strict';\n  this.channel_.setHandler(null);\n  delete this.channelHandler_;\n  this.channel_.disconnect();\n  delete this.channel_;\n\n  WebChannelBaseTransport.Channel.base(this, 'disposeInternal');\n};\n\n\n\n/**\n * The message event.\n *\n * @param {!Array<?>|!Object} array The data array from the underlying channel.\n * @constructor\n * @extends {goog.net.WebChannel.MessageEvent}\n * @final\n */\nWebChannelBaseTransport.Channel.MessageEvent = function(array) {\n  'use strict';\n  WebChannelBaseTransport.Channel.MessageEvent.base(this, 'constructor');\n\n  // single-metadata only\n  const metadata = array['__sm__'];\n  if (metadata) {\n    this.metadataKey = goog.object.getAnyKey(metadata);\n    if (this.metadataKey) {\n      this.data = goog.object.get(metadata, this.metadataKey);\n    } else {\n      this.data = metadata;  // empty\n    }\n  } else {\n    this.data = array;\n  }\n};\ngoog.inherits(\n    WebChannelBaseTransport.Channel.MessageEvent,\n    goog.net.WebChannel.MessageEvent);\n\n\n\n/**\n * The error event.\n *\n * @param {WebChannelBase.Error} error The error code.\n * @constructor\n * @extends {goog.net.WebChannel.ErrorEvent}\n * @final\n */\nWebChannelBaseTransport.Channel.ErrorEvent = function(error) {\n  'use strict';\n  WebChannelBaseTransport.Channel.ErrorEvent.base(this, 'constructor');\n\n  /**\n   * High-level status code.\n   */\n  this.status = goog.net.WebChannel.ErrorStatus.NETWORK_ERROR;\n\n  /**\n   * @const {WebChannelBase.Error} Internal error code, for debugging use only.\n   */\n  this.errorCode = error;\n};\ngoog.inherits(\n    WebChannelBaseTransport.Channel.ErrorEvent, goog.net.WebChannel.ErrorEvent);\n\n\n\n/**\n * Implementation of {@link WebChannelBase.Handler} interface.\n *\n * @param {!WebChannelBaseTransport.Channel} channel The enclosing WebChannel.\n *\n * @constructor\n * @extends {WebChannelBase.Handler}\n * @private\n */\nWebChannelBaseTransport.Channel.Handler_ = function(channel) {\n  'use strict';\n  WebChannelBaseTransport.Channel.Handler_.base(this, 'constructor');\n\n  /**\n   * @type {!WebChannelBaseTransport.Channel}\n   * @private\n   */\n  this.channel_ = channel;\n};\ngoog.inherits(WebChannelBaseTransport.Channel.Handler_, WebChannelBase.Handler);\n\n\n/**\n * @override\n */\nWebChannelBaseTransport.Channel.Handler_.prototype.channelOpened = function(\n    channel) {\n  'use strict';\n  goog.log.info(\n      this.channel_.logger_, 'WebChannel opened on ' + this.channel_.url_);\n  this.channel_.dispatchEvent(goog.net.WebChannel.EventType.OPEN);\n};\n\n\n/**\n * @override\n */\nWebChannelBaseTransport.Channel.Handler_.prototype.channelHandleArray =\n    function(channel, array) {\n  'use strict';\n  goog.asserts.assert(array, 'array expected to be defined');\n  this.channel_.dispatchEvent(\n      new WebChannelBaseTransport.Channel.MessageEvent(array));\n};\n\n\n/**\n * @override\n */\nWebChannelBaseTransport.Channel.Handler_.prototype.channelError = function(\n    channel, error) {\n  'use strict';\n  goog.log.info(\n      this.channel_.logger_,\n      'WebChannel aborted on ' + this.channel_.url_ +\n          ' due to channel error: ' + error);\n  this.channel_.dispatchEvent(\n      new WebChannelBaseTransport.Channel.ErrorEvent(error));\n};\n\n\n/**\n * @override\n */\nWebChannelBaseTransport.Channel.Handler_.prototype.channelClosed = function(\n    channel, opt_pendingMaps, opt_undeliveredMaps) {\n  'use strict';\n  goog.log.info(\n      this.channel_.logger_, 'WebChannel closed on ' + this.channel_.url_);\n  this.channel_.dispatchEvent(goog.net.WebChannel.EventType.CLOSE);\n};\n\n\n/**\n * @override\n */\nWebChannelBaseTransport.Channel.prototype.getRuntimeProperties = function() {\n  'use strict';\n  return new WebChannelBaseTransport.ChannelProperties(this, this.channel_);\n};\n\n\n\n/**\n * Implementation of the {@link goog.net.WebChannel.RuntimeProperties}.\n *\n * @param {!WebChannelBaseTransport.Channel} transportChannel The transport\n *     channel object.\n * @param {!WebChannelBase} channel The underlying channel object.\n *\n * @constructor\n * @implements {goog.net.WebChannel.RuntimeProperties}\n * @final\n */\nWebChannelBaseTransport.ChannelProperties = function(\n    transportChannel, channel) {\n  'use strict';\n  /**\n   * The transport channel object.\n   *\n   * @private @const {!WebChannelBaseTransport.Channel}\n   */\n  this.transportChannel_ = transportChannel;\n\n  /**\n   * The underlying channel object.\n   *\n   * @private @const {!WebChannelBase}\n   */\n  this.channel_ = channel;\n};\n\n\n/**\n * @override\n */\nWebChannelBaseTransport.ChannelProperties.prototype.getConcurrentRequestLimit =\n    function() {\n  'use strict';\n  return this.channel_.getForwardChannelRequestPool().getMaxSize();\n};\n\n\n/**\n * @override\n */\nWebChannelBaseTransport.ChannelProperties.prototype.isSpdyEnabled = function() {\n  'use strict';\n  return this.getConcurrentRequestLimit() > 1;\n};\n\n\n/**\n * @override\n */\nWebChannelBaseTransport.ChannelProperties.prototype.getPendingRequestCount =\n    function() {\n  'use strict';\n  return this.channel_.getForwardChannelRequestPool().getRequestCount();\n};\n\n\n/**\n * @override\n * @return {!Array<!goog.net.WebChannel.MessageData>}\n */\nWebChannelBaseTransport.ChannelProperties.prototype.getNonAckedMessages =\n    function() {\n  'use strict';\n  return this.channel_.getNonAckedMaps().map(\n      queued_map => this.transportChannel_.mapObjectToMessage_(queued_map.map));\n};\n\n\n/**\n * @override\n */\nWebChannelBaseTransport.ChannelProperties.prototype.getHttpSessionId =\n    function() {\n  'use strict';\n  return this.channel_.getHttpSessionId();\n};\n\n\n/**\n * @override\n */\nWebChannelBaseTransport.ChannelProperties.prototype.commit = function(\n    callback) {\n  'use strict';\n  this.channel_.setForwardChannelFlushCallback(callback);\n};\n\n\n/**\n * @override\n */\nWebChannelBaseTransport.ChannelProperties.prototype.notifyNonAckedMessageCount =\n    goog.abstractMethod;\n\n\n/**\n * @override\n */\nWebChannelBaseTransport.ChannelProperties.prototype.onCommit =\n    goog.abstractMethod;\n\n\n/**\n * @override\n */\nWebChannelBaseTransport.ChannelProperties.prototype.ackCommit =\n    goog.abstractMethod;\n\n\n/** @override */\nWebChannelBaseTransport.ChannelProperties.prototype.getLastStatusCode =\n    function() {\n  'use strict';\n  return this.channel_.getLastStatusCode();\n};\n});  // goog.scope\n","/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Bring in closure-library dependencies\n */\n\ngoog.provide('firebase.webchannel.wrapper');\n\n// goog.net.WebChannelTransport\ngoog.require('goog.net.createWebChannelTransport');\ngoog.require('goog.net.FetchXmlHttpFactory');\ngoog.require('goog.labs.net.webChannel.requestStats');\ngoog.require('goog.labs.net.webChannel.WebChannelBaseTransport');\n\n/**\n * NOTE: The `createWebChannel` function takes an options object as a second param\n * whose properties are typically mangled. We override these in externs/overrides.js\n * Without those externs, this does not function properly.\n */\ngoog.labs.net.webChannel.WebChannelBaseTransport.prototype['createWebChannel'] =\n  goog.labs.net.webChannel.WebChannelBaseTransport.prototype.createWebChannel;\ngoog.labs.net.webChannel.WebChannelBaseTransport.Channel.prototype['send'] =\n  goog.labs.net.webChannel.WebChannelBaseTransport.Channel.prototype.send;\ngoog.labs.net.webChannel.WebChannelBaseTransport.Channel.prototype['open'] =\n  goog.labs.net.webChannel.WebChannelBaseTransport.Channel.prototype.open;\ngoog.labs.net.webChannel.WebChannelBaseTransport.Channel.prototype['close'] =\n  goog.labs.net.webChannel.WebChannelBaseTransport.Channel.prototype.close;\n\n// goog.net.ErrorCode\ngoog.require('goog.net.ErrorCode');\ngoog.net.ErrorCode['NO_ERROR'] = goog.net.ErrorCode.NO_ERROR;\ngoog.net.ErrorCode['TIMEOUT'] = goog.net.ErrorCode.TIMEOUT;\ngoog.net.ErrorCode['HTTP_ERROR'] = goog.net.ErrorCode.HTTP_ERROR;\n\n// goog.net.ErrorType\ngoog.require('goog.net.EventType');\ngoog.net.EventType['COMPLETE'] = goog.net.EventType.COMPLETE;\n\n// goog.net.WebChannel\ngoog.require('goog.net.WebChannel');\ngoog.require('goog.events.EventTarget');\ngoog.net.WebChannel['EventType'] = goog.net.WebChannel.EventType;\ngoog.net.WebChannel.EventType['OPEN'] = goog.net.WebChannel.EventType.OPEN;\ngoog.net.WebChannel.EventType['CLOSE'] = goog.net.WebChannel.EventType.CLOSE;\ngoog.net.WebChannel.EventType['ERROR'] = goog.net.WebChannel.EventType.ERROR;\ngoog.net.WebChannel.EventType['MESSAGE'] =\n  goog.net.WebChannel.EventType.MESSAGE;\ngoog.events.EventTarget.prototype['listen'] =\n  goog.events.EventTarget.prototype.listen;\n\ngoog.require('goog.net.XhrIo');\ngoog.net.XhrIo.prototype['listenOnce'] = goog.net.XhrIo.prototype.listenOnce;\ngoog.net.XhrIo.prototype['getLastError'] =\n  goog.net.XhrIo.prototype.getLastError;\ngoog.net.XhrIo.prototype['getLastErrorCode'] =\n  goog.net.XhrIo.prototype.getLastErrorCode;\ngoog.net.XhrIo.prototype['getStatus'] = goog.net.XhrIo.prototype.getStatus;\ngoog.net.XhrIo.prototype['getResponseJson'] =\n  goog.net.XhrIo.prototype.getResponseJson;\ngoog.net.XhrIo.prototype['getResponseText'] =\n  goog.net.XhrIo.prototype.getResponseText;\ngoog.net.XhrIo.prototype['send'] = goog.net.XhrIo.prototype.send;\ngoog.net.XhrIo.prototype['setWithCredentials'] =\n  goog.net.XhrIo.prototype.setWithCredentials;\n\nmodule['exports']['createWebChannelTransport'] =\n  goog.net.createWebChannelTransport;\nmodule['exports']['getStatEventTarget'] =\n  goog.labs.net.webChannel.requestStats.getStatEventTarget;\nmodule['exports']['ErrorCode'] = goog.net.ErrorCode;\nmodule['exports']['EventType'] = goog.net.EventType;\nmodule['exports']['Event'] = goog.labs.net.webChannel.requestStats.Event;\nmodule['exports']['Stat'] = goog.labs.net.webChannel.requestStats.Stat;\nmodule['exports']['FetchXmlHttpFactory'] = goog.net.FetchXmlHttpFactory;\nmodule['exports']['WebChannel'] = goog.net.WebChannel;\nmodule['exports']['XhrIo'] = goog.net.XhrIo;\n","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Default factory for <code>WebChannelTransport</code> to\n * avoid exposing concrete classes to clients.\n */\n\ngoog.provide('goog.net.createWebChannelTransport');\n\ngoog.require('goog.labs.net.webChannel.WebChannelBaseTransport');\ngoog.requireType('goog.net.WebChannelTransport');\n\n\n/**\n * Create a new WebChannelTransport instance using the default implementation.\n * Throws an error message if no default transport available in the current\n * environment.\n *\n * @return {!goog.net.WebChannelTransport} the newly created transport instance.\n */\ngoog.net.createWebChannelTransport = function() {\n  'use strict';\n  return new goog.labs.net.webChannel.WebChannelBaseTransport();\n};\n"],"names":["goog","goog.global","this","self","goog.nullFunction","goog.isArrayLike","val","s","Array","isArray","type","length","goog.isObject","goog.getUid","obj","Object","prototype","hasOwnProperty","call","goog.UID_PROPERTY_","goog.uidCounter_","Math","random","goog.bindNative_","fn","selfObj","var_args","apply","bind","arguments","goog.bindJs_","boundArgs","slice","newArgs","unshift","goog.bind","Function","toString","indexOf","goog.bind.apply","goog.partial","args","push","goog.inherits","childCtor","parentCtor","tempCtor","superClass_","constructor","base","childCtor.base","me","methodName","i","goog.Disposable","disposed_","onDisposeCallbacks_","OFF","dispose","goog.Disposable.prototype.dispose","disposeInternal","goog.Disposable.MONITORING_MODE","goog.Disposable.MonitoringMode.OFF","goog.Disposable.prototype.disposeInternal","shift","arr","opt_fromIndex","fromIndex","toArray","object","rv","extend","arr1","arr2","len1","len2","j","goog.events.Event","opt_target","currentTarget","target","defaultPrevented","preventDefault","goog.events.Event.prototype.preventDefault","PASSIVE_EVENTS","goog.global.addEventListener","addEventListener","defineProperty","passive","options","get","goog.global.removeEventListener","removeEventListener","e","goog.string.internal.isEmptyOrWhitespace","str","test","goog.string.internal.trim","String","trim","exec","goog.string.internal.compareElements_","left","right","getNativeUserAgentString","navigator","goog.global.navigator","userAgent","matchUserAgent","goog.reflect.sinkValue","x","goog.reflect.cache","valueFn","cacheObj","goog.userAgent.isVersionOrHigherCache_","version","goog.userAgent.OPERA","goog.userAgent.IE","goog.userAgent.EDGE","goog.userAgent.EDGE_OR_IE","goog.userAgent.GECKO","toLowerCase","subString","goog.userAgent.WEBKIT","goog.userAgent.getDocumentMode_","doc","undefined","goog.userAgent.VERSION","goog.userAgent.getVersionRegexResult_","docMode","parseFloat","goog.userAgent.isVersionOrHigher","order","v1Subs","split","v2Subs","subCount","max","subIdx","v1Sub","v2Sub","v1Comp","v2Comp","v1CompNum","parseInt","v2CompNum","documentMode","ieVersion","goog.userAgent.DOCUMENT_MODE","goog.events.BrowserEvent","opt_e","opt_currentTarget","goog.events.Event.call","goog.events.BrowserEvent.base","relatedTarget","button","screenY","screenX","clientY","clientX","key","metaKey","shiftKey","altKey","ctrlKey","state","pointerId","pointerType","event_","init","relevantTouch","changedTouches","srcElement","MOUSEOVER","fromElement","MOUSEOUT","toElement","pageX","pageY","goog.events.BrowserEvent.IE_POINTER_TYPE_MAP","goog.events.BrowserEvent.superClass_.preventDefault.call","arg","TOUCH","PEN","MOUSE","goog.events.BrowserEvent.prototype.preventDefault","be","returnValue","goog.events.Listenable.IMPLEMENTED_BY_PROP","goog.events.ListenableKey.counter_","goog.events.Listener","listener","src","capture","opt_handler","proxy","handler","removed","callOnce","goog.events.Listener.prototype.markAsRemoved","forEach","f","opt_obj","clone","res","PROTOTYPE_FIELDS","source","goog.events.ListenerMap","listeners","typeCount_","add","goog.events.ListenerMap.prototype.add","opt_useCapture","opt_listenerScope","typeStr","listenerArray","index","goog.events.ListenerMap.findListenerIndex_","listenerObj","goog.events.ListenerMap.prototype.removeByKey","splice","markAsRemoved","goog.events.LISTENER_MAP_PROP_","goog.events.onStringMap_","goog.events.listen","opt_options","once","goog.events.wrapListener","listen","goog.events.listen_","Error","listenerMap","goog.events.getListenerMap_","goog.events.getProxy","goog.events.BrowserFeature.PASSIVE_EVENTS","attachEvent","goog.events.getOnString_","addListener","removeListener","eventObject","proxyCallbackFunction","goog.events.handleBrowserEvent_","goog.events.listenOnce","listenOnce","goog.events.unlisten","eventTargetListeners_","goog.events.unlistenByKey","removeByKey","detachEvent","goog.events.listenerCountEstimate_","goog.events.onString_","opt_evt","listenerFn","listenerHandler","goog.events.LISTENER_WRAPPER_PROP_","handleEvent","goog.events.EventTarget","goog.Disposable.call","actualEventTarget_","parentEventTarget_","goog.events.EventTarget.prototype.removeEventListener","opt_capture","opt_handlerScope","goog.events.EventTarget.prototype.dispatchEvent","ancestorsTree","ancestor","getParentEventTarget","oldEvent","opt_ancestorsTree","fireListeners","goog.events.EventTarget.prototype.disposeInternal","goog.events.EventTarget.superClass_.disposeInternal.call","removeAllListeners","goog.events.EventTarget.prototype.listen","goog.events.EventTarget.prototype.listenOnce","goog.events.EventTarget.prototype.fireListeners","concat","unlistenByKey","goog.json.serialize","remove","goog.async.run.workQueue_.remove","item","workHead_","next","workTail_","scope","module$contents$goog$async$WorkQueue_WorkQueue.freelist_.get","set","module$contents$goog$async$WorkQueue_WorkQueue.freelist_","goog.async.FreeList","create","reset","create_","reset_","occupants_","head_","WorkItem","throwException","exception","goog.global.setTimeout","setTimeout","goog.async.run","callback","opt_context","goog.async.run.schedule_","goog.async.run.initializeRunner_","goog.async.run.workQueueScheduled_","goog.async.run.workQueue_.add","promise","goog.global.Promise.resolve","Promise","resolve","then","goog.async.run.processWorkQueue","goog.async.run.workQueue_","WorkQueue","put","module$contents$goog$async$WorkQueue_WorkQueue.freelist_.put","module$contents$goog$async$WorkQueue_WorkQueue.DEFAULT_MAX_UNUSED","goog.Timer","opt_interval","opt_timerObject","goog.events.EventTarget.call","interval_","timerObject_","boundTick_","tick_","last_","Date","now","goog.Timer.prototype","JSC$2088_enabled","JSC$2088_timer_","goog.Timer.prototype.tick_","enabled","elapsed","goog.Timer.intervalScale","timer_","clearTimeout","dispatchEvent","dispatchTick","goog.Timer.TICK","stop","start","goog.Timer.prototype.start","goog.Timer.prototype.stop","goog.Timer.prototype.disposeInternal","goog.Timer.superClass_.disposeInternal.call","goog.Timer.callOnce","opt_delay","Number","goog.Timer.INVALID_TIMEOUT_ID_","doAction_","onTimer_","shouldFire_","args_","listener_","Throttle","interval","fire","goog.global.clearTimeout","goog.events.EventHandler","opt_scope","handler_","keys_","goog.events.EventHandler.typeArray_","goog.events.EventHandler.prototype.listen_","opt_fn","goog.events.EventHandler.prototype.removeAll","goog.events.EventHandler.prototype.disposeInternal","goog.events.EventHandler.superClass_.disposeInternal.call","removeAll","goog.events.EventHandler.prototype.handleEvent","goog.labs.net.webChannel.WebChannelDebug","redactEnabled_","disableRedact","WebChannelDebug.prototype.disableRedact","WebChannelDebug.prototype.xmlHttpChannelRequest","verb","uri","id","attempt","postData","info","out","params","keyValue","param","value","keyParts","WebChannelDebug.prototype.xmlHttpChannelResponseMetaData","readyState","statusCode","WebChannelDebug.prototype.xmlHttpChannelResponseText","responseText","opt_desc","redactResponse_","WebChannelDebug.prototype.timeoutResponse","WebChannelDebug.prototype.info","WebChannelDebug.prototype.redactResponse_","responseArray","JSON","parse","array","dataPart","goog.labs.net.webChannel.requestStats.Event","goog.labs.net.webChannel.requestStats.eventTarget_","requestStats.getStatEventTarget_","goog.labs.net.webChannel.requestStats.Event.SERVER_REACHABILITY_EVENT","SERVER_REACHABILITY_EVENT","requestStats.ServerReachabilityEvent","goog.labs.net.webChannel.requestStats.ServerReachabilityEvent","requestStats.notifyServerReachabilityEvent","reachabilityType","goog.labs.net.webChannel.requestStats.getStatEventTarget_","goog.labs.net.webChannel.requestStats.Event.STAT_EVENT","STAT_EVENT","requestStats.StatEvent","eventTarget","stat","goog.labs.net.webChannel.requestStats.StatEvent","requestStats.notifyStatEvent","goog.labs.net.webChannel.requestStats.Event.TIMING_EVENT","TIMING_EVENT","requestStats.TimingEvent","size","goog.labs.net.webChannel.requestStats.TimingEvent","requestStats.setTimeout","ms","goog.net.ErrorCode","NO_ERROR","ACCESS_DENIED","FILE_NOT_FOUND","FF_SILENT_ERROR","CUSTOM_ERROR","EXCEPTION","HTTP_ERROR","ABORT","TIMEOUT","OFFLINE","goog.net.EventType","COMPLETE","SUCCESS","ERROR","READY","READY_STATE_CHANGE","INCREMENTAL_DATA","PROGRESS","DOWNLOAD_PROGRESS","UPLOAD_PROGRESS","goog.net.XmlHttpFactory","cachedOptions_","goog.net.XmlHttpFactory.prototype.getOptions","internalGetOptions","goog.net.WebChannel","goog.net.WebChannel.EventType","OPEN","CLOSE","MESSAGE","goog.net.WebChannel.MessageEvent","goog.net.WebChannel.MessageEvent.base","goog.net.WebChannel.ErrorEvent","goog.net.WebChannel.ErrorEvent.base","goog.net.DefaultXmlHttpFactory","createInstance","goog.net.DefaultXmlHttpFactory.prototype.createInstance","XMLHttpRequest","goog.net.DefaultXmlHttpFactory.prototype.internalGetOptions","goog.net.XmlHttp.factory_","factory","goog.labs.net.webChannel.ChannelRequest","channel","channelDebug","opt_requestId","opt_retryId","channel_","channelDebug_","rid_","retryId_","eventHandler_","timeout_","goog.labs.net.webChannel.ChannelRequest.TIMEOUT_MS_","EDGE_POLLING_INTERVAL_","pollingTimer_","extraHeaders_","successful_","postData_","requestUri_","baseUri_","type_","requestStartTime_","watchDogTimeoutTime_","watchDogTimerId_","pendingMessages_","xmlHttp_","xmlHttpChunkStart_","lastError_","verb_","lastStatusCode_","cancelled_","readyStateChangeThrottleMs_","readyStateChangeThrottle_","firstByteReceived_","initialResponseDecoded_","decodeInitialResponse_","decodeChunks_","fetchResponseState_","goog.labs.net.webChannel.FetchResponseState","textDecoder","responseBuffer","responseArrivedForFetch","goog.labs.net.webChannel.ChannelRequest.INVALID_CHUNK_","goog.labs.net.webChannel.ChannelRequest.INCOMPLETE_CHUNK_","goog.labs.net.webChannel.ChannelRequest.prototype","ChannelRequest.prototype.setTimeout","timeout","ChannelRequest.prototype.xmlHttpPost","XML_HTTP","makeUnique","decodeChunks","sendXmlHttp_","ChannelRequest.prototype.sendXmlHttp_","hostPrefix","ensureWatchDogTimer_","values","setValues","queryData_","useSecondaryDomains","supportsCrossDomainXhrs_","createXhrIo","xmlHttpHandler_","listen_","readyStateChangeHandler_","headers","send","goog.labs.net.webChannel.requestStats.notifyServerReachabilityEvent","xmlHttpChannelRequest","ChannelRequest.prototype.readyStateChangeHandler_","evt","xhr","throttle","INTERACTIVE","getReadyState","ChannelRequest.prototype.xmlHttpHandler_","xmlhttp","onXmlHttpReadyStateChanged_","errorCode","getLastErrorCode","getStatus","getResponseText","getResponse","REQUEST_FAILED","REQUEST_SUCCEEDED","cancelWatchDogTimer_","status","useFetchStreamsForResponse_","responseChunks","responseLength","requestCompleted","TextDecoder","cleanup_","dispatchFailure_","goog.global.TextDecoder","decode","stream","xmlHttpChannelResponseMetaData","xhr_","getResponseHeader","goog.net.WebChannel.X_HTTP_INITIAL_RESPONSE","initialResponse","xmlHttpChannelResponseText","safeOnRequestData_","UNKNOWN_SESSION_ID","goog.labs.net.webChannel.requestStats.notifyStatEvent","REQUEST_UNKNOWN_SESSION_ID","decodeNextChunks_","pollResponse_","onRequestComplete","STATUS","REQUEST_BAD_STATUS","ex","ChannelRequest.prototype.useFetchStreamsForResponse_","CLOSE_REQUEST","usesFetchStreams_","ChannelRequest.prototype.decodeNextChunks_","decodeNextChunksSuccessful","chunkText","getNextChunk_","BAD_DATA","REQUEST_INCOMPLETE_DATA","REQUEST_BAD_DATA","maybeResetBuffer_","NO_DATA","REQUEST_NO_DATA","backChannelRequest_","request","detectBufferingProxy_","bpDetectionDone_","clearBpDetectionTimer_","NOPROXY","ChannelRequest.prototype.pollResponse_","ChannelRequest.prototype.getNextChunk_","sizeStartIndex","sizeEndIndex","substring","sizeAsString","isNaN","chunkStartIndex","substr","cancel","ChannelRequest.prototype.cancel","ChannelRequest.prototype.ensureWatchDogTimer_","startWatchDogTimer_","ChannelRequest.prototype.startWatchDogTimer_","time","goog.labs.net.webChannel.requestStats.setTimeout","onWatchDogTimeout_","ChannelRequest.prototype.cancelWatchDogTimer_","ChannelRequest.prototype.onWatchDogTimeout_","timeoutResponse","handleTimeout_","REQUEST_TIMEOUT","ChannelRequest.prototype.dispatchFailure_","CLOSED","state_","ChannelRequest.prototype.cleanup_","abort","ChannelRequest.prototype.safeOnRequestData_","data","hasRequest","forwardChannelRequestPool_","OPENED","response","wireCodec_","parser_","responseValues","backChannelTimerId_","handlePostResponse_","goog.labs.net.webChannel.WebChannelBase.RTT_ESTIMATE","clearDeadBackchannelTimer_","cancelBackChannelRequest_","maybeRetryBackChannel_","BACKCHANNEL_MISSING","lastPostResponseArrayId_","lastArrayId_","goog.labs.net.webChannel.WebChannelBase.OUTSTANDING_DATA_BACKCHANNEL_RETRY_CUTOFF","numOutstandingBackchannelBytes","enableStreaming_","backChannelRetryCount_","deadBackChannelTimerId_","onBackChannelDead_","getRequestCount","onForwardChannelFlushed_","forwardChannelFlushedCallback_","signalError_","BAD_RESPONSE","respArray","nextArray","onInput_","OPENING","sid_","hostPrefix_","serverHostPrefix","negotiatedVersion","channelVersion_","negotiatedServerVersion","serverVersion_","serverKeepaliveMs","backChannelRequestTimeoutMs_","applyControlHeaders_","clientProtocol","goog.net.WebChannel.X_CLIENT_WIRE_PROTOCOL","requestPool_","maxSize_","maxPoolSizeConfigured_","Set","request_","addRequest","getHttpSessionIdParam","httpSessionIdParam_","httpSessionIdHeader","goog.net.WebChannel.X_HTTP_SESSION_ID","setHttpSessionId","httpSessionId_","setParameterValue","forwardChannelUri_","channelOpened","handshakeRttMs_","startBackchannelAfterHandshake_","backChannelUri_","createDataUri","getBackChannelUri","path_","removeRequest","opt_timeout","ensureBackChannel_","outgoingMaps_","ensureForwardChannel_","STOP","disconnect","channelHandleArray","BACK_CHANNEL_ACTIVITY","goog.structs.getValues","col","getValues","Map","from","l","goog.structs.getKeys","getKeys","keys","goog.structs.forEach","goog.uri.utils.splitRe_","RegExp","goog.uri.utils.parseQueryData","encodedQuery","pairs","indexOfEquals","name","decodeURIComponent","replace","goog.Uri","opt_uri","opt_ignoreCase","domain_","userInfo_","scheme_","port_","fragment_","ignoreCase_","setScheme","setUserInfo","setDomain","setPort","setPath","goog.Uri.QueryData","encodedQuery_","keyMap_","count_","setQueryData","setFragment","m","match","result","SCHEME","goog.Uri.decodeOrEmpty_","USER_INFO","DOMAIN","PORT","PATH","QUERY_DATA","FRAGMENT","goog.Uri.prototype.toString","scheme","getScheme","goog.Uri.encodeSpecialChars_","goog.Uri.reDisallowedInSchemeOrUserInfo_","domain","getDomain","userInfo","getUserInfo","encodeURIComponent","doubleEncodedString","port","getPort","path","getPath","hasDomain","charAt","goog.Uri.reDisallowedInAbsolutePath_","goog.Uri.reDisallowedInRelativePath_","query","getEncodedQuery","fragment","getFragment","goog.Uri.reDisallowedInFragment_","join","goog.Uri.prototype.clone","goog.Uri.prototype.setScheme","newScheme","opt_decode","goog.Uri.prototype.setPort","newPort","goog.Uri.prototype.setQueryData","queryData","setIgnoreCase","goog.Uri.reDisallowedInQuery_","goog.Uri.prototype.setParameterValue","goog.Uri.prototype.makeUnique","RANDOM","floor","abs","opt_preserveReserved","decodeURI","unescapedPart","extra","opt_removeDoubleEncoding","encoded","encodeURI","goog.Uri.encodeChar_","ch","n","charCodeAt","opt_query","goog.Uri.QueryData.prototype.ensureKeyMapInitialized_","goog.Uri.QueryData.prototype","goog.Uri.QueryData.prototype.add","ensureKeyMapInitialized_","invalidateCache_","getKeyName_","goog.Uri.QueryData.prototype.remove","has","delete","goog.Uri.QueryData.prototype.containsKey","goog.Uri.QueryData.prototype.forEach","goog.Uri.QueryData.prototype.getKeys","vals","goog.Uri.QueryData.prototype.getValues","opt_key","containsKey","goog.Uri.QueryData.prototype.set","goog.Uri.QueryData.prototype.get","opt_default","goog.Uri.QueryData.prototype.setValues","goog.Uri.QueryData.prototype.toString","sb","encodedKey","goog.Uri.QueryData.prototype.getKeyName_","keyName","goog.Uri.QueryData.prototype.setIgnoreCase","ignoreCase","lowerCase","goog.labs.net.webChannel.Wire.QueuedMap","mapId","map","ForwardChannelRequestPool","opt_maxPoolSize","module$contents$goog$labs$net$webChannel$ForwardChannelRequestPool_ForwardChannelRequestPool.MAX_POOL_SIZE_","goog.global.PerformanceNavigationTiming","PerformanceNavigationTiming","entrys","goog.global.performance.getEntriesByType","performance","getEntriesByType","nextHopProtocol","goog.global.chrome","chrome","goog.global.chrome.loadTimes","loadTimes","wasFetchedViaSpdy","ForwardChannelRequestPool.prototype.isFull","ForwardChannelRequestPool.prototype.getRequestCount","ForwardChannelRequestPool.prototype.hasRequest","req","ForwardChannelRequestPool.prototype.addRequest","ForwardChannelRequestPool.prototype.removeRequest","ForwardChannelRequestPool.prototype.cancel","getPendingMessages","clear","ForwardChannelRequestPool.prototype.getPendingMessages","goog.json.NativeJsonProcessor","stringify","goog.json.NativeJsonProcessor.prototype.stringify","opt_replacer","goog.json.NativeJsonProcessor.prototype.parse","opt_reviver","goog.labs.net.webChannel.WireV8","WireV8.prototype.encodeMessage","message","buffer","opt_prefix","prefix","encodedValue","netUtils.testLoadImage","url","goog.global.Image","Image","img","onload","goog.labs.net.webChannel.netUtils.imageCallback_","onerror","onabort","ontimeout","goog.labs.net.webChannel.netUtils.NETWORK_TIMEOUT","netUtils.imageCallback_","debugText","goog.net.FetchXmlHttpFactory","opts","worker_","worker","streamBinaryChunks_","streamBinaryChunks","goog.net.FetchXmlHttpFactory.prototype.createInstance","instance","goog.net.FetchXmlHttp","goog.functions.constant","retValue","goog.net.FetchXmlHttp.base","credentialsMode_","goog.net.FetchXmlHttp.RequestState.UNSENT","responseType","statusText","onreadystatechange","requestHeaders_","Headers","responseHeaders_","method_","url_","inProgress_","textDecoder_","currentReader_","fetchResponse_","UNSENT","goog.net.FetchXmlHttp.prototype","open","goog.net.FetchXmlHttp.prototype.open","method","dispatchCallback_","goog.net.FetchXmlHttp.prototype.send","opt_data","requestInit","credentials","cache","fetch","Request","handleResponse_","handleSendFailure_","goog.net.FetchXmlHttp.prototype.abort","catch","DONE","requestDone_","goog.net.FetchXmlHttp.prototype.handleResponse_","HEADER_RECEIVED","LOADING","arrayBuffer","handleResponseArrayBuffer_","ReadableStream","body","getReader","readInputFromFetch_","text","handleResponseText_","goog.net.FetchXmlHttp.prototype.readInputFromFetch_","read","handleDataFromStream_","goog.net.FetchXmlHttp.prototype.handleDataFromStream_","dataPacket","Uint8Array","newText","done","goog.net.FetchXmlHttp.prototype.handleResponseText_","goog.net.FetchXmlHttp.prototype.handleResponseArrayBuffer_","responseArrayBuffer","goog.net.FetchXmlHttp.prototype.handleSendFailure_","goog.net.FetchXmlHttp.prototype.requestDone_","setRequestHeader","goog.net.FetchXmlHttp.prototype.setRequestHeader","header","append","goog.net.FetchXmlHttp.prototype.getResponseHeader","getAllResponseHeaders","goog.net.FetchXmlHttp.prototype.getAllResponseHeaders","lines","iter","entries","entry","pair","goog.net.FetchXmlHttp.prototype.dispatchCallback_","getCredentialsMode","setCredentialsMode","credentialsMode","goog.json.hybrid.parse","goog.net.XhrIo","opt_xmlHttpFactory","goog.net.XhrIo.base","xmlHttpFactory_","active_","xhrOptions_","lastUri_","lastErrorCode_","inAbort_","inOpen_","inSend_","errorDispatched_","timeoutInterval_","timeoutId_","responseType_","goog.net.XhrIo.ResponseType.DEFAULT","useXhr2Timeout_","withCredentials_","DEFAULT","goog.net.XhrIo.HTTP_SCHEME_PATTERN","goog.net.XhrIo.METHODS_WITH_FORM_DATA","goog.net.XhrIo.prototype","setWithCredentials","goog.net.XhrIo.prototype.setWithCredentials","withCredentials","JSC$2188_send","goog.net.XhrIo.prototype.send","opt_method","opt_content","opt_headers","toUpperCase","createXhr","goog.net.XmlHttp.factory_.createInstance","getOptions","goog.net.XmlHttp.factory_.getOptions","onReadyStateChange_","err","error_","content","getPrototypeOf","contentTypeKey","find","contentIsFormData","goog.net.XhrIo.CONTENT_TYPE_HEADER","goog.net.XhrIo.FORM_CONTENT_TYPE","cleanUpTimeoutTimer_","goog.net.XhrIo.shouldUseXhr2Timeout_","JSC$2188_timeout_","goog.net.XhrIo.prototype.timeout_","goog.net.XhrIo.prototype.error_","dispatchErrors_","cleanUpXhr_","goog.net.XhrIo.prototype.dispatchErrors_","goog.net.XhrIo.prototype.abort","opt_failureCode","goog.net.XhrIo.prototype.disposeInternal","goog.net.XhrIo.superClass_.disposeInternal.call","goog.net.XhrIo.prototype.disposeInternal.base","goog.net.XhrIo.prototype.onReadyStateChange_","isDisposed","onReadyStateChangeHelper_","onReadyStateChangeEntryPoint_","goog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_","goog.net.XhrIo.prototype.onReadyStateChangeHelper_","LOCAL_REQUEST_ERROR","isComplete","isSuccess","OK","CREATED","ACCEPTED","NO_CONTENT","PARTIAL_CONTENT","NOT_MODIFIED","QUIRK_IE_NO_CONTENT","goog.global.self","goog.global.self.location","location","protocol","goog.global.self.location.protocol","goog.net.XhrIo.HTTP_SCHEME_PATTERN.test","LOADED","getStatusText","goog.net.XhrIo.prototype.cleanUpXhr_","opt_fromDispose","clearedOnReadyStateChange","USE_NULL_FUNCTION","goog.net.XhrIo.prototype.cleanUpTimeoutTimer_","goog.net.XhrIo.prototype.getReadyState","UNINITIALIZED","goog.net.XhrIo.prototype.getStatus","goog.net.XhrIo.prototype.getResponseText","getResponseJson","goog.net.XhrIo.prototype.getResponseJson","opt_xssiPrefix","goog.net.XhrIo.prototype.getResponse","TEXT","ARRAY_BUFFER","mozResponseArrayBuffer","goog.net.XhrIo.prototype.getLastErrorCode","JSC$2188_getLastError","goog.net.XhrIo.prototype.getLastError","exports.generateHttpHeadersOverwriteParam","exports.setHttpHeadersWithOverwriteParam","urlParam","extraHeaders","httpHeaders","module$exports$goog$net$rpc$HttpCors.generateHttpHeadersOverwriteParam","getInternalChannelParam","paramName","defaultValue","internalChannelParams","goog.labs.net.webChannel.WebChannelBase","extraParams_","httpHeadersOverwriteParam_","initHeaders_","nextMapId_","nextRid_","failFast_","$jscomp.scope.getInternalChannelParam","forwardChannelTimerId_","allowStreamingMode_","backChannelAttemptId_","forwardChannelRetryCount_","baseRetryDelayMs_","retryDelaySeedMs_","forwardChannelMaxRetries_","forwardChannelRequestTimeoutMs_","xmlHttpFactory","useFetchStreams","supportsCrossDomainXhr","concurrentRequestLimit","fastHandshake_","fastHandshake","encodeInitMessageHeaders_","encodeInitMessageHeaders","blockingHandshake_","blockingHandshake","forceLongPolling","detectBufferingProxy","nonAckedMapsAtChannelClose_","bpDetectionTimerId_","goog.labs.net.webChannel.WebChannelBase.prototype","goog.labs.net.webChannel.Wire.LATEST_CHANNEL_VERSION","JSC$2195_state_","INIT","WebChannelBase.prototype.disconnect","cancelRequests_","rid","addAdditionalParams_","requestSent","goog.global.navigator.sendBeacon","sendBeacon","eltImg","onClose_","WebChannelBase.prototype.cancelBackChannelRequest_","WebChannelBase.prototype.cancelRequests_","clearForwardChannelTimer_","WebChannelBase.prototype.ensureForwardChannel_","isFull","onStartForwardChannelTimer_","WebChannelBase.prototype.maybeRetryForwardChannel_","getForwardChannelMaxRetries","getRetryTime_","WebChannelBase.prototype.onStartForwardChannelTimer_","opt_retryRequest","startForwardChannel_","total","goog.labs.net.webChannel.Wire.RAW_DATA_KEY","goog.labs.net.webChannel.WebChannelBase.MAX_CHARS_PER_GET_","goog.labs.net.webChannel.WebChannelBase.MAX_MAPS_PER_REQUEST_","requestText","dequeueOutgoingMaps_","goog.net.WebChannelTransport.CLIENT_VERSION","encodedHeaders","module$exports$goog$net$rpc$HttpCors.setHttpHeadersWithOverwriteParam","xmlHttpPost","makeForwardChannelRequest_","WebChannelBase.prototype.makeForwardChannelRequest_","requeuePendingMaps_","round","WebChannelBase.prototype.addAdditionalParams_","WebChannelBase.prototype.dequeueOutgoingMaps_","maxNum","count","min","badMapHandler","badMapError","offset","messageQueue","encodeMessage","pendingMessages","WebChannelBase.prototype.ensureBackChannel_","onStartBackChannelTimer_","WebChannelBase.prototype.maybeRetryBackChannel_","goog.labs.net.webChannel.WebChannelBase.BACK_CHANNEL_MAX_RETRIES","WebChannelBase.prototype.onStartBackChannelTimer_","startBackChannel_","bpDetectionTimeout","onBpDetectionTimer_","WebChannelBase.prototype.onBpDetectionTimer_","PROXY","WebChannelBase.prototype.clearBpDetectionTimer_","WebChannelBase.prototype.startBackChannel_","WebChannelBase.prototype.onBackChannelDead_","BACKCHANNEL_DEAD","WebChannelBase.prototype.clearDeadBackchannelTimer_","WebChannelBase.prototype.onRequestComplete","BACK_CHANNEL","FORWARD_CHANNEL","lastError","maybeRetryForwardChannel_","WebChannelBase.prototype.getRetryTime_","retryCount","retryTime","isActive","goog.labs.net.webChannel.WebChannelBase.INACTIVE_CHANNEL_RETRY_FACTOR","WebChannelBase.prototype.signalError_","error","imageUri","testNetworkCallback_","goog.global.location","goog.global.location.protocol","goog.labs.net.webChannel.netUtils.testLoadImage","ERROR_OTHER","onError_","channelError","WebChannelBase.prototype.testNetworkCallback_","networkUp","ERROR_NETWORK","WebChannelBase.prototype.onClose_","channelClosed","WebChannelBase.prototype.createDataUri","locationPage","hostName","hostname","opt_scheme","opt_domain","opt_port","getHttpSessionId","WebChannelBase.prototype.createXhrIo","isStreaming","WebChannelBase.Handler","goog.labs.net.webChannel.WebChannelBase.Handler.prototype","WebChannelBase.Handler.prototype.channelOpened","WebChannelBase.Handler.prototype.channelHandleArray","WebChannelBase.Handler.prototype.channelError","WebChannelBase.Handler.prototype.channelClosed","WebChannelBase.Handler.prototype.badMapError","goog.labs.net.webChannel.WebChannelBaseTransport","createWebChannel","WebChannelBaseTransport.prototype.createWebChannel","goog.labs.net.webChannel.WebChannelBaseTransport.Channel","WebChannelBaseTransport.Channel","goog.labs.net.webChannel.WebChannelBaseTransport.Channel.base","messageUrlParams_","messageUrlParams","messageHeaders","clientProtocolHeaderRequired","goog.net.WebChannel.X_CLIENT_PROTOCOL","goog.net.WebChannel.X_CLIENT_PROTOCOL_WEB_CHANNEL","initHeaders","initMessageHeaders","messageContentType","goog.net.WebChannel.X_WEBCHANNEL_CONTENT_TYPE","clientProfile","goog.net.WebChannel.X_WEBCHANNEL_CLIENT_PROFILE","httpHeadersOverwriteParam","supportsCrossDomainXhr_","sendRawJson_","sendRawJson","httpSessionIdParam","channelHandler_","goog.labs.net.webChannel.WebChannelBaseTransport.Channel.Handler_","WebChannelBaseTransport.Channel.prototype.open","supportCrossDomain","CONNECT_ATTEMPT","channelPath","opt_extraParams","connectChannel_","close","WebChannelBaseTransport.Channel.prototype.close","WebChannelBaseTransport.Channel.prototype.send","rawJson","messageToMapObject_","WebChannelBaseTransport.Channel.prototype.disposeInternal","goog.labs.net.webChannel.WebChannelBaseTransport.Channel.superClass_.disposeInternal.call","goog.labs.net.webChannel.WebChannelBaseTransport.Channel.prototype.disposeInternal.base","WebChannelBaseTransport.Channel.MessageEvent","goog.net.WebChannel.MessageEvent.call","goog.labs.net.webChannel.WebChannelBaseTransport.Channel.MessageEvent.base","metadata","metadataKey","goog.labs.net.webChannel.WebChannelBaseTransport.Channel.MessageEvent","WebChannelBaseTransport.Channel.ErrorEvent","goog.net.WebChannel.ErrorEvent.call","goog.labs.net.webChannel.WebChannelBaseTransport.Channel.ErrorEvent.base","NETWORK_ERROR","goog.labs.net.webChannel.WebChannelBaseTransport.Channel.ErrorEvent","WebChannelBaseTransport.Channel.Handler_","goog.labs.net.webChannel.WebChannelBase.Handler","WebChannelBaseTransport.Channel.Handler_.prototype.channelOpened","WebChannelBaseTransport.Channel.Handler_.prototype.channelHandleArray","WebChannelBaseTransport.Channel.Handler_.prototype.channelError","WebChannelBaseTransport.Channel.Handler_.prototype.channelClosed","getLastError","module","goog.net.createWebChannelTransport","requestStats.getStatEventTarget","goog.labs.net.webChannel.requestStats.Stat","TEST_STAGE_ONE_START","TEST_STAGE_TWO_START","TEST_STAGE_TWO_DATA_ONE","TEST_STAGE_TWO_DATA_TWO","TEST_STAGE_TWO_DATA_BOTH","TEST_STAGE_ONE_FAILED","TEST_STAGE_TWO_FAILED","BROWSER_OFFLINE"],"mappings":"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"}