3
3
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
4
5
5
use std:: borrow:: ToOwned ;
6
- use std:: cell:: LazyCell ;
7
6
use std:: mem;
8
7
use std:: sync:: LazyLock ;
9
8
@@ -16,17 +15,15 @@ use stylo_atoms::Atom;
16
15
17
16
use crate :: dom:: bindings:: cell:: { DomRefCell , Ref } ;
18
17
use crate :: dom:: bindings:: codegen:: Bindings :: AttrBinding :: AttrMethods ;
19
- use crate :: dom:: bindings:: inheritance:: Castable ;
18
+ use crate :: dom:: bindings:: codegen:: UnionTypes :: TrustedHTMLOrTrustedScriptOrTrustedScriptURLOrString as TrustedTypeOrString ;
19
+ use crate :: dom:: bindings:: error:: Fallible ;
20
20
use crate :: dom:: bindings:: root:: { DomRoot , LayoutDom , MutNullableDom } ;
21
21
use crate :: dom:: bindings:: str:: DOMString ;
22
- use crate :: dom:: customelementregistry:: CallbackReaction ;
23
22
use crate :: dom:: document:: Document ;
24
- use crate :: dom:: element:: { AttributeMutation , Element } ;
25
- use crate :: dom:: mutationobserver:: { Mutation , MutationObserver } ;
26
- use crate :: dom:: node:: Node ;
27
- use crate :: dom:: virtualmethods:: vtable_for;
23
+ use crate :: dom:: element:: Element ;
24
+ use crate :: dom:: node:: { Node , NodeTraits } ;
25
+ use crate :: dom:: trustedtypepolicyfactory:: TrustedTypePolicyFactory ;
28
26
use crate :: script_runtime:: CanGc ;
29
- use crate :: script_thread:: ScriptThread ;
30
27
31
28
// https://dom.spec.whatwg.org/#interface-attr
32
29
#[ dom_struct]
@@ -112,14 +109,41 @@ impl AttrMethods<crate::DomTypeHolder> for Attr {
112
109
DOMString :: from ( & * * self . value ( ) )
113
110
}
114
111
115
- // https://dom.spec.whatwg.org/#dom-attr-value
116
- fn SetValue ( & self , value : DOMString , can_gc : CanGc ) {
112
+ /// <https://dom.spec.whatwg.org/#set-an-existing-attribute-value>
113
+ fn SetValue ( & self , value : DOMString , can_gc : CanGc ) -> Fallible < ( ) > {
114
+ // Step 2. Otherwise:
117
115
if let Some ( owner) = self . owner ( ) {
118
- let value = owner. parse_attribute ( self . namespace ( ) , self . local_name ( ) , value) ;
119
- self . set_value ( value, & owner, can_gc) ;
116
+ // Step 2.1. Let originalElement be attribute’s element.
117
+ let original_element = owner. clone ( ) ;
118
+ // Step 2.2. Let verifiedValue be the result of calling
119
+ // get Trusted Types-compliant attribute value with attribute’s local name,
120
+ // attribute’s namespace, this, and value. [TRUSTED-TYPES]
121
+ let value = TrustedTypePolicyFactory :: get_trusted_types_compliant_attribute_value (
122
+ owner. namespace ( ) ,
123
+ owner. local_name ( ) ,
124
+ self . local_name ( ) ,
125
+ Some ( self . namespace ( ) ) ,
126
+ TrustedTypeOrString :: String ( value) ,
127
+ & owner. owner_global ( ) ,
128
+ can_gc,
129
+ ) ?;
130
+ if let Some ( owner) = self . owner ( ) {
131
+ // Step 2.4. If attribute’s element is not originalElement, then return.
132
+ if owner != original_element {
133
+ return Ok ( ( ) ) ;
134
+ }
135
+ // Step 2.5. Change attribute to verifiedValue.
136
+ let value = owner. parse_attribute ( self . namespace ( ) , self . local_name ( ) , value) ;
137
+ owner. change_attribute ( self , value, can_gc) ;
138
+ } else {
139
+ // Step 2.3. If attribute’s element is null, then set attribute’s value to verifiedValue, and return.
140
+ self . set_value ( value) ;
141
+ }
120
142
} else {
121
- * self . value . borrow_mut ( ) = AttrValue :: String ( value. into ( ) ) ;
143
+ // Step 1. If attribute’s element is null, then set attribute’s value to value.
144
+ self . set_value ( value) ;
122
145
}
146
+ Ok ( ( ) )
123
147
}
124
148
125
149
// https://dom.spec.whatwg.org/#dom-attr-name
@@ -154,41 +178,6 @@ impl AttrMethods<crate::DomTypeHolder> for Attr {
154
178
}
155
179
156
180
impl Attr {
157
- pub ( crate ) fn set_value ( & self , mut value : AttrValue , owner : & Element , can_gc : CanGc ) {
158
- let name = self . local_name ( ) . clone ( ) ;
159
- let namespace = self . namespace ( ) . clone ( ) ;
160
- let old_value = DOMString :: from ( & * * self . value ( ) ) ;
161
- let new_value = DOMString :: from ( & * value) ;
162
- let mutation = LazyCell :: new ( || Mutation :: Attribute {
163
- name : name. clone ( ) ,
164
- namespace : namespace. clone ( ) ,
165
- old_value : Some ( old_value. clone ( ) ) ,
166
- } ) ;
167
-
168
- MutationObserver :: queue_a_mutation_record ( owner. upcast :: < Node > ( ) , mutation) ;
169
-
170
- if owner. is_custom ( ) {
171
- let reaction = CallbackReaction :: AttributeChanged (
172
- name,
173
- Some ( old_value) ,
174
- Some ( new_value) ,
175
- namespace,
176
- ) ;
177
- ScriptThread :: enqueue_callback_reaction ( owner, reaction, None ) ;
178
- }
179
-
180
- assert_eq ! ( Some ( owner) , self . owner( ) . as_deref( ) ) ;
181
- owner. will_mutate_attr ( self ) ;
182
- self . swap_value ( & mut value) ;
183
- if is_relevant_attribute ( self . namespace ( ) , self . local_name ( ) ) {
184
- vtable_for ( owner. upcast ( ) ) . attribute_mutated (
185
- self ,
186
- AttributeMutation :: Set ( Some ( & value) ) ,
187
- can_gc,
188
- ) ;
189
- }
190
- }
191
-
192
181
/// Used to swap the attribute's value without triggering mutation events
193
182
pub ( crate ) fn swap_value ( & self , value : & mut AttrValue ) {
194
183
mem:: swap ( & mut * self . value . borrow_mut ( ) , value) ;
@@ -202,6 +191,10 @@ impl Attr {
202
191
self . value . borrow ( )
203
192
}
204
193
194
+ fn set_value ( & self , value : DOMString ) {
195
+ * self . value . borrow_mut ( ) = AttrValue :: String ( value. into ( ) ) ;
196
+ }
197
+
205
198
pub ( crate ) fn local_name ( & self ) -> & LocalName {
206
199
& self . identifier . local_name
207
200
}
0 commit comments