LibWeb: Parse support IDL files when generating bindings

Teach the bindings build to pass support IDL files alongside the regular
binding IDLs so BindingsGenerator parses the full declared IDL set into
a shared context.

Keep idl_files.cmake as the source of truth for parsed support IDLs, and
let Interface::will_generate_code() decide which parsed interfaces emit
generated bindings.
This commit is contained in:
Shannon Booth
2026-04-23 21:46:55 +02:00
committed by Shannon Booth
parent 5f3812ecca
commit a153732a64
Notes: github-actions[bot] 2026-04-24 18:09:46 +00:00
6 changed files with 117 additions and 17 deletions

View File

@@ -869,6 +869,7 @@ void Parser::parse_partial_interface(HashMap<ByteString, ByteString> extended_at
assert_string("interface"sv);
auto partial_interface = make<Interface>(context);
partial_interface->is_partial = true;
partial_interface->extended_attributes = move(extended_attributes);
parse_interface(*partial_interface);
parent.context.partial_interfaces.append(move(partial_interface));
@@ -916,6 +917,7 @@ void Parser::parse_partial_namespace(Interface& parent)
assert_string("namespace"sv);
auto partial_namespace = make<Interface>(context);
partial_namespace->is_partial = true;
parse_namespace(*partial_namespace);
parent.context.partial_namespaces.append(move(partial_namespace));
}

View File

@@ -319,9 +319,10 @@ bool Type::is_json(Context const& context) const
bool Interface::will_generate_code() const
{
return !name.is_empty()
|| !own_dictionaries.is_empty()
|| !own_enumerations.is_empty();
return !is_partial
&& (!name.is_empty()
|| !own_dictionaries.is_empty()
|| !own_enumerations.is_empty());
}
void EffectiveOverloadSet::remove_all_other_entries()

View File

@@ -280,6 +280,7 @@ public:
bool is_namespace { false };
bool is_mixin { false };
bool is_callback_interface { false };
bool is_partial { false };
HashMap<ByteString, ByteString> extended_attributes;

View File

@@ -567,3 +567,81 @@ libweb_js_bindings(XHR/XMLHttpRequestUpload)
libweb_js_bindings(XPath/XPathResult)
libweb_js_bindings(XPath/XPathExpression)
libweb_js_bindings(XPath/XPathEvaluator)
libweb_support_idl(ARIA/ARIAMixin)
libweb_support_idl(Animations/Animatable)
libweb_support_idl(CSS/ElementCSSInlineStyle)
libweb_support_idl(CSS/LinkStyle)
libweb_support_idl(DOM/ChildNode)
libweb_support_idl(DOM/DocumentOrShadowRoot)
libweb_support_idl(DOM/EventHandler)
libweb_support_idl(DOM/EventListener)
libweb_support_idl(DOM/ParentNode)
libweb_support_idl(DOM/Slottable)
libweb_support_idl(Encoding/TextEncoderCommon)
libweb_support_idl(Fetch/Body)
libweb_support_idl(Fetch/BodyInit)
libweb_support_idl(Fullscreen/DocumentExtensions)
libweb_support_idl(Fullscreen/DocumentOrShadowRootExtensions)
libweb_support_idl(Fullscreen/ElementExtensions)
libweb_support_idl(GPC/GlobalPrivacyControl)
libweb_support_idl(HTML/AbstractWorker)
libweb_support_idl(HTML/AnimationFrameProvider)
libweb_support_idl(HTML/Canvas/CanvasCompositing)
libweb_support_idl(HTML/Canvas/CanvasDrawImage)
libweb_support_idl(HTML/Canvas/CanvasDrawPath)
libweb_support_idl(HTML/Canvas/CanvasFillStrokeStyles)
libweb_support_idl(HTML/Canvas/CanvasFilters)
libweb_support_idl(HTML/Canvas/CanvasImageData)
libweb_support_idl(HTML/Canvas/CanvasImageSmoothing)
libweb_support_idl(HTML/Canvas/CanvasPath)
libweb_support_idl(HTML/Canvas/CanvasPathDrawingStyles)
libweb_support_idl(HTML/Canvas/CanvasRect)
libweb_support_idl(HTML/Canvas/CanvasSettings)
libweb_support_idl(HTML/Canvas/CanvasShadowStyles)
libweb_support_idl(HTML/Canvas/CanvasState)
libweb_support_idl(HTML/Canvas/CanvasText)
libweb_support_idl(HTML/Canvas/CanvasTextDrawingStyles)
libweb_support_idl(HTML/Canvas/CanvasTransform)
libweb_support_idl(HTML/Canvas/CanvasUserInterface)
libweb_support_idl(HTML/Canvas/OffscreenCanvasBase)
libweb_support_idl(HTML/HTMLHyperlinkElementUtils)
libweb_support_idl(HTML/HTMLOrSVGElement)
libweb_support_idl(HTML/NavigationType)
libweb_support_idl(HTML/NavigatorBeacon)
libweb_support_idl(HTML/NavigatorConcurrentHardware)
libweb_support_idl(HTML/NavigatorDeviceMemory)
libweb_support_idl(HTML/NavigatorID)
libweb_support_idl(HTML/NavigatorLanguage)
libweb_support_idl(HTML/NavigatorOnLine)
libweb_support_idl(HTML/PopoverTargetAttributes)
libweb_support_idl(HTML/Scripting/Fetching)
libweb_support_idl(HTML/UniversalGlobalScope)
libweb_support_idl(HTML/WindowDeprecated)
libweb_support_idl(HTML/WindowLocalStorage)
libweb_support_idl(HTML/WindowOrWorkerGlobalScope)
libweb_support_idl(HTML/WindowSessionStorage)
libweb_support_idl(HighResolutionTime/DOMHighResTimeStamp)
libweb_support_idl(HighResolutionTime/EpochTimeStamp)
libweb_support_idl(MediaCapture/MediaStreamConstraints)
libweb_support_idl(NavigationTiming/PerformanceExtensions)
libweb_support_idl(RequestIdleCallback/IdleRequest)
libweb_support_idl(SVG/SVGFilterPrimitiveStandardAttributes)
libweb_support_idl(SVG/SVGFitToViewBox)
libweb_support_idl(SVG/SVGURIReference)
libweb_support_idl(StorageAPI/NavigatorStorage)
libweb_support_idl(Streams/GenericTransformStream)
libweb_support_idl(Streams/QueuingStrategy)
libweb_support_idl(Streams/QueuingStrategyInit)
libweb_support_idl(Streams/ReadableStreamGenericReader)
libweb_support_idl(UIEvents/EventModifier)
libweb_support_idl(UIEvents/PointerEventHandlers)
libweb_support_idl(WebGL/Types)
libweb_support_idl(WebGL/WebGL2RenderingContextBase)
libweb_support_idl(WebGL/WebGL2RenderingContextOverloads)
libweb_support_idl(WebGL/WebGLRenderingContextBase)
libweb_support_idl(WebGL/WebGLRenderingContextOverloads)
libweb_support_idl(WebIDL/Function)
libweb_support_idl(XPath/XPathNSResolver)
libweb_generated_support_idl(CSS/GeneratedCSSStyleProperties)
libweb_generated_support_idl(CSS/GeneratedCSSNumericFactoryMethods)

View File

