Skip to content

Commit a9b9b46

Browse files
committed
core: use OnceCell for MovieClip.clip_event_handlers
These are only ever set once during initialization, so they don't need a `RefCell`
1 parent c3fe642 commit a9b9b46

File tree

2 files changed

+19
-16
lines changed

2 files changed

+19
-16
lines changed

core/src/avm1/globals/movie_clip.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -987,7 +987,7 @@ pub fn clone_sprite<'gc>(
987987
new_clip.set_matrix(context.gc(), *movie_clip.base().matrix());
988988
new_clip.set_color_transform(context.gc(), *movie_clip.base().color_transform());
989989

990-
new_clip.set_clip_event_handlers((&*movie_clip.clip_actions()).into());
990+
new_clip.init_clip_event_handlers(movie_clip.clip_actions().into());
991991

992992
if let Some(drawing) = movie_clip.drawing().as_deref().cloned() {
993993
*new_clip.drawing_mut(context.gc()) = drawing;

core/src/display_object/movie_clip.rs

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ pub struct MovieClipData<'gc> {
158158
container: RefLock<ChildContainer<'gc>>,
159159
object: Lock<Option<AvmObject<'gc>>>,
160160
#[collect(require_static)]
161-
clip_event_handlers: RefCell<Box<[ClipEventHandler]>>,
161+
clip_event_handlers: OnceCell<Box<[ClipEventHandler]>>,
162162
#[collect(require_static)]
163163
clip_event_flags: Cell<ClipEventFlag>,
164164
frame_scripts: RefLock<Vec<Option<Avm2Object<'gc>>>>,
@@ -207,7 +207,7 @@ impl<'gc> MovieClipData<'gc> {
207207
audio_stream: Cell::new(None),
208208
container: RefLock::new(ChildContainer::new(&movie)),
209209
object: Lock::new(None),
210-
clip_event_handlers: Default::default(),
210+
clip_event_handlers: OnceCell::new(),
211211
clip_event_flags: Cell::new(ClipEventFlag::empty()),
212212
frame_scripts: RefLock::new(Vec::new()),
213213
flags: Cell::new(MovieClipFlags::empty()),
@@ -677,9 +677,7 @@ impl<'gc> MovieClip<'gc> {
677677

678678
/// Does this clip have a unload handler
679679
pub fn has_unload_handler(&self) -> bool {
680-
self.0
681-
.clip_event_handlers
682-
.borrow()
680+
self.clip_actions()
683681
.iter()
684682
.any(|handler| handler.events.contains(ClipEventFlag::UNLOAD))
685683
}
@@ -1042,20 +1040,27 @@ impl<'gc> MovieClip<'gc> {
10421040
}
10431041

10441042
/// Gets the clip events for this MovieClip.
1045-
pub fn clip_actions(&self) -> Ref<'_, [ClipEventHandler]> {
1046-
Ref::map(self.0.clip_event_handlers.borrow(), |r| &**r)
1043+
pub fn clip_actions(self) -> &'gc [ClipEventHandler] {
1044+
match Gc::as_ref(self.0).clip_event_handlers.get() {
1045+
Some(handlers) => handlers,
1046+
None => &[],
1047+
}
10471048
}
10481049

10491050
/// Sets the clip actions (a.k.a. clip events) for this MovieClip.
10501051
/// Clip actions are created in the Flash IDE by using the `onEnterFrame`
10511052
/// tag on a MovieClip instance.
1052-
pub fn set_clip_event_handlers(self, event_handlers: Box<[ClipEventHandler]>) {
1053+
pub fn init_clip_event_handlers(self, event_handlers: Box<[ClipEventHandler]>) {
1054+
if self.0.clip_event_handlers.get().is_some() {
1055+
panic!("Clip event handlers already initialized");
1056+
}
1057+
10531058
let mut all_event_flags = ClipEventFlag::empty();
1054-
for handler in &event_handlers {
1059+
for handler in self.0.clip_event_handlers.get_or_init(|| event_handlers) {
10551060
all_event_flags |= handler.events;
10561061
}
1062+
10571063
self.0.clip_event_flags.set(all_event_flags);
1058-
self.0.clip_event_handlers.replace(event_handlers);
10591064
}
10601065

10611066
/// Returns an iterator of AVM1 `DoAction` blocks on the given frame number.
@@ -1277,7 +1282,7 @@ impl<'gc> MovieClip<'gc> {
12771282
(&place_object.clip_actions, child.as_movie_clip())
12781283
{
12791284
// Convert from `swf::ClipAction` to Ruffle's `ClipEventHandler`.
1280-
clip.set_clip_event_handlers(
1285+
clip.init_clip_event_handlers(
12811286
clip_actions
12821287
.iter()
12831288
.cloned()
@@ -1712,7 +1717,7 @@ impl<'gc> MovieClip<'gc> {
17121717

17131718
let mut events = Vec::new();
17141719

1715-
for event_handler in self.0.clip_event_handlers.borrow().iter() {
1720+
for event_handler in self.clip_actions().iter() {
17161721
if event_handler.events.contains(ClipEventFlag::INITIALIZE) {
17171722
context.action_queue.queue_action(
17181723
self.into(),
@@ -2649,9 +2654,7 @@ impl<'gc> TInteractiveObject<'gc> for MovieClip<'gc> {
26492654
if swf_version >= 5 {
26502655
if let Some(flag) = event.flag() {
26512656
for event_handler in self
2652-
.0
2653-
.clip_event_handlers
2654-
.borrow()
2657+
.clip_actions()
26552658
.iter()
26562659
.filter(|handler| handler.events.contains(flag))
26572660
{

0 commit comments

Comments
 (0)