resolve issue #36074 new_js_regex and matches_js_regex need a CanGc argument (#36111)

* new_js_regex and matches_js_regex need a CanGc argument

Signed-off-by: dericko681 <abonghoderick@gmail.com>

* new_js_regex and matches_js_regex need a CanGc argument

Signed-off-by: dericko681 <abonghoderick@gmail.com>

* edit Propagate CanGc arguments through new_js_regex and matches_js_regex

Signed-off-by: dericko681 <abonghoderick@gmail.com>

* Propagate CanGc arguments through new_js_regex and matches_js_regex

Signed-off-by: dericko681 <abonghoderick@gmail.com>

* Propagate CanGc arguments through new_js_regex and matches_js_regex

Signed-off-by: dericko681 <abonghoderick@gmail.com>

* Propagate CanGc arguments through new_js_regex and matches_js_regex

Signed-off-by: dericko681 <abonghoderick@gmail.com>

---------

Signed-off-by: dericko681 <abonghoderick@gmail.com>
This commit is contained in:
Kunga Derick Abongho 2025-03-29 14:09:56 +01:00 committed by GitHub
parent b5c8164e99
commit 83da63f638
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
60 changed files with 600 additions and 435 deletions

View file

@ -115,7 +115,7 @@ impl AttrMethods<crate::DomTypeHolder> for Attr {
fn SetValue(&self, value: DOMString) { fn SetValue(&self, value: DOMString) {
if let Some(owner) = self.owner() { if let Some(owner) = self.owner() {
let value = owner.parse_attribute(self.namespace(), self.local_name(), value); let value = owner.parse_attribute(self.namespace(), self.local_name(), value);
self.set_value(value, &owner); self.set_value(value, &owner, CanGc::note());
} else { } else {
*self.value.borrow_mut() = AttrValue::String(value.into()); *self.value.borrow_mut() = AttrValue::String(value.into());
} }
@ -153,7 +153,7 @@ impl AttrMethods<crate::DomTypeHolder> for Attr {
} }
impl Attr { impl Attr {
pub(crate) fn set_value(&self, mut value: AttrValue, owner: &Element) { pub(crate) fn set_value(&self, mut value: AttrValue, owner: &Element, can_gc: CanGc) {
let name = self.local_name().clone(); let name = self.local_name().clone();
let namespace = self.namespace().clone(); let namespace = self.namespace().clone();
let old_value = DOMString::from(&**self.value()); let old_value = DOMString::from(&**self.value());
@ -180,8 +180,11 @@ impl Attr {
owner.will_mutate_attr(self); owner.will_mutate_attr(self);
self.swap_value(&mut value); self.swap_value(&mut value);
if *self.namespace() == ns!() { if *self.namespace() == ns!() {
vtable_for(owner.upcast()) vtable_for(owner.upcast()).attribute_mutated(
.attribute_mutated(self, AttributeMutation::Set(Some(&value))); self,
AttributeMutation::Set(Some(&value)),
can_gc,
);
} }
} }

View file

@ -262,7 +262,7 @@ impl CharacterDataMethods<crate::DomTypeHolder> for CharacterData {
// https://dom.spec.whatwg.org/#dom-childnode-remove // https://dom.spec.whatwg.org/#dom-childnode-remove
fn Remove(&self) { fn Remove(&self) {
let node = self.upcast::<Node>(); let node = self.upcast::<Node>();
node.remove_self(); node.remove_self(CanGc::note());
} }
// https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-previouselementsibling // https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-previouselementsibling

View file

@ -878,7 +878,7 @@ pub(crate) fn upgrade_element(
// We know this element is is form-associated, so we can use the implementation of // We know this element is is form-associated, so we can use the implementation of
// `FormControl` for HTMLElement, which makes that assumption. // `FormControl` for HTMLElement, which makes that assumption.
// Step 9.1: Reset the form owner of element // Step 9.1: Reset the form owner of element
html_element.reset_form_owner(); html_element.reset_form_owner(can_gc);
if let Some(form) = html_element.form_owner() { if let Some(form) = html_element.form_owner() {
// Even though the tree hasn't structurally mutated, // Even though the tree hasn't structurally mutated,
// HTMLCollections need to be invalidated. // HTMLCollections need to be invalidated.

View file

@ -920,14 +920,14 @@ impl Document {
} }
/// Remove any existing association between the provided id and any elements in this document. /// Remove any existing association between the provided id and any elements in this document.
pub(crate) fn unregister_element_id(&self, to_unregister: &Element, id: Atom) { pub(crate) fn unregister_element_id(&self, to_unregister: &Element, id: Atom, can_gc: CanGc) {
self.document_or_shadow_root self.document_or_shadow_root
.unregister_named_element(&self.id_map, to_unregister, &id); .unregister_named_element(&self.id_map, to_unregister, &id);
self.reset_form_owner_for_listeners(&id); self.reset_form_owner_for_listeners(&id, can_gc);
} }
/// Associate an element present in this document with the provided id. /// Associate an element present in this document with the provided id.
pub(crate) fn register_element_id(&self, element: &Element, id: Atom) { pub(crate) fn register_element_id(&self, element: &Element, id: Atom, can_gc: CanGc) {
let root = self.GetDocumentElement().expect( let root = self.GetDocumentElement().expect(
"The element is in the document, so there must be a document \ "The element is in the document, so there must be a document \
element.", element.",
@ -938,7 +938,7 @@ impl Document {
&id, &id,
DomRoot::from_ref(root.upcast::<Node>()), DomRoot::from_ref(root.upcast::<Node>()),
); );
self.reset_form_owner_for_listeners(&id); self.reset_form_owner_for_listeners(&id, can_gc);
} }
/// Remove any existing association between the provided name and any elements in this document. /// Remove any existing association between the provided name and any elements in this document.
@ -3265,10 +3265,10 @@ impl Document {
id id
} }
pub(crate) fn unregister_media_controls(&self, id: &str) { pub(crate) fn unregister_media_controls(&self, id: &str, can_gc: CanGc) {
if let Some(ref media_controls) = self.media_controls.borrow_mut().remove(id) { if let Some(ref media_controls) = self.media_controls.borrow_mut().remove(id) {
let media_controls = DomRoot::from_ref(&**media_controls); let media_controls = DomRoot::from_ref(&**media_controls);
media_controls.Host().detach_shadow(); media_controls.Host().detach_shadow(can_gc);
} else { } else {
debug_assert!(false, "Trying to unregister unknown media controls"); debug_assert!(false, "Trying to unregister unknown media controls");
} }
@ -4512,14 +4512,14 @@ impl Document {
} }
} }
fn reset_form_owner_for_listeners(&self, id: &Atom) { fn reset_form_owner_for_listeners(&self, id: &Atom, can_gc: CanGc) {
let map = self.form_id_listener_map.borrow(); let map = self.form_id_listener_map.borrow();
if let Some(listeners) = map.get(id) { if let Some(listeners) = map.get(id) {
for listener in listeners { for listener in listeners {
listener listener
.as_maybe_form_control() .as_maybe_form_control()
.expect("Element must be a form control") .expect("Element must be a form control")
.reset_form_owner(); .reset_form_owner(can_gc);
} }
} }
} }
@ -5234,7 +5234,7 @@ impl DocumentMethods<crate::DomTypeHolder> for Document {
} }
// Step 3. // Step 3.
Node::adopt(node, self); Node::adopt(node, self, CanGc::note());
// Step 4. // Step 4.
Ok(DomRoot::from_ref(node)) Ok(DomRoot::from_ref(node))
@ -5945,7 +5945,7 @@ impl DocumentMethods<crate::DomTypeHolder> for Document {
} }
// Step 11. Replace all with null within document. // Step 11. Replace all with null within document.
Node::replace_all(None, self.upcast::<Node>()); Node::replace_all(None, self.upcast::<Node>(), can_gc);
// Specs and tests are in a state of flux about whether // Specs and tests are in a state of flux about whether
// we want to clear the selection when we remove the contents; // we want to clear the selection when we remove the contents;

View file

@ -104,6 +104,6 @@ impl DocumentTypeMethods<crate::DomTypeHolder> for DocumentType {
// https://dom.spec.whatwg.org/#dom-childnode-remove // https://dom.spec.whatwg.org/#dom-childnode-remove
fn Remove(&self) { fn Remove(&self) {
self.upcast::<Node>().remove_self(); self.upcast::<Node>().remove_self(CanGc::note());
} }
} }

View file

@ -40,7 +40,7 @@ impl DOMStringMap {
impl DOMStringMapMethods<crate::DomTypeHolder> for DOMStringMap { impl DOMStringMapMethods<crate::DomTypeHolder> for DOMStringMap {
// https://html.spec.whatwg.org/multipage/#dom-domstringmap-removeitem // https://html.spec.whatwg.org/multipage/#dom-domstringmap-removeitem
fn NamedDeleter(&self, name: DOMString) { fn NamedDeleter(&self, name: DOMString) {
self.element.delete_custom_attr(name) self.element.delete_custom_attr(name, CanGc::note())
} }
// https://html.spec.whatwg.org/multipage/#dom-domstringmap-setitem // https://html.spec.whatwg.org/multipage/#dom-domstringmap-setitem

View file

@ -566,7 +566,7 @@ impl Element {
// Step 4.3.1. Remove all of currentShadowRoots children, in tree order. // Step 4.3.1. Remove all of currentShadowRoots children, in tree order.
for child in current_shadow_root.upcast::<Node>().children() { for child in current_shadow_root.upcast::<Node>().children() {
child.remove_self(); child.remove_self(can_gc);
} }
// Step 4.3.2. Set currentShadowRoots declarative to false. // Step 4.3.2. Set currentShadowRoots declarative to false.
@ -621,7 +621,7 @@ impl Element {
tree_is_in_a_document_tree: self.upcast::<Node>().is_in_a_document_tree(), tree_is_in_a_document_tree: self.upcast::<Node>().is_in_a_document_tree(),
tree_is_in_a_shadow_tree: true, tree_is_in_a_shadow_tree: true,
}; };
shadow_root.bind_to_tree(&bind_context); shadow_root.bind_to_tree(&bind_context, can_gc);
let node = self.upcast::<Node>(); let node = self.upcast::<Node>();
node.dirty(NodeDamage::OtherNodeDamage); node.dirty(NodeDamage::OtherNodeDamage);
@ -630,7 +630,7 @@ impl Element {
Ok(shadow_root) Ok(shadow_root)
} }
pub(crate) fn detach_shadow(&self) { pub(crate) fn detach_shadow(&self, can_gc: CanGc) {
let Some(ref shadow_root) = self.shadow_root() else { let Some(ref shadow_root) = self.shadow_root() else {
unreachable!("Trying to detach a non-attached shadow root"); unreachable!("Trying to detach a non-attached shadow root");
}; };
@ -639,7 +639,7 @@ impl Element {
node.note_dirty_descendants(); node.note_dirty_descendants();
node.rev_version(); node.rev_version();
shadow_root.detach(); shadow_root.detach(can_gc);
self.ensure_rare_data().shadow_root = None; self.ensure_rare_data().shadow_root = None;
} }
@ -1635,10 +1635,10 @@ impl Element {
Some(self), Some(self),
can_gc, can_gc,
); );
self.push_attribute(&attr); self.push_attribute(&attr, can_gc);
} }
pub(crate) fn push_attribute(&self, attr: &Attr) { pub(crate) fn push_attribute(&self, attr: &Attr, can_gc: CanGc) {
let name = attr.local_name().clone(); let name = attr.local_name().clone();
let namespace = attr.namespace().clone(); let namespace = attr.namespace().clone();
let mutation = LazyCell::new(|| Mutation::Attribute { let mutation = LazyCell::new(|| Mutation::Attribute {
@ -1659,7 +1659,7 @@ impl Element {
self.will_mutate_attr(attr); self.will_mutate_attr(attr);
self.attrs.borrow_mut().push(Dom::from_ref(attr)); self.attrs.borrow_mut().push(Dom::from_ref(attr));
if attr.namespace() == &ns!() { if attr.namespace() == &ns!() {
vtable_for(self.upcast()).attribute_mutated(attr, AttributeMutation::Set(None)); vtable_for(self.upcast()).attribute_mutated(attr, AttributeMutation::Set(None), can_gc);
} }
} }
@ -1788,7 +1788,7 @@ impl Element {
.find(|attr| find(attr)) .find(|attr| find(attr))
.map(|js| DomRoot::from_ref(&**js)); .map(|js| DomRoot::from_ref(&**js));
if let Some(attr) = attr { if let Some(attr) = attr {
attr.set_value(value, self); attr.set_value(value, self, can_gc);
} else { } else {
self.push_new_attribute(local_name, value, name, namespace, prefix, can_gc); self.push_new_attribute(local_name, value, name, namespace, prefix, can_gc);
}; };
@ -1811,17 +1811,23 @@ impl Element {
&self, &self,
namespace: &Namespace, namespace: &Namespace,
local_name: &LocalName, local_name: &LocalName,
can_gc: CanGc,
) -> Option<DomRoot<Attr>> { ) -> Option<DomRoot<Attr>> {
self.remove_first_matching_attribute(|attr| { self.remove_first_matching_attribute(
attr.namespace() == namespace && attr.local_name() == local_name |attr| attr.namespace() == namespace && attr.local_name() == local_name,
}) can_gc,
)
} }
pub(crate) fn remove_attribute_by_name(&self, name: &LocalName) -> Option<DomRoot<Attr>> { pub(crate) fn remove_attribute_by_name(
self.remove_first_matching_attribute(|attr| attr.name() == name) &self,
name: &LocalName,
can_gc: CanGc,
) -> Option<DomRoot<Attr>> {
self.remove_first_matching_attribute(|attr| attr.name() == name, can_gc)
} }
fn remove_first_matching_attribute<F>(&self, find: F) -> Option<DomRoot<Attr>> fn remove_first_matching_attribute<F>(&self, find: F, can_gc: CanGc) -> Option<DomRoot<Attr>>
where where
F: Fn(&Attr) -> bool, F: Fn(&Attr) -> bool,
{ {
@ -1850,7 +1856,11 @@ impl Element {
self.attrs.borrow_mut().remove(idx); self.attrs.borrow_mut().remove(idx);
attr.set_owner(None); attr.set_owner(None);
if attr.namespace() == &ns!() { if attr.namespace() == &ns!() {
vtable_for(self.upcast()).attribute_mutated(&attr, AttributeMutation::Removed); vtable_for(self.upcast()).attribute_mutated(
&attr,
AttributeMutation::Removed,
can_gc,
);
} }
attr attr
}) })
@ -1892,7 +1902,7 @@ impl Element {
if value { if value {
self.set_string_attribute(local_name, DOMString::new(), can_gc); self.set_string_attribute(local_name, DOMString::new(), can_gc);
} else { } else {
self.remove_attribute(&ns!(), local_name); self.remove_attribute(&ns!(), local_name, can_gc);
} }
} }
@ -1961,7 +1971,7 @@ impl Element {
self.set_string_attribute(local_name, val, can_gc); self.set_string_attribute(local_name, val, can_gc);
}, },
None => { None => {
self.remove_attribute(&ns!(), local_name); self.remove_attribute(&ns!(), local_name, can_gc);
}, },
} }
} }
@ -2056,23 +2066,31 @@ impl Element {
&self, &self,
where_: AdjacentPosition, where_: AdjacentPosition,
node: &Node, node: &Node,
can_gc: CanGc,
) -> Fallible<Option<DomRoot<Node>>> { ) -> Fallible<Option<DomRoot<Node>>> {
let self_node = self.upcast::<Node>(); let self_node = self.upcast::<Node>();
match where_ { match where_ {
AdjacentPosition::BeforeBegin => { AdjacentPosition::BeforeBegin => {
if let Some(parent) = self_node.GetParentNode() { if let Some(parent) = self_node.GetParentNode() {
Node::pre_insert(node, &parent, Some(self_node)).map(Some) Node::pre_insert(node, &parent, Some(self_node), can_gc).map(Some)
} else { } else {
Ok(None) Ok(None)
} }
}, },
AdjacentPosition::AfterBegin => { AdjacentPosition::AfterBegin => Node::pre_insert(
Node::pre_insert(node, self_node, self_node.GetFirstChild().as_deref()).map(Some) node,
self_node,
self_node.GetFirstChild().as_deref(),
can_gc,
)
.map(Some),
AdjacentPosition::BeforeEnd => {
Node::pre_insert(node, self_node, None, can_gc).map(Some)
}, },
AdjacentPosition::BeforeEnd => Node::pre_insert(node, self_node, None).map(Some),
AdjacentPosition::AfterEnd => { AdjacentPosition::AfterEnd => {
if let Some(parent) = self_node.GetParentNode() { if let Some(parent) = self_node.GetParentNode() {
Node::pre_insert(node, &parent, self_node.GetNextSibling().as_deref()).map(Some) Node::pre_insert(node, &parent, self_node.GetNextSibling().as_deref(), can_gc)
.map(Some)
} else { } else {
Ok(None) Ok(None)
} }
@ -2437,7 +2455,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
Some(_index) => match force { Some(_index) => match force {
// Step 5. // Step 5.
None | Some(false) => { None | Some(false) => {
self.remove_attribute_by_name(&name); self.remove_attribute_by_name(&name, can_gc);
Ok(false) Ok(false)
}, },
// Step 6. // Step 6.
@ -2542,7 +2560,11 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
self.attrs.borrow_mut()[position] = Dom::from_ref(attr); self.attrs.borrow_mut()[position] = Dom::from_ref(attr);
old_attr.set_owner(None); old_attr.set_owner(None);
if attr.namespace() == &ns!() { if attr.namespace() == &ns!() {
vtable.attribute_mutated(attr, AttributeMutation::Set(Some(&old_attr.value()))); vtable.attribute_mutated(
attr,
AttributeMutation::Set(Some(&old_attr.value())),
CanGc::note(),
);
} }
// Step 6. // Step 6.
@ -2550,7 +2572,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
} else { } else {
// Step 5. // Step 5.
attr.set_owner(Some(self)); attr.set_owner(Some(self));
self.push_attribute(attr); self.push_attribute(attr, CanGc::note());
// Step 6. // Step 6.
Ok(None) Ok(None)
@ -2565,19 +2587,19 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
// https://dom.spec.whatwg.org/#dom-element-removeattribute // https://dom.spec.whatwg.org/#dom-element-removeattribute
fn RemoveAttribute(&self, name: DOMString) { fn RemoveAttribute(&self, name: DOMString) {
let name = self.parsed_name(name); let name = self.parsed_name(name);
self.remove_attribute_by_name(&name); self.remove_attribute_by_name(&name, CanGc::note());
} }
// https://dom.spec.whatwg.org/#dom-element-removeattributens // https://dom.spec.whatwg.org/#dom-element-removeattributens
fn RemoveAttributeNS(&self, namespace: Option<DOMString>, local_name: DOMString) { fn RemoveAttributeNS(&self, namespace: Option<DOMString>, local_name: DOMString) {
let namespace = namespace_from_domstring(namespace); let namespace = namespace_from_domstring(namespace);
let local_name = LocalName::from(local_name); let local_name = LocalName::from(local_name);
self.remove_attribute(&namespace, &local_name); self.remove_attribute(&namespace, &local_name, CanGc::note());
} }
// https://dom.spec.whatwg.org/#dom-element-removeattributenode // https://dom.spec.whatwg.org/#dom-element-removeattributenode
fn RemoveAttributeNode(&self, attr: &Attr) -> Fallible<DomRoot<Attr>> { fn RemoveAttributeNode(&self, attr: &Attr) -> Fallible<DomRoot<Attr>> {
self.remove_first_matching_attribute(|a| a == attr) self.remove_first_matching_attribute(|a| a == attr, CanGc::note())
.ok_or(Error::NotFound) .ok_or(Error::NotFound)
} }
@ -2951,7 +2973,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
} }
// Replace all with fragment within target. // Replace all with fragment within target.
Node::replace_all(Some(frag.upcast()), &target); Node::replace_all(Some(frag.upcast()), &target, can_gc);
} }
/// <https://html.spec.whatwg.org/multipage/#dom-element-gethtml> /// <https://html.spec.whatwg.org/multipage/#dom-element-gethtml>
@ -3013,7 +3035,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
// Step 1. // Step 1.
let frag = self.parse_fragment(value, can_gc)?; let frag = self.parse_fragment(value, can_gc)?;
Node::replace_all(Some(frag.upcast()), &target); Node::replace_all(Some(frag.upcast()), &target, can_gc);
Ok(()) Ok(())
} }
@ -3155,7 +3177,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
// https://dom.spec.whatwg.org/#dom-childnode-remove // https://dom.spec.whatwg.org/#dom-childnode-remove
fn Remove(&self) { fn Remove(&self) {
self.upcast::<Node>().remove_self(); self.upcast::<Node>().remove_self(CanGc::note());
} }
// https://dom.spec.whatwg.org/#dom-element-matches // https://dom.spec.whatwg.org/#dom-element-matches
@ -3213,7 +3235,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
element: &Element, element: &Element,
) -> Fallible<Option<DomRoot<Element>>> { ) -> Fallible<Option<DomRoot<Element>>> {
let where_ = where_.parse::<AdjacentPosition>()?; let where_ = where_.parse::<AdjacentPosition>()?;
let inserted_node = self.insert_adjacent(where_, element.upcast())?; let inserted_node = self.insert_adjacent(where_, element.upcast(), CanGc::note())?;
Ok(inserted_node.map(|node| DomRoot::downcast(node).unwrap())) Ok(inserted_node.map(|node| DomRoot::downcast(node).unwrap()))
} }
@ -3224,7 +3246,8 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
// Step 2. // Step 2.
let where_ = where_.parse::<AdjacentPosition>()?; let where_ = where_.parse::<AdjacentPosition>()?;
self.insert_adjacent(where_, text.upcast()).map(|_| ()) self.insert_adjacent(where_, text.upcast(), can_gc)
.map(|_| ())
} }
// https://w3c.github.io/DOM-Parsing/#dom-element-insertadjacenthtml // https://w3c.github.io/DOM-Parsing/#dom-element-insertadjacenthtml
@ -3263,7 +3286,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
let fragment = context.parse_fragment(text, can_gc)?; let fragment = context.parse_fragment(text, can_gc)?;
// Step 4. // Step 4.
self.insert_adjacent(position, fragment.upcast()) self.insert_adjacent(position, fragment.upcast(), can_gc)
.map(|_| ()) .map(|_| ())
} }
@ -3713,8 +3736,10 @@ impl VirtualMethods for Element {
.attribute_affects_presentational_hints(attr) .attribute_affects_presentational_hints(attr)
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
let node = self.upcast::<Node>(); let node = self.upcast::<Node>();
let doc = node.owner_doc(); let doc = node.owner_doc();
match attr.local_name() { match attr.local_name() {
@ -3776,25 +3801,25 @@ impl VirtualMethods for Element {
if let Some(old_value) = old_value { if let Some(old_value) = old_value {
let old_value = old_value.as_atom().clone(); let old_value = old_value.as_atom().clone();
if let Some(ref shadow_root) = containing_shadow_root { if let Some(ref shadow_root) = containing_shadow_root {
shadow_root.unregister_element_id(self, old_value); shadow_root.unregister_element_id(self, old_value, can_gc);
} else { } else {
doc.unregister_element_id(self, old_value); doc.unregister_element_id(self, old_value, can_gc);
} }
} }
if value != atom!("") { if value != atom!("") {
if let Some(ref shadow_root) = containing_shadow_root { if let Some(ref shadow_root) = containing_shadow_root {
shadow_root.register_element_id(self, value); shadow_root.register_element_id(self, value, can_gc);
} else { } else {
doc.register_element_id(self, value); doc.register_element_id(self, value, can_gc);
} }
} }
}, },
AttributeMutation::Removed => { AttributeMutation::Removed => {
if value != atom!("") { if value != atom!("") {
if let Some(ref shadow_root) = containing_shadow_root { if let Some(ref shadow_root) = containing_shadow_root {
shadow_root.unregister_element_id(self, value); shadow_root.unregister_element_id(self, value, can_gc);
} else { } else {
doc.unregister_element_id(self, value); doc.unregister_element_id(self, value, can_gc);
} }
} }
}, },
@ -3873,19 +3898,19 @@ impl VirtualMethods for Element {
} }
} }
fn bind_to_tree(&self, context: &BindContext) { fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.bind_to_tree(context); s.bind_to_tree(context, can_gc);
} }
if let Some(f) = self.as_maybe_form_control() { if let Some(f) = self.as_maybe_form_control() {
f.bind_form_control_to_tree(); f.bind_form_control_to_tree(can_gc);
} }
let doc = self.owner_document(); let doc = self.owner_document();
if let Some(ref shadow_root) = self.shadow_root() { if let Some(ref shadow_root) = self.shadow_root() {
shadow_root.bind_to_tree(context); shadow_root.bind_to_tree(context, can_gc);
} }
if !context.is_in_tree() { if !context.is_in_tree() {
@ -3896,9 +3921,9 @@ impl VirtualMethods for Element {
if let Some(ref id) = *self.id_attribute.borrow() { if let Some(ref id) = *self.id_attribute.borrow() {
if let Some(shadow_root) = self.containing_shadow_root() { if let Some(shadow_root) = self.containing_shadow_root() {
shadow_root.register_element_id(self, id.clone()); shadow_root.register_element_id(self, id.clone(), can_gc);
} else { } else {
doc.register_element_id(self, id.clone()); doc.register_element_id(self, id.clone(), can_gc);
} }
} }
if let Some(ref name) = self.name_attribute() { if let Some(ref name) = self.name_attribute() {
@ -3911,14 +3936,14 @@ impl VirtualMethods for Element {
doc.increment_dom_count(); doc.increment_dom_count();
} }
fn unbind_from_tree(&self, context: &UnbindContext) { fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context); self.super_type().unwrap().unbind_from_tree(context, can_gc);
if let Some(f) = self.as_maybe_form_control() { if let Some(f) = self.as_maybe_form_control() {
// TODO: The valid state of ancestors might be wrong if the form control element // TODO: The valid state of ancestors might be wrong if the form control element
// has a fieldset ancestor, for instance: `<form><fieldset><input>`, // has a fieldset ancestor, for instance: `<form><fieldset><input>`,
// if `<input>` is unbound, `<form><fieldset>` should trigger a call to `update_validity()`. // if `<input>` is unbound, `<form><fieldset>` should trigger a call to `update_validity()`.
f.unbind_form_control_from_tree(); f.unbind_form_control_from_tree(can_gc);
} }
if !context.tree_is_in_a_document_tree && !context.tree_is_in_a_shadow_tree { if !context.tree_is_in_a_document_tree && !context.tree_is_in_a_shadow_tree {
@ -3938,10 +3963,10 @@ impl VirtualMethods for Element {
// Only unregister the element id if the node was disconnected from it's shadow root // Only unregister the element id if the node was disconnected from it's shadow root
// (as opposed to the whole shadow tree being disconnected as a whole) // (as opposed to the whole shadow tree being disconnected as a whole)
if !self.upcast::<Node>().is_in_a_shadow_tree() { if !self.upcast::<Node>().is_in_a_shadow_tree() {
shadow_root.unregister_element_id(self, value.clone()); shadow_root.unregister_element_id(self, value.clone(), can_gc);
} }
} else { } else {
doc.unregister_element_id(self, value.clone()); doc.unregister_element_id(self, value.clone(), can_gc);
} }
} }
if let Some(ref value) = self.name_attribute() { if let Some(ref value) = self.name_attribute() {
@ -3980,8 +4005,8 @@ impl VirtualMethods for Element {
} }
} }
fn adopting_steps(&self, old_doc: &Document) { fn adopting_steps(&self, old_doc: &Document, can_gc: CanGc) {
self.super_type().unwrap().adopting_steps(old_doc); self.super_type().unwrap().adopting_steps(old_doc, can_gc);
if self.owner_document().is_html_document() != old_doc.is_html_document() { if self.owner_document().is_html_document() != old_doc.is_html_document() {
self.tag_name.clear(); self.tag_name.clear();
@ -4426,12 +4451,12 @@ impl Element {
element element
} }
pub(crate) fn is_invalid(&self, needs_update: bool) -> bool { pub(crate) fn is_invalid(&self, needs_update: bool, can_gc: CanGc) -> bool {
if let Some(validatable) = self.as_maybe_validatable() { if let Some(validatable) = self.as_maybe_validatable() {
if needs_update { if needs_update {
validatable validatable
.validity_state() .validity_state()
.perform_validation_and_update(ValidationFlags::all()); .perform_validation_and_update(ValidationFlags::all(), can_gc);
} }
return validatable.is_instance_validatable() && !validatable.satisfies_constraints(); return validatable.is_instance_validatable() && !validatable.satisfies_constraints();
} }
@ -4844,7 +4869,7 @@ pub(crate) fn set_cross_origin_attribute(
match value { match value {
Some(val) => element.set_string_attribute(&local_name!("crossorigin"), val, can_gc), Some(val) => element.set_string_attribute(&local_name!("crossorigin"), val, can_gc),
None => { None => {
element.remove_attribute(&ns!(), &local_name!("crossorigin")); element.remove_attribute(&ns!(), &local_name!("crossorigin"), can_gc);
}, },
} }
} }

View file

@ -253,7 +253,7 @@ impl ElementInternalsMethods<crate::DomTypeHolder> for ElementInternals {
// Step 4: For each entry `flag` → `value` of `flags`, set element's validity flag with the name // Step 4: For each entry `flag` → `value` of `flags`, set element's validity flag with the name
// `flag` to `value`. // `flag` to `value`.
self.validity_state().update_invalid_flags(bits); self.validity_state().update_invalid_flags(bits);
self.validity_state().update_pseudo_classes(); self.validity_state().update_pseudo_classes(CanGc::note());
// Step 5: Set element's validation message to the empty string if message is not given // Step 5: Set element's validation message to the empty string if message is not given
// or all of element's validity flags are false, or to message otherwise. // or all of element's validity flags are false, or to message otherwise.

View file

@ -584,7 +584,7 @@ impl Event {
if let Some(target) = self.GetTarget() { if let Some(target) = self.GetTarget() {
if let Some(node) = target.downcast::<Node>() { if let Some(node) = target.downcast::<Node>() {
let vtable = vtable_for(node); let vtable = vtable_for(node);
vtable.handle_event(self); vtable.handle_event(self, can_gc);
} }
} }
} }

View file

@ -100,8 +100,10 @@ impl VirtualMethods for HTMLAnchorElement {
} }
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match *attr.local_name() { match *attr.local_name() {
local_name!("rel") | local_name!("rev") => { local_name!("rel") | local_name!("rev") => {
@ -112,9 +114,9 @@ impl VirtualMethods for HTMLAnchorElement {
} }
} }
fn bind_to_tree(&self, context: &BindContext) { fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.bind_to_tree(context); s.bind_to_tree(context, can_gc);
} }
self.relations self.relations

View file

@ -321,8 +321,10 @@ impl VirtualMethods for HTMLAreaElement {
} }
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match *attr.local_name() { match *attr.local_name() {
local_name!("rel") | local_name!("rev") => { local_name!("rel") | local_name!("rev") => {
@ -333,9 +335,9 @@ impl VirtualMethods for HTMLAreaElement {
} }
} }
fn bind_to_tree(&self, context: &BindContext) { fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.bind_to_tree(context); s.bind_to_tree(context, can_gc);
} }
self.relations self.relations

View file

@ -117,20 +117,22 @@ impl VirtualMethods for HTMLBaseElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods) Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
if *attr.local_name() == local_name!("href") { if *attr.local_name() == local_name!("href") {
self.owner_document().refresh_base_element(); self.owner_document().refresh_base_element();
} }
} }
fn bind_to_tree(&self, context: &BindContext) { fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
self.super_type().unwrap().bind_to_tree(context); self.super_type().unwrap().bind_to_tree(context, can_gc);
self.bind_unbind(context.tree_is_in_a_document_tree); self.bind_unbind(context.tree_is_in_a_document_tree);
} }
fn unbind_from_tree(&self, context: &UnbindContext) { fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context); self.super_type().unwrap().unbind_from_tree(context, can_gc);
self.bind_unbind(context.tree_is_in_a_document_tree); self.bind_unbind(context.tree_is_in_a_document_tree);
} }
} }