@@ -236,6 +236,7 @@ function (generate_js_bindings target)
list(TRANSFORM generated_idl_targets PREPEND "generate_")
set(LIBWEB_ALL_BINDINGS_SOURCES)
set(LIBWEB_ALL_IDL_FILES)
set(LIBWEB_ALL_PARSED_IDL_FILES)
function(libweb_js_bindings class)
get_filename_component(basename "${class}" NAME)
@@ -256,6 +257,19 @@ function (generate_js_bindings target)
list(APPEND LIBWEB_ALL_IDL_FILES "${LIBWEB_INPUT_FOLDER}/${class}.idl")
set(LIBWEB_ALL_IDL_FILES ${LIBWEB_ALL_IDL_FILES} PARENT_SCOPE)
list(APPEND LIBWEB_ALL_PARSED_IDL_FILES "${LIBWEB_INPUT_FOLDER}/${class}.idl")
set(LIBWEB_ALL_PARSED_IDL_FILES ${LIBWEB_ALL_PARSED_IDL_FILES} PARENT_SCOPE)
endfunction()
function(libweb_support_idl class)
list(APPEND LIBWEB_ALL_PARSED_IDL_FILES "${LIBWEB_INPUT_FOLDER}/${class}.idl")
set(LIBWEB_ALL_PARSED_IDL_FILES ${LIBWEB_ALL_PARSED_IDL_FILES} PARENT_SCOPE)
endfunction()
function(libweb_generated_support_idl class)
list(APPEND LIBWEB_ALL_PARSED_IDL_FILES "${CMAKE_CURRENT_BINARY_DIR}/${class}.idl")
set(LIBWEB_ALL_PARSED_IDL_FILES ${LIBWEB_ALL_PARSED_IDL_FILES} PARENT_SCOPE)
endfunction()
function(generate_exposed_interface_files)
@@ -300,22 +314,29 @@ function (generate_js_bindings target)
endfunction()
include("idl_files.cmake")
list(REMOVE_DUPLICATES LIBWEB_ALL_PARSED_IDL_FILES)
set(LIBWEB_ALL_IDL_FILES_ARGUMENT ${LIBWEB_ALL_IDL_FILES})
set(LIBWEB_ALL_PARSED_IDL_FILES_ARGUMENT ${LIBWEB_ALL_PARSED_IDL_FILES})
if (WIN32)
list(JOIN LIBWEB_ALL_IDL_FILES "\n" idl_file_list)
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/all_idl_files.txt" CONTENT "${idl_file_list}" NEWLINE_STYLE UNIX)
set(LIBWEB_ALL_IDL_FILES_ARGUMENT "@${CMAKE_CURRENT_BINARY_DIR}/all_idl_files.txt")
list(JOIN LIBWEB_ALL_PARSED_IDL_FILES "\n" parsed_idl_file_list)
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/all_parsed_idl_files.txt" CONTENT "${parsed_idl_file_list}" NEWLINE_STYLE UNIX)
set(LIBWEB_ALL_PARSED_IDL_FILES_ARGUMENT "@${CMAKE_CURRENT_BINARY_DIR}/all_parsed_idl_files.txt")
endif()
add_custom_command(
OUTPUT ${LIBWEB_ALL_BINDINGS_SOURCES}
COMMAND "${CMAKE_COMMAND}" -E make_directory "Bindings"
COMMAND "$<TARGET_FILE:Lagom::BindingsGenerator>" -o "Bindings" --depfile "Bindings/all_bindings.d"
-b "${LIBWEB_INPUT_FOLDER}" -b "${CMAKE_CURRENT_BINARY_DIR}" ${LIBWEB_ALL_IDL_FILES_ARGUMENT}
-b "${LIBWEB_INPUT_FOLDER}" -b "${CMAKE_CURRENT_BINARY_DIR}"
${LIBWEB_ALL_PARSED_IDL_FILES_ARGUMENT}
VERBATIM
COMMENT "Generating LibWeb bindings"
DEPENDS Lagom::BindingsGenerator ${LIBWEB_ALL_IDL_FILES}
DEPENDS Lagom::BindingsGenerator ${LIBWEB_ALL_IDL_FILES} ${LIBWEB_ALL_PARSED_IDL_FILES}
DEPFILE ${CMAKE_CURRENT_BINARY_DIR}/Bindings/all_bindings.d
)

View File

@@ -143,8 +143,6 @@ ErrorOr<int> ladybird_main(Main::Arguments arguments)
Vector<ByteString> dependency_paths;
HashTable<ByteString> seen_dependency_paths;
Vector<ByteString> output_files;
Vector<LexicalPath> lexical_paths;
Vector<IDL::Interface*> interfaces;
auto append_dependency_path = [&](ByteString const& dependency_path) {
if (seen_dependency_paths.set(dependency_path) != AK::HashSetResult::InsertedNewEntry)
@@ -154,18 +152,12 @@ ErrorOr<int> ladybird_main(Main::Arguments arguments)
for (auto const& path : paths) {
auto file = TRY(Core::MappedFile::map(path, Core::MappedFile::Mode::ReadOnly));
lexical_paths.empend(path);
auto& lexical_path = lexical_paths.last();
auto lexical_path = LexicalPath { path };
auto import_base_paths = base_paths;
if (import_base_paths.is_empty())
import_base_paths.append(lexical_path.dirname());
auto module = IDL::Parser::parse(path, file->bytes(), move(import_base_paths), context);
VERIFY(module.interface.has_value());
auto& interface = module.interface.value();
interfaces.append(&interface);
append_dependency_path(path);
for (auto const& imported_file : module.imported_files)
append_dependency_path(imported_file);
@@ -174,13 +166,18 @@ ErrorOr<int> ladybird_main(Main::Arguments arguments)
for (auto& interface : context.owned_interfaces)
assign_fully_qualified_name(*interface);
for (size_t i = 0; i < paths.size(); ++i) {
auto const& lexical_path = lexical_paths[i];
auto& interface = *interfaces[i];
for (auto const& module : context.owned_modules) {
if (!module->interface.has_value())
continue;
auto& interface = module->interface.value();
if (!interface.will_generate_code())
continue;
if constexpr (BINDINGS_GENERATOR_DEBUG)
interface.dump();
auto lexical_path = LexicalPath { module->module_own_path };
auto path_prefix = LexicalPath::join(output_path, lexical_path.basename(LexicalPath::StripExtension::Yes));
auto header_path = ByteString::formatted("{}.h", path_prefix);
auto implementation_path = ByteString::formatted("{}.cpp", path_prefix);