@@ -99,8 +99,67 @@ static zend_always_inline dom_lxb_str_wrapper lxb_selectors_adapted_attr_value(c
99
99
return ret ;
100
100
}
101
101
102
+ static bool lxb_selectors_attrib_name_cmp (const lxb_css_selector_t * selector , const char * name , size_t len )
103
+ {
104
+ return selector -> name .length == len && lexbor_str_data_nlocmp_right ((const lxb_char_t * ) name , selector -> name .data , len );
105
+ }
106
+
107
+ /* From https://html.spec.whatwg.org/#case-sensitivity-of-selectors
108
+ * "Attribute selectors on an HTML element in an HTML document must treat the values of attributes with the following names as ASCII case-insensitive:" */
109
+ static bool lxb_selectors_is_lowercased_html_attrib_name (const lxb_css_selector_t * selector )
110
+ {
111
+ return lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("accept" ))
112
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("accept-charset" ))
113
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("align" ))
114
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("alink" ))
115
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("axis" ))
116
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("bgcolor" ))
117
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("charset" ))
118
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("checked" ))
119
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("clear" ))
120
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("codetype" ))
121
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("color" ))
122
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("compact" ))
123
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("declare" ))
124
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("defer" ))
125
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("dir" ))
126
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("direction" ))
127
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("disabled" ))
128
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("enctype" ))
129
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("face" ))
130
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("frame" ))
131
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("hreflang" ))
132
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("http-equiv" ))
133
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("lang" ))
134
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("language" ))
135
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("link" ))
136
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("media" ))
137
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("method" ))
138
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("multiple" ))
139
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("nohref" ))
140
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("noresize" ))
141
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("noshade" ))
142
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("nowrap" ))
143
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("readonly" ))
144
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("rel" ))
145
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("rev" ))
146
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("rules" ))
147
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("scope" ))
148
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("scrolling" ))
149
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("selected" ))
150
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("shape" ))
151
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("target" ))
152
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("text" ))
153
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("type" ))
154
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("valign" ))
155
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("valuetype" ))
156
+ || lxb_selectors_attrib_name_cmp (selector , ZEND_STRL ("vlink" ));
157
+ }
158
+
102
159
static void lxb_selectors_adapted_set_entry_id_ex (lxb_selectors_entry_t * entry , const lxb_css_selector_t * selector , const xmlNode * node )
103
160
{
161
+ entry -> id .attr_case_insensitive = lxb_selectors_is_lowercased_html_attrib_name (selector );
162
+
104
163
if (node -> doc != NULL && node -> doc -> dict != NULL ) {
105
164
const xmlChar * interned = xmlDictExists (node -> doc -> dict , selector -> name .data , selector -> name .length );
106
165
if (interned != NULL ) {
@@ -1304,10 +1363,10 @@ lxb_selectors_match_class(const lexbor_str_t *target, const lexbor_str_t *src,
1304
1363
}
1305
1364
1306
1365
static bool
1307
- lxb_selectors_match_attribute_value (const lxb_css_selector_attribute_t * attr , const lexbor_str_t * trg , const lexbor_str_t * src )
1366
+ lxb_selectors_match_attribute_value (const lxb_css_selector_attribute_t * attr , bool force_modifier_i , const lexbor_str_t * trg , const lexbor_str_t * src )
1308
1367
{
1309
1368
bool res ;
1310
- bool ins = attr -> modifier == LXB_CSS_SELECTOR_MODIFIER_I ;
1369
+ bool ins = attr -> modifier == LXB_CSS_SELECTOR_MODIFIER_I || force_modifier_i ;
1311
1370
1312
1371
switch (attr -> match ) {
1313
1372
case LXB_CSS_SELECTOR_MATCH_EQUAL : /* = */
@@ -1419,7 +1478,13 @@ lxb_selectors_match_attribute(const lxb_css_selector_t *selector,
1419
1478
}
1420
1479
1421
1480
dom_lxb_str_wrapper trg = lxb_selectors_adapted_attr_value (dom_attr );
1422
- bool res = lxb_selectors_match_attribute_value (attr , & trg .str , src );
1481
+ ZEND_ASSERT (node -> doc != NULL );
1482
+ bool res = lxb_selectors_match_attribute_value (
1483
+ attr ,
1484
+ entry -> id .attr_case_insensitive && php_dom_ns_is_html_and_document_is_html (node ),
1485
+ & trg .str ,
1486
+ src
1487
+ );
1423
1488
dom_lxb_str_wrapper_release (& trg );
1424
1489
return res ;
1425
1490
}
0 commit comments