es2015/DBFactory.js
function openConnection(databaseName, sortedSchemaDescriptors) {
  let version = sortedSchemaDescriptors.slice().pop().version
  let request = NativeDBAccessor.indexedDB.open(databaseName, version)
  
  return new Promise((resolve, reject) => {
    let wasBlocked = false
    let upgradeTriggered = false
    
    let migrationPromiseResolver, migrationPromiseRejector
    let migrationPromise = new Promise((resolve, reject) => {
      migrationPromiseResolver = resolve
      migrationPromiseRejector = reject
    })
    // prevent leaking the same error to the console twice
    migrationPromise.catch(() => {})
    
    request.onsuccess = () => {
      let database = new Database(request.result)
      resolve(database)
      migrationPromiseResolver()
    }

    request.onupgradeneeded = (event) => {
      if (!wasBlocked) {
        upgradeTriggered = true
      }
      
      let database = request.result
      let transaction = request.transaction
      
      if (wasBlocked) {
        transaction.abort()
        return
      }
      
      upgradeDatabaseSchema(databaseName, event, migrationPromise, database,
          transaction, sortedSchemaDescriptors, migrationPromiseResolver,
          migrationPromiseRejector).catch((error) => {
        transaction.abort()
      })
    }

    request.onerror = (event) => {
      handleConnectionError(event, request.error, wasBlocked, upgradeTriggered,
          reject, migrationPromiseRejector)
    }
    
    request.onblocked = () => {
      wasBlocked = true
      
      let error = new Error("A database upgrade was needed, but could not " +
          "be performed, because the attempt was blocked by a connection " +
          "that remained opened after receiving the notification")
      reject(error)
      migrationPromiseRejector(error)
    }
  })
}
function openConnection(databaseName, sortedSchemaDescriptors) {
  let version = sortedSchemaDescriptors.slice().pop().version
  let request = NativeDBAccessor.indexedDB.open(databaseName, version)
  
  return new Promise((resolve, reject) => {
    let wasBlocked = false
    let upgradeTriggered = false
    
    let migrationPromiseResolver, migrationPromiseRejector
    let migrationPromise = new Promise((resolve, reject) => {
      migrationPromiseResolver = resolve
      migrationPromiseRejector = reject
    })
    // prevent leaking the same error to the console twice
    migrationPromise.catch(() => {})
    
    request.onsuccess = () => {
      let database = new Database(request.result)
      resolve(database)
      migrationPromiseResolver()
    }

    request.onupgradeneeded = (event) => {
      if (!wasBlocked) {
        upgradeTriggered = true
      }
      
      let database = request.result
      let transaction = request.transaction
      
      if (wasBlocked) {
        transaction.abort()
        return
      }
      
      upgradeDatabaseSchema(databaseName, event, migrationPromise, database,
          transaction, sortedSchemaDescriptors, migrationPromiseResolver,
          migrationPromiseRejector).catch((error) => {
        transaction.abort()
      })
    }

    request.onerror = (event) => {
      handleConnectionError(event, request.error, wasBlocked, upgradeTriggered,
          reject, migrationPromiseRejector)
    }
    
    request.onblocked = () => {
      wasBlocked = true
      
      let error = new Error("A database upgrade was needed, but could not " +
          "be performed, because the attempt was blocked by a connection " +
          "that remained opened after receiving the notification")
      reject(error)
      migrationPromiseRejector(error)
    }
  })
}
Handles opening the connection to the database and wraps the whole process
in a promise.

@param {string} databaseName The name of the Indexed DB database to connect
to.
@param {(DatabaseSchema|UpgradedDatabaseSchema|Object)[]} sortedSchemaDescriptors
The database schema descriptors, sorted in ascending order by the
schema version number.
@return {Promise<Database>} A promise that resolves to the database
connection.