View file

@ -141,9 +141,9 @@ impl VirtualMethods for HTMLBodyElement {
.attribute_affects_presentational_hints(attr) .attribute_affects_presentational_hints(attr)
} }
fn bind_to_tree(&self, context: &BindContext) { fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.bind_to_tree(context); s.bind_to_tree(context, can_gc);
} }
if !context.tree_is_in_a_document_tree { if !context.tree_is_in_a_document_tree {
@ -176,7 +176,7 @@ impl VirtualMethods for HTMLBodyElement {
} }
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
let do_super_mutate = match (attr.local_name(), mutation) { let do_super_mutate = match (attr.local_name(), mutation) {
(name, AttributeMutation::Set(_)) if name.starts_with("on") => { (name, AttributeMutation::Set(_)) if name.starts_with("on") => {
let window = self.owner_window(); let window = self.owner_window();
@ -218,7 +218,9 @@ impl VirtualMethods for HTMLBodyElement {
}; };
if do_super_mutate { if do_super_mutate {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
} }
} }
} }

View file

@ -242,8 +242,10 @@ impl VirtualMethods for HTMLButtonElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods) Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match *attr.local_name() { match *attr.local_name() {
local_name!("disabled") => { local_name!("disabled") => {
let el = self.upcast::<Element>(); let el = self.upcast::<Element>();
@ -261,7 +263,7 @@ impl VirtualMethods for HTMLButtonElement {
} }
el.update_sequentially_focusable_status(CanGc::note()); el.update_sequentially_focusable_status(CanGc::note());
self.validity_state() self.validity_state()
.perform_validation_and_update(ValidationFlags::all()); .perform_validation_and_update(ValidationFlags::all(), can_gc);
}, },
local_name!("type") => match mutation { local_name!("type") => match mutation {
AttributeMutation::Set(_) => { AttributeMutation::Set(_) => {
@ -272,32 +274,32 @@ impl VirtualMethods for HTMLButtonElement {
}; };
self.button_type.set(value); self.button_type.set(value);
self.validity_state() self.validity_state()
.perform_validation_and_update(ValidationFlags::all()); .perform_validation_and_update(ValidationFlags::all(), can_gc);
}, },
AttributeMutation::Removed => { AttributeMutation::Removed => {
self.button_type.set(ButtonType::Submit); self.button_type.set(ButtonType::Submit);
}, },
}, },
local_name!("form") => { local_name!("form") => {
self.form_attribute_mutated(mutation); self.form_attribute_mutated(mutation, can_gc);
self.validity_state() self.validity_state()
.perform_validation_and_update(ValidationFlags::empty()); .perform_validation_and_update(ValidationFlags::empty(), can_gc);
}, },
_ => {}, _ => {},
} }
} }
fn bind_to_tree(&self, context: &BindContext) { fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.bind_to_tree(context); s.bind_to_tree(context, can_gc);
} }
self.upcast::<Element>() self.upcast::<Element>()
.check_ancestors_disabled_state_for_form_control(); .check_ancestors_disabled_state_for_form_control();
} }
fn unbind_from_tree(&self, context: &UnbindContext) { fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context); self.super_type().unwrap().unbind_from_tree(context, can_gc);
let node = self.upcast::<Node>(); let node = self.upcast::<Node>();
let el = self.upcast::<Element>(); let el = self.upcast::<Element>();

View file

@ -698,8 +698,10 @@ impl VirtualMethods for HTMLCanvasElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods) Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match attr.local_name() { match attr.local_name() {
&local_name!("width") | &local_name!("height") => self.recreate_contexts_after_resize(), &local_name!("width") | &local_name!("height") => self.recreate_contexts_after_resize(),
_ => (), _ => (),

View file

@ -122,7 +122,7 @@ impl HTMLDetailsElement {
.unwrap(); .unwrap();
let fallback_summary = let fallback_summary =
HTMLElement::new(local_name!("summary"), None, &document, None, can_gc); HTMLElement::new(local_name!("summary"), None, &document, None, CanGc::note());
fallback_summary fallback_summary
.upcast::<Node>() .upcast::<Node>()
.SetTextContent(Some(DEFAULT_SUMMARY.into()), can_gc); .SetTextContent(Some(DEFAULT_SUMMARY.into()), can_gc);
@ -232,8 +232,10 @@ impl VirtualMethods for HTMLDetailsElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods) Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
if attr.local_name() == &local_name!("open") { if attr.local_name() == &local_name!("open") {
self.update_shadow_tree_styles(CanGc::note()); self.update_shadow_tree_styles(CanGc::note());
@ -261,8 +263,8 @@ impl VirtualMethods for HTMLDetailsElement {
self.update_shadow_tree_contents(CanGc::note()); self.update_shadow_tree_contents(CanGc::note());
} }
fn bind_to_tree(&self, context: &BindContext) { fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
self.super_type().unwrap().bind_to_tree(context); self.super_type().unwrap().bind_to_tree(context, can_gc);
self.update_shadow_tree_contents(CanGc::note()); self.update_shadow_tree_contents(CanGc::note());
self.update_shadow_tree_styles(CanGc::note()); self.update_shadow_tree_styles(CanGc::note());

View file

@ -105,7 +105,7 @@ impl HTMLDialogElementMethods<crate::DomTypeHolder> for HTMLDialogElement {
// Step 1 & 2 // Step 1 & 2
if element if element
.remove_attribute(&ns!(), &local_name!("open")) .remove_attribute(&ns!(), &local_name!("open"), CanGc::note())
.is_none() .is_none()
{ {
return; return;

View file

@ -499,7 +499,7 @@ impl HTMLElementMethods<crate::DomTypeHolder> for HTMLElement {
let fragment = self.rendered_text_fragment(input, can_gc); let fragment = self.rendered_text_fragment(input, can_gc);
// Step 2: Replace all with fragment within element. // Step 2: Replace all with fragment within element.
Node::replace_all(Some(fragment.upcast()), self.upcast::<Node>()); Node::replace_all(Some(fragment.upcast()), self.upcast::<Node>(), can_gc);
} }
/// <https://html.spec.whatwg.org/multipage/#dom-outertext> /// <https://html.spec.whatwg.org/multipage/#dom-outertext>
@ -542,13 +542,13 @@ impl HTMLElementMethods<crate::DomTypeHolder> for HTMLElement {
// the next text node given next's previous sibling. // the next text node given next's previous sibling.
if let Some(next_sibling) = next { if let Some(next_sibling) = next {
if let Some(node) = next_sibling.GetPreviousSibling() { if let Some(node) = next_sibling.GetPreviousSibling() {
Self::merge_with_the_next_text_node(node); Self::merge_with_the_next_text_node(node, can_gc);
} }
} }
// Step 8: If previous is a Text node, then merge with the next text node given previous. // Step 8: If previous is a Text node, then merge with the next text node given previous.
if let Some(previous) = previous { if let Some(previous) = previous {
Self::merge_with_the_next_text_node(previous) Self::merge_with_the_next_text_node(previous, can_gc)
} }
Ok(()) Ok(())
@ -758,10 +758,11 @@ impl HTMLElement {
}) })
} }
pub(crate) fn delete_custom_attr(&self, local_name: DOMString) { pub(crate) fn delete_custom_attr(&self, local_name: DOMString, can_gc: CanGc) {
// FIXME(ajeffrey): Convert directly from DOMString to LocalName // FIXME(ajeffrey): Convert directly from DOMString to LocalName
let local_name = LocalName::from(to_snake_case(local_name)); let local_name = LocalName::from(to_snake_case(local_name));
self.as_element().remove_attribute(&ns!(), &local_name); self.as_element()
.remove_attribute(&ns!(), &local_name, can_gc);
} }
/// <https://html.spec.whatwg.org/multipage/#category-label> /// <https://html.spec.whatwg.org/multipage/#category-label>
@ -1039,7 +1040,7 @@ impl HTMLElement {
/// node. /// node.
/// ///
/// <https://html.spec.whatwg.org/multipage/#merge-with-the-next-text-node> /// <https://html.spec.whatwg.org/multipage/#merge-with-the-next-text-node>
fn merge_with_the_next_text_node(node: DomRoot<Node>) { fn merge_with_the_next_text_node(node: DomRoot<Node>, can_gc: CanGc) {
// Make sure node is a Text node // Make sure node is a Text node
if !node.is::<Text>() { if !node.is::<Text>() {
return; return;
@ -1063,7 +1064,7 @@ impl HTMLElement {
.expect("Got chars from Text"); .expect("Got chars from Text");
// Step 4:Remove next. // Step 4:Remove next.
next.remove_self(); next.remove_self(can_gc);
} }
} }
@ -1072,8 +1073,10 @@ impl VirtualMethods for HTMLElement {
Some(self.as_element() as &dyn VirtualMethods) Some(self.as_element() as &dyn VirtualMethods)
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
let element = self.as_element(); let element = self.as_element();
match (attr.local_name(), mutation) { match (attr.local_name(), mutation) {
(name, AttributeMutation::Set(_)) if name.starts_with("on") => { (name, AttributeMutation::Set(_)) if name.starts_with("on") => {
@ -1088,7 +1091,7 @@ impl VirtualMethods for HTMLElement {
); );
}, },
(&local_name!("form"), mutation) if self.is_form_associated_custom_element() => { (&local_name!("form"), mutation) if self.is_form_associated_custom_element() => {
self.form_attribute_mutated(mutation); self.form_attribute_mutated(mutation, can_gc);
}, },
// Adding a "disabled" attribute disables an enabled form element. // Adding a "disabled" attribute disables an enabled form element.
(&local_name!("disabled"), AttributeMutation::Set(_)) (&local_name!("disabled"), AttributeMutation::Set(_))
@ -1132,9 +1135,9 @@ impl VirtualMethods for HTMLElement {
} }
} }
fn bind_to_tree(&self, context: &BindContext) { fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
if let Some(super_type) = self.super_type() { if let Some(super_type) = self.super_type() {
super_type.bind_to_tree(context); super_type.bind_to_tree(context, can_gc);
} }
let element = self.as_element(); let element = self.as_element();
element.update_sequentially_focusable_status(CanGc::note()); element.update_sequentially_focusable_status(CanGc::note());
@ -1153,9 +1156,9 @@ impl VirtualMethods for HTMLElement {
} }
} }
fn unbind_from_tree(&self, context: &UnbindContext) { fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
if let Some(super_type) = self.super_type() { if let Some(super_type) = self.super_type() {
super_type.unbind_from_tree(context); super_type.unbind_from_tree(context, can_gc);
} }
// Unbinding from a tree might enable a form control, if a // Unbinding from a tree might enable a form control, if a

View file

@ -71,12 +71,12 @@ impl HTMLFieldSetElement {
) )
} }
pub(crate) fn update_validity(&self) { pub(crate) fn update_validity(&self, can_gc: CanGc) {
let has_invalid_child = self let has_invalid_child = self
.upcast::<Node>() .upcast::<Node>()
.traverse_preorder(ShadowIncluding::No) .traverse_preorder(ShadowIncluding::No)
.flat_map(DomRoot::downcast::<Element>) .flat_map(DomRoot::downcast::<Element>)
.any(|element| element.is_invalid(false)); .any(|element| element.is_invalid(false, can_gc));
self.upcast::<Element>() self.upcast::<Element>()
.set_state(ElementState::VALID, !has_invalid_child); .set_state(ElementState::VALID, !has_invalid_child);
@ -153,8 +153,10 @@ impl VirtualMethods for HTMLFieldSetElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods) Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match *attr.local_name() { match *attr.local_name() {
local_name!("disabled") => { local_name!("disabled") => {
let disabled_state = match mutation { let disabled_state = match mutation {
@ -243,7 +245,7 @@ impl VirtualMethods for HTMLFieldSetElement {
element.update_sequentially_focusable_status(CanGc::note()); element.update_sequentially_focusable_status(CanGc::note());
}, },
local_name!("form") => { local_name!("form") => {
self.form_attribute_mutated(mutation); self.form_attribute_mutated(mutation, can_gc);
}, },
_ => {}, _ => {},
} }

View file

@ -712,9 +712,11 @@ impl HTMLFormElement {
result result
} }
pub(crate) fn update_validity(&self) { pub(crate) fn update_validity(&self, can_gc: CanGc) {
let controls = self.controls.borrow(); let controls = self.controls.borrow();
let is_any_invalid = controls.iter().any(|control| control.is_invalid(false)); let is_any_invalid = controls
.iter()
.any(|control| control.is_invalid(false, can_gc));
self.upcast::<Element>() self.upcast::<Element>()
.set_state(ElementState::VALID, !is_any_invalid); .set_state(ElementState::VALID, !is_any_invalid);
@ -1087,7 +1089,7 @@ impl HTMLFormElement {
.iter() .iter()
.filter_map(|field| { .filter_map(|field| {
if let Some(element) = field.downcast::<Element>() { if let Some(element) = field.downcast::<Element>() {
if element.is_invalid(true) { if element.is_invalid(true, can_gc) {
Some(DomRoot::from_ref(element)) Some(DomRoot::from_ref(element))
} else { } else {
None None
@ -1306,17 +1308,17 @@ impl HTMLFormElement {
self.marked_for_reset.set(false); self.marked_for_reset.set(false);
} }
fn add_control<T: ?Sized + FormControl>(&self, control: &T) { fn add_control<T: ?Sized + FormControl>(&self, control: &T, can_gc: CanGc) {
{ {
let root = self.upcast::<Element>().root_element(); let root = self.upcast::<Element>().root_element();
let root = root.upcast::<Node>(); let root = root.upcast::<Node>();
let mut controls = self.controls.borrow_mut(); let mut controls = self.controls.borrow_mut();
controls.insert_pre_order(control.to_element(), root); controls.insert_pre_order(control.to_element(), root);
} }
self.update_validity(); self.update_validity(can_gc);
} }
fn remove_control<T: ?Sized + FormControl>(&self, control: &T) { fn remove_control<T: ?Sized + FormControl>(&self, control: &T, can_gc: CanGc) {
{ {
let control = control.to_element(); let control = control.to_element();
let mut controls = self.controls.borrow_mut(); let mut controls = self.controls.borrow_mut();
@ -1332,7 +1334,7 @@ impl HTMLFormElement {
let mut past_names_map = self.past_names_map.borrow_mut(); let mut past_names_map = self.past_names_map.borrow_mut();
past_names_map.0.retain(|_k, v| v.0 != control); past_names_map.0.retain(|_k, v| v.0 != control);
} }
self.update_validity(); self.update_validity(can_gc);
} }
} }
@ -1518,16 +1520,16 @@ pub(crate) trait FormControl: DomObject {
// Part of step 12. // Part of step 12.
// '..suppress the running of the reset the form owner algorithm // '..suppress the running of the reset the form owner algorithm
// when the parser subsequently attempts to insert the element..' // when the parser subsequently attempts to insert the element..'
fn set_form_owner_from_parser(&self, form: &HTMLFormElement) { fn set_form_owner_from_parser(&self, form: &HTMLFormElement, can_gc: CanGc) {
let elem = self.to_element(); let elem = self.to_element();
let node = elem.upcast::<Node>(); let node = elem.upcast::<Node>();
node.set_flag(NodeFlags::PARSER_ASSOCIATED_FORM_OWNER, true); node.set_flag(NodeFlags::PARSER_ASSOCIATED_FORM_OWNER, true);
form.add_control(self); form.add_control(self, can_gc);
self.set_form_owner(Some(form)); self.set_form_owner(Some(form));
} }
// https://html.spec.whatwg.org/multipage/#reset-the-form-owner // https://html.spec.whatwg.org/multipage/#reset-the-form-owner
fn reset_form_owner(&self) { fn reset_form_owner(&self, can_gc: CanGc) {
let elem = self.to_element(); let elem = self.to_element();
let node = elem.upcast::<Node>(); let node = elem.upcast::<Node>();
let old_owner = self.form_owner(); let old_owner = self.form_owner();
@ -1558,10 +1560,10 @@ pub(crate) trait FormControl: DomObject {
if old_owner != new_owner { if old_owner != new_owner {
if let Some(o) = old_owner { if let Some(o) = old_owner {
o.remove_control(self); o.remove_control(self, can_gc);
} }
if let Some(ref new_owner) = new_owner { if let Some(ref new_owner) = new_owner {
new_owner.add_control(self); new_owner.add_control(self, can_gc);
} }
// https://html.spec.whatwg.org/multipage/#custom-element-reactions:reset-the-form-owner // https://html.spec.whatwg.org/multipage/#custom-element-reactions:reset-the-form-owner
if let Some(html_elem) = elem.downcast::<HTMLElement>() { if let Some(html_elem) = elem.downcast::<HTMLElement>() {
@ -1580,7 +1582,7 @@ pub(crate) trait FormControl: DomObject {
} }
// https://html.spec.whatwg.org/multipage/#association-of-controls-and-forms // https://html.spec.whatwg.org/multipage/#association-of-controls-and-forms
fn form_attribute_mutated(&self, mutation: AttributeMutation) { fn form_attribute_mutated(&self, mutation: AttributeMutation, can_gc: CanGc) {
match mutation { match mutation {
AttributeMutation::Set(_) => { AttributeMutation::Set(_) => {
self.register_if_necessary(); self.register_if_necessary();
@ -1590,7 +1592,7 @@ pub(crate) trait FormControl: DomObject {
}, },
} }
self.reset_form_owner(); self.reset_form_owner(can_gc);
} }
// https://html.spec.whatwg.org/multipage/#association-of-controls-and-forms // https://html.spec.whatwg.org/multipage/#association-of-controls-and-forms
@ -1616,7 +1618,7 @@ pub(crate) trait FormControl: DomObject {
} }
// https://html.spec.whatwg.org/multipage/#association-of-controls-and-forms // https://html.spec.whatwg.org/multipage/#association-of-controls-and-forms
fn bind_form_control_to_tree(&self) { fn bind_form_control_to_tree(&self, can_gc: CanGc) {
let elem = self.to_element(); let elem = self.to_element();
let node = elem.upcast::<Node>(); let node = elem.upcast::<Node>();
@ -1628,12 +1630,12 @@ pub(crate) trait FormControl: DomObject {
node.set_flag(NodeFlags::PARSER_ASSOCIATED_FORM_OWNER, false); node.set_flag(NodeFlags::PARSER_ASSOCIATED_FORM_OWNER, false);
if !must_skip_reset { if !must_skip_reset {
self.form_attribute_mutated(AttributeMutation::Set(None)); self.form_attribute_mutated(AttributeMutation::Set(None), can_gc);
} }
} }
// https://html.spec.whatwg.org/multipage/#association-of-controls-and-forms // https://html.spec.whatwg.org/multipage/#association-of-controls-and-forms
fn unbind_form_control_from_tree(&self) { fn unbind_form_control_from_tree(&self, can_gc: CanGc) {
let elem = self.to_element(); let elem = self.to_element();
let has_form_attr = elem.has_attribute(&local_name!("form")); let has_form_attr = elem.has_attribute(&local_name!("form"));
let same_subtree = self let same_subtree = self
@ -1648,7 +1650,7 @@ pub(crate) trait FormControl: DomObject {
// subtree) if it appears later in the tree order. Hence invoke // subtree) if it appears later in the tree order. Hence invoke
// reset from here if this control has the form attribute set. // reset from here if this control has the form attribute set.
if !same_subtree || (self.is_listed() && has_form_attr) { if !same_subtree || (self.is_listed() && has_form_attr) {
self.reset_form_owner(); self.reset_form_owner(can_gc);
} }
} }
@ -1698,8 +1700,8 @@ impl VirtualMethods for HTMLFormElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods) Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
} }
fn unbind_from_tree(&self, context: &UnbindContext) { fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context); self.super_type().unwrap().unbind_from_tree(context, can_gc);
// Collect the controls to reset because reset_form_owner // Collect the controls to reset because reset_form_owner
// will mutably borrow self.controls // will mutably borrow self.controls
@ -1716,7 +1718,7 @@ impl VirtualMethods for HTMLFormElement {
control control
.as_maybe_form_control() .as_maybe_form_control()
.expect("Element must be a form control") .expect("Element must be a form control")
.reset_form_owner(); .reset_form_owner(can_gc);
} }
} }
@ -1730,8 +1732,10 @@ impl VirtualMethods for HTMLFormElement {
} }
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match *attr.local_name() { match *attr.local_name() {
local_name!("rel") | local_name!("rev") => { local_name!("rel") | local_name!("rev") => {
@ -1742,9 +1746,9 @@ impl VirtualMethods for HTMLFormElement {
} }
} }
fn bind_to_tree(&self, context: &BindContext) { fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.bind_to_tree(context); s.bind_to_tree(context, can_gc);
} }
self.relations self.relations

View file

@ -132,9 +132,9 @@ impl VirtualMethods for HTMLHeadElement {
fn super_type(&self) -> Option<&dyn VirtualMethods> { fn super_type(&self) -> Option<&dyn VirtualMethods> {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods) Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
} }
fn bind_to_tree(&self, context: &BindContext) { fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.bind_to_tree(context); s.bind_to_tree(context, can_gc);
} }
load_script(self); load_script(self);
} }

View file

@ -676,8 +676,10 @@ impl VirtualMethods for HTMLIFrameElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods) Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match *attr.local_name() { match *attr.local_name() {
local_name!("sandbox") => { local_name!("sandbox") => {
self.sandbox_allowance self.sandbox_allowance
@ -761,8 +763,8 @@ impl VirtualMethods for HTMLIFrameElement {
} }
} }
fn unbind_from_tree(&self, context: &UnbindContext) { fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context); self.super_type().unwrap().unbind_from_tree(context, can_gc);
let blocker = &self.load_blocker; let blocker = &self.load_blocker;
LoadBlocker::terminate(blocker, CanGc::note()); LoadBlocker::terminate(blocker, CanGc::note());

View file

@ -1743,13 +1743,15 @@ impl VirtualMethods for HTMLImageElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods) Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
} }
fn adopting_steps(&self, old_doc: &Document) { fn adopting_steps(&self, old_doc: &Document, can_gc: CanGc) {
self.super_type().unwrap().adopting_steps(old_doc); self.super_type().unwrap().adopting_steps(old_doc, can_gc);
self.update_the_image_data(CanGc::note()); self.update_the_image_data(CanGc::note());
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match attr.local_name() { match attr.local_name() {
&local_name!("src") | &local_name!("src") |
&local_name!("srcset") | &local_name!("srcset") |
@ -1774,7 +1776,7 @@ impl VirtualMethods for HTMLImageElement {
} }
} }
fn handle_event(&self, event: &Event) { fn handle_event(&self, event: &Event, _can_gc: CanGc) {
if event.type_() != atom!("click") { if event.type_() != atom!("click") {
return; return;
} }
@ -1814,9 +1816,9 @@ impl VirtualMethods for HTMLImageElement {
} }
} }
fn bind_to_tree(&self, context: &BindContext) { fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.bind_to_tree(context); s.bind_to_tree(context, can_gc);
} }
let document = self.owner_document(); let document = self.owner_document();
if context.tree_connected { if context.tree_connected {
@ -1832,8 +1834,8 @@ impl VirtualMethods for HTMLImageElement {
} }
} }
fn unbind_from_tree(&self, context: &UnbindContext) { fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context); self.super_type().unwrap().unbind_from_tree(context, can_gc);
let document = self.owner_document(); let document = self.owner_document();
document.unregister_responsive_image(self); document.unregister_responsive_image(self);

View file

@ -1340,7 +1340,7 @@ impl HTMLInputElementMethods<crate::DomTypeHolder> for HTMLInputElement {
} }
self.validity_state() self.validity_state()
.perform_validation_and_update(ValidationFlags::all()); .perform_validation_and_update(ValidationFlags::all(), can_gc);
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage); self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
Ok(()) Ok(())
} }
@ -2322,8 +2322,10 @@ impl VirtualMethods for HTMLInputElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods) Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match *attr.local_name() { match *attr.local_name() {
local_name!("disabled") => { local_name!("disabled") => {
let disabled_state = match mutation { let disabled_state = match mutation {
@ -2513,13 +2515,13 @@ impl VirtualMethods for HTMLInputElement {
} }
}, },
local_name!("form") => { local_name!("form") => {
self.form_attribute_mutated(mutation); self.form_attribute_mutated(mutation, can_gc);
}, },
_ => {}, _ => {},
} }
self.validity_state() self.validity_state()
.perform_validation_and_update(ValidationFlags::all()); .perform_validation_and_update(ValidationFlags::all(), can_gc);
} }
fn parse_plain_attribute(&self, name: &LocalName, value: DOMString) -> AttrValue { fn parse_plain_attribute(&self, name: &LocalName, value: DOMString) -> AttrValue {
@ -2540,21 +2542,21 @@ impl VirtualMethods for HTMLInputElement {
} }
} }
fn bind_to_tree(&self, context: &BindContext) { fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.bind_to_tree(context); s.bind_to_tree(context, can_gc);
} }
self.upcast::<Element>() self.upcast::<Element>()
.check_ancestors_disabled_state_for_form_control(); .check_ancestors_disabled_state_for_form_control();
for r in radio_group_iter(self, self.radio_group_name().as_ref()) { for r in radio_group_iter(self, self.radio_group_name().as_ref()) {
r.validity_state() r.validity_state()
.perform_validation_and_update(ValidationFlags::all()); .perform_validation_and_update(ValidationFlags::all(), can_gc);
} }
} }
fn unbind_from_tree(&self, context: &UnbindContext) { fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context); self.super_type().unwrap().unbind_from_tree(context, can_gc);
let node = self.upcast::<Node>(); let node = self.upcast::<Node>();
let el = self.upcast::<Element>(); let el = self.upcast::<Element>();
@ -2568,7 +2570,7 @@ impl VirtualMethods for HTMLInputElement {
} }
self.validity_state() self.validity_state()
.perform_validation_and_update(ValidationFlags::all()); .perform_validation_and_update(ValidationFlags::all(), can_gc);
} }
// This represents behavior for which the UIEvents spec and the // This represents behavior for which the UIEvents spec and the
@ -2576,9 +2578,9 @@ impl VirtualMethods for HTMLInputElement {
// Compare: // Compare:
// https://w3c.github.io/uievents/#default-action // https://w3c.github.io/uievents/#default-action
// https://dom.spec.whatwg.org/#action-versus-occurance // https://dom.spec.whatwg.org/#action-versus-occurance
fn handle_event(&self, event: &Event) { fn handle_event(&self, event: &Event, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.handle_event(event); s.handle_event(event, can_gc);
} }
if event.type_() == atom!("click") && !event.DefaultPrevented() { if event.type_() == atom!("click") && !event.DefaultPrevented() {
@ -2679,7 +2681,7 @@ impl VirtualMethods for HTMLInputElement {
} }
self.validity_state() self.validity_state()
.perform_validation_and_update(ValidationFlags::all()); .perform_validation_and_update(ValidationFlags::all(), can_gc);
} }
// https://html.spec.whatwg.org/multipage/#the-input-element%3Aconcept-node-clone-ext // https://html.spec.whatwg.org/multipage/#the-input-element%3Aconcept-node-clone-ext
@ -2688,9 +2690,10 @@ impl VirtualMethods for HTMLInputElement {
copy: &Node, copy: &Node,
maybe_doc: Option<&Document>, maybe_doc: Option<&Document>,
clone_children: CloneChildrenFlag, clone_children: CloneChildrenFlag,
can_gc: CanGc,
) { ) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.cloning_steps(copy, maybe_doc, clone_children); s.cloning_steps(copy, maybe_doc, clone_children, can_gc);
} }
let elem = copy.downcast::<HTMLInputElement>().unwrap(); let elem = copy.downcast::<HTMLInputElement>().unwrap();
elem.value_dirty.set(self.value_dirty.get()); elem.value_dirty.set(self.value_dirty.get());
@ -2701,7 +2704,7 @@ impl VirtualMethods for HTMLInputElement {
.borrow_mut() .borrow_mut()
.set_content(self.textinput.borrow().get_content()); .set_content(self.textinput.borrow().get_content());
elem.validity_state() elem.validity_state()
.perform_validation_and_update(ValidationFlags::all()); .perform_validation_and_update(ValidationFlags::all(), can_gc);
} }
} }
@ -2746,7 +2749,11 @@ impl Validatable for HTMLInputElement {
} }
} }
fn perform_validation(&self, validate_flags: ValidationFlags) -> ValidationFlags { fn perform_validation(
&self,
validate_flags: ValidationFlags,
_can_gc: CanGc,
) -> ValidationFlags {
let mut failed_flags = ValidationFlags::empty(); let mut failed_flags = ValidationFlags::empty();
let value = self.Value(); let value = self.Value();

View file

@ -157,10 +157,12 @@ impl VirtualMethods for HTMLLabelElement {
} }
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
if *attr.local_name() == local_name!("form") { if *attr.local_name() == local_name!("form") {
self.form_attribute_mutated(mutation); self.form_attribute_mutated(mutation, can_gc);
} }
} }
} }

