LibWeb: Add support for caching IDL attribute values

This lets us properly implement for [SameObject] for generated
constructs like FrozenArray<T>.
This commit is contained in:
Idan Horowitz 2025-08-21 00:02:24 +03:00 committed by Tim Flynn
commit 4c49ce5fe5
Notes: github-actions[bot] 2025-08-26 10:29:52 +00:00
2 changed files with 38 additions and 1 deletions

View file

@ -0,0 +1,18 @@
/*
* Copyright (c) 2025, Idan Horowitz <idan.horowitz@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#define DEFINE_CACHED_ATTRIBUTE(name) \
GC::Ptr<JS::Object> cached_##name() const { return m_cached_##name; } \
void set_cached_##name(GC::Ptr<JS::Object> cached_##name) { m_cached_##name = cached_##name; } \
\
private: \
GC::Ptr<JS::Object> m_cached_##name; \
\
public:
#define VISIT_CACHED_ATTRIBUTE(name) visitor.visit(m_cached_##name)

View file

@ -3924,6 +3924,17 @@ JS_DEFINE_NATIVE_FUNCTION(@class_name@::@attribute.getter_callback@)
[[maybe_unused]] auto* impl = TRY(impl_from(vm));
)~~~");
auto cache_result = false;
if (attribute.extended_attributes.contains("CachedAttribute")) {
VERIFY(attribute.readonly);
cache_result = true;
attribute_generator.append(R"~~~(
auto cached_@attribute.cpp_name@ = impl->cached_@attribute.cpp_name@();
if (cached_@attribute.cpp_name@)
return cached_@attribute.cpp_name@;
)~~~");
}
if (attribute.extended_attributes.contains("CEReactions")) {
// 1. Push a new element queue onto this object's relevant agent's custom element reactions stack.
attribute_generator.append(R"~~~(
@ -4268,7 +4279,15 @@ JS_DEFINE_NATIVE_FUNCTION(@class_name@::@attribute.getter_callback@)
)~~~");
}
generate_return_statement(generator, *attribute.type, interface);
if (cache_result) {
generate_wrap_statement(generator, "retval", *attribute.type, interface, ByteString::formatted("cached_{} =", attribute_generator.get("attribute.cpp_name")));
attribute_generator.append(R"~~~(
impl->set_cached_@attribute.cpp_name@(cached_@attribute.cpp_name@);
return cached_@attribute.cpp_name@;
)~~~");
} else {
generate_return_statement(generator, *attribute.type, interface);
}
if (generated_reflected_element_array) {
// 3. Let elementsAsFrozenArray be elements, converted to a FrozenArray<T>?.