ladybird/Libraries/LibWeb/IndexedDB/IDBIndex.cpp
Andreas Kling a6dfc74e93 LibWeb: Only set prototype once for object with IDL interface
Before this change, we were going through the chain of base classes for
each IDL interface object and having them set the prototype to their
prototype.

Instead of doing that, reorder things so that we set the right prototype
immediately in Foo::initialize(), and then don't bother in all the base
class overrides.

This knocks off a ~1% profile item on Speedometer 3.
2025-04-20 18:43:11 +02:00

104 lines
3.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 2024, stelar7 <dudedbz@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Runtime/Array.h>
#include <LibWeb/Bindings/IDBIndexPrototype.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/HTML/EventNames.h>
#include <LibWeb/IndexedDB/IDBIndex.h>
namespace Web::IndexedDB {
GC_DEFINE_ALLOCATOR(IDBIndex);
IDBIndex::~IDBIndex() = default;
IDBIndex::IDBIndex(JS::Realm& realm, GC::Ref<Index> index, GC::Ref<IDBObjectStore> object_store)
: PlatformObject(realm)
, m_index(index)
, m_object_store_handle(object_store)
, m_name(index->name())
{
}
GC::Ref<IDBIndex> IDBIndex::create(JS::Realm& realm, GC::Ref<Index> index, GC::Ref<IDBObjectStore> object_store)
{
return realm.create<IDBIndex>(realm, index, object_store);
}
void IDBIndex::initialize(JS::Realm& realm)
{
WEB_SET_PROTOTYPE_FOR_INTERFACE(IDBIndex);
Base::initialize(realm);
}
void IDBIndex::visit_edges(Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(m_index);
visitor.visit(m_object_store_handle);
}
// https://w3c.github.io/IndexedDB/#dom-idbindex-name
WebIDL::ExceptionOr<void> IDBIndex::set_name(String const& value)
{
auto& realm = this->realm();
// 1. Let name be the given value.
auto const& name = value;
// 2. Let transaction be thiss transaction.
auto transaction = this->transaction();
// 3. Let index be thiss index.
auto index = this->index();
// 4. If transaction is not an upgrade transaction, throw an "InvalidStateError" DOMException.
if (!transaction->is_upgrade_transaction())
return WebIDL::InvalidStateError::create(realm, "Transaction is not an upgrade transaction"_string);
// 5. If transactions state is not active, then throw a "TransactionInactiveError" DOMException.
if (transaction->state() != IDBTransaction::TransactionState::Active)
return WebIDL::TransactionInactiveError::create(realm, "Transaction is not active"_string);
// FIXME: 6. If index or indexs object store has been deleted, throw an "InvalidStateError" DOMException.
// 7. If indexs name is equal to name, terminate these steps.
if (index->name() == name)
return {};
// 8. If an index named name already exists in indexs object store, throw a "ConstraintError" DOMException.
if (index->object_store()->index_set().contains(name))
return WebIDL::ConstraintError::create(realm, "An index with the given name already exists"_string);
// 9. Set indexs name to name.
index->set_name(name);
// NOTE: Update the key in the map so it still matches the name
auto old_value = m_object_store_handle->index_set().take(m_name).release_value();
m_object_store_handle->index_set().set(name, old_value);
// 10. Set thiss name to name.
m_name = name;
return {};
}
// https://w3c.github.io/IndexedDB/#dom-idbindex-keypath
JS::Value IDBIndex::key_path() const
{
return m_index->key_path().visit(
[&](String const& value) -> JS::Value {
return JS::PrimitiveString::create(realm().vm(), value);
},
[&](Vector<String> const& value) -> JS::Value {
return JS::Array::create_from<String>(realm(), value.span(), [&](auto const& entry) -> JS::Value {
return JS::PrimitiveString::create(realm().vm(), entry);
});
});
}
}