Skip to content

Commit 3e791e3

Browse files
committed
Implement DOM\TokenList
1 parent bc09cd2 commit 3e791e3

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 html_collection.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 html_collection.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
@@ -78,6 +78,7 @@ zend_result dom_element_class_name_write(dom_object *obj, zval *newval);
7878
zend_result dom_element_id_read(dom_object *obj, zval *retval);
7979
zend_result dom_element_id_write(dom_object *obj, zval *newval);
8080
zend_result dom_element_schema_type_info_read(dom_object *obj, zval *retval);
81+
zend_result dom_element_class_list_read(dom_object *obj, zval *retval);
8182

8283
/* entity properties */
8384
zend_result dom_entity_public_id_read(dom_object *obj, zval *retval);
@@ -141,6 +142,11 @@ zend_result dom_processinginstruction_data_write(dom_object *obj, zval *newval);
141142
/* text properties */
142143
zend_result dom_text_whole_text_read(dom_object *obj, zval *retval);
143144

145+
/* token_list properties */
146+
zend_result dom_token_list_length_read(dom_object *obj, zval *retval);
147+
zend_result dom_token_list_value_read(dom_object *obj, zval *retval);
148+
zend_result dom_token_list_value_write(dom_object *obj, zval *newval);
149+
144150
#ifdef LIBXML_XPATH_ENABLED
145151
/* xpath properties */
146152
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
@@ -29,6 +29,7 @@
2929
#include "internal_helpers.h"
3030
#include "php_dom_arginfo.h"
3131
#include "dom_properties.h"
32+
#include "token_list.h"
3233
#include "zend_interfaces.h"
3334
#include "lexbor/lexbor/core/types.h"
3435
#include "lexbor/lexbor/core/lexbor.h"
@@ -79,6 +80,7 @@ PHP_DOM_EXPORT zend_class_entry *dom_modern_entityreference_class_entry;
7980
PHP_DOM_EXPORT zend_class_entry *dom_processinginstruction_class_entry;
8081
PHP_DOM_EXPORT zend_class_entry *dom_modern_processinginstruction_class_entry;
8182
PHP_DOM_EXPORT zend_class_entry *dom_abstract_base_document_class_entry;
83+
PHP_DOM_EXPORT zend_class_entry *dom_token_list_class_entry;
8284
#ifdef LIBXML_XPATH_ENABLED
8385
PHP_DOM_EXPORT zend_class_entry *dom_xpath_class_entry;
8486
PHP_DOM_EXPORT zend_class_entry *dom_modern_xpath_class_entry;
@@ -94,6 +96,7 @@ static zend_object_handlers dom_modern_nodelist_object_handlers;
9496
static zend_object_handlers dom_html_collection_object_handlers;
9597
static zend_object_handlers dom_object_namespace_node_handlers;
9698
static zend_object_handlers dom_modern_domimplementation_object_handlers;
99+
static zend_object_handlers dom_token_list_object_handlers;
97100
#ifdef LIBXML_XPATH_ENABLED
98101
zend_object_handlers dom_xpath_object_handlers;
99102
#endif
@@ -129,6 +132,7 @@ static HashTable dom_modern_entity_prop_handlers;
129132
static HashTable dom_processinginstruction_prop_handlers;
130133
static HashTable dom_modern_processinginstruction_prop_handlers;
131134
static HashTable dom_namespace_node_prop_handlers;
135+
static HashTable dom_token_list_prop_handlers;
132136
#ifdef LIBXML_XPATH_ENABLED
133137
static HashTable dom_xpath_prop_handlers;
134138
#endif
@@ -627,6 +631,18 @@ static zend_object *dom_object_namespace_node_clone_obj(zend_object *zobject)
627631
return clone;
628632
}
629633

