From 348db1c445fa45892a29057110aec1c870e8acaf Mon Sep 17 00:00:00 2001 From: devgianlu Date: Sun, 29 Dec 2024 15:20:12 +0100 Subject: [PATCH] LibIDL+IDLGenerators: Support generation of IDL partial dictionaries --- Libraries/LibIDL/IDLParser.cpp | 27 +++++++++++++++++-- Libraries/LibIDL/Types.h | 1 + .../BindingsGenerator/IDLGenerators.cpp | 19 ++++++++++--- 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/Libraries/LibIDL/IDLParser.cpp b/Libraries/LibIDL/IDLParser.cpp index f134a348f1f..598ca6169a1 100644 --- a/Libraries/LibIDL/IDLParser.cpp +++ b/Libraries/LibIDL/IDLParser.cpp @@ -829,6 +829,13 @@ void Parser::parse_typedef(Interface& interface) void Parser::parse_dictionary(Interface& interface) { + bool partial = false; + if (lexer.next_is("partial")) { + assert_string("partial"sv); + consume_whitespace(); + partial = true; + } + assert_string("dictionary"sv); consume_whitespace(); @@ -896,7 +903,13 @@ void Parser::parse_dictionary(Interface& interface) return one.name < two.name; }); - interface.dictionaries.set(name, move(dictionary)); + if (partial) { + auto& it = interface.partial_dictionaries.ensure(name); + it.append(move(dictionary)); + } else { + interface.dictionaries.set(name, move(dictionary)); + } + consume_whitespace(); } @@ -952,7 +965,7 @@ void Parser::parse_non_interface_entities(bool allow_interface, Interface& inter HashMap extended_attributes; if (lexer.consume_specific('[')) extended_attributes = parse_extended_attributes(); - if (lexer.next_is("dictionary")) { + if (lexer.next_is("dictionary") || lexer.next_is("partial dictionary")) { parse_dictionary(interface); } else if (lexer.next_is("enum")) { parse_enumeration(extended_attributes, interface); @@ -1093,6 +1106,11 @@ Interface& Parser::parse() for (auto& dictionary : import.dictionaries) interface.dictionaries.set(dictionary.key, dictionary.value); + for (auto& partial_dictionary : import.partial_dictionaries) { + auto& it = interface.partial_dictionaries.ensure(partial_dictionary.key); + it.extend(partial_dictionary.value); + } + for (auto& enumeration : import.enumerations) { auto enumeration_copy = enumeration.value; enumeration_copy.is_original_definition = false; @@ -1172,6 +1190,11 @@ Interface& Parser::parse() for (auto& dictionary_member : dictionary.value.members) resolve_typedef(interface, dictionary_member.type, &dictionary_member.extended_attributes); } + for (auto& dictionaries : interface.partial_dictionaries) { + for (auto& dictionary : dictionaries.value) + for (auto& dictionary_member : dictionary.members) + resolve_typedef(interface, dictionary_member.type, &dictionary_member.extended_attributes); + } for (auto& callback_function : interface.callback_functions) resolve_function_typedefs(interface, callback_function.value); diff --git a/Libraries/LibIDL/Types.h b/Libraries/LibIDL/Types.h index 36bd68ae615..1702ab798e9 100644 --- a/Libraries/LibIDL/Types.h +++ b/Libraries/LibIDL/Types.h @@ -297,6 +297,7 @@ public: Optional named_property_deleter; HashMap dictionaries; + HashMap> partial_dictionaries; HashMap enumerations; HashMap typedefs; HashMap mixins; diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp index 78100b9621e..900137caa4b 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp @@ -897,11 +897,23 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter @parameter.type.name@ @cpp_name@ {}; )~~~"); - auto* current_dictionary = &interface.dictionaries.find(parameter.type->name())->value; + auto current_dictionary_name = parameter.type->name(); + auto* current_dictionary = &interface.dictionaries.find(current_dictionary_name)->value; // FIXME: This (i) is a hack to make sure we don't generate duplicate variable names. static auto i = 0; while (true) { - for (auto& member : current_dictionary->members) { + Vector members; + for (auto& member : current_dictionary->members) + members.append(member); + + if (interface.partial_dictionaries.contains(current_dictionary_name)) { + auto& partial_dictionaries = interface.partial_dictionaries.find(current_dictionary_name)->value; + for (auto& partial_dictionary : partial_dictionaries) + for (auto& member : partial_dictionary.members) + members.append(member); + } + + for (auto& member : members) { dictionary_generator.set("member_key", member.name); auto member_js_name = make_input_acceptable_cpp(member.name.to_snakecase()); auto member_value_name = ByteString::formatted("{}_value_{}", member_js_name, i); @@ -953,7 +965,8 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter if (current_dictionary->parent_name.is_empty()) break; VERIFY(interface.dictionaries.contains(current_dictionary->parent_name)); - current_dictionary = &interface.dictionaries.find(current_dictionary->parent_name)->value; + current_dictionary_name = current_dictionary->parent_name; + current_dictionary = &interface.dictionaries.find(current_dictionary_name)->value; } } else if (interface.callback_functions.contains(parameter.type->name())) { // https://webidl.spec.whatwg.org/#es-callback-function