text: /**
   * @license
   * Copyright The Closure Library Authors.
   * SPDX-License-Identifier: Apache-2.0
   */
  
  /**
   * @fileoverview Wrapper for an IndexedDB database.
   */
  
  
  goog.provide('goog.db.IndexedDb');
  
  goog.require('goog.db.Error');
  goog.require('goog.db.ObjectStore');
  goog.require('goog.db.Transaction');
  goog.require('goog.events.Event');
  goog.require('goog.events.EventHandler');
  goog.require('goog.events.EventTarget');
  
  
  
  /**
   * Creates an IDBDatabase wrapper object. The database object has methods for
   * setting the version to change the structure of the database and for creating
   * transactions to get or modify the stored records. Should not be created
   * directly, call {@link goog.db.openDatabase} to set up the connection.
   *
   * @param {!IDBDatabase} db Underlying IndexedDB database object.
   * @constructor
   * @extends {goog.events.EventTarget}
   * @final
   */
  goog.db.IndexedDb = function(db) {
    'use strict';
    goog.db.IndexedDb.base(this, 'constructor');
  
    /**
     * Underlying IndexedDB database object.
     *
     * @type {!IDBDatabase}
     * @private
     */
    this.db_ = db;
  
    /**
     * Internal event handler that listens to IDBDatabase events.
     * @type {!goog.events.EventHandler<!goog.db.IndexedDb>}
     * @private
     */
    this.eventHandler_ = new goog.events.EventHandler(this);
  
    this.eventHandler_.listen(
        this.db_, goog.db.IndexedDb.EventType.ABORT,
        goog.bind(this.dispatchEvent, this, goog.db.IndexedDb.EventType.ABORT));
    this.eventHandler_.listen(
        this.db_, goog.db.IndexedDb.EventType.ERROR, this.dispatchError_);
    this.eventHandler_.listen(
        this.db_, goog.db.IndexedDb.EventType.VERSION_CHANGE,
        this.dispatchVersionChange_);
    this.eventHandler_.listen(
        this.db_, goog.db.IndexedDb.EventType.CLOSE,
        goog.bind(this.dispatchEvent, this, goog.db.IndexedDb.EventType.CLOSE));
  };
  goog.inherits(goog.db.IndexedDb, goog.events.EventTarget);
  
  
  /**
   * True iff the database connection is open.
   *
   * @type {boolean}
   * @private
   */
  goog.db.IndexedDb.prototype.open_ = true;
  
  
  /**
   * Dispatches a wrapped error event based on the given event.
   *
   * @param {!Event} ev The error event given to the underlying IDBDatabase.
   * @private
   */
  goog.db.IndexedDb.prototype.dispatchError_ = function(ev) {
    'use strict';
    const idbRequest = /** @type {?IDBRequest} */ (ev.target);
    const domError = idbRequest && idbRequest.error;
    const /** ?number */ errorCode = domError && domError.severity;
    this.dispatchEvent({
      type: goog.db.IndexedDb.EventType.ERROR,
      errorCode: errorCode,
    });
  };
  
  
  /**
   * Dispatches a wrapped version change event based on the given event.
   *
   * @param {!IDBVersionChangeEvent} ev The version change event given to the
   *     underlying IDBDatabase.
   * @private
   */
  goog.db.IndexedDb.prototype.dispatchVersionChange_ = function(ev) {
    'use strict';
    this.dispatchEvent(new goog.db.IndexedDb.VersionChangeEvent(
        ev.oldVersion, /** @type {number} */ (ev.newVersion)));
  };
  
  
  /**
   * Closes the database connection. Metadata queries can still be made after this
   * method is called, but otherwise this wrapper should not be used further.
   */
  goog.db.IndexedDb.prototype.close = function() {
    'use strict';
    if (this.open_) {
      this.db_.close();
      this.open_ = false;
    }
  };
  
  
  /**
   * @return {boolean} Whether a connection is open and the database can be used.
   */
  goog.db.IndexedDb.prototype.isOpen = function() {
    'use strict';
    return this.open_;
  };
  
  
  /**
   * @return {string} The name of this database.
   */
  goog.db.IndexedDb.prototype.getName = function() {
    'use strict';
    return this.db_.name;
  };
  
  
  /**
   * @return {number} The current database version.
   */
  goog.db.IndexedDb.prototype.getVersion = function() {
    'use strict';
    // TODO(bradfordcsmith): drop Number() call once closure compiler's externs
    // are updated
    return Number(this.db_.version);
  };
  
  
  /**
   * @return {!DOMStringList} List of object stores in this database.
   */
  goog.db.IndexedDb.prototype.getObjectStoreNames = function() {
    'use strict';
    return this.db_.objectStoreNames;
  };
  
  
  /**
   * Creates an object store in this database. Can only be called inside a
   * {@link goog.db.UpgradeNeededCallback}.
   *
   * @param {string} name Name for the new object store.
   * @param {!IDBObjectStoreParameters=} opt_params Options object.
   *     The available options are:
   *     keyPath, which is a string and determines what object attribute
   *     to use as the key when storing objects in this object store; and
   *     autoIncrement, which is a boolean, which defaults to false and determines
   *     whether the object store should automatically generate keys for stored
   *     objects. If keyPath is not provided and autoIncrement is false, then all
   *     insert operations must provide a key as a parameter.
   * @return {!goog.db.ObjectStore} The newly created object store.
   * @throws {goog.db.Error} If there's a problem creating the object store.
   */
  goog.db.IndexedDb.prototype.createObjectStore = function(name, opt_params) {
    'use strict';
    try {
      return new goog.db.ObjectStore(
          this.db_.createObjectStore(name, opt_params));
    } catch (ex) {
      throw goog.db.Error.fromException(ex, 'creating object store ' + name);
    }
  };
  
  
  /**
   * Deletes an object store. Can only be called inside a
   * {@link goog.db.UpgradeNeededCallback}.
   *
   * @param {string} name Name of the object store to delete.
   * @throws {goog.db.Error} If there's a problem deleting the object store.
   */
  goog.db.IndexedDb.prototype.deleteObjectStore = function(name) {
    'use strict';
    try {
      this.db_.deleteObjectStore(name);
    } catch (ex) {
      throw goog.db.Error.fromException(ex, 'deleting object store ' + name);
    }
  };
  
  
  /**
   * Creates a new transaction.
   *
   * @param {!Array<string>} storeNames A list of strings that contains the
   *     transaction's scope, the object stores that this transaction can operate
   *     on.
   * @param {goog.db.Transaction.TransactionMode=} opt_mode The mode of the
   *     transaction. If not present, the default is READ_ONLY.
   * @return {!goog.db.Transaction} The wrapper for the newly created transaction.
   * @throws {goog.db.Error} If there's a problem creating the transaction.
   */
  goog.db.IndexedDb.prototype.createTransaction = function(storeNames, opt_mode) {
    'use strict';
    try {
      // IndexedDB on Chrome 22+ requires that opt_mode not be passed rather than
      // be explicitly passed as undefined.
      const transaction = opt_mode ? this.db_.transaction(storeNames, opt_mode) :
                                     this.db_.transaction(storeNames);
      return new goog.db.Transaction(transaction, this);
    } catch (ex) {
      throw goog.db.Error.fromException(ex, 'creating transaction');
    }
  };
  
  
  /** @override */
  goog.db.IndexedDb.prototype.disposeInternal = function() {
    'use strict';
    goog.db.IndexedDb.base(this, 'disposeInternal');
    this.eventHandler_.dispose();
  };
  
  
  /**
   * Event types fired by a database.
   *
   * @enum {string} The event types for the web socket.
   */
  goog.db.IndexedDb.EventType = {
  
    /**
     * Fired when a transaction is aborted and the event bubbles to its database.
     */
    ABORT: 'abort',
  
    /**
     * Fired when the database connection is forcibly closed by the browser,
     * without an explicit call to IDBDatabase#close. This behavior is not in the
     * spec yet but will be added since it is necessary, see
     * https://www.w3.org/Bugs/Public/show_bug.cgi?id=22540.
     */
    CLOSE: 'close',
  
    /**
     * Fired when a transaction has an error.
     */
    ERROR: 'error',
  
    /**
     * Fired when someone (possibly in another window) is attempting to modify the
     * structure of the database. Since a change can only be made when there are
     * no active database connections, this usually means that the database should
     * be closed so that the other client can make its changes.
     */
    VERSION_CHANGE: 'versionchange'
  };
  
  
  
  /**
   * Event representing a (possibly attempted) change in the database structure.
   *
   * At time of writing, no Chrome versions support oldVersion or newVersion. See
   * http://crbug.com/153122.
   *
   * @param {number} oldVersion The previous version of the database.
   * @param {number} newVersion The version the database is being or has been
   *     updated to.
   * @constructor
   * @extends {goog.events.Event}
   * @final
   */
  goog.db.IndexedDb.VersionChangeEvent = function(oldVersion, newVersion) {
    'use strict';
    goog.db.IndexedDb.VersionChangeEvent.base(
        this, 'constructor', goog.db.IndexedDb.EventType.VERSION_CHANGE);
  
    /**
     * The previous version of the database.
     * @type {number}
     */
    this.oldVersion = oldVersion;
  
    /**
     * The version the database is being or has been updated to.
     * @type {number}
     */
    this.newVersion = newVersion;
  };
  goog.inherits(goog.db.IndexedDb.VersionChangeEvent, goog.events.Event);
  