Pārlūkot izejas kodu

LibWeb+LibXML: Cache the result of parsing the XHTML DTD and reuse it

There's no reason to parse this again and again every time we parse an
XHTML document.
Ali Mohammad Pur 10 mēneši atpakaļ
vecāks
revīzija
24c2ad059b

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 13 - 4
Userland/Libraries/LibWeb/XML/XMLDocumentBuilder.cpp


+ 1 - 1
Userland/Libraries/LibWeb/XML/XMLDocumentBuilder.h

@@ -21,7 +21,7 @@ enum class XMLScriptingSupport {
     Enabled,
     Enabled,
 };
 };
 
 
-ErrorOr<ByteString> resolve_xml_resource(XML::SystemID const&, Optional<XML::PublicID> const&);
+ErrorOr<Variant<ByteString, Vector<XML::MarkupDeclaration>>> resolve_xml_resource(XML::SystemID const&, Optional<XML::PublicID> const&);
 
 
 class XMLDocumentBuilder final : public XML::Listener {
 class XMLDocumentBuilder final : public XML::Listener {
 public:
 public:

+ 19 - 10
Userland/Libraries/LibXML/Parser/Parser.cpp

@@ -573,15 +573,21 @@ ErrorOr<void, ParseError> Parser::parse_doctype_decl()
             if (m_options.resolve_external_resource) {
             if (m_options.resolve_external_resource) {
                 auto resource_result = m_options.resolve_external_resource(doctype.external_id->system_id, doctype.external_id->public_id);
                 auto resource_result = m_options.resolve_external_resource(doctype.external_id->system_id, doctype.external_id->public_id);
                 if (!resource_result.is_error()) {
                 if (!resource_result.is_error()) {
-                    StringView resolved_source = resource_result.value();
-                    TemporaryChange source { m_source, resolved_source };
-                    TemporaryChange lexer { m_lexer, LineTrackingLexer(m_source) };
-                    auto declarations = TRY(parse_external_subset());
-                    if (!m_lexer.is_eof()) {
-                        return parse_error(
-                            m_lexer.current_position(),
-                            ByteString::formatted("Failed to resolve external subset '{}': garbage after declarations", doctype.external_id->system_id.system_literal));
-                    }
+                    auto declarations = TRY(resource_result.release_value().visit(
+                        [&](ByteString resolved_source) -> ErrorOr<Vector<MarkupDeclaration>, ParseError> {
+                            TemporaryChange source { m_source, resolved_source.view() };
+                            TemporaryChange lexer { m_lexer, LineTrackingLexer(m_source) };
+                            auto declarations = TRY(parse_external_subset());
+                            if (!m_lexer.is_eof()) {
+                                return parse_error(
+                                    m_lexer.current_position(),
+                                    ByteString::formatted("Failed to resolve external subset '{}': garbage after declarations", doctype.external_id->system_id.system_literal));
+                            }
+                            return declarations;
+                        },
+                        [&](Vector<MarkupDeclaration> declarations) -> ErrorOr<Vector<MarkupDeclaration>, ParseError> {
+                            return declarations;
+                        }));
                     doctype.markup_declarations.extend(move(declarations));
                     doctype.markup_declarations.extend(move(declarations));
                 }
                 }
             }
             }
@@ -1755,7 +1761,10 @@ ErrorOr<ByteString, ParseError> Parser::resolve_reference(EntityReference const&
                     if (result.is_error())
                     if (result.is_error())
                         return parse_error(m_lexer.position_for(0), ByteString::formatted("Failed to resolve external entity '{}': {}", reference.name, result.error()));
                         return parse_error(m_lexer.position_for(0), ByteString::formatted("Failed to resolve external entity '{}': {}", reference.name, result.error()));
 
 
-                    resolved = result.release_value();
+                    if (!result.value().has<ByteString>())
+                        return parse_error(m_lexer.position_for(0), ByteString::formatted("Failed to resolve external entity '{}': Resource is of the wrong type", reference.name));
+
+                    resolved = result.release_value().get<ByteString>();
                     return {};
                     return {};
                 }));
                 }));
             break;
             break;

+ 3 - 2
Userland/Libraries/LibXML/Parser/Parser.h

@@ -49,7 +49,7 @@ public:
         bool preserve_cdata { true };
         bool preserve_cdata { true };
         bool preserve_comments { false };
         bool preserve_comments { false };
         bool treat_errors_as_fatal { true };
         bool treat_errors_as_fatal { true };
-        Function<ErrorOr<ByteString>(SystemID const&, Optional<PublicID> const&)> resolve_external_resource {};
+        Function<ErrorOr<Variant<ByteString, Vector<MarkupDeclaration>>>(SystemID const&, Optional<PublicID> const&)> resolve_external_resource {};
     };
     };
 
 
     Parser(StringView source, Options options)
     Parser(StringView source, Options options)
@@ -70,6 +70,8 @@ public:
 
 
     Vector<ParseError> const& parse_error_causes() const { return m_parse_errors; }
     Vector<ParseError> const& parse_error_causes() const { return m_parse_errors; }
 
 
+    ErrorOr<Vector<MarkupDeclaration>, ParseError> parse_external_subset();
+
 private:
 private:
     struct EntityReference {
     struct EntityReference {
         Name name;
         Name name;
@@ -138,7 +140,6 @@ private:
     ErrorOr<StringView, ParseError> parse_system_id_literal();
     ErrorOr<StringView, ParseError> parse_system_id_literal();
     ErrorOr<StringView, ParseError> parse_cdata_section();
     ErrorOr<StringView, ParseError> parse_cdata_section();
     ErrorOr<ByteString, ParseError> parse_attribute_value_inner(StringView disallow);
     ErrorOr<ByteString, ParseError> parse_attribute_value_inner(StringView disallow);
-    ErrorOr<Vector<MarkupDeclaration>, ParseError> parse_external_subset();
     ErrorOr<void, ParseError> parse_text_declaration();
     ErrorOr<void, ParseError> parse_text_declaration();
 
 
     ErrorOr<void, ParseError> expect(StringView);
     ErrorOr<void, ParseError> expect(StringView);

+ 1 - 1
Userland/Utilities/xml.cpp

@@ -362,7 +362,7 @@ static auto parse(StringView contents)
         contents,
         contents,
         {
         {
             .preserve_comments = true,
             .preserve_comments = true,
-            .resolve_external_resource = [&](XML::SystemID const& system_id, Optional<XML::PublicID> const&) -> ErrorOr<ByteString> {
+            .resolve_external_resource = [&](XML::SystemID const& system_id, Optional<XML::PublicID> const&) -> ErrorOr<Variant<ByteString, Vector<XML::MarkupDeclaration>>> {
                 auto base = URL::create_with_file_scheme(s_path);
                 auto base = URL::create_with_file_scheme(s_path);
                 auto url = URL::Parser::basic_parse(system_id.system_literal, base);
                 auto url = URL::Parser::basic_parse(system_id.system_literal, base);
                 if (!url.is_valid())
                 if (!url.is_valid())

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels