Skip to content

Commit 24042b7

Browse files
committed
Implement DOM\TokenList
1 parent cfdbf77 commit 24042b7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2072
-15
lines changed

ext/dom/config.m4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ if test "$PHP_DOM" != "no"; then
3434
documenttype.c entity.c \
3535
nodelist.c text.c comment.c \
3636
entityreference.c \
37+
token_list.c \
3738
notation.c xpath.c dom_iterators.c \
3839
namednodemap.c xpath_callbacks.c \
3940
$LEXBOR_SOURCES],

ext/dom/config.w32

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ if (PHP_DOM == "yes") {
1414
node.c characterdata.c documenttype.c \
1515
entity.c nodelist.c text.c comment.c \
1616
entityreference.c \
17+
token_list.c \
1718
notation.c xpath.c dom_iterators.c \
1819
namednodemap.c xpath_callbacks.c", null, "-Iext/dom/lexbor");
1920

ext/dom/dom_ce.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ extern PHP_DOM_EXPORT zend_class_entry *dom_modern_entityreference_class_entry;
6161
extern PHP_DOM_EXPORT zend_class_entry *dom_processinginstruction_class_entry;
6262
extern PHP_DOM_EXPORT zend_class_entry *dom_modern_processinginstruction_class_entry;
6363
extern PHP_DOM_EXPORT zend_class_entry *dom_abstract_base_document_class_entry;
64+
extern PHP_DOM_EXPORT zend_class_entry *dom_token_list_class_entry;
6465
#ifdef LIBXML_XPATH_ENABLED
6566
extern PHP_DOM_EXPORT zend_class_entry *dom_xpath_class_entry;
6667
extern PHP_DOM_EXPORT zend_class_entry *dom_modern_xpath_class_entry;

ext/dom/dom_properties.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ zend_result dom_element_class_name_write(dom_object *obj, zval *newval);
8080
zend_result dom_element_id_read(dom_object *obj, zval *retval);
8181
zend_result dom_element_id_write(dom_object *obj, zval *newval);
8282
zend_result dom_element_schema_type_info_read(dom_object *obj, zval *retval);
83+
zend_result dom_element_class_list_read(dom_object *obj, zval *retval);
8384

8485
/* entity properties */
8586
zend_result dom_entity_public_id_read(dom_object *obj, zval *retval);
@@ -138,6 +139,11 @@ zend_result dom_processinginstruction_data_write(dom_object *obj, zval *newval);
138139
/* text properties */
139140
zend_result dom_text_whole_text_read(dom_object *obj, zval *retval);
140141

142+
/* token_list properties */
143+
zend_result dom_token_list_length_read(dom_object *obj, zval *retval);
144+
zend_result dom_token_list_value_read(dom_object *obj, zval *retval);
145+
zend_result dom_token_list_value_write(dom_object *obj, zval *newval);
146+
141147
#ifdef LIBXML_XPATH_ENABLED
142148
/* xpath properties */
143149
zend_result dom_xpath_document_read(dom_object *obj, zval *retval);

ext/dom/element.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "namespace_compat.h"
2626
#include "internal_helpers.h"
2727
#include "dom_properties.h"
28+
#include "token_list.h"
2829

2930
/*
3031
* class DOMElement extends DOMNode
@@ -174,6 +175,33 @@ zend_result dom_element_class_name_write(dom_object *obj, zval *newval)
174175
}
175176
/* }}} */
176177

178+
/* {{{ classList TokenList
179+
URL: https://dom.spec.whatwg.org/#dom-element-classlist
180+
*/
181+
zend_result dom_element_class_list_read(dom_object *obj, zval *retval)
182+
{
183+
const uint32_t PROP_INDEX = 20;
184+
185+
#if ZEND_DEBUG
186+
zend_string *class_list_str = ZSTR_INIT_LITERAL("classList", false);
187+
const zend_property_info *prop_info = zend_get_property_info(dom_modern_element_class_entry, class_list_str, 0);
188+
zend_string_release_ex(class_list_str, false);
189+
ZEND_ASSERT(OBJ_PROP_TO_NUM(prop_info->offset) == PROP_INDEX);
190+
#endif
191+
192+
zval *cached_token_list = OBJ_PROP_NUM(&obj->std, PROP_INDEX);
193+
if (Z_ISUNDEF_P(cached_token_list)) {
194+
object_init_ex(cached_token_list, dom_token_list_class_entry);
195+
dom_token_list_object *intern = php_dom_token_list_from_obj(Z_OBJ_P(cached_token_list));
196+
dom_token_list_ctor(intern, obj);
197+
}
198+
199+
ZVAL_OBJ_COPY(retval, Z_OBJ_P(cached_token_list));
200+
201+
return SUCCESS;
202+
}
203+
/* }}} */
204+
177205
/* {{{ id string
178206
URL: https://dom.spec.whatwg.org/#dom-element-id
179207
Since:

ext/dom/php_dom.c

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "internal_helpers.h"
2828
#include "php_dom_arginfo.h"
2929
#include "dom_properties.h"
30+
#include "token_list.h"
3031
#include "zend_interfaces.h"
3132
#include "lexbor/lexbor/core/types.h"
3233
#include "lexbor/lexbor/core/lexbor.h"
@@ -77,6 +78,7 @@ PHP_DOM_EXPORT zend_class_entry *dom_modern_entityreference_class_entry;
7778
PHP_DOM_EXPORT zend_class_entry *dom_processinginstruction_class_entry;
7879
PHP_DOM_EXPORT zend_class_entry *dom_modern_processinginstruction_class_entry;
7980
PHP_DOM_EXPORT zend_class_entry *dom_abstract_base_document_class_entry;
81+
PHP_DOM_EXPORT zend_class_entry *dom_token_list_class_entry;
8082
#ifdef LIBXML_XPATH_ENABLED
8183
PHP_DOM_EXPORT zend_class_entry *dom_xpath_class_entry;
8284
PHP_DOM_EXPORT zend_class_entry *dom_modern_xpath_class_entry;
@@ -91,6 +93,7 @@ static zend_object_handlers dom_modern_nnodemap_object_handlers;
9193
static zend_object_handlers dom_modern_nodelist_object_handlers;
9294
static zend_object_handlers dom_object_namespace_node_handlers;
9395
static zend_object_handlers dom_modern_domimplementation_object_handlers;
96+
static zend_object_handlers dom_token_list_object_handlers;
9497
#ifdef LIBXML_XPATH_ENABLED
9598
zend_object_handlers dom_xpath_object_handlers;
9699
#endif
@@ -124,6 +127,7 @@ static HashTable dom_modern_entity_prop_handlers;
124127
static HashTable dom_processinginstruction_prop_handlers;
125128
static HashTable dom_modern_processinginstruction_prop_handlers;
126129
static HashTable dom_namespace_node_prop_handlers;
130+
static HashTable dom_token_list_prop_handlers;
127131
#ifdef LIBXML_XPATH_ENABLED
128132
static HashTable dom_xpath_prop_handlers;
129133
#endif
@@ -623,6 +627,18 @@ static zend_object *dom_object_namespace_node_clone_obj(zend_object *zobject)
623627
return clone;
624628
}
625629

630+
static zend_object *dom_token_list_new(zend_class_entry *class_type)
631+
{
632+
dom_token_list_object *intern = zend_object_alloc(sizeof(*intern), class_type);
633+
634+
intern->dom.prop_handler = &dom_token_list_prop_handlers;
635+
636+
zend_object_std_init(&intern->dom.std, class_type);
637+
object_properties_init(&intern->dom.std, class_type);
638+
639+
return &intern->dom.std;
640+
}
641+
626642
static const zend_module_dep dom_deps[] = {
627643
ZEND_MOD_REQUIRED("libxml")
628644
ZEND_MOD_CONFLICTS("domxml")
@@ -648,7 +664,6 @@ zend_module_entry dom_module_entry = { /* {{{ */
648664
ZEND_GET_MODULE(dom)
649665
#endif
650666

651-
void dom_objects_free_storage(zend_object *object);
652667
void dom_nnodemap_objects_free_storage(zend_object *object);
653668
static zval *dom_nodelist_read_dimension(zend_object *object, zval *offset, int type, zval *rv);
654669
static int dom_nodelist_has_dimension(zend_object *object, zval *member, int check_empty);
@@ -721,6 +736,15 @@ PHP_MINIT_FUNCTION(dom)
721736
dom_object_namespace_node_handlers.free_obj = dom_object_namespace_node_free_storage;
722737
dom_object_namespace_node_handlers.clone_obj = dom_object_namespace_node_clone_obj;
723738

739+
memcpy(&dom_token_list_object_handlers, &dom_object_handlers, sizeof(zend_object_handlers));
740+
dom_token_list_object_handlers.offset = XtOffsetOf(dom_token_list_object, dom.std);
741+
dom_token_list_object_handlers.free_obj = dom_token_list_free_obj;
742+
/* The IDL has the [SameObject] constraint, which is incompatible with cloning because it imposes that there is only
743+
* one instance per parent object. */
744+
dom_token_list_object_handlers.clone_obj = NULL;
745+
dom_token_list_object_handlers.read_dimension = dom_token_list_read_dimension;
746+
dom_token_list_object_handlers.has_dimension = dom_token_list_has_dimension;
747+
724748
zend_hash_init(&classes, 0, NULL, NULL, true);
725749

726750
dom_domexception_class_entry = register_class_DOMException(zend_ce_exception);
@@ -1017,6 +1041,7 @@ PHP_MINIT_FUNCTION(dom)
10171041
DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "tagName", dom_element_tag_name_read, NULL);
10181042
DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "id", dom_element_id_read, dom_element_id_write);
10191043
DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "className", dom_element_class_name_read, dom_element_class_name_write);
1044+
DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "classList", dom_element_class_list_read, NULL);
10201045
DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "attributes", dom_node_attributes_read, NULL);
10211046
DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "firstElementChild", dom_parent_node_first_element_child_read, NULL);
10221047
DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "lastElementChild", dom_parent_node_last_element_child_read, NULL);
@@ -1191,6 +1216,16 @@ PHP_MINIT_FUNCTION(dom)
11911216
zend_hash_add_new_ptr(&classes, dom_modern_xpath_class_entry->name, &dom_xpath_prop_handlers);
11921217
#endif
11931218

1219+
dom_token_list_class_entry = register_class_DOM_TokenList(zend_ce_aggregate, zend_ce_countable);
1220+
dom_token_list_class_entry->create_object = dom_token_list_new;
1221+
dom_token_list_class_entry->default_object_handlers = &dom_token_list_object_handlers;
1222+
dom_token_list_class_entry->get_iterator = dom_token_list_get_iterator;
1223+
1224+
zend_hash_init(&dom_token_list_prop_handlers, 0, NULL, NULL, true);
1225+
DOM_REGISTER_PROP_HANDLER(&dom_token_list_prop_handlers, "length", dom_token_list_length_read, NULL);
1226+
DOM_REGISTER_PROP_HANDLER(&dom_token_list_prop_handlers, "value", dom_token_list_value_read, dom_token_list_value_write);
1227+
zend_hash_add_new_ptr(&classes, dom_token_list_class_entry->name, &dom_token_list_prop_handlers);
1228+
11941229
register_php_dom_symbols(module_number);
11951230

11961231
php_libxml_register_export(dom_node_class_entry, php_dom_export_node);
@@ -1254,6 +1289,7 @@ PHP_MSHUTDOWN_FUNCTION(dom) /* {{{ */
12541289
zend_hash_destroy(&dom_modern_entity_prop_handlers);
12551290
zend_hash_destroy(&dom_processinginstruction_prop_handlers);
12561291
zend_hash_destroy(&dom_modern_processinginstruction_prop_handlers);
1292+
zend_hash_destroy(&dom_token_list_prop_handlers);
12571293
#ifdef LIBXML_XPATH_ENABLED
12581294
zend_hash_destroy(&dom_xpath_prop_handlers);
12591295
#endif

