Repository: servo/servo
File: components/script/dom/indexeddb/idbfactory.rs (Rust)

Code before:
use crate::dom::bindings::str::DOMString;
use crate::dom::globalscope::GlobalScope;
use crate::dom::indexeddb::idbopendbrequest::IDBOpenDBRequest;
use crate::dom::promise::Promise;
use crate::indexeddb::{convert_value_to_key, map_backend_error_to_dom_error};
use crate::script_runtime::CanGc;

/// A non-jstraceable string wrapper for use in `HashMapTracedValues`.
#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
pub(crate) struct DBName(pub(crate) String);

#[dom_struct]
pub struct IDBFactory {
    reflector_: Reflector,
    /// <https://www.w3.org/TR/IndexedDB-2/#connection>
    /// The connections pending #open-a-database-connection.
    #[no_trace]
    pending_connections: DomRefCell<HashMap<DBName, HashSet<Uuid>>>,
}

impl IDBFactory {
    pub fn new_inherited() -> IDBFactory {
        IDBFactory {
            reflector_: Reflector::new(),
            pending_connections: Default::default(),
        }
    }

    pub fn new(global: &GlobalScope, can_gc: CanGc) -> DomRoot<IDBFactory> {
        reflect_dom_object(Box::new(IDBFactory::new_inherited()), global, can_gc)
    }

    fn note_start_of_open(&self, name: DBName, id: Uuid) {
        let mut pending = self.pending_connections.borrow_mut();
        let entry = pending.entry(name).or_default();
        entry.insert(id);
    }

    pub(crate) fn note_end_of_open(&self, name: &DBName, id: &Uuid) {
        let mut pending = self.pending_connections.borrow_mut();
        let empty = {
            let Some(entry) = pending.get_mut(name) else {
                return debug_assert!(
                    false,
                    "There should be a pending connection for {:?}",
                    name.0
                );
            };
            entry.remove(id);
            entry.is_empty()
        };

Review comment (suggestion):
This is the important part. The rest is just moving code form one module to the next. 

The idea is that this will, in subsequent PRs, switch from being just `pending_connections` to `connections`, tracking both the pending open flow and the subsequent communication for closing connections(when the backend queues task to fire event like `blocked`). 

Code after:
use crate::dom::bindings::error::{Error, ErrorToJsval, Fallible};
use crate::dom::bindings::import::base::SafeJSContext;
use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::DOMString;
use crate::dom::bindings::trace::HashMapTracedValues;
use crate::dom::event::{Event, EventBubbles, EventCancelable};
use crate::dom::globalscope::GlobalScope;
use crate::dom::indexeddb::idbdatabase::IDBDatabase;
use crate::dom::indexeddb::idbopendbrequest::IDBOpenDBRequest;
use crate::dom::promise::Promise;
use crate::indexeddb::{convert_value_to_key, map_backend_error_to_dom_error};
use crate::script_runtime::CanGc;

/// A non-jstraceable string wrapper for use in `HashMapTracedValues`.
#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
pub(crate) struct DBName(pub(crate) String);

#[dom_struct]
pub struct IDBFactory {
    reflector_: Reflector,
    /// <https://www.w3.org/TR/IndexedDB-2/#connection>
    /// The connections pending #open-a-database-connection.
    pending_connections:
        DomRefCell<HashMapTracedValues<DBName, HashMapTracedValues<Uuid, Dom<IDBOpenDBRequest>>>>,
}

impl IDBFactory {
    pub fn new_inherited() -> IDBFactory {
        IDBFactory {
            reflector_: Reflector::new(),
            pending_connections: Default::default(),
        }
    }

    pub fn new(global: &GlobalScope, can_gc: CanGc) -> DomRoot<IDBFactory> {
        reflect_dom_object(Box::new(IDBFactory::new_inherited()), global, can_gc)
    }

    /// <https://w3c.github.io/IndexedDB/#open-a-database-connection>
    /// The steps that continue on the script-thread.
    fn handle_open_db(
        &self,
        name: String,
        response: OpenDatabaseResult,
        request_id: Uuid,
        can_gc: CanGc,
    ) {
        let name = DBName(name);
        let request = {