Skip to content

Conversation

@d-ronnqvist
Copy link
Contributor

Bug/issue #, if applicable:

Summary

This is a follow up change from #1369

It adds tests for how the DocCHTML/MarkdownRenderer processes inline HTML—skipping any comments while preserving the rest. With these tests in place, I could refactor the implementation with more confidence and extract the inner loop into a private function.

Dependencies

None.

Testing

Nothing in particular for this PR. It only adds tests and makes minor code cleanup to functionality that is only exercised in tests so far. See #1366 for how it eventually does get used.

Checklist

Make sure you check off the following items. If they cannot be completed, provide a reason.

  • Added tests
  • Ran the ./bin/test script and it succeeded
  • Updated documentation if necessary

@d-ronnqvist
Copy link
Contributor Author

@swift-ci please test

Copy link
Contributor

@patshaughnessy patshaughnessy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks much better now - thanks for refactoring this! With the new comments and extracted functions it's much easier for me to follow the algorithm 👍


// On non-Darwin platforms, `XMLElement(xmlString:)` sometimes crashes for certain invalid / incomplete XML strings.
// To minimize the risk of this happening, don't try to parse the XML string as an empty HTML element unless it ends with "/>"
if rawHTML.hasSuffix("/>"), let parsed = try? XMLElement(xmlString: rawHTML) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you run into some crashes while running your new tests in Linux CI?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the Linux CI doesn't encounter any crashes with these changes. Locally, a Swift 6.0.3 container also didn't have any issues with the implementation in either 84dbf48 or e540ba3.

let element = elements.removeFirst()

guard let start = element as? InlineHTML else {
var remainder = Array(container)[...]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you're using a slice here, I imagine this is quite efficient, even though we are mutating remainder.

Copy link
Contributor Author

@d-ronnqvist d-ronnqvist Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, because a slice is a portion of a buffer that's owned by another object, mutating the slice can be thought of as updating the start and end indices, which is very cheap.

If you use the Godbolt Compiler Explorer you can see that these two implementations produce rather comparable assembly code:

// Iterating over an array
func iterate(over numbers: [Int], doing work: (Int) -> Void) {
    for number in numbers {
        work(number)
    }
}
// Mutating a slice by repeatedly popping the first element
func iterate(over numbers: [Int], doing work: (Int) -> Void) {
    var remainder = numbers[...]
    while let number = remainder.popFirst() {
        work(number)
    }
}

Further; if the "work" is known to the compiler, like in the comparison below, then the Swift compiler is more likely to be able to optimize away those extra retain and release calls:

// Iterating over an array
func sum(numbers: [Int]) -> Int {
    var total = 0
    for number in numbers {
        total += number
    }
    return total
}
// Mutating a slice by repeatedly popping the first element
func sum(numbers: [Int]) -> Int {
    var total = 0
    var remainder = numbers[...]
    while let number = remainder.popFirst() {
        total += number
    }
    return total
}

d-ronnqvist and others added 2 commits December 8, 2025 10:53
@d-ronnqvist
Copy link
Contributor Author

@swift-ci please test

@d-ronnqvist d-ronnqvist merged commit f561a86 into swiftlang:main Dec 8, 2025
2 checks passed
@d-ronnqvist d-ronnqvist deleted the output-html-parse-inline branch December 8, 2025 10:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants