Repository: servo/servo
File: components/storage/indexeddb/mod.rs (Rust)

Code before:
        // Step 4: Let db be the database named name in origin, or null otherwise.
        let (db_version, version) = match self.databases.entry(idb_description.clone()) {
            Entry::Vacant(e) => {
                // Step 5: If version is undefined, let version be 1 if db is null, or db’s version otherwise.
                // Note: done below with the zero as first tuple item.

                // https://www.w3.org/TR/IndexedDB-2/#open-a-database
                // Step 6: If db is null, let db be a new database with name name, version 0, and no object stores.
                // If creation or opening fails, return an appropriate error to the open request.
                let engine = match SqliteEngine::new(
                    idb_base_dir,
                    &idb_description,
                    self.thread_pool.clone(),
                ) {
                    Ok(engine) => engine,
                    Err(err) => {
                        let _ = sender.send(Err(backend_error_from_sqlite_error(err)));
                        return;
                    },
                };
                let created_db_path = engine.created_db_path();
                let db = IndexedDBEnvironment::new(engine);
                let db_version = match db.version() {
                    Ok(version) => version,
                    Err(err) => {
                        let _ = sender.send(Err(backend_error_from_sqlite_error(err)));
                        return;
                    },
                };

                let version = if created_db_path {
                    requested_version.unwrap_or(1)
                } else {
                    requested_version.unwrap_or(db_version)
                };

                e.insert(db);
                (db_version, version)
            },
            Entry::Occupied(db) => {
                let db_version = match db.get().version() {
                    Ok(version) => version,
                    Err(err) => {
                        let _ = sender.send(Err(backend_error_from_sqlite_error(err)));
                        return;
                    },
                };
                // Step 5: If version is undefined, let version be 1 if db is null, or db’s version otherwise.
                (db_version, requested_version.unwrap_or(db_version))
            },
        };

Review comment (bug):
Let's log debug if the send errors. see                 debug!("Script exit during indexeddb database open"); elsewhere

Code after:
                let db_version = match db.get().version() {
                    Ok(version) => version,
                    Err(err) => {
                        if let Err(e) = sender.send(Err(backend_error_from_sqlite_error(err))) {
                            debug!("Script exit during indexeddb database open {:?}", e);
                        }
                        return;
                    },
                };
                // Step 5: If version is undefined, let version be 1 if db is null, or db’s version otherwise.
                (db_version, requested_version.unwrap_or(db_version))
            },
        };

        // Step 7: If db’s version is greater than version,
        // return a newly created "VersionError" DOMException
        // and abort these steps.
        if version < db_version {
            if sender.send(Ok(OpenDatabaseResult::VersionError)).is_err() {
                debug!("Script exit during indexeddb database open");
            }
            return;
        }

        // Let connection be a new connection to db.
        // Set connection’s version to version.
        // TODO: track connections in the backend(each script `IDBDatabase` should have a matching connection).

        // Step 10: If db’s version is less than version, then:
        if db_version < version {
            // Step 10.1: Let openConnections be the set of all connections,
            // except connection, associated with db.
            // Step 10.2: For each entry of openConnections
            // that does not have its close pending flag set to true,
            // queue a database task to fire a version change event
            // named versionchange at entry with db’s version and version.
            // Step 10.3: Wait for all of the events to be fired.
            // Step 10.4: If any of the connections in openConnections are still not closed,
            // queue a database task to fire a version change event named blocked
            // at request with db’s version and version.
            // Step 10.5: Wait until all connections in openConnections are closed.
            // TODO: implement connections.

            // Step 10.6: Run upgrade a database using connection, version and request.
            self.upgrade_database(idb_description, version, db_name, sender);
            return;
        }

        // Step 11:
        if sender
            .send(Ok(OpenDatabaseResult::Connection {