View file

@ -61,17 +61,17 @@ impl VirtualMethods for HTMLLegendElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods) Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
} }
fn bind_to_tree(&self, context: &BindContext) { fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.bind_to_tree(context); s.bind_to_tree(context, can_gc);
} }
self.upcast::<Element>() self.upcast::<Element>()
.check_ancestors_disabled_state_for_form_control(); .check_ancestors_disabled_state_for_form_control();
} }
fn unbind_from_tree(&self, context: &UnbindContext) { fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context); self.super_type().unwrap().unbind_from_tree(context, can_gc);
let node = self.upcast::<Node>(); let node = self.upcast::<Node>();
let el = self.upcast::<Element>(); let el = self.upcast::<Element>();

View file

@ -216,8 +216,10 @@ impl VirtualMethods for HTMLLinkElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods) Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
if !self.upcast::<Node>().is_connected() || mutation.is_removal() { if !self.upcast::<Node>().is_connected() || mutation.is_removal() {
return; return;
} }
@ -265,9 +267,9 @@ impl VirtualMethods for HTMLLinkElement {
} }
} }
fn bind_to_tree(&self, context: &BindContext) { fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.bind_to_tree(context); s.bind_to_tree(context, can_gc);
} }
self.relations self.relations
@ -294,9 +296,9 @@ impl VirtualMethods for HTMLLinkElement {
} }
} }
fn unbind_from_tree(&self, context: &UnbindContext) { fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.unbind_from_tree(context); s.unbind_from_tree(context, can_gc);
} }
if let Some(s) = self.stylesheet.borrow_mut().take() { if let Some(s) = self.stylesheet.borrow_mut().take() {

View file

@ -1956,9 +1956,9 @@ impl HTMLMediaElement {
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage); self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
} }
fn remove_controls(&self) { fn remove_controls(&self, can_gc: CanGc) {
if let Some(id) = self.media_controls_id.borrow_mut().take() { if let Some(id) = self.media_controls_id.borrow_mut().take() {
self.owner_document().unregister_media_controls(&id); self.owner_document().unregister_media_controls(&id, can_gc);
} }
} }
@ -2486,8 +2486,10 @@ impl VirtualMethods for HTMLMediaElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods) Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match *attr.local_name() { match *attr.local_name() {
local_name!("muted") => { local_name!("muted") => {
@ -2502,9 +2504,9 @@ impl VirtualMethods for HTMLMediaElement {
}, },
local_name!("controls") => { local_name!("controls") => {
if mutation.new_value(attr).is_some() { if mutation.new_value(attr).is_some() {
self.render_controls(CanGc::note()); self.render_controls(can_gc);
} else { } else {
self.remove_controls(); self.remove_controls(can_gc);
} }
}, },
_ => (), _ => (),
@ -2512,10 +2514,10 @@ impl VirtualMethods for HTMLMediaElement {
} }
// https://html.spec.whatwg.org/multipage/#playing-the-media-resource:remove-an-element-from-a-document // https://html.spec.whatwg.org/multipage/#playing-the-media-resource:remove-an-element-from-a-document
fn unbind_from_tree(&self, context: &UnbindContext) { fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context); self.super_type().unwrap().unbind_from_tree(context, can_gc);
self.remove_controls(); self.remove_controls(can_gc);
if context.tree_connected { if context.tree_connected {
let task = MediaElementMicrotask::PauseIfNotInDocument { let task = MediaElementMicrotask::PauseIfNotInDocument {

View file

@ -252,9 +252,9 @@ impl VirtualMethods for HTMLMetaElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods) Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
} }
fn bind_to_tree(&self, context: &BindContext) { fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.bind_to_tree(context); s.bind_to_tree(context, can_gc);
} }
if context.tree_connected { if context.tree_connected {
@ -262,17 +262,17 @@ impl VirtualMethods for HTMLMetaElement {
} }
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.attribute_mutated(attr, mutation); s.attribute_mutated(attr, mutation, can_gc);
} }
self.process_referrer_attribute(); self.process_referrer_attribute();
} }
fn unbind_from_tree(&self, context: &UnbindContext) { fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.unbind_from_tree(context); s.unbind_from_tree(context, can_gc);
} }
if context.tree_connected { if context.tree_connected {

View file

@ -331,8 +331,10 @@ impl VirtualMethods for HTMLMeterElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods) Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
let is_important_attribute = matches!( let is_important_attribute = matches!(
attr.local_name(), attr.local_name(),
@ -354,8 +356,8 @@ impl VirtualMethods for HTMLMeterElement {
self.update_state(CanGc::note()); self.update_state(CanGc::note());
} }
fn bind_to_tree(&self, context: &BindContext) { fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
self.super_type().unwrap().bind_to_tree(context); self.super_type().unwrap().bind_to_tree(context, can_gc);
self.update_state(CanGc::note()); self.update_state(CanGc::note());
} }

View file

@ -153,8 +153,10 @@ impl VirtualMethods for HTMLObjectElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods) Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match *attr.local_name() { match *attr.local_name() {
local_name!("data") => { local_name!("data") => {
if let AttributeMutation::Set(_) = mutation { if let AttributeMutation::Set(_) = mutation {
@ -162,7 +164,7 @@ impl VirtualMethods for HTMLObjectElement {
} }
}, },
local_name!("form") => { local_name!("form") => {
self.form_attribute_mutated(mutation); self.form_attribute_mutated(mutation, can_gc);
}, },
_ => {}, _ => {},
} }

View file

@ -64,11 +64,11 @@ impl HTMLOptGroupElement {
) )
} }
fn update_select_validity(&self) { fn update_select_validity(&self, can_gc: CanGc) {
if let Some(select) = self.owner_select_element() { if let Some(select) = self.owner_select_element() {
select select
.validity_state() .validity_state()
.perform_validation_and_update(ValidationFlags::all()); .perform_validation_and_update(ValidationFlags::all(), can_gc);
} }
} }
@ -98,8 +98,10 @@ impl VirtualMethods for HTMLOptGroupElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods) Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
if attr.local_name() == &local_name!("disabled") { if attr.local_name() == &local_name!("disabled") {
let disabled_state = match mutation { let disabled_state = match mutation {
AttributeMutation::Set(None) => true, AttributeMutation::Set(None) => true,
@ -132,21 +134,21 @@ impl VirtualMethods for HTMLOptGroupElement {
} }
} }
fn bind_to_tree(&self, context: &BindContext) { fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.bind_to_tree(context); s.bind_to_tree(context, can_gc);
} }
self.update_select_validity(); self.update_select_validity(can_gc);
} }
fn unbind_from_tree(&self, context: &UnbindContext) { fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context); self.super_type().unwrap().unbind_from_tree(context, can_gc);
if let Some(select) = context.parent.downcast::<HTMLSelectElement>() { if let Some(select) = context.parent.downcast::<HTMLSelectElement>() {
select select
.validity_state() .validity_state()
.perform_validation_and_update(ValidationFlags::all()); .perform_validation_and_update(ValidationFlags::all(), can_gc);
} }
} }
} }

View file

