mirror of
https://github.com/servo/servo.git
synced 2025-08-02 20:20:14 +01:00
Fix an issue with the rooting of animating nodes
Make sure nodes removed from map of rooted animating nodes are rooted on the stack before triggering event handlers. We also make sure not to call `from_untrusted_node_address` on nodes that aren't guaranteed to be rooted. Fixes #26498.
This commit is contained in:
parent
c5617efff0
commit
c4a38beee4
1 changed files with 10 additions and 9 deletions
|
@ -2976,13 +2976,10 @@ impl ScriptThread {
|
||||||
///
|
///
|
||||||
/// TODO(mrobinson): Add support for more events.
|
/// TODO(mrobinson): Add support for more events.
|
||||||
fn handle_transition_or_animation_event(&self, event: &TransitionOrAnimationEvent) {
|
fn handle_transition_or_animation_event(&self, event: &TransitionOrAnimationEvent) {
|
||||||
let js_runtime = self.js_runtime.rt();
|
// We limit the scope of the borrow here so that we aren't holding it when
|
||||||
let node = unsafe { from_untrusted_node_address(js_runtime, event.node) };
|
// sending events. Event handlers may trigger another layout, resulting in
|
||||||
|
// a double mutable borrow of `animating_nodes`.
|
||||||
// We limit the scope of the borrow here, so that we don't maintain this borrow
|
let node = {
|
||||||
// and then incidentally trigger another layout. That might result in a double
|
|
||||||
// mutable borrow of `animating_nodes`.
|
|
||||||
{
|
|
||||||
let mut animating_nodes = self.animating_nodes.borrow_mut();
|
let mut animating_nodes = self.animating_nodes.borrow_mut();
|
||||||
let nodes = match animating_nodes.get_mut(&event.pipeline_id) {
|
let nodes = match animating_nodes.get_mut(&event.pipeline_id) {
|
||||||
Some(nodes) => nodes,
|
Some(nodes) => nodes,
|
||||||
|
@ -2995,7 +2992,7 @@ impl ScriptThread {
|
||||||
|
|
||||||
let node_index = nodes
|
let node_index = nodes
|
||||||
.iter()
|
.iter()
|
||||||
.position(|n| &**n as *const _ == &*node as *const _);
|
.position(|n| n.to_untrusted_node_address() == event.node);
|
||||||
let node_index = match node_index {
|
let node_index = match node_index {
|
||||||
Some(node_index) => node_index,
|
Some(node_index) => node_index,
|
||||||
None => {
|
None => {
|
||||||
|
@ -3006,10 +3003,14 @@ impl ScriptThread {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// We need to root the node now, because if we remove it from the map
|
||||||
|
// a garbage collection might clean it up while we are sending events.
|
||||||
|
let node = DomRoot::from_ref(&*nodes[node_index]);
|
||||||
if event.event_type.finalizes_transition_or_animation() {
|
if event.event_type.finalizes_transition_or_animation() {
|
||||||
nodes.remove(node_index);
|
nodes.remove(node_index);
|
||||||
}
|
}
|
||||||
}
|
node
|
||||||
|
};
|
||||||
|
|
||||||
let event_atom = match event.event_type {
|
let event_atom = match event.event_type {
|
||||||
TransitionOrAnimationEventType::AnimationEnd => atom!("animationend"),
|
TransitionOrAnimationEventType::AnimationEnd => atom!("animationend"),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue