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) {
if let Some(owner) = self.owner() {
let value = owner.parse_attribute(self.namespace(), self.local_name(), value);
self.set_value(value, &owner);
self.set_value(value, &owner, CanGc::note());
} else {
*self.value.borrow_mut() = AttrValue::String(value.into());
}
@ -153,7 +153,7 @@ impl AttrMethods<crate::DomTypeHolder> for 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 namespace = self.namespace().clone();
let old_value = DOMString::from(&**self.value());
@ -180,8 +180,11 @@ impl Attr {
owner.will_mutate_attr(self);
self.swap_value(&mut value);
if *self.namespace() == ns!() {
vtable_for(owner.upcast())
.attribute_mutated(self, AttributeMutation::Set(Some(&value)));
vtable_for(owner.upcast()).attribute_mutated(
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
fn Remove(&self) {
let node = self.upcast::<Node>();
node.remove_self();
node.remove_self(CanGc::note());
}
// 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
// `FormControl` for HTMLElement, which makes that assumption.
// 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() {
// Even though the tree hasn't structurally mutated,
// 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.
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.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.
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(
"The element is in the document, so there must be a document \
element.",
@ -938,7 +938,7 @@ impl Document {
&id,
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.
@ -3265,10 +3265,10 @@ impl Document {
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) {
let media_controls = DomRoot::from_ref(&**media_controls);
media_controls.Host().detach_shadow();
media_controls.Host().detach_shadow(can_gc);
} else {
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();
if let Some(listeners) = map.get(id) {
for listener in listeners {
listener
.as_maybe_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.
Node::adopt(node, self);
Node::adopt(node, self, CanGc::note());
// Step 4.
Ok(DomRoot::from_ref(node))
@ -5945,7 +5945,7 @@ impl DocumentMethods<crate::DomTypeHolder> for 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
// 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
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 {
// https://html.spec.whatwg.org/multipage/#dom-domstringmap-removeitem
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

View file

@ -566,7 +566,7 @@ impl Element {
// Step 4.3.1. Remove all of currentShadowRoots children, in tree order.
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.
@ -621,7 +621,7 @@ impl Element {
tree_is_in_a_document_tree: self.upcast::<Node>().is_in_a_document_tree(),
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>();
node.dirty(NodeDamage::OtherNodeDamage);
@ -630,7 +630,7 @@ impl Element {
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 {
unreachable!("Trying to detach a non-attached shadow root");
};
@ -639,7 +639,7 @@ impl Element {
node.note_dirty_descendants();
node.rev_version();
shadow_root.detach();
shadow_root.detach(can_gc);
self.ensure_rare_data().shadow_root = None;
}
@ -1635,10 +1635,10 @@ impl Element {
Some(self),
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 namespace = attr.namespace().clone();
let mutation = LazyCell::new(|| Mutation::Attribute {
@ -1659,7 +1659,7 @@ impl Element {
self.will_mutate_attr(attr);
self.attrs.borrow_mut().push(Dom::from_ref(attr));
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))
.map(|js| DomRoot::from_ref(&**js));
if let Some(attr) = attr {
attr.set_value(value, self);
attr.set_value(value, self, can_gc);
} else {
self.push_new_attribute(local_name, value, name, namespace, prefix, can_gc);
};
@ -1811,17 +1811,23 @@ impl Element {
&self,
namespace: &Namespace,
local_name: &LocalName,
can_gc: CanGc,
) -> Option<DomRoot<Attr>> {
self.remove_first_matching_attribute(|attr| {
attr.namespace() == namespace && attr.local_name() == local_name
})
self.remove_first_matching_attribute(
|attr| attr.namespace() == namespace && attr.local_name() == local_name,
can_gc,
)
}
pub(crate) fn remove_attribute_by_name(&self, name: &LocalName) -> Option<DomRoot<Attr>> {
self.remove_first_matching_attribute(|attr| attr.name() == name)
pub(crate) fn remove_attribute_by_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
F: Fn(&Attr) -> bool,
{
@ -1850,7 +1856,11 @@ impl Element {
self.attrs.borrow_mut().remove(idx);
attr.set_owner(None);
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
})
@ -1892,7 +1902,7 @@ impl Element {
if value {
self.set_string_attribute(local_name, DOMString::new(), can_gc);
} 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);
},
None => {
self.remove_attribute(&ns!(), local_name);
self.remove_attribute(&ns!(), local_name, can_gc);
},
}
}
@ -2056,23 +2066,31 @@ impl Element {
&self,
where_: AdjacentPosition,
node: &Node,
can_gc: CanGc,
) -> Fallible<Option<DomRoot<Node>>> {
let self_node = self.upcast::<Node>();
match where_ {
AdjacentPosition::BeforeBegin => {
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 {
Ok(None)
}
},
AdjacentPosition::AfterBegin => {
Node::pre_insert(node, self_node, self_node.GetFirstChild().as_deref()).map(Some)
AdjacentPosition::AfterBegin => Node::pre_insert(
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 => {
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 {
Ok(None)
}
@ -2437,7 +2455,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
Some(_index) => match force {
// Step 5.
None | Some(false) => {
self.remove_attribute_by_name(&name);
self.remove_attribute_by_name(&name, can_gc);
Ok(false)
},
// Step 6.
@ -2542,7 +2560,11 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
self.attrs.borrow_mut()[position] = Dom::from_ref(attr);
old_attr.set_owner(None);
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.
@ -2550,7 +2572,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
} else {
// Step 5.
attr.set_owner(Some(self));
self.push_attribute(attr);
self.push_attribute(attr, CanGc::note());
// Step 6.
Ok(None)
@ -2565,19 +2587,19 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
// https://dom.spec.whatwg.org/#dom-element-removeattribute
fn RemoveAttribute(&self, name: DOMString) {
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
fn RemoveAttributeNS(&self, namespace: Option<DOMString>, local_name: DOMString) {
let namespace = namespace_from_domstring(namespace);
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
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)
}
@ -2951,7 +2973,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
}
// 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>
@ -3013,7 +3035,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
// Step 1.
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(())
}
@ -3155,7 +3177,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
// https://dom.spec.whatwg.org/#dom-childnode-remove
fn Remove(&self) {
self.upcast::<Node>().remove_self();
self.upcast::<Node>().remove_self(CanGc::note());
}
// https://dom.spec.whatwg.org/#dom-element-matches
@ -3213,7 +3235,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
element: &Element,
) -> Fallible<Option<DomRoot<Element>>> {
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()))
}
@ -3224,7 +3246,8 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
// Step 2.
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
@ -3263,7 +3286,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
let fragment = context.parse_fragment(text, can_gc)?;
// Step 4.
self.insert_adjacent(position, fragment.upcast())
self.insert_adjacent(position, fragment.upcast(), can_gc)
.map(|_| ())
}
@ -3713,8 +3736,10 @@ impl VirtualMethods for Element {
.attribute_affects_presentational_hints(attr)
}
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
self.super_type().unwrap().attribute_mutated(attr, mutation);
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
let node = self.upcast::<Node>();
let doc = node.owner_doc();
match attr.local_name() {
@ -3776,25 +3801,25 @@ impl VirtualMethods for Element {
if let Some(old_value) = old_value {
let old_value = old_value.as_atom().clone();
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 {
doc.unregister_element_id(self, old_value);
doc.unregister_element_id(self, old_value, can_gc);
}
}
if value != atom!("") {
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 {
doc.register_element_id(self, value);
doc.register_element_id(self, value, can_gc);
}
}
},
AttributeMutation::Removed => {
if value != atom!("") {
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 {
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() {
s.bind_to_tree(context);
s.bind_to_tree(context, can_gc);
}
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();
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() {
@ -3896,9 +3921,9 @@ impl VirtualMethods for Element {
if let Some(ref id) = *self.id_attribute.borrow() {
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 {
doc.register_element_id(self, id.clone());
doc.register_element_id(self, id.clone(), can_gc);
}
}
if let Some(ref name) = self.name_attribute() {
@ -3911,14 +3936,14 @@ impl VirtualMethods for Element {
doc.increment_dom_count();
}
fn unbind_from_tree(&self, context: &UnbindContext) {
self.super_type().unwrap().unbind_from_tree(context);
fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context, can_gc);
if let Some(f) = self.as_maybe_form_control() {
// TODO: The valid state of ancestors might be wrong if the form control element
// has a fieldset ancestor, for instance: `<form><fieldset><input>`,
// 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 {
@ -3938,10 +3963,10 @@ impl VirtualMethods for Element {
// 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)
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 {
doc.unregister_element_id(self, value.clone());
doc.unregister_element_id(self, value.clone(), can_gc);
}
}
if let Some(ref value) = self.name_attribute() {
@ -3980,8 +4005,8 @@ impl VirtualMethods for Element {
}
}
fn adopting_steps(&self, old_doc: &Document) {
self.super_type().unwrap().adopting_steps(old_doc);
fn adopting_steps(&self, old_doc: &Document, can_gc: CanGc) {
self.super_type().unwrap().adopting_steps(old_doc, can_gc);
if self.owner_document().is_html_document() != old_doc.is_html_document() {
self.tag_name.clear();
@ -4426,12 +4451,12 @@ impl 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 needs_update {
validatable
.validity_state()
.perform_validation_and_update(ValidationFlags::all());
.perform_validation_and_update(ValidationFlags::all(), can_gc);
}
return validatable.is_instance_validatable() && !validatable.satisfies_constraints();
}
@ -4844,7 +4869,7 @@ pub(crate) fn set_cross_origin_attribute(
match value {
Some(val) => element.set_string_attribute(&local_name!("crossorigin"), val, can_gc),
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
// `flag` to `value`.
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
// 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(node) = target.downcast::<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) {
self.super_type().unwrap().attribute_mutated(attr, mutation);
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match *attr.local_name() {
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() {
s.bind_to_tree(context);
s.bind_to_tree(context, can_gc);
}
self.relations

View file

@ -321,8 +321,10 @@ impl VirtualMethods for HTMLAreaElement {
}
}
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
self.super_type().unwrap().attribute_mutated(attr, mutation);
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match *attr.local_name() {
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() {
s.bind_to_tree(context);
s.bind_to_tree(context, can_gc);
}
self.relations

View file

@ -117,20 +117,22 @@ impl VirtualMethods for HTMLBaseElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
}
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
self.super_type().unwrap().attribute_mutated(attr, mutation);
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
if *attr.local_name() == local_name!("href") {
self.owner_document().refresh_base_element();
}
}
fn bind_to_tree(&self, context: &BindContext) {
self.super_type().unwrap().bind_to_tree(context);
fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
self.super_type().unwrap().bind_to_tree(context, can_gc);
self.bind_unbind(context.tree_is_in_a_document_tree);
}
fn unbind_from_tree(&self, context: &UnbindContext) {
self.super_type().unwrap().unbind_from_tree(context);
fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context, can_gc);
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)
}
fn bind_to_tree(&self, context: &BindContext) {
fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
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 {
@ -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) {
(name, AttributeMutation::Set(_)) if name.starts_with("on") => {
let window = self.owner_window();
@ -218,7 +218,9 @@ impl VirtualMethods for HTMLBodyElement {
};
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)
}
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
self.super_type().unwrap().attribute_mutated(attr, mutation);
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match *attr.local_name() {
local_name!("disabled") => {
let el = self.upcast::<Element>();
@ -261,7 +263,7 @@ impl VirtualMethods for HTMLButtonElement {
}
el.update_sequentially_focusable_status(CanGc::note());
self.validity_state()
.perform_validation_and_update(ValidationFlags::all());
.perform_validation_and_update(ValidationFlags::all(), can_gc);
},
local_name!("type") => match mutation {
AttributeMutation::Set(_) => {
@ -272,32 +274,32 @@ impl VirtualMethods for HTMLButtonElement {
};
self.button_type.set(value);
self.validity_state()
.perform_validation_and_update(ValidationFlags::all());
.perform_validation_and_update(ValidationFlags::all(), can_gc);
},
AttributeMutation::Removed => {
self.button_type.set(ButtonType::Submit);
},
},
local_name!("form") => {
self.form_attribute_mutated(mutation);
self.form_attribute_mutated(mutation, can_gc);
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() {
s.bind_to_tree(context);
s.bind_to_tree(context, can_gc);
}
self.upcast::<Element>()
.check_ancestors_disabled_state_for_form_control();
}
fn unbind_from_tree(&self, context: &UnbindContext) {
self.super_type().unwrap().unbind_from_tree(context);
fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context, can_gc);
let node = self.upcast::<Node>();
let el = self.upcast::<Element>();

View file

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

View file

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

View file

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

View file

@ -499,7 +499,7 @@ impl HTMLElementMethods<crate::DomTypeHolder> for HTMLElement {
let fragment = self.rendered_text_fragment(input, can_gc);
// 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>
@ -542,13 +542,13 @@ impl HTMLElementMethods<crate::DomTypeHolder> for HTMLElement {
// the next text node given next's previous sibling.
if let Some(next_sibling) = next {
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.
if let Some(previous) = previous {
Self::merge_with_the_next_text_node(previous)
Self::merge_with_the_next_text_node(previous, can_gc)
}
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
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>
@ -1039,7 +1040,7 @@ impl HTMLElement {
/// 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
if !node.is::<Text>() {
return;
@ -1063,7 +1064,7 @@ impl HTMLElement {
.expect("Got chars from Text");
// 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)
}
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
self.super_type().unwrap().attribute_mutated(attr, mutation);
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
let element = self.as_element();
match (attr.local_name(), mutation) {
(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() => {
self.form_attribute_mutated(mutation);
self.form_attribute_mutated(mutation, can_gc);
},
// Adding a "disabled" attribute disables an enabled form element.
(&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() {
super_type.bind_to_tree(context);
super_type.bind_to_tree(context, can_gc);
}
let element = self.as_element();
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() {
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

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

View file

@ -712,9 +712,11 @@ impl HTMLFormElement {
result
}
pub(crate) fn update_validity(&self) {
pub(crate) fn update_validity(&self, can_gc: CanGc) {
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>()
.set_state(ElementState::VALID, !is_any_invalid);
@ -1087,7 +1089,7 @@ impl HTMLFormElement {
.iter()
.filter_map(|field| {
if let Some(element) = field.downcast::<Element>() {
if element.is_invalid(true) {
if element.is_invalid(true, can_gc) {
Some(DomRoot::from_ref(element))
} else {
None
@ -1306,17 +1308,17 @@ impl HTMLFormElement {
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 = root.upcast::<Node>();
let mut controls = self.controls.borrow_mut();
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 mut controls = self.controls.borrow_mut();
@ -1332,7 +1334,7 @@ impl HTMLFormElement {
let mut past_names_map = self.past_names_map.borrow_mut();
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.
// '..suppress the running of the reset the form owner algorithm
// 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 node = elem.upcast::<Node>();
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));
}
// 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 node = elem.upcast::<Node>();
let old_owner = self.form_owner();
@ -1558,10 +1560,10 @@ pub(crate) trait FormControl: DomObject {
if old_owner != new_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 {
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
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
fn form_attribute_mutated(&self, mutation: AttributeMutation) {
fn form_attribute_mutated(&self, mutation: AttributeMutation, can_gc: CanGc) {
match mutation {
AttributeMutation::Set(_) => {
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
@ -1616,7 +1618,7 @@ pub(crate) trait FormControl: DomObject {
}
// 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 node = elem.upcast::<Node>();
@ -1628,12 +1630,12 @@ pub(crate) trait FormControl: DomObject {
node.set_flag(NodeFlags::PARSER_ASSOCIATED_FORM_OWNER, false);
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
fn unbind_form_control_from_tree(&self) {
fn unbind_form_control_from_tree(&self, can_gc: CanGc) {
let elem = self.to_element();
let has_form_attr = elem.has_attribute(&local_name!("form"));
let same_subtree = self
@ -1648,7 +1650,7 @@ pub(crate) trait FormControl: DomObject {
// subtree) if it appears later in the tree order. Hence invoke
// reset from here if this control has the form attribute set.
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)
}
fn unbind_from_tree(&self, context: &UnbindContext) {
self.super_type().unwrap().unbind_from_tree(context);
fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context, can_gc);
// Collect the controls to reset because reset_form_owner
// will mutably borrow self.controls
@ -1716,7 +1718,7 @@ impl VirtualMethods for HTMLFormElement {
control
.as_maybe_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) {
self.super_type().unwrap().attribute_mutated(attr, mutation);
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match *attr.local_name() {
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() {
s.bind_to_tree(context);
s.bind_to_tree(context, can_gc);
}
self.relations

View file

@ -132,9 +132,9 @@ impl VirtualMethods for HTMLHeadElement {
fn super_type(&self) -> Option<&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() {
s.bind_to_tree(context);
s.bind_to_tree(context, can_gc);
}
load_script(self);
}

View file

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

View file

@ -1743,13 +1743,15 @@ impl VirtualMethods for HTMLImageElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
}
fn adopting_steps(&self, old_doc: &Document) {
self.super_type().unwrap().adopting_steps(old_doc);
fn adopting_steps(&self, old_doc: &Document, can_gc: CanGc) {
self.super_type().unwrap().adopting_steps(old_doc, can_gc);
self.update_the_image_data(CanGc::note());
}
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
self.super_type().unwrap().attribute_mutated(attr, mutation);
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match attr.local_name() {
&local_name!("src") |
&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") {
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() {
s.bind_to_tree(context);
s.bind_to_tree(context, can_gc);
}
let document = self.owner_document();
if context.tree_connected {
@ -1832,8 +1834,8 @@ impl VirtualMethods for HTMLImageElement {
}
}
fn unbind_from_tree(&self, context: &UnbindContext) {
self.super_type().unwrap().unbind_from_tree(context);
fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context, can_gc);
let document = self.owner_document();
document.unregister_responsive_image(self);

View file

@ -1340,7 +1340,7 @@ impl HTMLInputElementMethods<crate::DomTypeHolder> for HTMLInputElement {
}
self.validity_state()
.perform_validation_and_update(ValidationFlags::all());
.perform_validation_and_update(ValidationFlags::all(), can_gc);
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
Ok(())
}
@ -2322,8 +2322,10 @@ impl VirtualMethods for HTMLInputElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
}
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
self.super_type().unwrap().attribute_mutated(attr, mutation);
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match *attr.local_name() {
local_name!("disabled") => {
let disabled_state = match mutation {
@ -2513,13 +2515,13 @@ impl VirtualMethods for HTMLInputElement {
}
},
local_name!("form") => {
self.form_attribute_mutated(mutation);
self.form_attribute_mutated(mutation, can_gc);
},
_ => {},
}
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 {
@ -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() {
s.bind_to_tree(context);
s.bind_to_tree(context, can_gc);
}
self.upcast::<Element>()
.check_ancestors_disabled_state_for_form_control();
for r in radio_group_iter(self, self.radio_group_name().as_ref()) {
r.validity_state()
.perform_validation_and_update(ValidationFlags::all());
.perform_validation_and_update(ValidationFlags::all(), can_gc);
}
}
fn unbind_from_tree(&self, context: &UnbindContext) {
self.super_type().unwrap().unbind_from_tree(context);
fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context, can_gc);
let node = self.upcast::<Node>();
let el = self.upcast::<Element>();
@ -2568,7 +2570,7 @@ impl VirtualMethods for HTMLInputElement {
}
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
@ -2576,9 +2578,9 @@ impl VirtualMethods for HTMLInputElement {
// Compare:
// https://w3c.github.io/uievents/#default-action
// 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() {
s.handle_event(event);
s.handle_event(event, can_gc);
}
if event.type_() == atom!("click") && !event.DefaultPrevented() {
@ -2679,7 +2681,7 @@ impl VirtualMethods for HTMLInputElement {
}
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
@ -2688,9 +2690,10 @@ impl VirtualMethods for HTMLInputElement {
copy: &Node,
maybe_doc: Option<&Document>,
clone_children: CloneChildrenFlag,
can_gc: CanGc,
) {
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();
elem.value_dirty.set(self.value_dirty.get());
@ -2701,7 +2704,7 @@ impl VirtualMethods for HTMLInputElement {
.borrow_mut()
.set_content(self.textinput.borrow().get_content());
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 value = self.Value();

View file

@ -157,10 +157,12 @@ impl VirtualMethods for HTMLLabelElement {
}
}
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
self.super_type().unwrap().attribute_mutated(attr, mutation);
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
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)
}
fn bind_to_tree(&self, context: &BindContext) {
fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
if let Some(s) = self.super_type() {
s.bind_to_tree(context);
s.bind_to_tree(context, can_gc);
}
self.upcast::<Element>()
.check_ancestors_disabled_state_for_form_control();
}
fn unbind_from_tree(&self, context: &UnbindContext) {
self.super_type().unwrap().unbind_from_tree(context);
fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context, can_gc);
let node = self.upcast::<Node>();
let el = self.upcast::<Element>();

View file

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

View file

@ -1956,9 +1956,9 @@ impl HTMLMediaElement {
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() {
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)
}
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
self.super_type().unwrap().attribute_mutated(attr, mutation);
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match *attr.local_name() {
local_name!("muted") => {
@ -2502,9 +2504,9 @@ impl VirtualMethods for HTMLMediaElement {
},
local_name!("controls") => {
if mutation.new_value(attr).is_some() {
self.render_controls(CanGc::note());
self.render_controls(can_gc);
} 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
fn unbind_from_tree(&self, context: &UnbindContext) {
self.super_type().unwrap().unbind_from_tree(context);
fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context, can_gc);
self.remove_controls();
self.remove_controls(can_gc);
if context.tree_connected {
let task = MediaElementMicrotask::PauseIfNotInDocument {

View file

@ -252,9 +252,9 @@ impl VirtualMethods for HTMLMetaElement {
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() {
s.bind_to_tree(context);
s.bind_to_tree(context, can_gc);
}
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() {
s.attribute_mutated(attr, mutation);
s.attribute_mutated(attr, mutation, can_gc);
}
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() {
s.unbind_from_tree(context);
s.unbind_from_tree(context, can_gc);
}
if context.tree_connected {

View file

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

View file

@ -153,8 +153,10 @@ impl VirtualMethods for HTMLObjectElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
}
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
self.super_type().unwrap().attribute_mutated(attr, mutation);
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match *attr.local_name() {
local_name!("data") => {
if let AttributeMutation::Set(_) = mutation {
@ -162,7 +164,7 @@ impl VirtualMethods for HTMLObjectElement {
}
},
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() {
select
.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)
}
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
self.super_type().unwrap().attribute_mutated(attr, mutation);
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
if attr.local_name() == &local_name!("disabled") {
let disabled_state = match mutation {
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() {
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) {
self.super_type().unwrap().unbind_from_tree(context);
fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context, can_gc);
if let Some(select) = context.parent.downcast::<HTMLSelectElement>() {
select
.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
.upcast::<Node>()
.ancestors()
@ -150,7 +150,7 @@ impl HTMLOptionElement {
{
select
.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.set_selectedness(selected);
option.update_select_validity();
option.update_select_validity(can_gc);
Ok(option)
}
@ -286,7 +286,7 @@ impl HTMLOptionElementMethods<crate::DomTypeHolder> for HTMLOptionElement {
self.dirtiness.set(true);
self.selectedness.set(selected);
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
@ -300,8 +300,10 @@ impl VirtualMethods for HTMLOptionElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
}
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
self.super_type().unwrap().attribute_mutated(attr, mutation);
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match *attr.local_name() {
local_name!("disabled") => {
let el = self.upcast::<Element>();
@ -316,7 +318,7 @@ impl VirtualMethods for HTMLOptionElement {
el.check_parent_disabled_state_for_option();
},
}
self.update_select_validity();
self.update_select_validity(can_gc);
},
local_name!("selected") => {
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() {
s.bind_to_tree(context);
s.bind_to_tree(context, can_gc);
}
self.upcast::<Element>()
.check_parent_disabled_state_for_option();
self.pick_if_selected_and_reset();
self.update_select_validity();
self.update_select_validity(can_gc);
}
fn unbind_from_tree(&self, context: &UnbindContext) {
self.super_type().unwrap().unbind_from_tree(context);
fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context, can_gc);
if let Some(select) = context
.parent
@ -362,7 +364,7 @@ impl VirtualMethods for HTMLOptionElement {
{
select
.validity_state()
.perform_validation_and_update(ValidationFlags::all());
.perform_validation_and_update(ValidationFlags::all(), can_gc);
select.ask_for_reset();
}

View file

@ -117,7 +117,7 @@ impl HTMLOptionsCollectionMethods<crate::DomTypeHolder> for HTMLOptionsCollectio
let node = value.upcast::<Node>();
let root = self.upcast().root_node();
if n >= 0 {
Node::pre_insert(node, &root, None).map(|_| ())
Node::pre_insert(node, &root, None, can_gc).map(|_| ())
} else {
let child = self.upcast().IndexedGetter(index).unwrap();
let child_node = child.upcast::<Node>();
@ -220,7 +220,7 @@ impl HTMLOptionsCollectionMethods<crate::DomTypeHolder> for HTMLOptionsCollectio
};
// 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>

View file

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

View file

@ -1242,8 +1242,10 @@ impl VirtualMethods for HTMLScriptElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
}
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
self.super_type().unwrap().attribute_mutated(attr, mutation);
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
if *attr.local_name() == local_name!("src") {
if let AttributeMutation::Set(_) = mutation {
if !self.parser_inserted.get() && self.upcast::<Node>().is_connected() {
@ -1288,9 +1290,10 @@ impl VirtualMethods for HTMLScriptElement {
copy: &Node,
maybe_doc: Option<&Document>,
clone_children: CloneChildrenFlag,
can_gc: CanGc,
) {
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

View file

@ -356,7 +356,7 @@ impl HTMLSelectElementMethods<crate::DomTypeHolder> for HTMLSelectElement {
}
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
@ -421,12 +421,14 @@ impl VirtualMethods for HTMLSelectElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
}
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
self.super_type().unwrap().attribute_mutated(attr, mutation);
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match *attr.local_name() {
local_name!("required") => {
self.validity_state()
.perform_validation_and_update(ValidationFlags::VALUE_MISSING);
.perform_validation_and_update(ValidationFlags::VALUE_MISSING, can_gc);
},
local_name!("disabled") => {
let el = self.upcast::<Element>();
@ -443,26 +445,26 @@ impl VirtualMethods for HTMLSelectElement {
}
self.validity_state()
.perform_validation_and_update(ValidationFlags::VALUE_MISSING);
.perform_validation_and_update(ValidationFlags::VALUE_MISSING, can_gc);
},
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() {
s.bind_to_tree(context);
s.bind_to_tree(context, can_gc);
}
self.upcast::<Element>()
.check_ancestors_disabled_state_for_form_control();
}
fn unbind_from_tree(&self, context: &UnbindContext) {
self.super_type().unwrap().unbind_from_tree(context);
fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context, can_gc);
let node = self.upcast::<Node>();
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())
}
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();
// 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>
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
self.super_type().unwrap().attribute_mutated(attr, mutation);
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
if attr.local_name() == &local_name!("name") && attr.namespace() == &ns!() {
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() {
s.bind_to_tree(context);
s.bind_to_tree(context, can_gc);
}
if !context.tree_is_in_a_shadow_tree {
@ -500,9 +502,9 @@ impl VirtualMethods for HTMLSlotElement {
.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() {
s.unbind_from_tree(context);
s.unbind_from_tree(context, can_gc);
}
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)
}
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
self.super_type().unwrap().attribute_mutated(attr, mutation);
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match attr.local_name() {
&local_name!("srcset") |
&local_name!("sizes") |
@ -90,8 +92,8 @@ impl VirtualMethods for HTMLSourceElement {
}
/// <https://html.spec.whatwg.org/multipage/#the-source-element:nodes-are-inserted>
fn bind_to_tree(&self, context: &BindContext) {
self.super_type().unwrap().bind_to_tree(context);
fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
self.super_type().unwrap().bind_to_tree(context, can_gc);
let parent = self.upcast::<Node>().GetParentNode().unwrap();
if let Some(media) = parent.downcast::<HTMLMediaElement>() {
media.handle_source_child_insertion(CanGc::note());
@ -103,8 +105,8 @@ impl VirtualMethods for HTMLSourceElement {
);
}
fn unbind_from_tree(&self, context: &UnbindContext) {
self.super_type().unwrap().unbind_from_tree(context);
fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context, can_gc);
if let Some(next_sibling) = context.next_sibling {
let next_sibling_iterator = next_sibling.inclusively_following_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) {
self.super_type().unwrap().bind_to_tree(context);
fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
self.super_type().unwrap().bind_to_tree(context, can_gc);
// https://html.spec.whatwg.org/multipage/#update-a-style-block
// 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() {
s.unbind_from_tree(context);
s.unbind_from_tree(context, can_gc);
}
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() {
s.attribute_mutated(attr, mutation);
s.attribute_mutated(attr, mutation, can_gc);
}
let node = self.upcast::<Node>();

View file

@ -114,6 +114,7 @@ impl HTMLTableElement {
atom: &LocalName,
section: Option<&HTMLTableSectionElement>,
reference_predicate: P,
can_gc: CanGc,
) -> ErrorResult
where
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>();
@ -163,9 +164,9 @@ impl HTMLTableElement {
// https://html.spec.whatwg.org/multipage/#dom-table-deletethead
// 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) {
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
fn SetCaption(&self, new_caption: Option<&HTMLTableCaptionElement>) -> Fallible<()> {
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 {
@ -239,7 +240,7 @@ impl HTMLTableElementMethods<crate::DomTypeHolder> for HTMLTableElement {
// https://html.spec.whatwg.org/multipage/#dom-table-deletecaption
fn DeleteCaption(&self) {
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
fn SetTHead(&self, thead: Option<&HTMLTableSectionElement>) -> ErrorResult {
self.set_first_section_of_type(&local_name!("thead"), thead, |n| {
!n.is::<HTMLTableCaptionElement>() && !n.is::<HTMLTableColElement>()
})
self.set_first_section_of_type(
&local_name!("thead"),
thead,
|n| !n.is::<HTMLTableCaptionElement>() && !n.is::<HTMLTableColElement>(),
CanGc::note(),
)
}
// 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
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
@ -272,20 +276,25 @@ impl HTMLTableElementMethods<crate::DomTypeHolder> for HTMLTableElement {
// https://html.spec.whatwg.org/multipage/#dom-table-tfoot
fn SetTFoot(&self, tfoot: Option<&HTMLTableSectionElement>) -> ErrorResult {
self.set_first_section_of_type(&local_name!("tfoot"), tfoot, |n| {
if n.is::<HTMLTableCaptionElement>() || n.is::<HTMLTableColElement>() {
return false;
}
if n.is::<HTMLTableSectionElement>() {
let name = n.local_name();
if name == &local_name!("thead") || name == &local_name!("tbody") {
self.set_first_section_of_type(
&local_name!("tfoot"),
tfoot,
|n| {
if n.is::<HTMLTableCaptionElement>() || n.is::<HTMLTableColElement>() {
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
@ -295,7 +304,7 @@ impl HTMLTableElementMethods<crate::DomTypeHolder> for HTMLTableElement {
// https://html.spec.whatwg.org/multipage/#dom-table-deletetfoot
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
@ -434,7 +443,7 @@ impl HTMLTableElementMethods<crate::DomTypeHolder> for HTMLTableElement {
}
// 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(())
}
@ -503,8 +512,10 @@ impl VirtualMethods for HTMLTableElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
}
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
self.super_type().unwrap().attribute_mutated(attr, mutation);
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match *attr.local_name() {
local_name!("border") => {
// According to HTML5 § 14.3.9, invalid values map to 1px.

View file

@ -104,13 +104,19 @@ impl HTMLTableRowElementMethods<crate::DomTypeHolder> for HTMLTableRowElement {
index,
|| self.Cells(),
|| HTMLTableCellElement::new(local_name!("td"), None, &node.owner_doc(), None, can_gc),
can_gc,
)
}
// https://html.spec.whatwg.org/multipage/#dom-tr-deletecell
fn DeleteCell(&self, index: i32) -> ErrorResult {
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

View file

@ -77,13 +77,19 @@ impl HTMLTableSectionElementMethods<crate::DomTypeHolder> for HTMLTableSectionEl
index,
|| self.Rows(),
|| HTMLTableRowElement::new(local_name!("tr"), None, &node.owner_doc(), None, can_gc),
can_gc,
)
}
// https://html.spec.whatwg.org/multipage/#dom-tbody-deleterow
fn DeleteRow(&self, index: i32) -> ErrorResult {
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>
fn adopting_steps(&self, old_doc: &Document) {
self.super_type().unwrap().adopting_steps(old_doc);
fn adopting_steps(&self, old_doc: &Document, can_gc: CanGc) {
self.super_type().unwrap().adopting_steps(old_doc, can_gc);
// Step 1.
let doc = self
.owner_document()
.appropriate_template_contents_owner_document(CanGc::note());
// 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>
@ -129,10 +129,11 @@ impl VirtualMethods for HTMLTemplateElement {
copy: &Node,
maybe_doc: Option<&Document>,
clone_children: CloneChildrenFlag,
can_gc: CanGc,
) {
self.super_type()
.unwrap()
.cloning_steps(copy, maybe_doc, clone_children);
.cloning_steps(copy, maybe_doc, clone_children, can_gc);
if clone_children == CloneChildrenFlag::DoNotCloneChildren {
// Step 1.
return;

View file

@ -347,7 +347,7 @@ impl HTMLTextAreaElementMethods<crate::DomTypeHolder> for HTMLTextAreaElement {
}
self.validity_state()
.perform_validation_and_update(ValidationFlags::all());
.perform_validation_and_update(ValidationFlags::all(), CanGc::note());
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
}
@ -468,8 +468,10 @@ impl VirtualMethods for HTMLTextAreaElement {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
}
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
self.super_type().unwrap().attribute_mutated(attr, mutation);
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
match *attr.local_name() {
local_name!("disabled") => {
let el = self.upcast::<Element>();
@ -538,25 +540,25 @@ impl VirtualMethods for HTMLTextAreaElement {
}
},
local_name!("form") => {
self.form_attribute_mutated(mutation);
self.form_attribute_mutated(mutation, can_gc);
},
_ => {},
}
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() {
s.bind_to_tree(context);
s.bind_to_tree(context, can_gc);
}
self.upcast::<Element>()
.check_ancestors_disabled_state_for_form_control();
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 {
@ -576,8 +578,8 @@ impl VirtualMethods for HTMLTextAreaElement {
}
}
fn unbind_from_tree(&self, context: &UnbindContext) {
self.super_type().unwrap().unbind_from_tree(context);
fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context, can_gc);
let node = self.upcast::<Node>();
let el = self.upcast::<Element>();
@ -591,7 +593,7 @@ impl VirtualMethods for HTMLTextAreaElement {
}
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
@ -601,9 +603,10 @@ impl VirtualMethods for HTMLTextAreaElement {
copy: &Node,
maybe_doc: Option<&Document>,
clone_children: CloneChildrenFlag,
can_gc: CanGc,
) {
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();
el.value_dirty.set(self.value_dirty.get());
@ -612,7 +615,7 @@ impl VirtualMethods for HTMLTextAreaElement {
textinput.set_content(self.textinput.borrow().get_content());
}
el.validity_state()
.perform_validation_and_update(ValidationFlags::all());
.perform_validation_and_update(ValidationFlags::all(), can_gc);
}
fn children_changed(&self, mutation: &ChildrenMutation) {
@ -625,9 +628,9 @@ impl VirtualMethods for HTMLTextAreaElement {
}
// 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() {
s.handle_event(event);
s.handle_event(event, can_gc);
}
if event.type_() == atom!("click") && !event.DefaultPrevented() {
@ -691,7 +694,7 @@ impl VirtualMethods for HTMLTextAreaElement {
}
self.validity_state()
.perform_validation_and_update(ValidationFlags::all());
.perform_validation_and_update(ValidationFlags::all(), can_gc);
}
fn pop(&self) {
@ -735,7 +738,11 @@ impl Validatable for HTMLTextAreaElement {
!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 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() {
s.bind_to_tree(context);
s.bind_to_tree(context, can_gc);
}
let node = self.upcast::<Node>();
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)
}
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
self.super_type().unwrap().attribute_mutated(attr, mutation);
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
if attr.local_name() == &local_name!("poster") {
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>> {
let name = self.owner.parsed_name(name);
self.owner
.remove_attribute_by_name(&name)
.remove_attribute_by_name(&name, CanGc::note())
.ok_or(Error::NotFound)
}
@ -91,7 +91,7 @@ impl NamedNodeMapMethods<crate::DomTypeHolder> for NamedNodeMap {
) -> Fallible<DomRoot<Attr>> {
let ns = namespace_from_domstring(namespace);
self.owner
.remove_attribute(&ns, &LocalName::from(local_name))
.remove_attribute(&ns, &LocalName::from(local_name), CanGc::note())
.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.
///
/// 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.prev_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.
debug_assert!(!node.get_flag(NodeFlags::HAS_DIRTY_DESCENDANTS));
vtable_for(&node).bind_to_tree(&BindContext {
tree_connected: parent_is_connected,
tree_is_in_a_document_tree: parent_is_in_a_document_tree,
tree_is_in_a_shadow_tree: parent_in_shadow_tree,
});
vtable_for(&node).bind_to_tree(
&BindContext {
tree_connected: parent_is_connected,
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.
/// <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
const RESET_FLAGS: NodeFlags = NodeFlags::IS_IN_A_DOCUMENT_TREE
.union(NodeFlags::IS_CONNECTED)
@ -356,7 +359,7 @@ impl Node {
// 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,
// 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.
if is_parent_connected {
@ -374,7 +377,7 @@ impl Node {
/// Removes the given child from this node's list of children.
///
/// 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));
self.note_dirty_descendants();
@ -413,7 +416,7 @@ impl Node {
child.parent_node.set(None);
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 {
@ -958,7 +961,7 @@ impl Node {
};
// 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(())
}
@ -983,7 +986,7 @@ impl Node {
.node_from_nodes_and_strings(nodes, can_gc)?;
// 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(())
}
@ -1008,7 +1011,7 @@ impl Node {
parent.ReplaceChild(&node, self)?;
} else {
// 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(())
}
@ -1020,7 +1023,7 @@ impl Node {
let node = doc.node_from_nodes_and_strings(nodes, can_gc)?;
// Step 2.
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>
@ -1040,7 +1043,7 @@ impl Node {
// Step 2.
Node::ensure_pre_insertion_validity(&node, self, None)?;
// Step 3.
Node::replace_all(Some(&node), self);
Node::replace_all(Some(&node), self, can_gc);
Ok(())
}
@ -1185,9 +1188,9 @@ impl Node {
.peekable()
}
pub(crate) fn remove_self(&self) {
pub(crate) fn remove_self(&self, can_gc: CanGc) {
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,
get_items: F,
new_child: G,
_can_gc: CanGc,
) -> Fallible<DomRoot<HTMLElement>>
where
F: Fn() -> DomRoot<HTMLCollection>,
@ -1305,6 +1309,7 @@ impl Node {
index: i32,
get_items: F,
is_delete_type: G,
can_gc: CanGc,
) -> ErrorResult
where
F: Fn() -> DomRoot<HTMLCollection>,
@ -1329,7 +1334,7 @@ impl Node {
},
};
element.upcast::<Node>().remove_self();
element.upcast::<Node>().remove_self(can_gc);
Ok(())
}
@ -2046,7 +2051,7 @@ impl Node {
}
/// <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();
// Step 1. Let oldDocument be nodes node document.
@ -2054,7 +2059,7 @@ impl Node {
old_doc.add_script_and_layout_blocker();
// 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:
if &*old_doc != document {
@ -2089,7 +2094,7 @@ impl Node {
// 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.
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,
parent: &Node,
child: Option<&Node>,
can_gc: CanGc,
) -> Fallible<DomRoot<Node>> {
// Step 1.
Node::ensure_pre_insertion_validity(node, parent, child)?;
@ -2235,7 +2241,7 @@ impl Node {
};
// Step 4.
Node::adopt(node, &parent.owner_document());
Node::adopt(node, &parent.owner_document(), can_gc);
// Step 5.
Node::insert(
@ -2243,6 +2249,7 @@ impl Node {
parent,
reference_child,
SuppressObserver::Unsuppressed,
CanGc::note(),
);
// Step 6.
@ -2255,6 +2262,7 @@ impl Node {
parent: &Node,
child: Option<&Node>,
suppress_observers: SuppressObserver,
can_gc: CanGc,
) {
node.owner_doc().add_script_and_layout_blocker();
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)));
// Step 4.
for kid in &*new_nodes {
Node::remove(kid, node, SuppressObserver::Suppressed);
Node::remove(kid, node, SuppressObserver::Suppressed, can_gc);
}
// Step 5.
vtable_for(node).children_changed(&ChildrenMutation::replace_all(new_nodes.r(), &[]));
@ -2309,7 +2317,7 @@ impl Node {
// Step 7.
for kid in new_nodes {
// 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"
// 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>
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();
// Step 1.
if let Some(node) = node {
Node::adopt(node, &parent.owner_doc());
Node::adopt(node, &parent.owner_doc(), can_gc);
}
// Step 2.
rooted_vec!(let removed_nodes <- parent.children().map(|c| DomRoot::as_traced(&c)));
@ -2429,11 +2437,11 @@ impl Node {
};
// Step 4.
for child in &*removed_nodes {
Node::remove(child, parent, SuppressObserver::Suppressed);
Node::remove(child, parent, SuppressObserver::Suppressed, can_gc);
}
// Step 5.
if let Some(node) = node {
Node::insert(node, parent, None, SuppressObserver::Suppressed);
Node::insert(node, parent, None, SuppressObserver::Suppressed, can_gc);
}
// Step 6.
vtable_for(parent).children_changed(&ChildrenMutation::replace_all(
@ -2456,15 +2464,15 @@ impl Node {
/// <https://dom.spec.whatwg.org/multipage/#string-replace-all>
pub(crate) fn string_replace_all(string: DOMString, parent: &Node, can_gc: CanGc) {
if string.len() == 0 {
Node::replace_all(None, parent);
Node::replace_all(None, parent, can_gc);
} else {
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>
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.
match child.GetParentNode() {
Some(ref node) if &**node != parent => return Err(Error::NotFound),
@ -2473,14 +2481,14 @@ impl Node {
}
// Step 2.
Node::remove(child, parent, SuppressObserver::Unsuppressed);
Node::remove(child, parent, SuppressObserver::Unsuppressed, can_gc);
// Step 3.
Ok(DomRoot::from_ref(child))
}
/// <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();
// Step 2.
@ -2517,7 +2525,7 @@ impl Node {
// Step 7. Remove node from its parent's children.
// 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.
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,
// 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
// result of cloning child with document and the clone children flag set, to copy.
if clone_children == CloneChildrenFlag::CloneChildren {
for child in node.children() {
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?
let _inserted_node =
Node::pre_insert(&child_copy, copy_shadow_root.upcast::<Node>(), None);
let _inserted_node = Node::pre_insert(
&child_copy,
copy_shadow_root.upcast::<Node>(),
None,
can_gc,
);
}
}
}
@ -3115,7 +3127,7 @@ impl NodeMethods<crate::DomTypeHolder> for Node {
};
// Step 3.
Node::replace_all(node.as_deref(), self);
Node::replace_all(node.as_deref(), self, can_gc);
},
NodeTypeId::Attr => {
let attr = self.downcast::<Attr>().unwrap();
@ -3131,12 +3143,12 @@ impl NodeMethods<crate::DomTypeHolder> for Node {
/// <https://dom.spec.whatwg.org/#dom-node-insertbefore>
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>
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>
@ -3238,11 +3250,11 @@ impl NodeMethods<crate::DomTypeHolder> for Node {
// Step 10.
let document = self.owner_document();
Node::adopt(node, &document);
Node::adopt(node, &document, CanGc::note());
let removed_child = if node != child {
// Step 11.
Node::remove(child, self, SuppressObserver::Suppressed);
Node::remove(child, self, SuppressObserver::Suppressed, CanGc::note());
Some(child)
} else {
None
@ -3261,7 +3273,13 @@ impl NodeMethods<crate::DomTypeHolder> for Node {
};
// Step 13.
Node::insert(node, self, reference_child, SuppressObserver::Suppressed);
Node::insert(
node,
self,
reference_child,
SuppressObserver::Suppressed,
CanGc::note(),
);
// Step 14.
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>
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>
@ -3297,7 +3315,7 @@ impl NodeMethods<crate::DomTypeHolder> for Node {
let cdata = text.upcast::<CharacterData>();
let mut length = cdata.Length();
if length == 0 {
Node::remove(&node, self, SuppressObserver::Unsuppressed);
Node::remove(&node, self, SuppressObserver::Unsuppressed, CanGc::note());
continue;
}
while children
@ -3313,7 +3331,12 @@ impl NodeMethods<crate::DomTypeHolder> for Node {
let sibling_cdata = sibling.downcast::<CharacterData>().unwrap();
length += sibling_cdata.Length();
cdata.append_data(&sibling_cdata.data());
Node::remove(&sibling, self, SuppressObserver::Unsuppressed);
Node::remove(
&sibling,
self,
SuppressObserver::Unsuppressed,
CanGc::note(),
);
}
} else {
node.Normalize();
@ -3726,8 +3749,8 @@ impl VirtualMethods for Node {
// This handles the ranges mentioned in steps 2-3 when removing a node.
/// <https://dom.spec.whatwg.org/#concept-node-remove>
fn unbind_from_tree(&self, context: &UnbindContext) {
self.super_type().unwrap().unbind_from_tree(context);
fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
self.super_type().unwrap().unbind_from_tree(context, can_gc);
if !self.ranges_is_empty() {
self.ranges().drain_to_parent(context, self);
}

View file

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

View file

@ -713,7 +713,7 @@ where
fn next(&mut self) -> Option<DomRoot<Node>> {
let next = self.inner.next()?;
next.remove_self();
next.remove_self(CanGc::note());
Some(next)
}
@ -1264,7 +1264,7 @@ impl TreeSink for Sink {
let control = elem.and_then(|e| e.as_maybe_form_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);
let node = self.upcast::<Node>();
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);
}
@ -221,7 +221,7 @@ impl ShadowRoot {
/// Remove any existing association between the provided id and any elements
/// 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_fragment.id_map(),
to_unregister,
@ -230,7 +230,7 @@ impl ShadowRoot {
}
/// 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
.upcast::<Node>()
.inclusive_ancestors(ShadowIncluding::No)
@ -445,7 +445,7 @@ impl ShadowRootMethods<crate::DomTypeHolder> for ShadowRoot {
};
// 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>
@ -462,9 +462,9 @@ impl VirtualMethods for ShadowRoot {
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() {
s.bind_to_tree(context);
s.bind_to_tree(context, can_gc);
}
if context.tree_connected {
@ -482,17 +482,20 @@ impl VirtualMethods for ShadowRoot {
// Out-of-document elements never have the descendants flag set
debug_assert!(!node.get_flag(NodeFlags::HAS_DIRTY_DESCENDANTS));
vtable_for(&node).bind_to_tree(&BindContext {
tree_connected: context.tree_connected,
tree_is_in_a_document_tree: false,
tree_is_in_a_shadow_tree: true,
});
vtable_for(&node).bind_to_tree(
&BindContext {
tree_connected: context.tree_connected,
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() {
s.unbind_from_tree(context);
s.unbind_from_tree(context, can_gc);
}
if context.tree_connected {

View file

@ -79,8 +79,10 @@ impl VirtualMethods for SVGSVGElement {
Some(self.upcast::<SVGGraphicsElement>() as &dyn VirtualMethods)
}
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
self.super_type().unwrap().attribute_mutated(attr, mutation);
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
self.super_type()
.unwrap()
.attribute_mutated(attr, mutation, can_gc);
}
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;
// 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()
}

View file

@ -107,7 +107,7 @@ impl ValidityState {
// https://html.spec.whatwg.org/multipage/#custom-validity-error-message
pub(crate) fn set_custom_error_message(&self, error: DOMString) {
*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
@ -115,12 +115,16 @@ impl ValidityState {
/// if [ValidationFlags::CUSTOM_ERROR] is in `update_flags` and a custom
/// error has been set on this [ValidityState], the state will be updated
/// 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();
invalid_flags.remove(update_flags);
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);
}
@ -132,7 +136,7 @@ impl ValidityState {
}
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) {
@ -143,7 +147,7 @@ impl ValidityState {
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() {
let is_valid = self.invalid_flags.get().is_empty();
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_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>)
.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/. */
use html5ever::LocalName;
use script_bindings::script_runtime::CanGc;
use style::attr::AttrValue;
use crate::dom::attr::Attr;
@ -72,9 +73,9 @@ pub(crate) trait VirtualMethods {
/// Called when attributes of a node are mutated.
/// <https://dom.spec.whatwg.org/#attribute-is-set>
/// <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() {
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
/// 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() {
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.
/// Implements removing steps:
/// <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() {
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.
fn handle_event(&self, event: &Event) {
fn handle_event(&self, event: &Event, can_gc: CanGc) {
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>
fn adopting_steps(&self, old_doc: &Document) {
fn adopting_steps(&self, old_doc: &Document, can_gc: CanGc) {
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,
maybe_doc: Option<&Document>,
clone_children: CloneChildrenFlag,
can_gc: CanGc,
) {
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) => {
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) => {
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,
pipeline: PipelineId,
reply: IpcSender<ServoUrl>,
_can_gc: CanGc,
) {
reply
.send(