@ -141,7 +141,7 @@ impl HTMLOptionElement {
} }
} }
fn update_select_validity(&self) { fn update_select_validity(&self, can_gc: CanGc) {
if let Some(select) = self if let Some(select) = self
.upcast::<Node>() .upcast::<Node>()
.ancestors() .ancestors()
@ -150,7 +150,7 @@ impl HTMLOptionElement {
{ {
select select
.validity_state() .validity_state()
.perform_validation_and_update(ValidationFlags::all()); .perform_validation_and_update(ValidationFlags::all(), can_gc);
} }
} }
} }
@ -207,7 +207,7 @@ impl HTMLOptionElementMethods<crate::DomTypeHolder> for HTMLOptionElement {
option.SetDefaultSelected(default_selected); option.SetDefaultSelected(default_selected);
option.set_selectedness(selected); option.set_selectedness(selected);
option.update_select_validity(); option.update_select_validity(can_gc);
Ok(option) Ok(option)
} }
@ -286,7 +286,7 @@ impl HTMLOptionElementMethods<crate::DomTypeHolder> for HTMLOptionElement {
self.dirtiness.set(true); self.dirtiness.set(true);
self.selectedness.set(selected); self.selectedness.set(selected);
self.pick_if_selected_and_reset(); self.pick_if_selected_and_reset();
self.update_select_validity(); self.update_select_validity(CanGc::note());
} }
// https://html.spec.whatwg.org/multipage/#dom-option-index // https://html.spec.whatwg.org/multipage/#dom-option-index
@ -300,8 +300,10 @@ impl VirtualMethods for HTMLOptionElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods) Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match *attr.local_name() { match *attr.local_name() {
local_name!("disabled") => { local_name!("disabled") => {
let el = self.upcast::<Element>(); let el = self.upcast::<Element>();
@ -316,7 +318,7 @@ impl VirtualMethods for HTMLOptionElement {
el.check_parent_disabled_state_for_option(); el.check_parent_disabled_state_for_option();
}, },
} }
self.update_select_validity(); self.update_select_validity(can_gc);
}, },
local_name!("selected") => { local_name!("selected") => {
match mutation { match mutation {
@ -333,26 +335,26 @@ impl VirtualMethods for HTMLOptionElement {
} }
}, },
} }
self.update_select_validity(); self.update_select_validity(can_gc);
}, },
_ => {}, _ => {},
} }
} }
fn bind_to_tree(&self, context: &BindContext) { fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.bind_to_tree(context); s.bind_to_tree(context, can_gc);
} }
self.upcast::<Element>() self.upcast::<Element>()
.check_parent_disabled_state_for_option(); .check_parent_disabled_state_for_option();
self.pick_if_selected_and_reset(); self.pick_if_selected_and_reset();
self.update_select_validity(); self.update_select_validity(can_gc);
} }
fn unbind_from_tree(&self, context: &UnbindContext) { fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context); self.super_type().unwrap().unbind_from_tree(context, can_gc);
if let Some(select) = context if let Some(select) = context
.parent .parent
@ -362,7 +364,7 @@ impl VirtualMethods for HTMLOptionElement {
{ {
select select
.validity_state() .validity_state()
.perform_validation_and_update(ValidationFlags::all()); .perform_validation_and_update(ValidationFlags::all(), can_gc);
select.ask_for_reset(); select.ask_for_reset();
} }

View file

@ -117,7 +117,7 @@ impl HTMLOptionsCollectionMethods<crate::DomTypeHolder> for HTMLOptionsCollectio
let node = value.upcast::<Node>(); let node = value.upcast::<Node>();
let root = self.upcast().root_node(); let root = self.upcast().root_node();
if n >= 0 { if n >= 0 {
Node::pre_insert(node, &root, None).map(|_| ()) Node::pre_insert(node, &root, None, can_gc).map(|_| ())
} else { } else {
let child = self.upcast().IndexedGetter(index).unwrap(); let child = self.upcast().IndexedGetter(index).unwrap();
let child_node = child.upcast::<Node>(); let child_node = child.upcast::<Node>();
@ -220,7 +220,7 @@ impl HTMLOptionsCollectionMethods<crate::DomTypeHolder> for HTMLOptionsCollectio
}; };
// Step 6 // Step 6
Node::pre_insert(node, &parent, reference_node.as_deref()).map(|_| ()) Node::pre_insert(node, &parent, reference_node.as_deref(), CanGc::note()).map(|_| ())
} }
/// <https://html.spec.whatwg.org/multipage/#dom-htmloptionscollection-remove> /// <https://html.spec.whatwg.org/multipage/#dom-htmloptionscollection-remove>

View file

@ -159,10 +159,12 @@ impl VirtualMethods for HTMLOutputElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods) Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
if attr.local_name() == &local_name!("form") { if attr.local_name() == &local_name!("form") {
self.form_attribute_mutated(mutation); self.form_attribute_mutated(mutation, can_gc);
} }
} }
} }

View file

@ -227,8 +227,10 @@ impl VirtualMethods for HTMLProgressElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods) Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
let is_important_attribute = matches!( let is_important_attribute = matches!(
attr.local_name(), attr.local_name(),
@ -239,8 +241,8 @@ impl VirtualMethods for HTMLProgressElement {
} }
} }
fn bind_to_tree(&self, context: &BindContext) { fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
self.super_type().unwrap().bind_to_tree(context); self.super_type().unwrap().bind_to_tree(context, can_gc);
self.update_state(CanGc::note()); self.update_state(CanGc::note());
} }

View file

