Fix GC borrow hazard in XRInputSourceArray (#33857)

Signed-off-by: L Ashwin B <lashwinib@gmail.com>
This commit is contained in:
chickenleaf 2024-10-16 16:38:31 +05:30 committed by GitHub
parent fa1f7e5839
commit 2e0fbfcb95
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -36,7 +36,6 @@ impl XRInputSourceArray {
} }
pub fn add_input_sources(&self, session: &XRSession, inputs: &[InputSource], can_gc: CanGc) { pub fn add_input_sources(&self, session: &XRSession, inputs: &[InputSource], can_gc: CanGc) {
let mut input_sources = self.input_sources.borrow_mut();
let global = self.global(); let global = self.global();
let mut added = vec![]; let mut added = vec![];
@ -44,11 +43,15 @@ impl XRInputSourceArray {
// This is quadratic, but won't be a problem for the only case // This is quadratic, but won't be a problem for the only case
// where we add multiple input sources (the initial input sources case) // where we add multiple input sources (the initial input sources case)
debug_assert!( debug_assert!(
!input_sources.iter().any(|i| i.id() == info.id), !self
.input_sources
.borrow()
.iter()
.any(|i| i.id() == info.id),
"Should never add a duplicate input id!" "Should never add a duplicate input id!"
); );
let input = XRInputSource::new(&global, session, info.clone(), can_gc); let input = XRInputSource::new(&global, session, info.clone(), can_gc);
input_sources.push(Dom::from_ref(&input)); self.input_sources.borrow_mut().push(Dom::from_ref(&input));
added.push(input); added.push(input);
} }
@ -62,15 +65,12 @@ impl XRInputSourceArray {
&[], &[],
can_gc, can_gc,
); );
// Release the refcell guard
drop(input_sources);
event.upcast::<Event>().fire(session.upcast()); event.upcast::<Event>().fire(session.upcast());
} }
pub fn remove_input_source(&self, session: &XRSession, id: InputId, can_gc: CanGc) { pub fn remove_input_source(&self, session: &XRSession, id: InputId, can_gc: CanGc) {
let mut input_sources = self.input_sources.borrow_mut();
let global = self.global(); let global = self.global();
let removed = if let Some(i) = input_sources.iter().find(|i| i.id() == id) { let removed = if let Some(i) = self.input_sources.borrow().iter().find(|i| i.id() == id) {
i.gamepad().update_connected(false, false); i.gamepad().update_connected(false, false);
[DomRoot::from_ref(&**i)] [DomRoot::from_ref(&**i)]
} else { } else {
@ -87,9 +87,7 @@ impl XRInputSourceArray {
&removed, &removed,
can_gc, can_gc,
); );
input_sources.retain(|i| i.id() != id); self.input_sources.borrow_mut().retain(|i| i.id() != id);
// release the refcell guard
drop(input_sources);
event.upcast::<Event>().fire(session.upcast()); event.upcast::<Event>().fire(session.upcast());
} }
@ -100,10 +98,9 @@ impl XRInputSourceArray {
info: InputSource, info: InputSource,
can_gc: CanGc, can_gc: CanGc,
) { ) {
let mut input_sources = self.input_sources.borrow_mut();
let global = self.global(); let global = self.global();
let root; let root;
let removed = if let Some(i) = input_sources.iter().find(|i| i.id() == id) { let removed = if let Some(i) = self.input_sources.borrow().iter().find(|i| i.id() == id) {
i.gamepad().update_connected(false, false); i.gamepad().update_connected(false, false);
root = [DomRoot::from_ref(&**i)]; root = [DomRoot::from_ref(&**i)];
&root as &[_] &root as &[_]
@ -111,9 +108,9 @@ impl XRInputSourceArray {
warn!("Could not find removed input source with id {:?}", id); warn!("Could not find removed input source with id {:?}", id);
&[] &[]
}; };
input_sources.retain(|i| i.id() != id); self.input_sources.borrow_mut().retain(|i| i.id() != id);
let input = XRInputSource::new(&global, session, info, can_gc); let input = XRInputSource::new(&global, session, info, can_gc);
input_sources.push(Dom::from_ref(&input)); self.input_sources.borrow_mut().push(Dom::from_ref(&input));
let added = [input]; let added = [input];
@ -127,8 +124,6 @@ impl XRInputSourceArray {
removed, removed,
can_gc, can_gc,
); );
// release the refcell guard
drop(input_sources);
event.upcast::<Event>().fire(session.upcast()); event.upcast::<Event>().fire(session.upcast());
} }