Skip to content

Corrections to return type of loading DOM documents #11803

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,11 @@ PHP 8.3 UPGRADE NOTES

- Dom:
. Changed DOMCharacterData::appendData() tentative return type to true.
. DOMDocument::loadHTML(), DOMDocument::loadHTMLFile(), DOMDocument::loadXML(),
and DOMDocument::loadXMLFile() now have a tentative return type of bool.
Previously, this was documented as having a return type of DOMDocument|bool,
but DOMDocument cannot be returned since PHP 8.0 as it is no longer statically
callable.

- Gd:
. Changed imagerotate signature, removed the `ignore_transparent` argument
Expand Down
135 changes: 59 additions & 76 deletions ext/dom/document.c
Original file line number Diff line number Diff line change
Expand Up @@ -1317,20 +1317,14 @@ static xmlDocPtr dom_document_parser(zval *id, int mode, char *source, size_t so

/* {{{ static void dom_parse_document(INTERNAL_FUNCTION_PARAMETERS, int mode) */
static void dom_parse_document(INTERNAL_FUNCTION_PARAMETERS, int mode) {
zval *id;
xmlDoc *docp = NULL, *newdoc;
dom_doc_propsptr doc_prop;
dom_object *intern;
char *source;
size_t source_len;
int refcount, ret;
int refcount;
zend_long options = 0;

id = getThis();
if (id != NULL && ! instanceof_function(Z_OBJCE_P(id), dom_document_class_entry)) {
id = NULL;
}

if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &source, &source_len, &options) == FAILURE) {
RETURN_THROWS();
}
Expand All @@ -1348,48 +1342,44 @@ static void dom_parse_document(INTERNAL_FUNCTION_PARAMETERS, int mode) {
RETURN_FALSE;
}

newdoc = dom_document_parser(id, mode, source, source_len, options);
newdoc = dom_document_parser(ZEND_THIS, mode, source, source_len, options);

if (!newdoc)
RETURN_FALSE;

if (id != NULL) {
intern = Z_DOMOBJ_P(id);
size_t old_modification_nr = 0;
if (intern != NULL) {
docp = (xmlDocPtr) dom_object_get_node(intern);
doc_prop = NULL;
if (docp != NULL) {
const php_libxml_doc_ptr *doc_ptr = docp->_private;
ZEND_ASSERT(doc_ptr != NULL); /* Must exist, we have a document */
old_modification_nr = doc_ptr->cache_tag.modification_nr;
php_libxml_decrement_node_ptr((php_libxml_node_object *) intern);
doc_prop = intern->document->doc_props;
intern->document->doc_props = NULL;
refcount = php_libxml_decrement_doc_ref((php_libxml_node_object *)intern);
if (refcount != 0) {
docp->_private = NULL;
}
}
intern->document = NULL;
if (php_libxml_increment_doc_ref((php_libxml_node_object *)intern, newdoc) == -1) {
RETURN_FALSE;
intern = Z_DOMOBJ_P(ZEND_THIS);
size_t old_modification_nr = 0;
if (intern != NULL) {
docp = (xmlDocPtr) dom_object_get_node(intern);
doc_prop = NULL;
if (docp != NULL) {
const php_libxml_doc_ptr *doc_ptr = docp->_private;
ZEND_ASSERT(doc_ptr != NULL); /* Must exist, we have a document */
old_modification_nr = doc_ptr->cache_tag.modification_nr;
php_libxml_decrement_node_ptr((php_libxml_node_object *) intern);
doc_prop = intern->document->doc_props;
intern->document->doc_props = NULL;
refcount = php_libxml_decrement_doc_ref((php_libxml_node_object *)intern);
if (refcount != 0) {
docp->_private = NULL;
}
intern->document->doc_props = doc_prop;
}

php_libxml_increment_node_ptr((php_libxml_node_object *)intern, (xmlNodePtr)newdoc, (void *)intern);
/* Since iterators should invalidate, we need to start the modification number from the old counter */
if (old_modification_nr != 0) {
php_libxml_doc_ptr* doc_ptr = (php_libxml_doc_ptr*) ((php_libxml_node_object*) intern)->node; /* downcast */
doc_ptr->cache_tag.modification_nr = old_modification_nr;
php_libxml_invalidate_node_list_cache(doc_ptr);
intern->document = NULL;
if (php_libxml_increment_doc_ref((php_libxml_node_object *)intern, newdoc) == -1) {
RETURN_FALSE;
}
intern->document->doc_props = doc_prop;
}

RETURN_TRUE;
} else {
DOM_RET_OBJ((xmlNodePtr) newdoc, &ret, NULL);
php_libxml_increment_node_ptr((php_libxml_node_object *)intern, (xmlNodePtr)newdoc, (void *)intern);
/* Since iterators should invalidate, we need to start the modification number from the old counter */
if (old_modification_nr != 0) {
php_libxml_doc_ptr* doc_ptr = (php_libxml_doc_ptr*) ((php_libxml_node_object*) intern)->node; /* downcast */
doc_ptr->cache_tag.modification_nr = old_modification_nr;
php_libxml_invalidate_node_list_cache(doc_ptr);
}

RETURN_TRUE;
}
/* }}} end dom_parser_document */

Expand Down Expand Up @@ -1847,18 +1837,15 @@ PHP_METHOD(DOMDocument, relaxNGValidateSource)

static void dom_load_html(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */
{
zval *id;
xmlDoc *docp = NULL, *newdoc;
dom_object *intern;
dom_doc_propsptr doc_prop;
char *source;
size_t source_len;
int refcount, ret;
int refcount;
zend_long options = 0;
htmlParserCtxtPtr ctxt;

id = getThis();

if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &source, &source_len, &options) == FAILURE) {
RETURN_THROWS();
}
Expand Down Expand Up @@ -1908,43 +1895,39 @@ static void dom_load_html(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */
if (!newdoc)
RETURN_FALSE;

if (id != NULL && instanceof_function(Z_OBJCE_P(id), dom_document_class_entry)) {
intern = Z_DOMOBJ_P(id);
size_t old_modification_nr = 0;
if (intern != NULL) {
docp = (xmlDocPtr) dom_object_get_node(intern);
doc_prop = NULL;
if (docp != NULL) {
const php_libxml_doc_ptr *doc_ptr = docp->_private;
ZEND_ASSERT(doc_ptr != NULL); /* Must exist, we have a document */
old_modification_nr = doc_ptr->cache_tag.modification_nr;
php_libxml_decrement_node_ptr((php_libxml_node_object *) intern);
doc_prop = intern->document->doc_props;
intern->document->doc_props = NULL;
refcount = php_libxml_decrement_doc_ref((php_libxml_node_object *)intern);
if (refcount != 0) {
docp->_private = NULL;
}
}
intern->document = NULL;
if (php_libxml_increment_doc_ref((php_libxml_node_object *)intern, newdoc) == -1) {
RETURN_FALSE;
intern = Z_DOMOBJ_P(ZEND_THIS);
size_t old_modification_nr = 0;
if (intern != NULL) {
docp = (xmlDocPtr) dom_object_get_node(intern);
doc_prop = NULL;
if (docp != NULL) {
const php_libxml_doc_ptr *doc_ptr = docp->_private;
ZEND_ASSERT(doc_ptr != NULL); /* Must exist, we have a document */
old_modification_nr = doc_ptr->cache_tag.modification_nr;
php_libxml_decrement_node_ptr((php_libxml_node_object *) intern);
doc_prop = intern->document->doc_props;
intern->document->doc_props = NULL;
refcount = php_libxml_decrement_doc_ref((php_libxml_node_object *)intern);
if (refcount != 0) {
docp->_private = NULL;
}
intern->document->doc_props = doc_prop;
}

php_libxml_increment_node_ptr((php_libxml_node_object *)intern, (xmlNodePtr)newdoc, (void *)intern);
/* Since iterators should invalidate, we need to start the modification number from the old counter */
if (old_modification_nr != 0) {
php_libxml_doc_ptr* doc_ptr = (php_libxml_doc_ptr*) ((php_libxml_node_object*) intern)->node; /* downcast */
doc_ptr->cache_tag.modification_nr = old_modification_nr;
php_libxml_invalidate_node_list_cache(doc_ptr);
intern->document = NULL;
if (php_libxml_increment_doc_ref((php_libxml_node_object *)intern, newdoc) == -1) {
RETURN_FALSE;
}
intern->document->doc_props = doc_prop;
}

RETURN_TRUE;
} else {
DOM_RET_OBJ((xmlNodePtr) newdoc, &ret, NULL);
php_libxml_increment_node_ptr((php_libxml_node_object *)intern, (xmlNodePtr)newdoc, (void *)intern);
/* Since iterators should invalidate, we need to start the modification number from the old counter */
if (old_modification_nr != 0) {
php_libxml_doc_ptr* doc_ptr = (php_libxml_doc_ptr*) ((php_libxml_node_object*) intern)->node; /* downcast */
doc_ptr->cache_tag.modification_nr = old_modification_nr;
php_libxml_invalidate_node_list_cache(doc_ptr);
}

RETURN_TRUE;
}
/* }}} */

Expand Down
16 changes: 8 additions & 8 deletions ext/dom/php_dom.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -774,11 +774,11 @@ public function getElementsByTagNameNS(?string $namespace, string $localName): D
/** @return DOMNode|false */
public function importNode(DOMNode $node, bool $deep = false) {}

/** @return DOMDocument|bool */
public function load(string $filename, int $options = 0) {} // TODO return type shouldn't depend on the call scope
/** @tentative-return-type */
public function load(string $filename, int $options = 0): bool {}

/** @return DOMDocument|bool */
public function loadXML(string $source, int $options = 0) {} // TODO return type shouldn't depend on the call scope
/** @tentative-return-type */
public function loadXML(string $source, int $options = 0): bool {}

/** @tentative-return-type */
public function normalizeDocument(): void {}
Expand All @@ -790,11 +790,11 @@ public function registerNodeClass(string $baseClass, ?string $extendedClass): bo
public function save(string $filename, int $options = 0): int|false {}

#ifdef LIBXML_HTML_ENABLED
/** @return DOMDocument|bool */
public function loadHTML(string $source, int $options = 0) {} // TODO return type shouldn't depend on the call scope
/** @tentative-return-type */
public function loadHTML(string $source, int $options = 0): bool {}

/** @return DOMDocument|bool */
public function loadHTMLFile(string $filename, int $options = 0) {} // TODO return type shouldn't depend on the call scope
/** @tentative-return-type */
public function loadHTMLFile(string $filename, int $options = 0): bool {}

/** @tentative-return-type */
public function saveHTML(?DOMNode $node = null): string|false {}
Expand Down
10 changes: 5 additions & 5 deletions ext/dom/php_dom_arginfo.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.