Repository: LadybirdBrowser/ladybird
File: Libraries/LibWeb/HTML/XMLSerializer.cpp (C++)

Code before:
    if (require_well_formed == RequireWellFormed::Yes) {
        // FIXME: Check comment's data against the XML Char production.

        if (comment.data().contains("--"sv))
            return WebIDL::InvalidStateError::create(comment.realm(), "Comment data contains two adjacent hyphens"_string);

        if (comment.data().ends_with('-'))
            return WebIDL::InvalidStateError::create(comment.realm(), "Comment data ends with a hyphen"_string);
    }

    // Otherwise, return the concatenation of "<!--", node's data, and "-->".
    return MUST(String::formatted("<!--{}-->", comment.data()));
}

// https://w3c.github.io/DOM-Parsing/#xml-serializing-a-text-node
static WebIDL::ExceptionOr<String> serialize_text(DOM::Text const& text, [[maybe_unused]] RequireWellFormed require_well_formed)
{
    // 1. If the require well-formed flag is set (its value is true), and node's data contains characters that are not matched by the XML Char production,
    //    then throw an exception; the serialization of this node's data would not be well-formed.
    if (require_well_formed == RequireWellFormed::Yes) {
        auto const& data = text.data();
        for (auto it = data.code_points().begin(); it != data.code_points().end(); ++it) {
            u32 code_point = *it;
            // XML 1.0 Char production:
            // https://www.w3.org/TR/xml/#charsets
            // #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
            bool is_valid_xml_char = code_point == 0x9 || code_point == 0xA || code_point == 0xD || (code_point >= 0x20 && code_point <= 0xD7FF) || (code_point >= 0xE000 && code_point <= 0xFFFD) || (code_point >= 0x10000 && code_point <= 0x10FFFF);
            if (!is_valid_xml_char)
                return WebIDL::InvalidStateError::create(text.realm(), "Text contains characters not allowed in XML"_string);
        }
    }

    // 2. Let markup be the value of node's data.
    auto markup = text.data();

    // 3. Replace any occurrences of "&" in markup by "&amp;".
    markup = MUST(markup.replace("&"sv, "&amp;"sv, ReplaceMode::All));

    // 4. Replace any occurrences of "<" in markup by "&lt;".
    markup = MUST(markup.replace("<"sv, "&lt;"sv, ReplaceMode::All));

    // 5. Replace any occurrences of ">" in markup by "&gt;".
    markup = MUST(markup.replace(">"sv, "&gt;"sv, ReplaceMode::All));

    // 6. Return the value of markup.
    return markup;
}

// https://w3c.github.io/DOM-Parsing/#xml-serializing-a-documentfragment-node
static WebIDL::ExceptionOr<String> serialize_document_fragment(DOM::DocumentFragment const& document_fragment, Optional<FlyString>& namespace_, HashMap<FlyString, Vector<Optional<FlyString>>>& namespace_prefix_map, u64& prefix_index, RequireWellFormed require_well_formed)
{

Review comment (suggestion):
Github won't let me comment on the line, but we can remove `[[maybe_unused]]` from the `require_well_formed` argument to this function

Code after:
    if (require_well_formed == RequireWellFormed::Yes) {
        // FIXME: Check comment's data against the XML Char production.

        if (comment.data().contains("--"sv))
            return WebIDL::InvalidStateError::create(comment.realm(), "Comment data contains two adjacent hyphens"_string);

        if (comment.data().ends_with('-'))
            return WebIDL::InvalidStateError::create(comment.realm(), "Comment data ends with a hyphen"_string);
    }

    // Otherwise, return the concatenation of "<!--", node's data, and "-->".
    return MUST(String::formatted("<!--{}-->", comment.data()));
}

static bool is_valid_xml_char(u32 code_point)
{
    // XML 1.0 Char production:
    // https://www.w3.org/TR/xml/#charsets
    // #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
    return code_point == 0x9 || code_point == 0xA || code_point == 0xD || (code_point >= 0x20 && code_point <= 0xD7FF) || (code_point >= 0xE000 && code_point <= 0xFFFD) || (code_point >= 0x10000 && code_point <= 0x10FFFF);
}

// https://w3c.github.io/DOM-Parsing/#xml-serializing-a-text-node
static WebIDL::ExceptionOr<String> serialize_text(DOM::Text const& text, RequireWellFormed require_well_formed)
{
    // 1. If the require well-formed flag is set (its value is true), and node's data contains characters that are not matched by the XML Char production,
    //    then throw an exception; the serialization of this node's data would not be well-formed.
    if (require_well_formed == RequireWellFormed::Yes) {
        for (u32 code_point : text.data().code_points()) {
            if (!is_valid_xml_char(code_point))
                return WebIDL::InvalidStateError::create(text.realm(), "Text contains characters not allowed in XML"_string);
        }
    }

    // 2. Let markup be the value of node's data.
    auto markup = text.data();

    // 3. Replace any occurrences of "&" in markup by "&amp;".
    markup = MUST(markup.replace("&"sv, "&amp;"sv, ReplaceMode::All));

    // 4. Replace any occurrences of "<" in markup by "&lt;".
    markup = MUST(markup.replace("<"sv, "&lt;"sv, ReplaceMode::All));

    // 5. Replace any occurrences of ">" in markup by "&gt;".
    markup = MUST(markup.replace(">"sv, "&gt;"sv, ReplaceMode::All));

    // 6. Return the value of markup.
    return markup;
}

// https://w3c.github.io/DOM-Parsing/#xml-serializing-a-documentfragment-node