ext/dom/php_dom.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ static inline dom_object_namespace_node *php_dom_namespace_node_obj_from_obj(zen
125125

126126
#define DOM_HTML_NO_DEFAULT_NS (1U << 31)
127127

128+
void dom_objects_free_storage(zend_object *object);
128129
dom_object *dom_object_get_data(xmlNodePtr obj);
129130
dom_doc_propsptr dom_get_doc_props(php_libxml_ref_obj *document);
130131
libxml_doc_props const* dom_get_doc_props_read_only(const php_libxml_ref_obj *document);

ext/dom/php_dom.stub.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,6 +1301,8 @@ class Element extends Node implements ParentNode, ChildNode
13011301

13021302
public string $id;
13031303
public string $className;
1304+
/** @readonly */
1305+
public TokenList $classList;
13041306

13051307
/** @implementation-alias DOMNode::hasAttributes */
13061308
public function hasAttributes(): bool {}
@@ -1636,6 +1638,32 @@ public function saveXML(?Node $node = null, int $options = 0): string|false {}
16361638
public function saveXMLFile(string $filename, int $options = 0): int|false {}
16371639
}
16381640

1641+
/**
1642+
* @not-serializable
1643+
* @strict-properties
1644+
*/
1645+
final class TokenList implements IteratorAggregate, Countable
1646+
{
1647+
/** @implementation-alias DOM\Node::__construct */
1648+
private function __construct() {}
1649+
1650+
/** @readonly */
1651+
public int $length;
1652+
public function item(int $index): ?string {}
1653+
public function contains(string $token): bool {}
1654+
public function add(string ...$tokens): void {}
1655+
public function remove(string ...$tokens): void {}
1656+
public function toggle(string $token, ?bool $force = null): bool {}
1657+
public function replace(string $token, string $newToken): bool {}
1658+
public function supports(string $token): bool {}
1659+
public string $value;
1660+
1661+
/** @tentative-return-type */
1662+
public function count(): int {}
1663+
1664+
public function getIterator(): \Iterator {}
1665+
}
1666+
16391667
#ifdef LIBXML_XPATH_ENABLED
16401668
/** @not-serializable */
16411669
final class XPath

ext/dom/php_dom_arginfo.h

Lines changed: 87 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)