diff options
-rw-r--r-- | components/layout/layout_task.rs | 7 | ||||
-rw-r--r-- | components/layout/wrapper.rs | 6 | ||||
-rw-r--r-- | components/script/dom/document.rs | 31 | ||||
-rw-r--r-- | components/script/dom/element.rs | 5 | ||||
-rw-r--r-- | components/style/restyle_hints.rs | 5 | ||||
-rw-r--r-- | components/style/selector_matching.rs | 4 |
6 files changed, 23 insertions, 35 deletions
diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs index 7a615b02f6b..bdf1b613562 100644 --- a/components/layout/layout_task.rs +++ b/components/layout/layout_task.rs @@ -1213,13 +1213,12 @@ impl LayoutTask { } } - let state_changes = document.drain_element_state_changes(); + let modified_elements = document.drain_modified_elements(); if !needs_dirtying { - for &(el, state_change) in state_changes.iter() { - debug_assert!(!state_change.is_empty()); + for &(el, old_state) in modified_elements.iter() { let hint = rw_data.stylist.restyle_hint_for_state_change(&el, el.get_state(), - state_change); + old_state); el.note_restyle_hint(hint); } } diff --git a/components/layout/wrapper.rs b/components/layout/wrapper.rs index 04d3470fb64..ae8462426e8 100644 --- a/components/layout/wrapper.rs +++ b/components/layout/wrapper.rs @@ -375,10 +375,10 @@ impl<'le> LayoutDocument<'le> { self.as_node().children().find(LayoutNode::is_element) } - pub fn drain_element_state_changes(&self) -> Vec<(LayoutElement, ElementState)> { + pub fn drain_modified_elements(&self) -> Vec<(LayoutElement, ElementState)> { unsafe { - let changes = self.document.drain_element_state_changes(); - Vec::from_iter(changes.iter().map(|&(el, state)| + let elements = self.document.drain_modified_elements(); + Vec::from_iter(elements.iter().map(|&(el, state)| (LayoutElement { element: el, chain: PhantomData, diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 90e5697dd33..161a5639ceb 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -175,8 +175,8 @@ pub struct Document { /// This field is set to the document itself for inert documents. /// https://html.spec.whatwg.org/multipage/#appropriate-template-contents-owner-document appropriate_template_contents_owner_document: MutNullableHeap<JS<Document>>, - /// The collection of ElementStates that have been changed since the last restyle. - element_state_changes: DOMRefCell<HashMap<JS<Element>, ElementState>>, + /// For each element that has had a state change since the last restyle, track the original state. + modified_elements: DOMRefCell<HashMap<JS<Element>, ElementState>>, /// http://w3c.github.io/touch-events/#dfn-active-touch-point active_touch_points: DOMRefCell<Vec<JS<Touch>>>, } @@ -308,7 +308,7 @@ impl Document { pub fn needs_reflow(&self) -> bool { self.GetDocumentElement().is_some() && - (self.upcast::<Node>().get_has_dirty_descendants() || !self.element_state_changes.borrow().is_empty()) + (self.upcast::<Node>().get_has_dirty_descendants() || !self.modified_elements.borrow().is_empty()) } /// Returns the first `base` element in the DOM that has an `href` attribute. @@ -1230,7 +1230,7 @@ pub enum DocumentSource { #[allow(unsafe_code)] pub trait LayoutDocumentHelpers { unsafe fn is_html_document_for_layout(&self) -> bool; - unsafe fn drain_element_state_changes(&self) -> Vec<(LayoutJS<Element>, ElementState)>; + unsafe fn drain_modified_elements(&self) -> Vec<(LayoutJS<Element>, ElementState)>; } #[allow(unsafe_code)] @@ -1242,9 +1242,9 @@ impl LayoutDocumentHelpers for LayoutJS<Document> { #[inline] #[allow(unrooted_must_root)] - unsafe fn drain_element_state_changes(&self) -> Vec<(LayoutJS<Element>, ElementState)> { - let mut changes = (*self.unsafe_get()).element_state_changes.borrow_mut_for_layout(); - let drain = changes.drain(); + unsafe fn drain_modified_elements(&self) -> Vec<(LayoutJS<Element>, ElementState)> { + let mut elements = (*self.unsafe_get()).modified_elements.borrow_mut_for_layout(); + let drain = elements.drain(); let layout_drain = drain.map(|(k, v)| (k.to_layout(), v)); Vec::from_iter(layout_drain) } @@ -1313,7 +1313,7 @@ impl Document { reflow_timeout: Cell::new(None), base_element: Default::default(), appropriate_template_contents_owner_document: Default::default(), - element_state_changes: DOMRefCell::new(HashMap::new()), + modified_elements: DOMRefCell::new(HashMap::new()), active_touch_points: DOMRefCell::new(Vec::new()), } } @@ -1380,18 +1380,9 @@ impl Document { self.idmap.borrow().get(&id).map(|ref elements| Root::from_ref(&*(*elements)[0])) } - pub fn record_element_state_change(&self, el: &Element, which: ElementState) { - let mut map = self.element_state_changes.borrow_mut(); - let empty; - { - let states = map.entry(JS::from_ref(el)) - .or_insert(ElementState::empty()); - states.toggle(which); - empty = states.is_empty(); - } - if empty { - map.remove(&JS::from_ref(el)); - } + pub fn element_state_will_change(&self, el: &Element) { + let mut map = self.modified_elements.borrow_mut(); + map.entry(JS::from_ref(el)).or_insert(el.get_state()); } } diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 7d605ecd133..d420e9b5405 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -1814,14 +1814,13 @@ impl Element { if state.contains(which) == value { return } + let node = self.upcast::<Node>(); + node.owner_doc().element_state_will_change(self); match value { true => state.insert(which), false => state.remove(which), }; self.state.set(state); - - let node = self.upcast::<Node>(); - node.owner_doc().record_element_state_change(self, which); } pub fn get_active_state(&self) -> bool { diff --git a/components/style/restyle_hints.rs b/components/style/restyle_hints.rs index fe143c3e315..c180c13dcde 100644 --- a/components/style/restyle_hints.rs +++ b/components/style/restyle_hints.rs @@ -195,11 +195,10 @@ impl StateDependencySet { StateDependencySet { deps: Vec::new() } } - pub fn compute_hint<E>(&self, el: &E, current_state: ElementState, state_changes: ElementState) + pub fn compute_hint<E>(&self, el: &E, current_state: ElementState, old_state: ElementState) -> RestyleHint where E: Element, E: Clone { let mut hint = RestyleHint::empty(); - let mut old_state = current_state; - old_state.toggle(state_changes); + let state_changes = current_state ^ old_state; for dep in &self.deps { if state_changes.intersects(dep.state) { let old_el: ElementWrapper<E> = ElementWrapper::new_with_override(el.clone(), old_state); diff --git a/components/style/selector_matching.rs b/components/style/selector_matching.rs index 53f1a0d3589..8cc56e693eb 100644 --- a/components/style/selector_matching.rs +++ b/components/style/selector_matching.rs @@ -174,10 +174,10 @@ impl Stylist { pub fn restyle_hint_for_state_change<E>(&self, element: &E, current_state: ElementState, - state_change: ElementState) + old_state: ElementState) -> RestyleHint where E: Element + Clone { - self.state_deps.compute_hint(element, current_state, state_change) + self.state_deps.compute_hint(element, current_state, old_state) } pub fn set_device(&mut self, device: Device) { |