mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
Don't fire slotchange events when there's already a pending event for the same slot (#35222)
* Don't fire slotchange events if there is already a pending event for the same slot Signed-off-by: Simon Wülker <simon.wuelker@arcor.de> * Update WPT expectations Signed-off-by: Simon Wülker <simon.wuelker@arcor.de> --------- Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
This commit is contained in:
parent
5e9de2cb61
commit
64b40ea700
4 changed files with 33 additions and 49 deletions
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::{Cell, RefCell};
|
||||||
|
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use html5ever::{local_name, namespace_url, ns, LocalName, Prefix};
|
use html5ever::{local_name, namespace_url, ns, LocalName, Prefix};
|
||||||
|
@ -26,6 +26,7 @@ use crate::dom::document::Document;
|
||||||
use crate::dom::element::{AttributeMutation, Element};
|
use crate::dom::element::{AttributeMutation, Element};
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::htmlelement::HTMLElement;
|
use crate::dom::htmlelement::HTMLElement;
|
||||||
|
use crate::dom::mutationobserver::MutationObserver;
|
||||||
use crate::dom::node::{Node, ShadowIncluding};
|
use crate::dom::node::{Node, ShadowIncluding};
|
||||||
use crate::dom::text::Text;
|
use crate::dom::text::Text;
|
||||||
use crate::dom::virtualmethods::VirtualMethods;
|
use crate::dom::virtualmethods::VirtualMethods;
|
||||||
|
@ -42,6 +43,11 @@ pub struct HTMLSlotElement {
|
||||||
|
|
||||||
/// <https://html.spec.whatwg.org/multipage/#manually-assigned-nodes>
|
/// <https://html.spec.whatwg.org/multipage/#manually-assigned-nodes>
|
||||||
manually_assigned_nodes: RefCell<Vec<Slottable>>,
|
manually_assigned_nodes: RefCell<Vec<Slottable>>,
|
||||||
|
|
||||||
|
/// Whether there is a queued signal change for this element
|
||||||
|
///
|
||||||
|
/// Necessary to avoid triggering too many slotchange events
|
||||||
|
is_in_agents_signal_slots: Cell<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HTMLSlotElementMethods<crate::DomTypeHolder> for HTMLSlotElement {
|
impl HTMLSlotElementMethods<crate::DomTypeHolder> for HTMLSlotElement {
|
||||||
|
@ -165,6 +171,7 @@ impl HTMLSlotElement {
|
||||||
htmlelement: HTMLElement::new_inherited(local_name, prefix, document),
|
htmlelement: HTMLElement::new_inherited(local_name, prefix, document),
|
||||||
assigned_nodes: Default::default(),
|
assigned_nodes: Default::default(),
|
||||||
manually_assigned_nodes: Default::default(),
|
manually_assigned_nodes: Default::default(),
|
||||||
|
is_in_agents_signal_slots: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,7 +326,7 @@ impl HTMLSlotElement {
|
||||||
// then run signal a slot change for slot.
|
// then run signal a slot change for slot.
|
||||||
let slots_are_identical = self.assigned_nodes.borrow().iter().eq(slottables.iter());
|
let slots_are_identical = self.assigned_nodes.borrow().iter().eq(slottables.iter());
|
||||||
if !slots_are_identical {
|
if !slots_are_identical {
|
||||||
ScriptThread::signal_a_slot_change(self);
|
self.signal_a_slot_change();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 3. Set slot’s assigned nodes to slottables.
|
// Step 3. Set slot’s assigned nodes to slottables.
|
||||||
|
@ -330,6 +337,25 @@ impl HTMLSlotElement {
|
||||||
slottable.set_assigned_slot(DomRoot::from_ref(self));
|
slottable.set_assigned_slot(DomRoot::from_ref(self));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <https://dom.spec.whatwg.org/#signal-a-slot-change>
|
||||||
|
pub(crate) fn signal_a_slot_change(&self) {
|
||||||
|
if self.is_in_agents_signal_slots.get() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.is_in_agents_signal_slots.set(true);
|
||||||
|
|
||||||
|
// Step 1. Append slot to slot’s relevant agent’s signal slots.
|
||||||
|
ScriptThread::add_signal_slot(self);
|
||||||
|
|
||||||
|
// Step 2. Queue a mutation observer microtask.
|
||||||
|
MutationObserver::queue_mutation_observer_microtask();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn remove_from_signal_slots(&self) {
|
||||||
|
debug_assert!(self.is_in_agents_signal_slots.get());
|
||||||
|
self.is_in_agents_signal_slots.set(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Slottable {
|
impl Slottable {
|
||||||
|
|
|
@ -2171,7 +2171,7 @@ impl Node {
|
||||||
if parent.is_in_a_shadow_tree() {
|
if parent.is_in_a_shadow_tree() {
|
||||||
if let Some(slot_element) = parent.downcast::<HTMLSlotElement>() {
|
if let Some(slot_element) = parent.downcast::<HTMLSlotElement>() {
|
||||||
if !slot_element.has_assigned_nodes() {
|
if !slot_element.has_assigned_nodes() {
|
||||||
ScriptThread::signal_a_slot_change(slot_element);
|
slot_element.signal_a_slot_change();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2373,7 +2373,7 @@ impl Node {
|
||||||
if parent.is_in_a_shadow_tree() {
|
if parent.is_in_a_shadow_tree() {
|
||||||
if let Some(slot_element) = parent.downcast::<HTMLSlotElement>() {
|
if let Some(slot_element) = parent.downcast::<HTMLSlotElement>() {
|
||||||
if !slot_element.has_assigned_nodes() {
|
if !slot_element.has_assigned_nodes() {
|
||||||
ScriptThread::signal_a_slot_change(slot_element);
|
slot_element.signal_a_slot_change();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -529,6 +529,9 @@ impl ScriptThread {
|
||||||
.signal_slots
|
.signal_slots
|
||||||
.take()
|
.take()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
.inspect(|slot| {
|
||||||
|
slot.remove_from_signal_slots();
|
||||||
|
})
|
||||||
.map(|slot| slot.as_rooted())
|
.map(|slot| slot.as_rooted())
|
||||||
.collect()
|
.collect()
|
||||||
})
|
})
|
||||||
|
@ -3746,15 +3749,6 @@ impl ScriptThread {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://dom.spec.whatwg.org/#signal-a-slot-change>
|
|
||||||
pub(crate) fn signal_a_slot_change(slot: &HTMLSlotElement) {
|
|
||||||
// Step 1. Append slot to slot’s relevant agent’s signal slots.
|
|
||||||
ScriptThread::add_signal_slot(slot);
|
|
||||||
|
|
||||||
// Step 2. Queue a mutation observer microtask.
|
|
||||||
MutationObserver::queue_mutation_observer_microtask();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for ScriptThread {
|
impl Drop for ScriptThread {
|
||||||
|
|
|
@ -1,40 +1,4 @@
|
||||||
[slotchange-event.html]
|
[slotchange-event.html]
|
||||||
[slotchange event must fire on a default slot element inside an open shadow root in a document]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[slotchange event must fire on a default slot element inside a closed shadow root in a document]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[slotchange event must fire on a default slot element inside an open shadow root not in a document]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[slotchange event must fire on a default slot element inside a closed shadow root not in a document]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[slotchange event must fire on a named slot element insidean open shadow root in a document]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[slotchange event must fire on a named slot element insidea closed shadow root in a document]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[slotchange event must fire on a named slot element insidean open shadow root not in a document]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[slotchange event must fire on a named slot element insidea closed shadow root not in a document]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[slotchange event must fire on a slot element inside an open shadow root in a document even if the slot was removed immediately after the assigned nodes were mutated]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[slotchange event must fire on a slot element inside a closed shadow root in a document even if the slot was removed immediately after the assigned nodes were mutated]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[slotchange event must fire on a slot element inside an open shadow root not in a document even if the slot was removed immediately after the assigned nodes were mutated]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[slotchange event must fire on a slot element inside a closed shadow root not in a document even if the slot was removed immediately after the assigned nodes were mutated]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[slotchange event must fire on a slot element inside an open shadow root in a document when innerHTML modifies the children of the shadow host]
|
[slotchange event must fire on a slot element inside an open shadow root in a document when innerHTML modifies the children of the shadow host]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue