Commit 540fd6e96bb for php.net

commit 540fd6e96bb12a466cb0e4ea4696fd1ad618ef7f
Author: Niels Dossche <7771979+ndossche@users.noreply.github.com>
Date:   Mon Nov 3 18:46:56 2025 +0100

    dom: Optimize splitText() (#20371)

    This avoids duplicating the intermediate strings, by transferring
    ownership.

    It's hard to measure the improvement in a reliable way, as we have to
    operate on the same node. The following benchmark shows a nice
    improvement (although not perfect as a benchmark):
    ```php
    <?php

    $dom = new DOMDocument;
    $dom->loadXML('<root>testabcdef</root>');
    $text = $dom->documentElement->firstChild;

    for ($i = 0; $i < 1000000; $i++) {
        $text2 = clone $text;
        $text2->splitText(5);
    }
    ```

    Only tested on my desktop i7-4790:
    ```
    Benchmark 1: ./sapi/cli/php x.php
      Time (mean ± σ):     284.1 ms ±   2.8 ms    [User: 280.0 ms, System: 3.0 ms]
      Range (min … max):   281.4 ms … 291.3 ms    10 runs

    Benchmark 2: ./sapi/cli/php_old x.php
      Time (mean ± σ):     314.0 ms ±   7.8 ms    [User: 309.2 ms, System: 2.9 ms]
      Range (min … max):   306.5 ms … 328.0 ms    10 runs

    Summary
      ./sapi/cli/php x.php ran
        1.11 ± 0.03 times faster than ./sapi/cli/php_old x.php
    ```

diff --git a/UPGRADING b/UPGRADING
index f4a455caefa..7a3aff95da8 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -117,5 +117,8 @@ PHP 8.6 UPGRADE NOTES
   . Arguments are now passed more efficiently to known constructors (e.g. when
     using new self()).

+- DOM:
+  . Made splitText() faster and consume less memory.
+
 - JSON:
   . Improve performance of encoding arrays and objects.
diff --git a/ext/dom/text.c b/ext/dom/text.c
index b08619252b8..4c503201c8b 100644
--- a/ext/dom/text.c
+++ b/ext/dom/text.c
@@ -127,17 +127,18 @@ PHP_METHOD(DOMText, splitText)
 	first = xmlUTF8Strndup(cur, (int)offset);
 	second = xmlUTF8Strsub(cur, (int)offset, (int)(length - offset));

-	xmlNodeSetContent(node, first);
-	nnode = xmlNewDocText(node->doc, second);
-
-	xmlFree(first);
-	xmlFree(second);
+	xmlNodeSetContent(node, NULL);
+	node->content = first;
+	nnode = xmlNewDocText(node->doc, NULL);

 	if (nnode == NULL) {
+		xmlFree(second);
 		php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true);
 		RETURN_THROWS();
 	}

+	nnode->content = second;
+
 	if (node->parent != NULL) {
 		nnode->type = XML_ELEMENT_NODE;
 		xmlAddNextSibling(node, nnode);