LibWeb/Bindings: Generate struct definitions from IDL dictionaries

Previously we were inconsistent by generating code for enum definitions
but not generating code for dictionaries. With future changes to the
IDL generator to expose helpers to convert to and from IDL values
this produced circular depdendencies. To solve this problem, also
generate the dictionary definitions in bindings headers.
This commit is contained in:
Shannon Booth
2026-05-01 19:01:23 +02:00
committed by Andreas Kling
parent 7ad946c669
commit 5adfd1c43a
Notes: github-actions[bot] 2026-05-09 08:51:32 +00:00
406 changed files with 1963 additions and 2837 deletions

View File

@@ -13,6 +13,79 @@ namespace Web::URLPattern {
GC_DEFINE_ALLOCATOR(URLPattern);
static URL::Pattern::Init to_internal_url_pattern_init(Bindings::URLPatternInit const& init)
{
return {
.protocol = init.protocol,
.username = init.username,
.password = init.password,
.hostname = init.hostname,
.port = init.port,
.pathname = init.pathname,
.search = init.search,
.hash = init.hash,
.base_url = init.base_url,
};
}
static Bindings::URLPatternInit to_bindings_url_pattern_init(URL::Pattern::Init const& init)
{
return {
.base_url = init.base_url,
.hash = init.hash,
.hostname = init.hostname,
.password = init.password,
.pathname = init.pathname,
.port = init.port,
.protocol = init.protocol,
.search = init.search,
.username = init.username,
};
}
static URL::Pattern::Input to_internal_url_pattern_input(URLPatternInput const& input)
{
return input.visit(
[](String const& input_string) -> URL::Pattern::Input { return input_string; },
[](Bindings::URLPatternInit const& input_init) -> URL::Pattern::Input { return to_internal_url_pattern_init(input_init); });
}
static Bindings::URLPatternComponentResult to_bindings_url_pattern_component_result(URL::Pattern::Component::Result const& result)
{
OrderedHashMap<String, Variant<String, Empty, Empty>> groups;
for (auto const& [key, value] : result.groups) {
groups.set(key, value.visit([](String const& string_value) -> Variant<String, Empty, Empty> { return string_value; }, [](Empty) -> Variant<String, Empty, Empty> { return Empty {}; }));
}
return {
.groups = move(groups),
.input = result.input,
};
}
static Bindings::URLPatternResult to_bindings_url_pattern_result(URL::Pattern::Result const& result)
{
Vector<Variant<String, Bindings::URLPatternInit>> inputs;
inputs.ensure_capacity(result.inputs.size());
for (auto const& input : result.inputs) {
inputs.unchecked_append(input.visit(
[](String const& string_value) -> Variant<String, Bindings::URLPatternInit> { return string_value; },
[](URL::Pattern::Init const& init_value) -> Variant<String, Bindings::URLPatternInit> { return to_bindings_url_pattern_init(init_value); }));
}
return {
.hash = to_bindings_url_pattern_component_result(result.hash),
.hostname = to_bindings_url_pattern_component_result(result.hostname),
.inputs = move(inputs),
.password = to_bindings_url_pattern_component_result(result.password),
.pathname = to_bindings_url_pattern_component_result(result.pathname),
.port = to_bindings_url_pattern_component_result(result.port),
.protocol = to_bindings_url_pattern_component_result(result.protocol),
.search = to_bindings_url_pattern_component_result(result.search),
.username = to_bindings_url_pattern_component_result(result.username),
};
}
URLPattern::URLPattern(JS::Realm& realm, URL::Pattern::Pattern pattern)
: PlatformObject(realm)
, m_url_pattern(move(pattern))
@@ -45,7 +118,7 @@ WebIDL::ExceptionOr<GC::Ref<URLPattern>> URLPattern::construct_impl(JS::Realm& r
WebIDL::ExceptionOr<GC::Ref<URLPattern>> URLPattern::create(JS::Realm& realm, URLPatternInput const& input, Optional<String> const& base_url, URLPatternOptions const& options)
{
// 1. Set thiss associated URL pattern to the result of create given input, baseURL, and options.
auto pattern_or_error = URL::Pattern::Pattern::create(input, base_url, options.ignore_case ? URL::Pattern::IgnoreCase::Yes : URL::Pattern::IgnoreCase::No);
auto pattern_or_error = URL::Pattern::Pattern::create(to_internal_url_pattern_input(input), base_url, options.ignore_case ? URL::Pattern::IgnoreCase::Yes : URL::Pattern::IgnoreCase::No);
if (pattern_or_error.is_error())
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, pattern_or_error.error().message };
return realm.create<URLPattern>(realm, pattern_or_error.release_value());
@@ -55,7 +128,7 @@ WebIDL::ExceptionOr<GC::Ref<URLPattern>> URLPattern::create(JS::Realm& realm, UR
WebIDL::ExceptionOr<bool> URLPattern::test(URLPatternInput const& input, Optional<String> const& base_url) const
{
// 1. Let result be the result of match given this's associated URL pattern, input, and baseURL if given.
auto result_or_error = m_url_pattern.match(input, base_url);
auto result_or_error = m_url_pattern.match(to_internal_url_pattern_input(input), base_url);
if (result_or_error.is_error())
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, result_or_error.error().message };
auto result = result_or_error.release_value();
@@ -72,10 +145,13 @@ WebIDL::ExceptionOr<bool> URLPattern::test(URLPatternInput const& input, Optiona
WebIDL::ExceptionOr<Optional<URLPatternResult>> URLPattern::exec(URLPatternInput const& input, Optional<String> const& base_url) const
{
// 1. Return the result of match given this's associated URL pattern, input, and baseURL if given.
auto result_or_error = m_url_pattern.match(input, base_url);
auto result_or_error = m_url_pattern.match(to_internal_url_pattern_input(input), base_url);
if (result_or_error.is_error())
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, result_or_error.error().message };
return result_or_error.release_value();
auto result = result_or_error.release_value();
if (!result.has_value())
return Optional<URLPatternResult> {};
return to_bindings_url_pattern_result(*result);
}
// https://urlpattern.spec.whatwg.org/#dom-urlpattern-protocol