From 9ee2473aa4ff65699d1aa5ad937d4a98d304efe9 Mon Sep 17 00:00:00 2001 From: Andrew Kaster Date: Sat, 22 Mar 2025 19:12:30 -0600 Subject: [PATCH] LibWeb+LibGC: Import GC swift module into LibWeb and an initial user Start work on a speculative HTML Parser in Swift. This component will walk ahead of the normal HTML parser looking for fetch() requests to make while the normal parser is blocked. This work exposed many holes in the Swift C++ interop component, which have been reported upstream. --- Libraries/LibWeb/CMakeLists.txt | 3 +- Libraries/LibWeb/HTML/Parser/HTMLParser.h | 6 +- .../HTML/Parser/SpeculativeHTMLParser.swift | 60 +++++++++++++++++++ Libraries/LibWeb/Loader/FileRequest.h | 3 +- Tests/LibWeb/CMakeLists.txt | 2 +- 5 files changed, 70 insertions(+), 4 deletions(-) create mode 100644 Libraries/LibWeb/HTML/Parser/SpeculativeHTMLParser.swift diff --git a/Libraries/LibWeb/CMakeLists.txt b/Libraries/LibWeb/CMakeLists.txt index c2afad4e37c..565542c078b 100644 --- a/Libraries/LibWeb/CMakeLists.txt +++ b/Libraries/LibWeb/CMakeLists.txt @@ -999,7 +999,8 @@ if (ENABLE_SWIFT) HTML/Parser/HTMLToken.swift HTML/Parser/HTMLTokenizer.swift HTML/Parser/HTMLTokenizerHelpers.cpp + HTML/Parser/SpeculativeHTMLParser.swift ) target_link_libraries(LibWeb PRIVATE AK Collections) - add_swift_target_properties(LibWeb LAGOM_LIBRARIES AK LibGfx) + add_swift_target_properties(LibWeb LAGOM_LIBRARIES AK LibGfx LibGC COMPILE_DEFINITIONS LIBGC_WORKAROUND_BOOL_BITFIELD) endif() diff --git a/Libraries/LibWeb/HTML/Parser/HTMLParser.h b/Libraries/LibWeb/HTML/Parser/HTMLParser.h index 45b53fc99a0..16902a40c76 100644 --- a/Libraries/LibWeb/HTML/Parser/HTMLParser.h +++ b/Libraries/LibWeb/HTML/Parser/HTMLParser.h @@ -214,10 +214,14 @@ private: GC::Ptr m_character_insertion_node; StringBuilder m_character_insertion_builder; -}; +} SWIFT_UNSAFE_REFERENCE; RefPtr parse_dimension_value(StringView); RefPtr parse_nonzero_dimension_value(StringView); Optional parse_legacy_color_value(StringView); +// Swift interop +using HTMLParserGCPtr = GC::Ptr; +using HTMLParserGCRef = GC::Ref; + } diff --git a/Libraries/LibWeb/HTML/Parser/SpeculativeHTMLParser.swift b/Libraries/LibWeb/HTML/Parser/SpeculativeHTMLParser.swift new file mode 100644 index 00000000000..fae5d34d124 --- /dev/null +++ b/Libraries/LibWeb/HTML/Parser/SpeculativeHTMLParser.swift @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2025, Andrew Kaster > + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +import AK +import Collections +import Foundation +import GC +@_exported import WebCxx + +// Workaround for https://github.com/swiftlang/swift/issues/80231 +// If any line of this changes, the whole thing breaks though +extension GC.Cell.Visitor { + public func visit(_ parser: Web.HTML.HTMLParserGCPtr) { + if let parser = parser.ptr() { + let cell: GC.Cell = cxxCast(parser) + visit(cell) + } + } +} + +struct SpeculativeMockElement { + let name: Swift.String + let localName: Swift.String + let attributes: [HTMLToken.Attribute] + var children: [SpeculativeMockElement] + + init(name: Swift.String, localName: Swift.String, attributes: [HTMLToken.Attribute]) { + self.name = name + self.localName = localName + self.attributes = attributes + self.children = [] + } + + mutating func appendChild(_ child: consuming SpeculativeMockElement) { + children.append(child) + } +} + +public final class SpeculativeHTMLParser: HeapAllocatable { + var parser = Web.HTML.HTMLParserGCPtr() // FIXME: Want HTMLParserGCRef here, but how to initialize it? + + public init(cell: GC.Cell) { + self.cell = cell + } + public var cell: GC.Cell + + public static func create(on heap: GC.Heap, `for` parser: Web.HTML.HTMLParserGCPtr) -> GC.Cell { + precondition(heap.is_gc_deferred()) + let _self = allocate(on: heap) + _self.pointee.parser = parser + return _self.pointee.cell + } + + public func visitEdges(_ visitor: GC.Cell.Visitor) { + visitor.visit(parser) + } +} diff --git a/Libraries/LibWeb/Loader/FileRequest.h b/Libraries/LibWeb/Loader/FileRequest.h index 05f862dafb7..8e7828915e6 100644 --- a/Libraries/LibWeb/Loader/FileRequest.h +++ b/Libraries/LibWeb/Loader/FileRequest.h @@ -9,6 +9,7 @@ #include #include #include +#include namespace Web { @@ -22,6 +23,6 @@ public: private: ByteString m_path {}; -}; +} SWIFT_UNSAFE_REFERENCE; // FIXME: This type is actually move-only, not unsafe } diff --git a/Tests/LibWeb/CMakeLists.txt b/Tests/LibWeb/CMakeLists.txt index bd34970a44f..fa0c06e3782 100644 --- a/Tests/LibWeb/CMakeLists.txt +++ b/Tests/LibWeb/CMakeLists.txt @@ -29,6 +29,6 @@ if (ENABLE_SWIFT) target_sources(TestLibWebSwift PRIVATE ../Resources/SwiftTestMain.swift) set_target_properties(TestLibWebSwift PROPERTIES SUFFIX .swift-testing) - target_link_libraries(TestLibWebSwift PRIVATE AK LibWeb SwiftTesting::SwiftTesting) + target_link_libraries(TestLibWebSwift PRIVATE AK LibWeb LibGC SwiftTesting::SwiftTesting) add_test(NAME TestLibWebSwift COMMAND TestLibWebSwift) endif()