diff --git a/boa_engine/src/object/shape/shared_shape/forward_transition.rs b/boa_engine/src/object/shape/shared_shape/forward_transition.rs index ba9c9488c83..6eaf32fa281 100644 --- a/boa_engine/src/object/shape/shared_shape/forward_transition.rs +++ b/boa_engine/src/object/shape/shared_shape/forward_transition.rs @@ -55,4 +55,24 @@ impl ForwardTransition { }; transitions.get(key).cloned() } + + /// Prunes the [`WeakGc`]s that have been garbage collected. + pub(super) fn prune_property_transitions(&self) { + let mut this = self.inner.borrow_mut(); + let Some(transitions) = this.properties.as_deref_mut() else { + return; + }; + + transitions.retain(|_, v| v.is_upgradable()); + } + + /// Prunes the [`WeakGc`]s that have been garbage collected. + pub(super) fn prune_prototype_transitions(&self) { + let mut this = self.inner.borrow_mut(); + let Some(transitions) = this.prototypes.as_deref_mut() else { + return; + }; + + transitions.retain(|_, v| v.is_upgradable()); + } } diff --git a/boa_engine/src/object/shape/shared_shape/mod.rs b/boa_engine/src/object/shape/shared_shape/mod.rs index 0da7b69b479..3c702639ef0 100644 --- a/boa_engine/src/object/shape/shared_shape/mod.rs +++ b/boa_engine/src/object/shape/shared_shape/mod.rs @@ -192,6 +192,8 @@ impl SharedShape { if let Some(inner) = shape.upgrade() { return Self { inner }; } + + self.forward_transitions().prune_prototype_transitions(); } let new_inner_shape = Inner { forward_transitions: ForwardTransition::default(), @@ -217,6 +219,8 @@ impl SharedShape { if let Some(inner) = shape.upgrade() { return Self { inner }; } + + self.forward_transitions().prune_property_transitions(); } let property_table = self.property_table().add_property_deep_clone_if_needed( @@ -266,6 +270,8 @@ impl SharedShape { action, }; } + + self.forward_transitions().prune_property_transitions(); } // The attribute change transitions, didn't change from accessor to data property or vice-versa. diff --git a/boa_gc/src/pointers/ephemeron.rs b/boa_gc/src/pointers/ephemeron.rs index c63da65fd72..f7dfd50a47c 100644 --- a/boa_gc/src/pointers/ephemeron.rs +++ b/boa_gc/src/pointers/ephemeron.rs @@ -31,6 +31,13 @@ impl Ephemeron { // `inner_ptr`. unsafe { self.inner_ptr.get().as_ref().value().cloned() } } + + /// Checks if the [`Ephemeron`] has a value. + pub fn has_value(&self) -> bool { + // SAFETY: this is safe because `Ephemeron` is tracked to always point to a valid pointer + // `inner_ptr`. + unsafe { self.inner_ptr.get().as_ref().value().is_some() } + } } impl Ephemeron { diff --git a/boa_gc/src/pointers/weak.rs b/boa_gc/src/pointers/weak.rs index edeadd7add3..6bbb9762d39 100644 --- a/boa_gc/src/pointers/weak.rs +++ b/boa_gc/src/pointers/weak.rs @@ -23,6 +23,11 @@ impl WeakGc { pub fn upgrade(&self) -> Option> { self.inner.value() } + + /// Check if the [`WeakGc`] can be upgraded. + pub fn is_upgradable(&self) -> bool { + self.inner.has_value() + } } impl Clone for WeakGc {