634+
static zend_object *dom_token_list_new(zend_class_entry *class_type)
635+
{
636+
dom_token_list_object *intern = zend_object_alloc(sizeof(*intern), class_type);
637+
638+
intern->dom.prop_handler = &dom_token_list_prop_handlers;
639+
640+
zend_object_std_init(&intern->dom.std, class_type);
641+
object_properties_init(&intern->dom.std, class_type);
642+
643+
return &intern->dom.std;
644+
}
645+
630646
static const zend_module_dep dom_deps[] = {
631647
ZEND_MOD_REQUIRED("libxml")
632648
ZEND_MOD_CONFLICTS("domxml")
@@ -652,7 +668,6 @@ zend_module_entry dom_module_entry = { /* {{{ */
652668
ZEND_GET_MODULE(dom)
653669
#endif
654670

655-
void dom_objects_free_storage(zend_object *object);
656671
void dom_nnodemap_objects_free_storage(zend_object *object);
657672
static zval *dom_nodelist_read_dimension(zend_object *object, zval *offset, int type, zval *rv);
658673
static int dom_nodelist_has_dimension(zend_object *object, zval *member, int check_empty);
@@ -726,6 +741,15 @@ PHP_MINIT_FUNCTION(dom)
726741
dom_object_namespace_node_handlers.free_obj = dom_object_namespace_node_free_storage;
727742
dom_object_namespace_node_handlers.clone_obj = dom_object_namespace_node_clone_obj;
728743

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

731755
dom_domexception_class_entry = register_class_DOMException(zend_ce_exception);
@@ -1022,6 +1046,7 @@ PHP_MINIT_FUNCTION(dom)
10221046
DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "tagName", dom_element_tag_name_read, NULL);
10231047
DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "id", dom_element_id_read, dom_element_id_write);
10241048
DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "className", dom_element_class_name_read, dom_element_class_name_write);
1049+
DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "classList", dom_element_class_list_read, NULL);
10251050
DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "attributes", dom_node_attributes_read, NULL);
10261051
DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "firstElementChild", dom_parent_node_first_element_child_read, NULL);
10271052
DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "lastElementChild", dom_parent_node_last_element_child_read, NULL);
@@ -1210,6 +1235,16 @@ PHP_MINIT_FUNCTION(dom)
12101235
zend_hash_add_new_ptr(&classes, dom_modern_xpath_class_entry->name, &dom_xpath_prop_handlers);
12111236
#endif
12121237

1238+
dom_token_list_class_entry = register_class_Dom_TokenList(zend_ce_aggregate, zend_ce_countable);
1239+
dom_token_list_class_entry->create_object = dom_token_list_new;
1240+
dom_token_list_class_entry->default_object_handlers = &dom_token_list_object_handlers;
1241+
dom_token_list_class_entry->get_iterator = dom_token_list_get_iterator;
1242+
1243+
zend_hash_init(&dom_token_list_prop_handlers, 0, NULL, NULL, true);
1244+
DOM_REGISTER_PROP_HANDLER(&dom_token_list_prop_handlers, "length", dom_token_list_length_read, NULL);
1245+
DOM_REGISTER_PROP_HANDLER(&dom_token_list_prop_handlers, "value", dom_token_list_value_read, dom_token_list_value_write);
1246+
zend_hash_add_new_ptr(&classes, dom_token_list_class_entry->name, &dom_token_list_prop_handlers);
1247+
12131248
register_php_dom_symbols(module_number);
12141249

12151250
php_libxml_register_export(dom_node_class_entry, php_dom_export_node);
@@ -1275,6 +1310,7 @@ PHP_MSHUTDOWN_FUNCTION(dom) /* {{{ */
12751310
zend_hash_destroy(&dom_modern_entity_prop_handlers);
12761311
zend_hash_destroy(&dom_processinginstruction_prop_handlers);
12771312
zend_hash_destroy(&dom_modern_processinginstruction_prop_handlers);
1313+
zend_hash_destroy(&dom_token_list_prop_handlers);
12781314
#ifdef LIBXML_XPATH_ENABLED
12791315
zend_hash_destroy(&dom_xpath_prop_handlers);
12801316
#endif

ext/dom/php_dom.h

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

123123
#define DOM_HTML_NO_DEFAULT_NS (1U << 31)
124124

125+
void dom_objects_free_storage(zend_object *object);
125126
dom_doc_propsptr dom_get_doc_props(php_libxml_ref_obj *document);
126127
libxml_doc_props const* dom_get_doc_props_read_only(const php_libxml_ref_obj *document);
127128
zend_object *dom_objects_new(zend_class_entry *class_type);

ext/dom/php_dom.stub.php

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

12941294
public string $id;
12951295
public string $className;
1296+
/** @readonly */
1297+
public TokenList $classList;
12961298

12971299
/** @implementation-alias DOMNode::hasAttributes */
12981300
public function hasAttributes(): bool {}
@@ -1626,6 +1628,32 @@ public function saveXml(?Node $node = null, int $options = 0): string|false {}
16261628
public function saveXmlFile(string $filename, int $options = 0): int|false {}
16271629
}
16281630

1631+
/**
1632+
* @not-serializable
1633+
* @strict-properties
1634+
*/
1635+
final class TokenList implements IteratorAggregate, Countable
1636+
{
1637+
/** @implementation-alias Dom\Node::__construct */
1638+
private function __construct() {}
1639+
1640+
/** @readonly */
1641+
public int $length;
1642+
public function item(int $index): ?string {}
1643+
public function contains(string $token): bool {}
1644+
public function add(string ...$tokens): void {}
1645+
public function remove(string ...$tokens): void {}
1646+
public function toggle(string $token, ?bool $force = null): bool {}
1647+
public function replace(string $token, string $newToken): bool {}
1648+
public function supports(string $token): bool {}
1649+
public string $value;
1650+
1651+
/** @tentative-return-type */
1652+
public function count(): int {}
1653+
1654+
public function getIterator(): \Iterator {}
1655+
}
1656+
16291657
#ifdef LIBXML_XPATH_ENABLED
16301658
/** @not-serializable */
16311659
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)