@ -1242,8 +1242,10 @@ impl VirtualMethods for HTMLScriptElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods) Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
if *attr.local_name() == local_name!("src") { if *attr.local_name() == local_name!("src") {
if let AttributeMutation::Set(_) = mutation { if let AttributeMutation::Set(_) = mutation {
if !self.parser_inserted.get() && self.upcast::<Node>().is_connected() { if !self.parser_inserted.get() && self.upcast::<Node>().is_connected() {
@ -1288,9 +1290,10 @@ impl VirtualMethods for HTMLScriptElement {
copy: &Node, copy: &Node,
maybe_doc: Option<&Document>, maybe_doc: Option<&Document>,
clone_children: CloneChildrenFlag, clone_children: CloneChildrenFlag,
can_gc: CanGc,
) { ) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.cloning_steps(copy, maybe_doc, clone_children); s.cloning_steps(copy, maybe_doc, clone_children, can_gc);
} }
// https://html.spec.whatwg.org/multipage/#already-started // https://html.spec.whatwg.org/multipage/#already-started

View file

@ -356,7 +356,7 @@ impl HTMLSelectElementMethods<crate::DomTypeHolder> for HTMLSelectElement {
} }
self.validity_state() self.validity_state()
.perform_validation_and_update(ValidationFlags::VALUE_MISSING); .perform_validation_and_update(ValidationFlags::VALUE_MISSING, CanGc::note());
} }
// https://html.spec.whatwg.org/multipage/#dom-select-selectedindex // https://html.spec.whatwg.org/multipage/#dom-select-selectedindex
@ -421,12 +421,14 @@ impl VirtualMethods for HTMLSelectElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods) Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match *attr.local_name() { match *attr.local_name() {
local_name!("required") => { local_name!("required") => {
self.validity_state() self.validity_state()
.perform_validation_and_update(ValidationFlags::VALUE_MISSING); .perform_validation_and_update(ValidationFlags::VALUE_MISSING, can_gc);
}, },
local_name!("disabled") => { local_name!("disabled") => {
let el = self.upcast::<Element>(); let el = self.upcast::<Element>();
@ -443,26 +445,26 @@ impl VirtualMethods for HTMLSelectElement {
} }
self.validity_state() self.validity_state()
.perform_validation_and_update(ValidationFlags::VALUE_MISSING); .perform_validation_and_update(ValidationFlags::VALUE_MISSING, can_gc);
}, },
local_name!("form") => { local_name!("form") => {
self.form_attribute_mutated(mutation); self.form_attribute_mutated(mutation, can_gc);
}, },
_ => {}, _ => {},
} }
} }
fn bind_to_tree(&self, context: &BindContext) { fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.bind_to_tree(context); s.bind_to_tree(context, can_gc);
} }
self.upcast::<Element>() self.upcast::<Element>()
.check_ancestors_disabled_state_for_form_control(); .check_ancestors_disabled_state_for_form_control();
} }
fn unbind_from_tree(&self, context: &UnbindContext) { fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context); self.super_type().unwrap().unbind_from_tree(context, can_gc);
let node = self.upcast::<Node>(); let node = self.upcast::<Node>();
let el = self.upcast::<Element>(); let el = self.upcast::<Element>();
@ -517,7 +519,11 @@ impl Validatable for HTMLSelectElement {
!self.upcast::<Element>().disabled_state() && !is_barred_by_datalist_ancestor(self.upcast()) !self.upcast::<Element>().disabled_state() && !is_barred_by_datalist_ancestor(self.upcast())
} }
fn perform_validation(&self, validate_flags: ValidationFlags) -> ValidationFlags { fn perform_validation(
&self,
validate_flags: ValidationFlags,
_can_gc: CanGc,
) -> ValidationFlags {
let mut failed_flags = ValidationFlags::empty(); let mut failed_flags = ValidationFlags::empty();
// https://html.spec.whatwg.org/multipage/#suffering-from-being-missing // https://html.spec.whatwg.org/multipage/#suffering-from-being-missing

View file

@ -461,8 +461,10 @@ impl VirtualMethods for HTMLSlotElement {
} }
/// <https://dom.spec.whatwg.org/#shadow-tree-slots> /// <https://dom.spec.whatwg.org/#shadow-tree-slots>
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
if attr.local_name() == &local_name!("name") && attr.namespace() == &ns!() { if attr.local_name() == &local_name!("name") && attr.namespace() == &ns!() {
if let Some(shadow_root) = self.containing_shadow_root() { if let Some(shadow_root) = self.containing_shadow_root() {
@ -486,9 +488,9 @@ impl VirtualMethods for HTMLSlotElement {
} }
} }
fn bind_to_tree(&self, context: &super::node::BindContext) { fn bind_to_tree(&self, context: &super::node::BindContext, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.bind_to_tree(context); s.bind_to_tree(context, can_gc);
} }
if !context.tree_is_in_a_shadow_tree { if !context.tree_is_in_a_shadow_tree {
@ -500,9 +502,9 @@ impl VirtualMethods for HTMLSlotElement {
.register_slot(self); .register_slot(self);
} }
fn unbind_from_tree(&self, context: &super::node::UnbindContext) { fn unbind_from_tree(&self, context: &super::node::UnbindContext, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.unbind_from_tree(context); s.unbind_from_tree(context, can_gc);
} }
if let Some(shadow_root) = self.containing_shadow_root() { if let Some(shadow_root) = self.containing_shadow_root() {

View file

@ -72,8 +72,10 @@ impl VirtualMethods for HTMLSourceElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods) Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match attr.local_name() { match attr.local_name() {
&local_name!("srcset") | &local_name!("srcset") |
&local_name!("sizes") | &local_name!("sizes") |
@ -90,8 +92,8 @@ impl VirtualMethods for HTMLSourceElement {
} }
/// <https://html.spec.whatwg.org/multipage/#the-source-element:nodes-are-inserted> /// <https://html.spec.whatwg.org/multipage/#the-source-element:nodes-are-inserted>
fn bind_to_tree(&self, context: &BindContext) { fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
self.super_type().unwrap().bind_to_tree(context); self.super_type().unwrap().bind_to_tree(context, can_gc);
let parent = self.upcast::<Node>().GetParentNode().unwrap(); let parent = self.upcast::<Node>().GetParentNode().unwrap();
if let Some(media) = parent.downcast::<HTMLMediaElement>() { if let Some(media) = parent.downcast::<HTMLMediaElement>() {
media.handle_source_child_insertion(CanGc::note()); media.handle_source_child_insertion(CanGc::note());
@ -103,8 +105,8 @@ impl VirtualMethods for HTMLSourceElement {
); );
} }
fn unbind_from_tree(&self, context: &UnbindContext) { fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context); self.super_type().unwrap().unbind_from_tree(context, can_gc);
if let Some(next_sibling) = context.next_sibling { if let Some(next_sibling) = context.next_sibling {
let next_sibling_iterator = next_sibling.inclusively_following_siblings(); let next_sibling_iterator = next_sibling.inclusively_following_siblings();
HTMLSourceElement::iterate_next_html_image_element_siblings( HTMLSourceElement::iterate_next_html_image_element_siblings(

View file

@ -220,8 +220,8 @@ impl VirtualMethods for HTMLStyleElement {
} }
} }
fn bind_to_tree(&self, context: &BindContext) { fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
self.super_type().unwrap().bind_to_tree(context); self.super_type().unwrap().bind_to_tree(context, can_gc);
// https://html.spec.whatwg.org/multipage/#update-a-style-block // https://html.spec.whatwg.org/multipage/#update-a-style-block
// Handles the case when: // Handles the case when:
@ -244,9 +244,9 @@ impl VirtualMethods for HTMLStyleElement {
} }
} }
fn unbind_from_tree(&self, context: &UnbindContext) { fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.unbind_from_tree(context); s.unbind_from_tree(context, can_gc);
} }
if context.tree_connected { if context.tree_connected {
@ -254,9 +254,9 @@ impl VirtualMethods for HTMLStyleElement {
} }
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.attribute_mutated(attr, mutation); s.attribute_mutated(attr, mutation, can_gc);
} }
let node = self.upcast::<Node>(); let node = self.upcast::<Node>();

View file

@ -114,6 +114,7 @@ impl HTMLTableElement {
atom: &LocalName, atom: &LocalName,
section: Option<&HTMLTableSectionElement>, section: Option<&HTMLTableSectionElement>,
reference_predicate: P, reference_predicate: P,
can_gc: CanGc,
) -> ErrorResult ) -> ErrorResult
where where
P: FnMut(&DomRoot<Element>) -> bool, P: FnMut(&DomRoot<Element>) -> bool,
@ -124,7 +125,7 @@ impl HTMLTableElement {
} }
} }
self.delete_first_section_of_type(atom); self.delete_first_section_of_type(atom, can_gc);
let node = self.upcast::<Node>(); let node = self.upcast::<Node>();
@ -163,9 +164,9 @@ impl HTMLTableElement {
// https://html.spec.whatwg.org/multipage/#dom-table-deletethead // https://html.spec.whatwg.org/multipage/#dom-table-deletethead
// https://html.spec.whatwg.org/multipage/#dom-table-deletetfoot // https://html.spec.whatwg.org/multipage/#dom-table-deletetfoot
fn delete_first_section_of_type(&self, atom: &LocalName) { fn delete_first_section_of_type(&self, atom: &LocalName, can_gc: CanGc) {
if let Some(thead) = self.get_first_section_of_type(atom) { if let Some(thead) = self.get_first_section_of_type(atom) {
thead.upcast::<Node>().remove_self(); thead.upcast::<Node>().remove_self(can_gc);
} }
} }
@ -206,7 +207,7 @@ impl HTMLTableElementMethods<crate::DomTypeHolder> for HTMLTableElement {
// https://html.spec.whatwg.org/multipage/#dom-table-caption // https://html.spec.whatwg.org/multipage/#dom-table-caption
fn SetCaption(&self, new_caption: Option<&HTMLTableCaptionElement>) -> Fallible<()> { fn SetCaption(&self, new_caption: Option<&HTMLTableCaptionElement>) -> Fallible<()> {
if let Some(ref caption) = self.GetCaption() { if let Some(ref caption) = self.GetCaption() {
caption.upcast::<Node>().remove_self(); caption.upcast::<Node>().remove_self(CanGc::note());
} }
if let Some(caption) = new_caption { if let Some(caption) = new_caption {
@ -239,7 +240,7 @@ impl HTMLTableElementMethods<crate::DomTypeHolder> for HTMLTableElement {
// https://html.spec.whatwg.org/multipage/#dom-table-deletecaption // https://html.spec.whatwg.org/multipage/#dom-table-deletecaption
fn DeleteCaption(&self) { fn DeleteCaption(&self) {
if let Some(caption) = self.GetCaption() { if let Some(caption) = self.GetCaption() {
caption.upcast::<Node>().remove_self(); caption.upcast::<Node>().remove_self(CanGc::note());
} }
} }
@ -250,9 +251,12 @@ impl HTMLTableElementMethods<crate::DomTypeHolder> for HTMLTableElement {
// https://html.spec.whatwg.org/multipage/#dom-table-thead // https://html.spec.whatwg.org/multipage/#dom-table-thead
fn SetTHead(&self, thead: Option<&HTMLTableSectionElement>) -> ErrorResult { fn SetTHead(&self, thead: Option<&HTMLTableSectionElement>) -> ErrorResult {
self.set_first_section_of_type(&local_name!("thead"), thead, |n| { self.set_first_section_of_type(
!n.is::<HTMLTableCaptionElement>() && !n.is::<HTMLTableColElement>() &local_name!("thead"),
}) thead,
|n| !n.is::<HTMLTableCaptionElement>() && !n.is::<HTMLTableColElement>(),
CanGc::note(),
)
} }
// https://html.spec.whatwg.org/multipage/#dom-table-createthead // https://html.spec.whatwg.org/multipage/#dom-table-createthead
@ -262,7 +266,7 @@ impl HTMLTableElementMethods<crate::DomTypeHolder> for HTMLTableElement {
// https://html.spec.whatwg.org/multipage/#dom-table-deletethead // https://html.spec.whatwg.org/multipage/#dom-table-deletethead
fn DeleteTHead(&self) { fn DeleteTHead(&self) {
self.delete_first_section_of_type(&local_name!("thead")) self.delete_first_section_of_type(&local_name!("thead"), CanGc::note())
} }
// https://html.spec.whatwg.org/multipage/#dom-table-tfoot // https://html.spec.whatwg.org/multipage/#dom-table-tfoot
@ -272,20 +276,25 @@ impl HTMLTableElementMethods<crate::DomTypeHolder> for HTMLTableElement {
// https://html.spec.whatwg.org/multipage/#dom-table-tfoot // https://html.spec.whatwg.org/multipage/#dom-table-tfoot
fn SetTFoot(&self, tfoot: Option<&HTMLTableSectionElement>) -> ErrorResult { fn SetTFoot(&self, tfoot: Option<&HTMLTableSectionElement>) -> ErrorResult {
self.set_first_section_of_type(&local_name!("tfoot"), tfoot, |n| { self.set_first_section_of_type(
if n.is::<HTMLTableCaptionElement>() || n.is::<HTMLTableColElement>() { &local_name!("tfoot"),
return false; tfoot,
} |n| {
if n.is::<HTMLTableCaptionElement>() || n.is::<HTMLTableColElement>() {
if n.is::<HTMLTableSectionElement>() {
let name = n.local_name();
if name == &local_name!("thead") || name == &local_name!("tbody") {
return false; return false;
} }
}
true if n.is::<HTMLTableSectionElement>() {
}) let name = n.local_name();
if name == &local_name!("thead") || name == &local_name!("tbody") {
return false;
}
}
true
},
CanGc::note(),
)
} }
// https://html.spec.whatwg.org/multipage/#dom-table-createtfoot // https://html.spec.whatwg.org/multipage/#dom-table-createtfoot
@ -295,7 +304,7 @@ impl HTMLTableElementMethods<crate::DomTypeHolder> for HTMLTableElement {
// https://html.spec.whatwg.org/multipage/#dom-table-deletetfoot // https://html.spec.whatwg.org/multipage/#dom-table-deletetfoot
fn DeleteTFoot(&self) { fn DeleteTFoot(&self) {
self.delete_first_section_of_type(&local_name!("tfoot")) self.delete_first_section_of_type(&local_name!("tfoot"), CanGc::note())
} }
// https://html.spec.whatwg.org/multipage/#dom-table-tbodies // https://html.spec.whatwg.org/multipage/#dom-table-tbodies
@ -434,7 +443,7 @@ impl HTMLTableElementMethods<crate::DomTypeHolder> for HTMLTableElement {
} }
// Step 3: Otherwise, remove the indexth element in the rows collection from its parent. // Step 3: Otherwise, remove the indexth element in the rows collection from its parent.
DomRoot::upcast::<Node>(rows.Item(index as u32).unwrap()).remove_self(); DomRoot::upcast::<Node>(rows.Item(index as u32).unwrap()).remove_self(CanGc::note());
Ok(()) Ok(())
} }
@ -503,8 +512,10 @@ impl VirtualMethods for HTMLTableElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods) Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match *attr.local_name() { match *attr.local_name() {
local_name!("border") => { local_name!("border") => {
// According to HTML5 § 14.3.9, invalid values map to 1px. // According to HTML5 § 14.3.9, invalid values map to 1px.

View file

@ -104,13 +104,19 @@ impl HTMLTableRowElementMethods<crate::DomTypeHolder> for HTMLTableRowElement {
index, index,
|| self.Cells(), || self.Cells(),
|| HTMLTableCellElement::new(local_name!("td"), None, &node.owner_doc(), None, can_gc), || HTMLTableCellElement::new(local_name!("td"), None, &node.owner_doc(), None, can_gc),
can_gc,
) )
} }
// https://html.spec.whatwg.org/multipage/#dom-tr-deletecell // https://html.spec.whatwg.org/multipage/#dom-tr-deletecell
fn DeleteCell(&self, index: i32) -> ErrorResult { fn DeleteCell(&self, index: i32) -> ErrorResult {
let node = self.upcast::<Node>(); let node = self.upcast::<Node>();
node.delete_cell_or_row(index, || self.Cells(), |n| n.is::<HTMLTableCellElement>()) node.delete_cell_or_row(
index,
|| self.Cells(),
|n| n.is::<HTMLTableCellElement>(),
CanGc::note(),
)
} }
// https://html.spec.whatwg.org/multipage/#dom-tr-rowindex // https://html.spec.whatwg.org/multipage/#dom-tr-rowindex

View file

@ -77,13 +77,19 @@ impl HTMLTableSectionElementMethods<crate::DomTypeHolder> for HTMLTableSectionEl
index, index,
|| self.Rows(), || self.Rows(),
|| HTMLTableRowElement::new(local_name!("tr"), None, &node.owner_doc(), None, can_gc), || HTMLTableRowElement::new(local_name!("tr"), None, &node.owner_doc(), None, can_gc),
can_gc,
) )
} }
// https://html.spec.whatwg.org/multipage/#dom-tbody-deleterow // https://html.spec.whatwg.org/multipage/#dom-tbody-deleterow
fn DeleteRow(&self, index: i32) -> ErrorResult { fn DeleteRow(&self, index: i32) -> ErrorResult {
let node = self.upcast::<Node>(); let node = self.upcast::<Node>();
node.delete_cell_or_row(index, || self.Rows(), |n| n.is::<HTMLTableRowElement>()) node.delete_cell_or_row(
index,
|| self.Rows(),
|n| n.is::<HTMLTableRowElement>(),
CanGc::note(),
)
} }
} }

View file

@ -113,14 +113,14 @@ impl VirtualMethods for HTMLTemplateElement {
} }
/// <https://html.spec.whatwg.org/multipage/#template-adopting-steps> /// <https://html.spec.whatwg.org/multipage/#template-adopting-steps>
fn adopting_steps(&self, old_doc: &Document) { fn adopting_steps(&self, old_doc: &Document, can_gc: CanGc) {
self.super_type().unwrap().adopting_steps(old_doc); self.super_type().unwrap().adopting_steps(old_doc, can_gc);
// Step 1. // Step 1.
let doc = self let doc = self
.owner_document() .owner_document()
.appropriate_template_contents_owner_document(CanGc::note()); .appropriate_template_contents_owner_document(CanGc::note());
// Step 2. // Step 2.
Node::adopt(self.Content(CanGc::note()).upcast(), &doc); Node::adopt(self.Content(CanGc::note()).upcast(), &doc, can_gc);
} }
/// <https://html.spec.whatwg.org/multipage/#the-template-element:concept-node-clone-ext> /// <https://html.spec.whatwg.org/multipage/#the-template-element:concept-node-clone-ext>
@ -129,10 +129,11 @@ impl VirtualMethods for HTMLTemplateElement {
copy: &Node, copy: &Node,
maybe_doc: Option<&Document>, maybe_doc: Option<&Document>,
clone_children: CloneChildrenFlag, clone_children: CloneChildrenFlag,
can_gc: CanGc,
) { ) {
self.super_type() self.super_type()
.unwrap() .unwrap()
.cloning_steps(copy, maybe_doc, clone_children); .cloning_steps(copy, maybe_doc, clone_children, can_gc);
if clone_children == CloneChildrenFlag::DoNotCloneChildren { if clone_children == CloneChildrenFlag::DoNotCloneChildren {
// Step 1. // Step 1.
return; return;

View file

@ -347,7 +347,7 @@ impl HTMLTextAreaElementMethods<crate::DomTypeHolder> for HTMLTextAreaElement {
} }
self.validity_state() self.validity_state()
.perform_validation_and_update(ValidationFlags::all()); .perform_validation_and_update(ValidationFlags::all(), CanGc::note());
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage); self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
} }
@ -468,8 +468,10 @@ impl VirtualMethods for HTMLTextAreaElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods) Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match *attr.local_name() { match *attr.local_name() {
local_name!("disabled") => { local_name!("disabled") => {
let el = self.upcast::<Element>(); let el = self.upcast::<Element>();
@ -538,25 +540,25 @@ impl VirtualMethods for HTMLTextAreaElement {
} }
}, },
local_name!("form") => { local_name!("form") => {
self.form_attribute_mutated(mutation); self.form_attribute_mutated(mutation, can_gc);
}, },
_ => {}, _ => {},
} }
self.validity_state() self.validity_state()
.perform_validation_and_update(ValidationFlags::all()); .perform_validation_and_update(ValidationFlags::all(), can_gc);
} }
fn bind_to_tree(&self, context: &BindContext) { fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.bind_to_tree(context); s.bind_to_tree(context, can_gc);
} }
self.upcast::<Element>() self.upcast::<Element>()
.check_ancestors_disabled_state_for_form_control(); .check_ancestors_disabled_state_for_form_control();
self.validity_state() self.validity_state()
.perform_validation_and_update(ValidationFlags::all()); .perform_validation_and_update(ValidationFlags::all(), can_gc);
} }
fn parse_plain_attribute(&self, name: &LocalName, value: DOMString) -> AttrValue { fn parse_plain_attribute(&self, name: &LocalName, value: DOMString) -> AttrValue {
@ -576,8 +578,8 @@ impl VirtualMethods for HTMLTextAreaElement {
} }
} }
fn unbind_from_tree(&self, context: &UnbindContext) { fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context); self.super_type().unwrap().unbind_from_tree(context, can_gc);
let node = self.upcast::<Node>(); let node = self.upcast::<Node>();
let el = self.upcast::<Element>(); let el = self.upcast::<Element>();
@ -591,7 +593,7 @@ impl VirtualMethods for HTMLTextAreaElement {
} }
self.validity_state() self.validity_state()
.perform_validation_and_update(ValidationFlags::all()); .perform_validation_and_update(ValidationFlags::all(), can_gc);
} }
// The cloning steps for textarea elements must propagate the raw value // The cloning steps for textarea elements must propagate the raw value
@ -601,9 +603,10 @@ impl VirtualMethods for HTMLTextAreaElement {
copy: &Node, copy: &Node,
maybe_doc: Option<&Document>, maybe_doc: Option<&Document>,
clone_children: CloneChildrenFlag, clone_children: CloneChildrenFlag,
can_gc: CanGc,
) { ) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.cloning_steps(copy, maybe_doc, clone_children); s.cloning_steps(copy, maybe_doc, clone_children, can_gc);
} }
let el = copy.downcast::<HTMLTextAreaElement>().unwrap(); let el = copy.downcast::<HTMLTextAreaElement>().unwrap();
el.value_dirty.set(self.value_dirty.get()); el.value_dirty.set(self.value_dirty.get());
@ -612,7 +615,7 @@ impl VirtualMethods for HTMLTextAreaElement {
textinput.set_content(self.textinput.borrow().get_content()); textinput.set_content(self.textinput.borrow().get_content());
} }
el.validity_state() el.validity_state()
.perform_validation_and_update(ValidationFlags::all()); .perform_validation_and_update(ValidationFlags::all(), can_gc);
} }
fn children_changed(&self, mutation: &ChildrenMutation) { fn children_changed(&self, mutation: &ChildrenMutation) {
@ -625,9 +628,9 @@ impl VirtualMethods for HTMLTextAreaElement {
} }
// copied and modified from htmlinputelement.rs // copied and modified from htmlinputelement.rs
fn handle_event(&self, event: &Event) { fn handle_event(&self, event: &Event, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.handle_event(event); s.handle_event(event, can_gc);
} }
if event.type_() == atom!("click") && !event.DefaultPrevented() { if event.type_() == atom!("click") && !event.DefaultPrevented() {
@ -691,7 +694,7 @@ impl VirtualMethods for HTMLTextAreaElement {
} }
self.validity_state() self.validity_state()
.perform_validation_and_update(ValidationFlags::all()); .perform_validation_and_update(ValidationFlags::all(), can_gc);
} }
fn pop(&self) { fn pop(&self) {
@ -735,7 +738,11 @@ impl Validatable for HTMLTextAreaElement {
!is_barred_by_datalist_ancestor(self.upcast()) !is_barred_by_datalist_ancestor(self.upcast())
} }
fn perform_validation(&self, validate_flags: ValidationFlags) -> ValidationFlags { fn perform_validation(
&self,
validate_flags: ValidationFlags,
_can_gc: CanGc,
) -> ValidationFlags {
let mut failed_flags = ValidationFlags::empty(); let mut failed_flags = ValidationFlags::empty();
let textinput = self.textinput.borrow(); let textinput = self.textinput.borrow();

View file

@ -92,9 +92,9 @@ impl VirtualMethods for HTMLTitleElement {
} }
} }
fn bind_to_tree(&self, context: &BindContext) { fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.bind_to_tree(context); s.bind_to_tree(context, can_gc);
} }
let node = self.upcast::<Node>(); let node = self.upcast::<Node>();
if context.tree_is_in_a_document_tree { if context.tree_is_in_a_document_tree {

View file

@ -305,8 +305,10 @@ impl VirtualMethods for HTMLVideoElement {
Some(self.upcast::<HTMLMediaElement>() as &dyn VirtualMethods) Some(self.upcast::<HTMLMediaElement>() as &dyn VirtualMethods)
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
if attr.local_name() == &local_name!("poster") { if attr.local_name() == &local_name!("poster") {
if let Some(new_value) = mutation.new_value(attr) { if let Some(new_value) = mutation.new_value(attr) {

View file

@ -79,7 +79,7 @@ impl NamedNodeMapMethods<crate::DomTypeHolder> for NamedNodeMap {
fn RemoveNamedItem(&self, name: DOMString) -> Fallible<DomRoot<Attr>> { fn RemoveNamedItem(&self, name: DOMString) -> Fallible<DomRoot<Attr>> {
let name = self.owner.parsed_name(name); let name = self.owner.parsed_name(name);
self.owner self.owner
.remove_attribute_by_name(&name) .remove_attribute_by_name(&name, CanGc::note())
.ok_or(Error::NotFound) .ok_or(Error::NotFound)
} }
@ -91,7 +91,7 @@ impl NamedNodeMapMethods<crate::DomTypeHolder> for NamedNodeMap {
) -> Fallible<DomRoot<Attr>> { ) -> Fallible<DomRoot<Attr>> {
let ns = namespace_from_domstring(namespace); let ns = namespace_from_domstring(namespace);
self.owner self.owner
.remove_attribute(&ns, &LocalName::from(local_name)) .remove_attribute(&ns, &LocalName::from(local_name), CanGc::note())
.ok_or(Error::NotFound) .ok_or(Error::NotFound)
} }

View file

@ -248,7 +248,7 @@ impl Node {
/// Adds a new child to the end of this node's list of children. /// Adds a new child to the end of this node's list of children.
/// ///
/// Fails unless `new_child` is disconnected from the tree. /// Fails unless `new_child` is disconnected from the tree.
fn add_child(&self, new_child: &Node, before: Option<&Node>) { fn add_child(&self, new_child: &Node, before: Option<&Node>, can_gc: CanGc) {
assert!(new_child.parent_node.get().is_none()); assert!(new_child.parent_node.get().is_none());
assert!(new_child.prev_sibling.get().is_none()); assert!(new_child.prev_sibling.get().is_none());
assert!(new_child.next_sibling.get().is_none()); assert!(new_child.next_sibling.get().is_none());
@ -307,11 +307,14 @@ impl Node {
// Out-of-document elements never have the descendants flag set. // Out-of-document elements never have the descendants flag set.
debug_assert!(!node.get_flag(NodeFlags::HAS_DIRTY_DESCENDANTS)); debug_assert!(!node.get_flag(NodeFlags::HAS_DIRTY_DESCENDANTS));
vtable_for(&node).bind_to_tree(&BindContext { vtable_for(&node).bind_to_tree(
tree_connected: parent_is_connected, &BindContext {
tree_is_in_a_document_tree: parent_is_in_a_document_tree, tree_connected: parent_is_connected,
tree_is_in_a_shadow_tree: parent_in_shadow_tree, tree_is_in_a_document_tree: parent_is_in_a_document_tree,
}); tree_is_in_a_shadow_tree: parent_in_shadow_tree,
},
can_gc,
);
} }
} }
@ -323,7 +326,7 @@ impl Node {
/// Clean up flags and runs steps 11-14 of remove a node. /// Clean up flags and runs steps 11-14 of remove a node.
/// <https://dom.spec.whatwg.org/#concept-node-remove> /// <https://dom.spec.whatwg.org/#concept-node-remove>
pub(crate) fn complete_remove_subtree(root: &Node, context: &UnbindContext) { pub(crate) fn complete_remove_subtree(root: &Node, context: &UnbindContext, can_gc: CanGc) {
// Flags that reset when a node is disconnected // Flags that reset when a node is disconnected
const RESET_FLAGS: NodeFlags = NodeFlags::IS_IN_A_DOCUMENT_TREE const RESET_FLAGS: NodeFlags = NodeFlags::IS_IN_A_DOCUMENT_TREE
.union(NodeFlags::IS_CONNECTED) .union(NodeFlags::IS_CONNECTED)
@ -356,7 +359,7 @@ impl Node {
// This needs to be in its own loop, because unbind_from_tree may // This needs to be in its own loop, because unbind_from_tree may
// rely on the state of IS_IN_DOC of the context node's descendants, // rely on the state of IS_IN_DOC of the context node's descendants,
// e.g. when removing a <form>. // e.g. when removing a <form>.
vtable_for(&node).unbind_from_tree(context); vtable_for(&node).unbind_from_tree(context, can_gc);
// Step 12 & 14.2. Enqueue disconnected custom element reactions. // Step 12 & 14.2. Enqueue disconnected custom element reactions.
if is_parent_connected { if is_parent_connected {
@ -374,7 +377,7 @@ impl Node {
/// Removes the given child from this node's list of children. /// Removes the given child from this node's list of children.
/// ///
/// Fails unless `child` is a child of this node. /// Fails unless `child` is a child of this node.
fn remove_child(&self, child: &Node, cached_index: Option<u32>) { fn remove_child(&self, child: &Node, cached_index: Option<u32>, can_gc: CanGc) {
assert!(child.parent_node.get().as_deref() == Some(self)); assert!(child.parent_node.get().as_deref() == Some(self));
self.note_dirty_descendants(); self.note_dirty_descendants();
@ -413,7 +416,7 @@ impl Node {
child.parent_node.set(None); child.parent_node.set(None);
self.children_count.set(self.children_count.get() - 1); self.children_count.set(self.children_count.get() - 1);
Self::complete_remove_subtree(child, &context); Self::complete_remove_subtree(child, &context, can_gc);
} }
pub(crate) fn to_untrusted_node_address(&self) -> UntrustedNodeAddress { pub(crate) fn to_untrusted_node_address(&self) -> UntrustedNodeAddress {
@ -958,7 +961,7 @@ impl Node {
}; };
// Step 6. // Step 6.
Node::pre_insert(&node, &parent, viable_previous_sibling.as_deref())?; Node::pre_insert(&node, &parent, viable_previous_sibling.as_deref(), can_gc)?;
Ok(()) Ok(())
} }
@ -983,7 +986,7 @@ impl Node {
.node_from_nodes_and_strings(nodes, can_gc)?; .node_from_nodes_and_strings(nodes, can_gc)?;
// Step 5. // Step 5.
Node::pre_insert(&node, &parent, viable_next_sibling.as_deref())?; Node::pre_insert(&node, &parent, viable_next_sibling.as_deref(), can_gc)?;
Ok(()) Ok(())
} }
@ -1008,7 +1011,7 @@ impl Node {
parent.ReplaceChild(&node, self)?; parent.ReplaceChild(&node, self)?;
} else { } else {
// Step 6. // Step 6.
Node::pre_insert(&node, &parent, viable_next_sibling.as_deref())?; Node::pre_insert(&node, &parent, viable_next_sibling.as_deref(), can_gc)?;
} }
Ok(()) Ok(())
} }
@ -1020,7 +1023,7 @@ impl Node {
let node = doc.node_from_nodes_and_strings(nodes, can_gc)?; let node = doc.node_from_nodes_and_strings(nodes, can_gc)?;
// Step 2. // Step 2.
let first_child = self.first_child.get(); let first_child = self.first_child.get();
Node::pre_insert(&node, self, first_child.as_deref()).map(|_| ()) Node::pre_insert(&node, self, first_child.as_deref(), can_gc).map(|_| ())
} }
/// <https://dom.spec.whatwg.org/#dom-parentnode-append> /// <https://dom.spec.whatwg.org/#dom-parentnode-append>
@ -1040,7 +1043,7 @@ impl Node {
// Step 2. // Step 2.
Node::ensure_pre_insertion_validity(&node, self, None)?; Node::ensure_pre_insertion_validity(&node, self, None)?;
// Step 3. // Step 3.
Node::replace_all(Some(&node), self); Node::replace_all(Some(&node), self, can_gc);
Ok(()) Ok(())
} }
@ -1185,9 +1188,9 @@ impl Node {
.peekable() .peekable()
} }
pub(crate) fn remove_self(&self) { pub(crate) fn remove_self(&self, can_gc: CanGc) {
if let Some(ref parent) = self.GetParentNode() { if let Some(ref parent) = self.GetParentNode() {
Node::remove(self, parent, SuppressObserver::Unsuppressed); Node::remove(self, parent, SuppressObserver::Unsuppressed, can_gc);
} }
} }
@ -1264,6 +1267,7 @@ impl Node {
index: i32, index: i32,
get_items: F, get_items: F,
new_child: G, new_child: G,
_can_gc: CanGc,
) -> Fallible<DomRoot<HTMLElement>> ) -> Fallible<DomRoot<HTMLElement>>
where where
F: Fn() -> DomRoot<HTMLCollection>, F: Fn() -> DomRoot<HTMLCollection>,
@ -1305,6 +1309,7 @@ impl Node {
index: i32, index: i32,
get_items: F, get_items: F,
is_delete_type: G, is_delete_type: G,
can_gc: CanGc,
) -> ErrorResult ) -> ErrorResult
where where
F: Fn() -> DomRoot<HTMLCollection>, F: Fn() -> DomRoot<HTMLCollection>,
@ -1329,7 +1334,7 @@ impl Node {
}, },
}; };
element.upcast::<Node>().remove_self(); element.upcast::<Node>().remove_self(can_gc);
Ok(()) Ok(())
} }
@ -2046,7 +2051,7 @@ impl Node {
} }
/// <https://dom.spec.whatwg.org/#concept-node-adopt> /// <https://dom.spec.whatwg.org/#concept-node-adopt>
pub(crate) fn adopt(node: &Node, document: &Document) { pub(crate) fn adopt(node: &Node, document: &Document, can_gc: CanGc) {
document.add_script_and_layout_blocker(); document.add_script_and_layout_blocker();
// Step 1. Let oldDocument be nodes node document. // Step 1. Let oldDocument be nodes node document.
@ -2054,7 +2059,7 @@ impl Node {
old_doc.add_script_and_layout_blocker(); old_doc.add_script_and_layout_blocker();
// Step 2. If nodes parent is non-null, then remove node. // Step 2. If nodes parent is non-null, then remove node.
node.remove_self(); node.remove_self(can_gc);
// Step 3. If document is not oldDocument: // Step 3. If document is not oldDocument:
if &*old_doc != document { if &*old_doc != document {
@ -2089,7 +2094,7 @@ impl Node {
// Step 3.3 For each inclusiveDescendant in nodes shadow-including inclusive descendants, // Step 3.3 For each inclusiveDescendant in nodes shadow-including inclusive descendants,
// in shadow-including tree order, run the adopting steps with inclusiveDescendant and oldDocument. // in shadow-including tree order, run the adopting steps with inclusiveDescendant and oldDocument.
for descendant in node.traverse_preorder(ShadowIncluding::Yes) { for descendant in node.traverse_preorder(ShadowIncluding::Yes) {
vtable_for(&descendant).adopting_steps(&old_doc); vtable_for(&descendant).adopting_steps(&old_doc, can_gc);
} }
} }
@ -2220,6 +2225,7 @@ impl Node {
node: &Node, node: &Node,
parent: &Node, parent: &Node,
child: Option<&Node>, child: Option<&Node>,
can_gc: CanGc,
) -> Fallible<DomRoot<Node>> { ) -> Fallible<DomRoot<Node>> {
// Step 1. // Step 1.
Node::ensure_pre_insertion_validity(node, parent, child)?; Node::ensure_pre_insertion_validity(node, parent, child)?;
@ -2235,7 +2241,7 @@ impl Node {
}; };
// Step 4. // Step 4.
Node::adopt(node, &parent.owner_document()); Node::adopt(node, &parent.owner_document(), can_gc);
// Step 5. // Step 5.
Node::insert( Node::insert(
@ -2243,6 +2249,7 @@ impl Node {
parent, parent,
reference_child, reference_child,
SuppressObserver::Unsuppressed, SuppressObserver::Unsuppressed,
CanGc::note(),
); );
// Step 6. // Step 6.
@ -2255,6 +2262,7 @@ impl Node {
parent: &Node, parent: &Node,
child: Option<&Node>, child: Option<&Node>,
suppress_observers: SuppressObserver, suppress_observers: SuppressObserver,
can_gc: CanGc,
) { ) {
node.owner_doc().add_script_and_layout_blocker(); node.owner_doc().add_script_and_layout_blocker();
debug_assert!(*node.owner_doc() == *parent.owner_doc()); debug_assert!(*node.owner_doc() == *parent.owner_doc());
@ -2280,7 +2288,7 @@ impl Node {
new_nodes.extend(node.children().map(|kid| Dom::from_ref(&*kid))); new_nodes.extend(node.children().map(|kid| Dom::from_ref(&*kid)));
// Step 4. // Step 4.
for kid in &*new_nodes { for kid in &*new_nodes {
Node::remove(kid, node, SuppressObserver::Suppressed); Node::remove(kid, node, SuppressObserver::Suppressed, can_gc);
} }
// Step 5. // Step 5.
vtable_for(node).children_changed(&ChildrenMutation::replace_all(new_nodes.r(), &[])); vtable_for(node).children_changed(&ChildrenMutation::replace_all(new_nodes.r(), &[]));
@ -2309,7 +2317,7 @@ impl Node {
// Step 7. // Step 7.
for kid in new_nodes { for kid in new_nodes {
// Step 7.1. // Step 7.1.
parent.add_child(kid, child); parent.add_child(kid, child, can_gc);
// Step 7.4 If parent is a shadow host whose shadow roots slot assignment is "named" // Step 7.4 If parent is a shadow host whose shadow roots slot assignment is "named"
// and node is a slottable, then assign a slot for node. // and node is a slottable, then assign a slot for node.
@ -2407,11 +2415,11 @@ impl Node {
} }
/// <https://dom.spec.whatwg.org/#concept-node-replace-all> /// <https://dom.spec.whatwg.org/#concept-node-replace-all>
pub(crate) fn replace_all(node: Option<&Node>, parent: &Node) { pub(crate) fn replace_all(node: Option<&Node>, parent: &Node, can_gc: CanGc) {
parent.owner_doc().add_script_and_layout_blocker(); parent.owner_doc().add_script_and_layout_blocker();
// Step 1. // Step 1.
if let Some(node) = node { if let Some(node) = node {
Node::adopt(node, &parent.owner_doc()); Node::adopt(node, &parent.owner_doc(), can_gc);
} }
// Step 2. // Step 2.
rooted_vec!(let removed_nodes <- parent.children().map(|c| DomRoot::as_traced(&c))); rooted_vec!(let removed_nodes <- parent.children().map(|c| DomRoot::as_traced(&c)));
@ -2429,11 +2437,11 @@ impl Node {
}; };
// Step 4. // Step 4.
for child in &*removed_nodes { for child in &*removed_nodes {
Node::remove(child, parent, SuppressObserver::Suppressed); Node::remove(child, parent, SuppressObserver::Suppressed, can_gc);
} }
// Step 5. // Step 5.
if let Some(node) = node { if let Some(node) = node {
Node::insert(node, parent, None, SuppressObserver::Suppressed); Node::insert(node, parent, None, SuppressObserver::Suppressed, can_gc);
} }
// Step 6. // Step 6.
vtable_for(parent).children_changed(&ChildrenMutation::replace_all( vtable_for(parent).children_changed(&ChildrenMutation::replace_all(
@ -2456,15 +2464,15 @@ impl Node {
/// <https://dom.spec.whatwg.org/multipage/#string-replace-all> /// <https://dom.spec.whatwg.org/multipage/#string-replace-all>
pub(crate) fn string_replace_all(string: DOMString, parent: &Node, can_gc: CanGc) { pub(crate) fn string_replace_all(string: DOMString, parent: &Node, can_gc: CanGc) {
if string.len() == 0 { if string.len() == 0 {
Node::replace_all(None, parent); Node::replace_all(None, parent, can_gc);
} else { } else {
let text = Text::new(string, &parent.owner_document(), can_gc); let text = Text::new(string, &parent.owner_document(), can_gc);
Node::replace_all(Some(text.upcast::<Node>()), parent); Node::replace_all(Some(text.upcast::<Node>()), parent, can_gc);
}; };
} }
/// <https://dom.spec.whatwg.org/#concept-node-pre-remove> /// <https://dom.spec.whatwg.org/#concept-node-pre-remove>
fn pre_remove(child: &Node, parent: &Node) -> Fallible<DomRoot<Node>> { fn pre_remove(child: &Node, parent: &Node, can_gc: CanGc) -> Fallible<DomRoot<Node>> {
// Step 1. // Step 1.
match child.GetParentNode() { match child.GetParentNode() {
Some(ref node) if &**node != parent => return Err(Error::NotFound), Some(ref node) if &**node != parent => return Err(Error::NotFound),
@ -2473,14 +2481,14 @@ impl Node {
} }
// Step 2. // Step 2.
Node::remove(child, parent, SuppressObserver::Unsuppressed); Node::remove(child, parent, SuppressObserver::Unsuppressed, can_gc);
// Step 3. // Step 3.
Ok(DomRoot::from_ref(child)) Ok(DomRoot::from_ref(child))
} }
/// <https://dom.spec.whatwg.org/#concept-node-remove> /// <https://dom.spec.whatwg.org/#concept-node-remove>
fn remove(node: &Node, parent: &Node, suppress_observers: SuppressObserver) { fn remove(node: &Node, parent: &Node, suppress_observers: SuppressObserver, can_gc: CanGc) {
parent.owner_doc().add_script_and_layout_blocker(); parent.owner_doc().add_script_and_layout_blocker();
// Step 2. // Step 2.
@ -2517,7 +2525,7 @@ impl Node {
// Step 7. Remove node from its parent's children. // Step 7. Remove node from its parent's children.
// Step 11-14. Run removing steps and enqueue disconnected custom element reactions for the subtree. // Step 11-14. Run removing steps and enqueue disconnected custom element reactions for the subtree.
parent.remove_child(node, cached_index); parent.remove_child(node, cached_index, can_gc);
// Step 8. If node is assigned, then run assign slottables for nodes assigned slot. // Step 8. If node is assigned, then run assign slottables for nodes assigned slot.
if let Some(slot) = node.assigned_slot() { if let Some(slot) = node.assigned_slot() {
@ -2707,14 +2715,14 @@ impl Node {
// Step 5: Run any cloning steps defined for node in other applicable specifications and pass copy, // Step 5: Run any cloning steps defined for node in other applicable specifications and pass copy,
// node, document, and the clone children flag if set, as parameters. // node, document, and the clone children flag if set, as parameters.
vtable_for(node).cloning_steps(&copy, maybe_doc, clone_children); vtable_for(node).cloning_steps(&copy, maybe_doc, clone_children, can_gc);
// Step 6. If the clone children flag is set, then for each child child of node, in tree order: append the // Step 6. If the clone children flag is set, then for each child child of node, in tree order: append the
// result of cloning child with document and the clone children flag set, to copy. // result of cloning child with document and the clone children flag set, to copy.
if clone_children == CloneChildrenFlag::CloneChildren { if clone_children == CloneChildrenFlag::CloneChildren {
for child in node.children() { for child in node.children() {
let child_copy = Node::clone(&child, Some(&document), clone_children, can_gc); let child_copy = Node::clone(&child, Some(&document), clone_children, can_gc);
let _inserted_node = Node::pre_insert(&child_copy, &copy, None); let _inserted_node = Node::pre_insert(&child_copy, &copy, None, can_gc);
} }
} }
@ -2757,8 +2765,12 @@ impl Node {
); );
// TODO: Should we handle the error case here and in step 6? // TODO: Should we handle the error case here and in step 6?
let _inserted_node = let _inserted_node = Node::pre_insert(
Node::pre_insert(&child_copy, copy_shadow_root.upcast::<Node>(), None); &child_copy,
copy_shadow_root.upcast::<Node>(),
None,
can_gc,
);
} }
} }
} }
@ -3115,7 +3127,7 @@ impl NodeMethods<crate::DomTypeHolder> for Node {
}; };
// Step 3. // Step 3.
Node::replace_all(node.as_deref(), self); Node::replace_all(node.as_deref(), self, can_gc);
}, },
NodeTypeId::Attr => { NodeTypeId::Attr => {
let attr = self.downcast::<Attr>().unwrap(); let attr = self.downcast::<Attr>().unwrap();
@ -3131,12 +3143,12 @@ impl NodeMethods<crate::DomTypeHolder> for Node {
/// <https://dom.spec.whatwg.org/#dom-node-insertbefore> /// <https://dom.spec.whatwg.org/#dom-node-insertbefore>
fn InsertBefore(&self, node: &Node, child: Option<&Node>) -> Fallible<DomRoot<Node>> { fn InsertBefore(&self, node: &Node, child: Option<&Node>) -> Fallible<DomRoot<Node>> {
Node::pre_insert(node, self, child) Node::pre_insert(node, self, child, CanGc::note())
} }
/// <https://dom.spec.whatwg.org/#dom-node-appendchild> /// <https://dom.spec.whatwg.org/#dom-node-appendchild>
fn AppendChild(&self, node: &Node) -> Fallible<DomRoot<Node>> { fn AppendChild(&self, node: &Node) -> Fallible<DomRoot<Node>> {
Node::pre_insert(node, self, None) Node::pre_insert(node, self, None, CanGc::note())
} }
/// <https://dom.spec.whatwg.org/#concept-node-replace> /// <https://dom.spec.whatwg.org/#concept-node-replace>
@ -3238,11 +3250,11 @@ impl NodeMethods<crate::DomTypeHolder> for Node {
// Step 10. // Step 10.
let document = self.owner_document(); let document = self.owner_document();
Node::adopt(node, &document); Node::adopt(node, &document, CanGc::note());
let removed_child = if node != child { let removed_child = if node != child {
// Step 11. // Step 11.
Node::remove(child, self, SuppressObserver::Suppressed); Node::remove(child, self, SuppressObserver::Suppressed, CanGc::note());
Some(child) Some(child)
} else { } else {
None None
@ -3261,7 +3273,13 @@ impl NodeMethods<crate::DomTypeHolder> for Node {
}; };
// Step 13. // Step 13.
Node::insert(node, self, reference_child, SuppressObserver::Suppressed); Node::insert(
node,
self,
reference_child,
SuppressObserver::Suppressed,
CanGc::note(),
);
// Step 14. // Step 14.
vtable_for(self).children_changed(&ChildrenMutation::replace( vtable_for(self).children_changed(&ChildrenMutation::replace(
@ -3286,7 +3304,7 @@ impl NodeMethods<crate::DomTypeHolder> for Node {
/// <https://dom.spec.whatwg.org/#dom-node-removechild> /// <https://dom.spec.whatwg.org/#dom-node-removechild>
fn RemoveChild(&self, node: &Node) -> Fallible<DomRoot<Node>> { fn RemoveChild(&self, node: &Node) -> Fallible<DomRoot<Node>> {
Node::pre_remove(node, self) Node::pre_remove(node, self, CanGc::note())
} }
/// <https://dom.spec.whatwg.org/#dom-node-normalize> /// <https://dom.spec.whatwg.org/#dom-node-normalize>
@ -3297,7 +3315,7 @@ impl NodeMethods<crate::DomTypeHolder> for Node {
let cdata = text.upcast::<CharacterData>(); let cdata = text.upcast::<CharacterData>();
let mut length = cdata.Length(); let mut length = cdata.Length();
if length == 0 { if length == 0 {
Node::remove(&node, self, SuppressObserver::Unsuppressed); Node::remove(&node, self, SuppressObserver::Unsuppressed, CanGc::note());
continue; continue;
} }
while children while children
@ -3313,7 +3331,12 @@ impl NodeMethods<crate::DomTypeHolder> for Node {
let sibling_cdata = sibling.downcast::<CharacterData>().unwrap(); let sibling_cdata = sibling.downcast::<CharacterData>().unwrap();
length += sibling_cdata.Length(); length += sibling_cdata.Length();
cdata.append_data(&sibling_cdata.data()); cdata.append_data(&sibling_cdata.data());
Node::remove(&sibling, self, SuppressObserver::Unsuppressed); Node::remove(
&sibling,
self,
SuppressObserver::Unsuppressed,
CanGc::note(),
);
} }
} else { } else {
node.Normalize(); node.Normalize();
@ -3726,8 +3749,8 @@ impl VirtualMethods for Node {
// This handles the ranges mentioned in steps 2-3 when removing a node. // This handles the ranges mentioned in steps 2-3 when removing a node.
/// <https://dom.spec.whatwg.org/#concept-node-remove> /// <https://dom.spec.whatwg.org/#concept-node-remove>
fn unbind_from_tree(&self, context: &UnbindContext) { fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context); self.super_type().unwrap().unbind_from_tree(context, can_gc);
if !self.ranges_is_empty() { if !self.ranges_is_empty() {
self.ranges().drain_to_parent(context, self); self.ranges().drain_to_parent(context, self);
} }

View file

@ -884,7 +884,7 @@ impl RangeMethods<crate::DomTypeHolder> for Range {
}; };
// Step 9. // Step 9.
node.remove_self(); node.remove_self(can_gc);
// Step 10. // Step 10.
let new_offset = reference_node let new_offset = reference_node
@ -900,7 +900,7 @@ impl RangeMethods<crate::DomTypeHolder> for Range {
}; };
// Step 12. // Step 12.
Node::pre_insert(node, &parent, reference_node.as_deref())?; Node::pre_insert(node, &parent, reference_node.as_deref(), can_gc)?;
// Step 13. // Step 13.
if self.collapsed() { if self.collapsed() {
@ -980,7 +980,7 @@ impl RangeMethods<crate::DomTypeHolder> for Range {
// Step 8. // Step 8.
for child in &*contained_children { for child in &*contained_children {
child.remove_self(); child.remove_self(CanGc::note());
} }
// Step 9. // Step 9.
@ -1023,7 +1023,7 @@ impl RangeMethods<crate::DomTypeHolder> for Range {
let fragment = self.ExtractContents(can_gc)?; let fragment = self.ExtractContents(can_gc)?;
// Step 4. // Step 4.
Node::replace_all(None, new_parent); Node::replace_all(None, new_parent, can_gc);
// Step 5. // Step 5.
self.InsertNode(new_parent, can_gc)?; self.InsertNode(new_parent, can_gc)?;

View file

@ -546,7 +546,7 @@ impl Tokenizer {
let control = elem.and_then(|e| e.as_maybe_form_control()); let control = elem.and_then(|e| e.as_maybe_form_control());
if let Some(control) = control { if let Some(control) = control {
control.set_form_owner_from_parser(&form); control.set_form_owner_from_parser(&form, can_gc);
} }
}, },
ParseOperation::Pop { node } => { ParseOperation::Pop { node } => {

View file

@ -713,7 +713,7 @@ where
fn next(&mut self) -> Option<DomRoot<Node>> { fn next(&mut self) -> Option<DomRoot<Node>> {
let next = self.inner.next()?; let next = self.inner.next()?;
next.remove_self(); next.remove_self(CanGc::note());
Some(next) Some(next)
} }
@ -1264,7 +1264,7 @@ impl TreeSink for Sink {
let control = elem.and_then(|e| e.as_maybe_form_control()); let control = elem.and_then(|e| e.as_maybe_form_control());
if let Some(control) = control { if let Some(control) = control {
control.set_form_owner_from_parser(&form); control.set_form_owner_from_parser(&form, CanGc::note());
} }
} }

View file

@ -153,11 +153,11 @@ impl ShadowRoot {
) )
} }
pub(crate) fn detach(&self) { pub(crate) fn detach(&self, can_gc: CanGc) {
self.document.unregister_shadow_root(self); self.document.unregister_shadow_root(self);
let node = self.upcast::<Node>(); let node = self.upcast::<Node>();
node.set_containing_shadow_root(None); node.set_containing_shadow_root(None);
Node::complete_remove_subtree(node, &UnbindContext::new(node, None, None, None)); Node::complete_remove_subtree(node, &UnbindContext::new(node, None, None, None), can_gc);
self.host.set(None); self.host.set(None);
} }
@ -221,7 +221,7 @@ impl ShadowRoot {
/// Remove any existing association between the provided id and any elements /// Remove any existing association between the provided id and any elements
/// in this shadow tree. /// in this shadow tree.
pub(crate) fn unregister_element_id(&self, to_unregister: &Element, id: Atom) { pub(crate) fn unregister_element_id(&self, to_unregister: &Element, id: Atom, _can_gc: CanGc) {
self.document_or_shadow_root.unregister_named_element( self.document_or_shadow_root.unregister_named_element(
self.document_fragment.id_map(), self.document_fragment.id_map(),
to_unregister, to_unregister,
@ -230,7 +230,7 @@ impl ShadowRoot {
} }
/// Associate an element present in this shadow tree with the provided id. /// Associate an element present in this shadow tree with the provided id.
pub(crate) fn register_element_id(&self, element: &Element, id: Atom) { pub(crate) fn register_element_id(&self, element: &Element, id: Atom, _can_gc: CanGc) {
let root = self let root = self
.upcast::<Node>() .upcast::<Node>()
.inclusive_ancestors(ShadowIncluding::No) .inclusive_ancestors(ShadowIncluding::No)
@ -445,7 +445,7 @@ impl ShadowRootMethods<crate::DomTypeHolder> for ShadowRoot {
}; };
// Step 4. Replace all with fragment within this. // Step 4. Replace all with fragment within this.
Node::replace_all(Some(frag.upcast()), self.upcast()); Node::replace_all(Some(frag.upcast()), self.upcast(), can_gc);
} }
/// <https://dom.spec.whatwg.org/#dom-shadowroot-slotassignment> /// <https://dom.spec.whatwg.org/#dom-shadowroot-slotassignment>
@ -462,9 +462,9 @@ impl VirtualMethods for ShadowRoot {
Some(self.upcast::<DocumentFragment>() as &dyn VirtualMethods) Some(self.upcast::<DocumentFragment>() as &dyn VirtualMethods)
} }
fn bind_to_tree(&self, context: &BindContext) { fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.bind_to_tree(context); s.bind_to_tree(context, can_gc);
} }
if context.tree_connected { if context.tree_connected {
@ -482,17 +482,20 @@ impl VirtualMethods for ShadowRoot {
// Out-of-document elements never have the descendants flag set // Out-of-document elements never have the descendants flag set
debug_assert!(!node.get_flag(NodeFlags::HAS_DIRTY_DESCENDANTS)); debug_assert!(!node.get_flag(NodeFlags::HAS_DIRTY_DESCENDANTS));
vtable_for(&node).bind_to_tree(&BindContext { vtable_for(&node).bind_to_tree(
tree_connected: context.tree_connected, &BindContext {
tree_is_in_a_document_tree: false, tree_connected: context.tree_connected,
tree_is_in_a_shadow_tree: true, tree_is_in_a_document_tree: false,
}); tree_is_in_a_shadow_tree: true,
},
can_gc,
);
} }
} }
fn unbind_from_tree(&self, context: &UnbindContext) { fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.unbind_from_tree(context); s.unbind_from_tree(context, can_gc);
} }
if context.tree_connected { if context.tree_connected {

View file

@ -79,8 +79,10 @@ impl VirtualMethods for SVGSVGElement {
Some(self.upcast::<SVGGraphicsElement>() as &dyn VirtualMethods) Some(self.upcast::<SVGGraphicsElement>() as &dyn VirtualMethods)
} }
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
} }
fn parse_plain_attribute(&self, name: &LocalName, value: DOMString) -> AttrValue { fn parse_plain_attribute(&self, name: &LocalName, value: DOMString) -> AttrValue {

View file

@ -25,7 +25,11 @@ pub(crate) trait Validatable {
fn is_instance_validatable(&self) -> bool; fn is_instance_validatable(&self) -> bool;
// Check if element satisfies its constraints, excluding custom errors // Check if element satisfies its constraints, excluding custom errors
fn perform_validation(&self, _validate_flags: ValidationFlags) -> ValidationFlags { fn perform_validation(
&self,
_validate_flags: ValidationFlags,
_can_gc: CanGc,
) -> ValidationFlags {
ValidationFlags::empty() ValidationFlags::empty()
} }

View file

@ -107,7 +107,7 @@ impl ValidityState {
// https://html.spec.whatwg.org/multipage/#custom-validity-error-message // https://html.spec.whatwg.org/multipage/#custom-validity-error-message
pub(crate) fn set_custom_error_message(&self, error: DOMString) { pub(crate) fn set_custom_error_message(&self, error: DOMString) {
*self.custom_error_message.borrow_mut() = error; *self.custom_error_message.borrow_mut() = error;
self.perform_validation_and_update(ValidationFlags::CUSTOM_ERROR); self.perform_validation_and_update(ValidationFlags::CUSTOM_ERROR, CanGc::note());
} }
/// Given a set of [ValidationFlags], recalculate their value by performing /// Given a set of [ValidationFlags], recalculate their value by performing
@ -115,12 +115,16 @@ impl ValidityState {
/// if [ValidationFlags::CUSTOM_ERROR] is in `update_flags` and a custom /// if [ValidationFlags::CUSTOM_ERROR] is in `update_flags` and a custom
/// error has been set on this [ValidityState], the state will be updated /// error has been set on this [ValidityState], the state will be updated
/// to reflect the existance of a custom error. /// to reflect the existance of a custom error.
pub(crate) fn perform_validation_and_update(&self, update_flags: ValidationFlags) { pub(crate) fn perform_validation_and_update(
&self,
update_flags: ValidationFlags,
can_gc: CanGc,
) {
let mut invalid_flags = self.invalid_flags.get(); let mut invalid_flags = self.invalid_flags.get();
invalid_flags.remove(update_flags); invalid_flags.remove(update_flags);
if let Some(validatable) = self.element.as_maybe_validatable() { if let Some(validatable) = self.element.as_maybe_validatable() {
let new_flags = validatable.perform_validation(update_flags); let new_flags = validatable.perform_validation(update_flags, can_gc);
invalid_flags.insert(new_flags); invalid_flags.insert(new_flags);
} }
@ -132,7 +136,7 @@ impl ValidityState {
} }
self.invalid_flags.set(invalid_flags); self.invalid_flags.set(invalid_flags);
self.update_pseudo_classes(); self.update_pseudo_classes(can_gc);
} }
pub(crate) fn update_invalid_flags(&self, update_flags: ValidationFlags) { pub(crate) fn update_invalid_flags(&self, update_flags: ValidationFlags) {
@ -143,7 +147,7 @@ impl ValidityState {
self.invalid_flags.get() self.invalid_flags.get()
} }
pub(crate) fn update_pseudo_classes(&self) { pub(crate) fn update_pseudo_classes(&self, can_gc: CanGc) {
if self.element.is_instance_validatable() { if self.element.is_instance_validatable() {
let is_valid = self.invalid_flags.get().is_empty(); let is_valid = self.invalid_flags.get().is_empty();
self.element.set_state(ElementState::VALID, is_valid); self.element.set_state(ElementState::VALID, is_valid);
@ -155,7 +159,7 @@ impl ValidityState {
if let Some(form_control) = self.element.as_maybe_form_control() { if let Some(form_control) = self.element.as_maybe_form_control() {
if let Some(form_owner) = form_control.form_owner() { if let Some(form_owner) = form_control.form_owner() {
form_owner.update_validity(); form_owner.update_validity(can_gc);
} }
} }
@ -166,7 +170,7 @@ impl ValidityState {
.filter_map(DomRoot::downcast::<HTMLFieldSetElement>) .filter_map(DomRoot::downcast::<HTMLFieldSetElement>)
.next() .next()
{ {
fieldset.update_validity(); fieldset.update_validity(can_gc);
} }
} }
} }

View file

@ -3,6 +3,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use html5ever::LocalName; use html5ever::LocalName;
use script_bindings::script_runtime::CanGc;
use style::attr::AttrValue; use style::attr::AttrValue;
use crate::dom::attr::Attr; use crate::dom::attr::Attr;
@ -72,9 +73,9 @@ pub(crate) trait VirtualMethods {
/// Called when attributes of a node are mutated. /// Called when attributes of a node are mutated.
/// <https://dom.spec.whatwg.org/#attribute-is-set> /// <https://dom.spec.whatwg.org/#attribute-is-set>
/// <https://dom.spec.whatwg.org/#attribute-is-removed> /// <https://dom.spec.whatwg.org/#attribute-is-removed>
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.attribute_mutated(attr, mutation); s.attribute_mutated(attr, mutation, can_gc);
} }
} }
@ -107,9 +108,9 @@ pub(crate) trait VirtualMethods {
/// Called when a Node is appended to a tree, where 'tree_connected' indicates /// Called when a Node is appended to a tree, where 'tree_connected' indicates
/// whether the tree is part of a Document. /// whether the tree is part of a Document.
fn bind_to_tree(&self, context: &BindContext) { fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.bind_to_tree(context); s.bind_to_tree(context, can_gc);
} }
} }
@ -117,9 +118,9 @@ pub(crate) trait VirtualMethods {
/// indicates whether the tree is part of a Document. /// indicates whether the tree is part of a Document.
/// Implements removing steps: /// Implements removing steps:
/// <https://dom.spec.whatwg.org/#concept-node-remove-ext> /// <https://dom.spec.whatwg.org/#concept-node-remove-ext>
fn unbind_from_tree(&self, context: &UnbindContext) { fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.unbind_from_tree(context); s.unbind_from_tree(context, can_gc);
} }
} }
@ -131,16 +132,16 @@ pub(crate) trait VirtualMethods {
} }
/// Called during event dispatch after the bubbling phase completes. /// Called during event dispatch after the bubbling phase completes.
fn handle_event(&self, event: &Event) { fn handle_event(&self, event: &Event, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.handle_event(event); s.handle_event(event, can_gc);
} }
} }
/// <https://dom.spec.whatwg.org/#concept-node-adopt-ext> /// <https://dom.spec.whatwg.org/#concept-node-adopt-ext>
fn adopting_steps(&self, old_doc: &Document) { fn adopting_steps(&self, old_doc: &Document, can_gc: CanGc) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.adopting_steps(old_doc); s.adopting_steps(old_doc, can_gc);
} }
} }
@ -150,9 +151,10 @@ pub(crate) trait VirtualMethods {
copy: &Node, copy: &Node,
maybe_doc: Option<&Document>, maybe_doc: Option<&Document>,
clone_children: CloneChildrenFlag, clone_children: CloneChildrenFlag,
can_gc: CanGc,
) { ) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.cloning_steps(copy, maybe_doc, clone_children); s.cloning_steps(copy, maybe_doc, clone_children, can_gc);
} }
} }

View file

@ -2311,7 +2311,7 @@ impl ScriptThread {
) )
}, },
WebDriverScriptCommand::GetUrl(reply) => { WebDriverScriptCommand::GetUrl(reply) => {
webdriver_handlers::handle_get_url(&documents, pipeline_id, reply) webdriver_handlers::handle_get_url(&documents, pipeline_id, reply, can_gc)
}, },
WebDriverScriptCommand::IsEnabled(element_id, reply) => { WebDriverScriptCommand::IsEnabled(element_id, reply) => {
webdriver_handlers::handle_is_enabled(&documents, pipeline_id, element_id, reply) webdriver_handlers::handle_is_enabled(&documents, pipeline_id, element_id, reply)

View file

@ -1148,6 +1148,7 @@ pub(crate) fn handle_get_url(
documents: &DocumentCollection, documents: &DocumentCollection,
pipeline: PipelineId, pipeline: PipelineId,
reply: IpcSender<ServoUrl>, reply: IpcSender<ServoUrl>,
_can_gc: CanGc,
) { ) {
reply reply
.send( .send(