mirror of
https://github.com/php/php-src.git
synced 2025-08-15 13:38:49 +02:00
Merge branch 'PHP-8.4'
* PHP-8.4: Fix GH-18744: PHP 8.4 classList works not correctly if copy HTMLElement by clone keyword.
This commit is contained in:
commit
307ff3bdea
4 changed files with 62 additions and 7 deletions
|
@ -177,10 +177,7 @@ zend_result dom_element_class_name_write(dom_object *obj, zval *newval)
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ classList TokenList
|
||||
URL: https://dom.spec.whatwg.org/#dom-element-classlist
|
||||
*/
|
||||
zend_result dom_element_class_list_read(dom_object *obj, zval *retval)
|
||||
zval *dom_element_class_list_zval(dom_object *obj)
|
||||
{
|
||||
const uint32_t PROP_INDEX = 0;
|
||||
|
||||
|
@ -191,7 +188,15 @@ zend_result dom_element_class_list_read(dom_object *obj, zval *retval)
|
|||
ZEND_ASSERT(OBJ_PROP_TO_NUM(prop_info->offset) == PROP_INDEX);
|
||||
#endif
|
||||
|
||||
zval *cached_token_list = OBJ_PROP_NUM(&obj->std, PROP_INDEX);
|
||||
return OBJ_PROP_NUM(&obj->std, PROP_INDEX);
|
||||
}
|
||||
|
||||
/* {{{ classList TokenList
|
||||
URL: https://dom.spec.whatwg.org/#dom-element-classlist
|
||||
*/
|
||||
zend_result dom_element_class_list_read(dom_object *obj, zval *retval)
|
||||
{
|
||||
zval *cached_token_list = dom_element_class_list_zval(obj);
|
||||
if (Z_ISUNDEF_P(cached_token_list)) {
|
||||
object_init_ex(cached_token_list, dom_token_list_class_entry);
|
||||
dom_token_list_object *intern = php_dom_token_list_from_obj(Z_OBJ_P(cached_token_list));
|
||||
|
|
|
@ -99,6 +99,7 @@ static zend_object_handlers dom_modern_nodelist_object_handlers;
|
|||
static zend_object_handlers dom_html_collection_object_handlers;
|
||||
static zend_object_handlers dom_object_namespace_node_handlers;
|
||||
static zend_object_handlers dom_modern_domimplementation_object_handlers;
|
||||
static zend_object_handlers dom_modern_element_object_handlers;
|
||||
static zend_object_handlers dom_token_list_object_handlers;
|
||||
#ifdef LIBXML_XPATH_ENABLED
|
||||
zend_object_handlers dom_xpath_object_handlers;
|
||||
|
@ -662,6 +663,21 @@ static zend_object *dom_objects_store_clone_obj(zend_object *zobject) /* {{{ */
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_object *dom_modern_element_clone_obj(zend_object *zobject)
|
||||
{
|
||||
zend_object *clone = dom_objects_store_clone_obj(zobject);
|
||||
|
||||
/* The $classList property is unique per element, and cached due to its [[SameObject]] requirement.
|
||||
* Remove it from the clone so the clone will get a fresh instance upon demand. */
|
||||
zval *class_list = dom_element_class_list_zval(php_dom_obj_from_obj(clone));
|
||||
if (!Z_ISUNDEF_P(class_list)) {
|
||||
zval_ptr_dtor(class_list);
|
||||
ZVAL_UNDEF(class_list);
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
static zend_object *dom_object_namespace_node_clone_obj(zend_object *zobject)
|
||||
{
|
||||
dom_object_namespace_node *intern = php_dom_namespace_node_obj_from_obj(zobject);
|
||||
|
@ -756,6 +772,9 @@ PHP_MINIT_FUNCTION(dom)
|
|||
* one instance per parent object. */
|
||||
dom_modern_domimplementation_object_handlers.clone_obj = NULL;
|
||||
|
||||
memcpy(&dom_modern_element_object_handlers, &dom_object_handlers, sizeof(zend_object_handlers));
|
||||
dom_modern_element_object_handlers.clone_obj = dom_modern_element_clone_obj;
|
||||
|
||||
memcpy(&dom_nnodemap_object_handlers, &dom_object_handlers, sizeof(zend_object_handlers));
|
||||
dom_nnodemap_object_handlers.free_obj = dom_nnodemap_objects_free_storage;
|
||||
dom_nnodemap_object_handlers.read_dimension = dom_nodemap_read_dimension;
|
||||
|
@ -1086,7 +1105,7 @@ PHP_MINIT_FUNCTION(dom)
|
|||
|
||||
dom_modern_element_class_entry = register_class_Dom_Element(dom_modern_node_class_entry, dom_modern_parentnode_class_entry, dom_modern_childnode_class_entry);
|
||||
dom_modern_element_class_entry->create_object = dom_objects_new;
|
||||
dom_modern_element_class_entry->default_object_handlers = &dom_object_handlers;
|
||||
dom_modern_element_class_entry->default_object_handlers = &dom_modern_element_object_handlers;
|
||||
|
||||
zend_hash_init(&dom_modern_element_prop_handlers, 0, NULL, NULL, true);
|
||||
DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "namespaceURI", dom_node_namespace_uri_read, NULL);
|
||||
|
@ -1111,7 +1130,7 @@ PHP_MINIT_FUNCTION(dom)
|
|||
|
||||
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;
|
||||
dom_html_element_class_entry->default_object_handlers = &dom_modern_element_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);
|
||||
|
|
|
@ -179,6 +179,7 @@ bool php_dom_create_nullable_object(xmlNodePtr obj, zval *return_value, dom_obje
|
|||
xmlNodePtr dom_clone_node(php_dom_libxml_ns_mapper *ns_mapper, xmlNodePtr node, xmlDocPtr doc, bool recursive);
|
||||
void dom_set_document_ref_pointers(xmlNodePtr node, php_libxml_ref_obj *document);
|
||||
void dom_set_document_ref_pointers_attr(xmlAttrPtr attr, php_libxml_ref_obj *document);
|
||||
zval *dom_element_class_list_zval(dom_object *obj);
|
||||
|
||||
typedef enum {
|
||||
DOM_LOAD_STRING = 0,
|
||||
|
|
30
ext/dom/tests/modern/token_list/gh18744.phpt
Normal file
30
ext/dom/tests/modern/token_list/gh18744.phpt
Normal file
|
@ -0,0 +1,30 @@
|
|||
--TEST--
|
||||
GH-18744 (classList works not correctly if copy HTMLElement by clone keyword.)
|
||||
--EXTENSIONS--
|
||||
dom
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$doc = \Dom\HTMLDocument::createEmpty();
|
||||
$ele1 = $doc->createElement('div');
|
||||
$ele1->classList->add('foo');
|
||||
$ele2 = clone $ele1;
|
||||
$ele2->classList->add('bar');
|
||||
|
||||
echo "Element1 class: " . $ele1->getAttribute('class');
|
||||
echo "\n";
|
||||
echo "Element2 class: " . $ele2->getAttribute('class');
|
||||
echo "\n";
|
||||
|
||||
var_dump($ele1->classList !== $ele2->classList);
|
||||
// These comparisons are not pointless: they're getters and should not create new objects
|
||||
var_dump($ele1->classList === $ele1->classList);
|
||||
var_dump($ele2->classList === $ele2->classList);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Element1 class: foo
|
||||
Element2 class: foo bar
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
Loading…
Add table
Add a link
Reference in a new issue