From c113fbb64015deff22a3a0a5ccc5cb12fb0cb7d9 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 18 Apr 2020 12:10:09 +0200 Subject: [PATCH] Always upgrade existing weak child references in the rule tree Just because we didn't find a child when read-locking a node children list doesn't mean it still won't exist while we wait to upgrade the read lock into a write lock to create the child. --- components/style/rule_tree/core.rs | 37 ++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/components/style/rule_tree/core.rs b/components/style/rule_tree/core.rs index 2c11868201a..ab389aa4e31 100644 --- a/components/style/rule_tree/core.rs +++ b/components/style/rule_tree/core.rs @@ -402,18 +402,31 @@ impl StrongRuleNode { return child.upgrade(); } let mut children = RwLockUpgradableReadGuard::upgrade(children); - let weak = children.get_or_insert_with( - key, - |node| node.p.key(), - move || { - let root = unsafe { root.downgrade() }; - let strong = - StrongRuleNode::new(Box::new(RuleNode::new(root, self.clone(), source, level))); - let weak = unsafe { strong.downgrade() }; - mem::forget(strong); - weak - }, - ); + let mut is_new = false; + let weak = { + let is_new = &mut is_new; + children.get_or_insert_with( + key, + |node| node.p.key(), + move || { + *is_new = true; + let root = unsafe { root.downgrade() }; + let strong = StrongRuleNode::new(Box::new(RuleNode::new( + root, + self.clone(), + source, + level, + ))); + let weak = unsafe { strong.downgrade() }; + mem::forget(strong); + weak + }, + ) + }; + + if !is_new { + return weak.upgrade(); + } unsafe { StrongRuleNode::from_unsafe_box(UnsafeBox::clone(&weak.p)) } }