diff --git a/ext/dom/dom_ce.h b/ext/dom/dom_ce.h index 4dee3430533..13e58957df3 100644 --- a/ext/dom/dom_ce.h +++ b/ext/dom/dom_ce.h @@ -44,6 +44,7 @@ extern PHP_DOM_EXPORT zend_class_entry *dom_attr_class_entry; extern PHP_DOM_EXPORT zend_class_entry *dom_modern_attr_class_entry; extern PHP_DOM_EXPORT zend_class_entry *dom_element_class_entry; extern PHP_DOM_EXPORT zend_class_entry *dom_modern_element_class_entry; +extern PHP_DOM_EXPORT zend_class_entry *dom_html_element_class_entry; extern PHP_DOM_EXPORT zend_class_entry *dom_text_class_entry; extern PHP_DOM_EXPORT zend_class_entry *dom_modern_text_class_entry; extern PHP_DOM_EXPORT zend_class_entry *dom_comment_class_entry; diff --git a/ext/dom/html_document.c b/ext/dom/html_document.c index bf1186074e8..7d367020888 100644 --- a/ext/dom/html_document.c +++ b/ext/dom/html_document.c @@ -1423,7 +1423,8 @@ zend_result dom_html_document_body_write(dom_object *obj, zval *newval) dom_object *newval_intern = Z_DOMOBJ_P(newval); if (newval_intern->ptr != NULL) { xmlNodePtr newval_node = ((php_libxml_node_ptr *) newval_intern->ptr)->node; - if (php_dom_ns_is_fast(newval_node, php_dom_ns_is_html_magic_token) && dom_accept_body_name(newval_node->name)) { + /* Note: because this property has type HTMLElement, we know the namespace is correct. */ + if (dom_accept_body_name(newval_node->name)) { /* 2. If the new value is the same as the body element, return. */ const xmlNode *current_body_element = dom_html_document_element_read_raw(docp, dom_accept_body_name); if (current_body_element == newval_node) { diff --git a/ext/dom/internal_helpers.h b/ext/dom/internal_helpers.h index a19367dd477..b74a735ad2e 100644 --- a/ext/dom/internal_helpers.h +++ b/ext/dom/internal_helpers.h @@ -47,7 +47,6 @@ static zend_always_inline zend_class_entry *dom_get_dtd_namednodemap_ce(bool mod DOM_DEF_GET_CE_FUNC(node) DOM_DEF_GET_CE_FUNC(documenttype) -DOM_DEF_GET_CE_FUNC(element) DOM_DEF_GET_CE_FUNC(attr) DOM_DEF_GET_CE_FUNC(entity) DOM_DEF_GET_CE_FUNC(entityreference) diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c index 4c239ee896b..83dc12c6428 100644 --- a/ext/dom/php_dom.c +++ b/ext/dom/php_dom.c @@ -63,6 +63,7 @@ PHP_DOM_EXPORT zend_class_entry *dom_attr_class_entry; PHP_DOM_EXPORT zend_class_entry *dom_modern_attr_class_entry; PHP_DOM_EXPORT zend_class_entry *dom_element_class_entry; PHP_DOM_EXPORT zend_class_entry *dom_modern_element_class_entry; +PHP_DOM_EXPORT zend_class_entry *dom_html_element_class_entry; PHP_DOM_EXPORT zend_class_entry *dom_text_class_entry; PHP_DOM_EXPORT zend_class_entry *dom_modern_text_class_entry; PHP_DOM_EXPORT zend_class_entry *dom_comment_class_entry; @@ -1042,6 +1043,11 @@ PHP_MINIT_FUNCTION(dom) DOM_OVERWRITE_PROP_HANDLER(&dom_modern_element_prop_handlers, "textContent", dom_node_text_content_read, dom_node_text_content_write); zend_hash_add_new_ptr(&classes, dom_modern_element_class_entry->name, &dom_modern_element_prop_handlers); + dom_html_element_class_entry = register_class_Dom_HTMLElement(dom_modern_element_class_entry); + dom_html_element_class_entry->create_object = dom_objects_new; + dom_html_element_class_entry->default_object_handlers = &dom_object_handlers; + zend_hash_add_new_ptr(&classes, dom_html_element_class_entry->name, &dom_modern_element_prop_handlers); + dom_text_class_entry = register_class_DOMText(dom_characterdata_class_entry); dom_text_class_entry->create_object = dom_objects_new; dom_text_class_entry->default_object_handlers = &dom_object_handlers; @@ -1541,6 +1547,19 @@ void php_dom_create_iterator(zval *return_value, dom_iterator_type iterator_type } /* }}} */ +static zend_always_inline zend_class_entry *dom_get_element_ce(const xmlNode *node, bool modern) +{ + if (modern) { + if (php_dom_ns_is_fast(node, php_dom_ns_is_html_magic_token)) { + return dom_html_element_class_entry; + } else { + return dom_modern_element_class_entry; + } + } else { + return dom_element_class_entry; + } +} + /* {{{ php_dom_create_object */ PHP_DOM_EXPORT bool php_dom_create_object(xmlNodePtr obj, zval *return_value, dom_object *domobj) { @@ -1572,7 +1591,7 @@ PHP_DOM_EXPORT bool php_dom_create_object(xmlNodePtr obj, zval *return_value, do } case XML_ELEMENT_NODE: { - ce = dom_get_element_ce(modern); + ce = dom_get_element_ce(obj, modern); break; } case XML_ATTRIBUTE_NODE: diff --git a/ext/dom/php_dom.stub.php b/ext/dom/php_dom.stub.php index e2d374b7efa..1f6f2bb8bc8 100644 --- a/ext/dom/php_dom.stub.php +++ b/ext/dom/php_dom.stub.php @@ -1374,6 +1374,10 @@ namespace Dom public function replaceChildren(Node|string ...$nodes): void {} } + class HTMLElement extends Element + { + } + class Attr extends Node { /** @readonly */ @@ -1581,9 +1585,9 @@ namespace Dom public function importLegacyNode(\DOMNode $node, bool $deep = false): Node {} - public ?Element $body; + public ?HTMLElement $body; /** @readonly */ - public ?Element $head; + public ?HTMLElement $head; public string $title; } diff --git a/ext/dom/php_dom_arginfo.h b/ext/dom/php_dom_arginfo.h index c3cc6187575..dae80f6fe3c 100644 --- a/ext/dom/php_dom_arginfo.h +++ b/ext/dom/php_dom_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 7a2c28838f431eff28dea8cc5356dbcd38921592 */ + * Stub hash: eda699f0d524fae5ae76a3a395438a16989c2af8 */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_dom_import_simplexml, 0, 1, DOMElement, 0) ZEND_ARG_TYPE_INFO(0, node, IS_OBJECT, 0) @@ -1674,6 +1674,10 @@ static const zend_function_entry class_Dom_Element_methods[] = { ZEND_FE_END }; +static const zend_function_entry class_Dom_HTMLElement_methods[] = { + ZEND_FE_END +}; + static const zend_function_entry class_Dom_Attr_methods[] = { ZEND_RAW_FENTRY("isId", zim_DOMAttr_isId, arginfo_class_Dom_Attr_isId, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_FE_END @@ -3080,6 +3084,16 @@ static zend_class_entry *register_class_Dom_Element(zend_class_entry *class_entr return class_entry; } +static zend_class_entry *register_class_Dom_HTMLElement(zend_class_entry *class_entry_Dom_Element) +{ + zend_class_entry ce, *class_entry; + + INIT_NS_CLASS_ENTRY(ce, "Dom", "HTMLElement", class_Dom_HTMLElement_methods); + class_entry = zend_register_internal_class_ex(&ce, class_entry_Dom_Element); + + return class_entry; +} + static zend_class_entry *register_class_Dom_Attr(zend_class_entry *class_entry_Dom_Node) { zend_class_entry ce, *class_entry; @@ -3445,15 +3459,15 @@ static zend_class_entry *register_class_Dom_Document(zend_class_entry *class_ent zval property_body_default_value; ZVAL_UNDEF(&property_body_default_value); zend_string *property_body_name = zend_string_init("body", sizeof("body") - 1, 1); - zend_string *property_body_class_Dom_Element = zend_string_init("Dom\\Element", sizeof("Dom\\Element")-1, 1); - zend_declare_typed_property(class_entry, property_body_name, &property_body_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_body_class_Dom_Element, 0, MAY_BE_NULL)); + zend_string *property_body_class_Dom_HTMLElement = zend_string_init("Dom\\HTMLElement", sizeof("Dom\\HTMLElement")-1, 1); + zend_declare_typed_property(class_entry, property_body_name, &property_body_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_body_class_Dom_HTMLElement, 0, MAY_BE_NULL)); zend_string_release(property_body_name); zval property_head_default_value; ZVAL_UNDEF(&property_head_default_value); zend_string *property_head_name = zend_string_init("head", sizeof("head") - 1, 1); - zend_string *property_head_class_Dom_Element = zend_string_init("Dom\\Element", sizeof("Dom\\Element")-1, 1); - zend_declare_typed_property(class_entry, property_head_name, &property_head_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_head_class_Dom_Element, 0, MAY_BE_NULL)); + zend_string *property_head_class_Dom_HTMLElement = zend_string_init("Dom\\HTMLElement", sizeof("Dom\\HTMLElement")-1, 1); + zend_declare_typed_property(class_entry, property_head_name, &property_head_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_head_class_Dom_HTMLElement, 0, MAY_BE_NULL)); zend_string_release(property_head_name); zval property_title_default_value; diff --git a/ext/dom/tests/modern/html/interactions/Document_body_setter_errors.phpt b/ext/dom/tests/modern/html/interactions/Document_body_setter_errors.phpt index 9913dbb12ae..1f934fcff89 100644 --- a/ext/dom/tests/modern/html/interactions/Document_body_setter_errors.phpt +++ b/ext/dom/tests/modern/html/interactions/Document_body_setter_errors.phpt @@ -11,7 +11,7 @@ function testNormalReplace($cb) var_dump($dom->body?->nodeName); try { $dom->body = $cb($dom); - } catch (DOMException $e) { + } catch (Throwable $e) { echo $e->getMessage(), "\n"; } var_dump($dom->body?->nodeName); @@ -50,11 +50,11 @@ The new body must either be a body or a frameset tag string(4) "BODY" --- Right element tag in wrong namespace --- string(4) "BODY" -The new body must either be a body or a frameset tag +Cannot assign Dom\Element to property Dom\Document::$body of type ?Dom\HTMLElement string(4) "BODY" --- Right element tag in no namespace --- string(4) "BODY" -The new body must either be a body or a frameset tag +Cannot assign Dom\Element to property Dom\Document::$body of type ?Dom\HTMLElement string(4) "BODY" --- Set body without document element --- A body can only be set if there is a document element diff --git a/ext/dom/tests/modern/html/interactions/HTMLDocument_registerNodeClass_03.phpt b/ext/dom/tests/modern/html/interactions/HTMLDocument_registerNodeClass_03.phpt index 7a4d2d32797..6616eb5d114 100644 --- a/ext/dom/tests/modern/html/interactions/HTMLDocument_registerNodeClass_03.phpt +++ b/ext/dom/tests/modern/html/interactions/HTMLDocument_registerNodeClass_03.phpt @@ -5,7 +5,7 @@ dom --FILE-- foo", LIBXML_NOERROR); -$dom->registerNodeClass("Dom\\Element", "Custom"); +$dom->registerNodeClass("Dom\\HTMLElement", "Custom"); var_dump($dom->getElementsByTagName('div')[0]->reverseTagName()); diff --git a/ext/dom/tests/modern/html/interactions/HTMLDocument_should_retain_properties_and_owner_01.phpt b/ext/dom/tests/modern/html/interactions/HTMLDocument_should_retain_properties_and_owner_01.phpt index cdd98b58526..5051c3f9aab 100644 --- a/ext/dom/tests/modern/html/interactions/HTMLDocument_should_retain_properties_and_owner_01.phpt +++ b/ext/dom/tests/modern/html/interactions/HTMLDocument_should_retain_properties_and_owner_01.phpt @@ -5,10 +5,10 @@ dom --FILE-- foo

", LIBXML_NOERROR); -$dom->registerNodeClass("Dom\\Element", "MyElement"); +$dom->registerNodeClass("Dom\\HTMLElement", "MyElement"); // Destroy reference to the DOM $child = $dom->documentElement; diff --git a/ext/dom/tests/modern/html/interactions/HTMLDocument_should_retain_properties_and_owner_02.phpt b/ext/dom/tests/modern/html/interactions/HTMLDocument_should_retain_properties_and_owner_02.phpt index b216b399a16..b160c72f0a5 100644 --- a/ext/dom/tests/modern/html/interactions/HTMLDocument_should_retain_properties_and_owner_02.phpt +++ b/ext/dom/tests/modern/html/interactions/HTMLDocument_should_retain_properties_and_owner_02.phpt @@ -5,10 +5,10 @@ dom --FILE-- foo

", LIBXML_NOERROR); -$dom->registerNodeClass("Dom\\Element", "MyElement"); +$dom->registerNodeClass("Dom\\HTMLElement", "MyElement"); $child = $dom->documentElement->appendChild($dom->createElement('html')); // Destroy reference to the DOM diff --git a/ext/dom/tests/modern/spec/Element_prefix_readonly.phpt b/ext/dom/tests/modern/spec/Element_prefix_readonly.phpt index 7ebc3efaadc..78625fcb6f7 100644 --- a/ext/dom/tests/modern/spec/Element_prefix_readonly.phpt +++ b/ext/dom/tests/modern/spec/Element_prefix_readonly.phpt @@ -14,5 +14,5 @@ try { echo $dom->saveXml(); ?> --EXPECT-- -Cannot modify readonly property Dom\Element::$prefix +Cannot modify readonly property Dom\HTMLElement::$prefix