diff --git a/LICENSE.md b/LICENSE.md index f8f503cf4b4b..c978c4e9f7e8 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -359,7 +359,6 @@ Ruffle depends on third-party libraries with compatible licenses. | [fxhash](https://github.com/cbreeden/fxhash) | [Apache-2.0](#Apache-20)/[MIT](#MIT) | Copyright (c) cbreeden | | [gc-arena](https://github.com/kyren/gc-arena) | [MIT](#MIT) | Copyright (c) kyren | | [gc-arena-derive](https://github.com/kyren/gc-arena) | [MIT](#MIT) | Copyright (c) kyren | -| [generational-arena](https://github.com/fitzgen/generational-arena) | [MPL-2.0](#MPL-20) | Copyright (c) Nick Fitzgerald | | [getrandom](https://github.com/rust-random/getrandom) | [Apache-2.0](#Apache-20)/[MIT](#MIT) | Copyright 2018 Developers of the Rand project Copyright (c) 2014 The Rust Project Developers | | [gfx-auxil](https://github.com/gfx-rs/gfx) | [Apache-2.0](#Apache-20)/[MIT](#MIT) | Copyright (c) The Gfx-rs Developers | | [gfx-backend-dx11](https://github.com/gfx-rs/gfx) | [Apache-2.0](#Apache-20)/[MIT](#MIT) | Copyright (c) The Gfx-rs Developers | @@ -529,7 +528,7 @@ Ruffle depends on third-party libraries with compatible licenses. | [sid](https://github.com/nical/sid) | [Apache-2.0](#Apache-20)/[MIT](#MIT) | Copyright (c) Nicolas Silva | | [slab](https://github.com/carllerche/slab) | [MIT](#MIT) | Copyright (c) 2019 Carl Lerche | | [slice-deque](https://github.com/gnzlbg/slice_deque) | [Apache-2.0](#Apache-20)/[MIT](#MIT) | Copyright (c) 2017 Gonzalo Brito Gadeschi Copyright (c) 2017 The Rust Project Developers | -| [slotmap](https://github.com/orlp/slotmap) | [Zlib](#Zlib) | Copyright (c) 2018 Orson Peters | +| [slotmap](https://github.com/orlp/slotmap) | [Zlib](#Zlib) | Copyright (c) 2021 Orson Peters | | [sluice](https://github.com/sagebind/sluice) | [MIT](#MIT) | Copyright (c) 2017 Stephen M. Coakley | | [smallvec](https://github.com/servo/rust-smallvec) | [Apache-2.0](#Apache-20)/[MIT](#MIT) | Copyright (c) 2018 The Servo Project Developers | | [smithay-client-toolkit](https://github.com/smithay/client-toolkit) | [MIT](#MIT) | Copyright (c) 2018 Victor Berger | diff --git a/core/src/backend/audio.rs b/core/src/backend/audio.rs index ba5364cf5104..f9a0acfdf9e5 100644 --- a/core/src/backend/audio.rs +++ b/core/src/backend/audio.rs @@ -7,7 +7,7 @@ use crate::{ }; use downcast_rs::Downcast; use gc_arena::Collect; -use slotmap::{DefaultKey, Key, SlotMap}; +use slotmap::{new_key_type, Key, SlotMap}; #[cfg(feature = "audio")] pub mod decoders; @@ -35,8 +35,11 @@ mod decoders { use thiserror::Error; use web_time::Duration; -pub type SoundHandle = DefaultKey; -pub type SoundInstanceHandle = DefaultKey; +new_key_type! { + pub struct SoundHandle; + pub struct SoundInstanceHandle; +} + pub type DecodeError = decoders::Error; #[derive(Eq, PartialEq, Clone, Copy, Debug)] @@ -212,7 +215,7 @@ pub struct NullAudioBackend { impl NullAudioBackend { pub fn new() -> NullAudioBackend { NullAudioBackend { - sounds: SlotMap::new(), + sounds: SlotMap::with_key(), volume: 1.0, } } diff --git a/core/src/backend/audio/mixer.rs b/core/src/backend/audio/mixer.rs index ab6d548c625a..420c5442d601 100644 --- a/core/src/backend/audio/mixer.rs +++ b/core/src/backend/audio/mixer.rs @@ -239,8 +239,8 @@ impl AudioMixer { /// Creates a new `AudioMixer` with the given number of channels and sample rate. pub fn new(num_output_channels: u8, output_sample_rate: u32) -> Self { Self { - sounds: SlotMap::new(), - sound_instances: Arc::new(Mutex::new(SlotMap::new())), + sounds: SlotMap::with_key(), + sound_instances: Arc::new(Mutex::new(SlotMap::with_key())), volume: Arc::new(RwLock::new(1.0)), num_output_channels, output_sample_rate, @@ -636,13 +636,6 @@ impl AudioMixer { .sound_instances .lock() .expect("Cannot be called reentrant"); - // This is a workaround for a bug in generational-arena: - // Arena::clear does not properly bump the generational index, allowing for stale references - // to continue to work (this caused #1315). Arena::remove will force a generation bump. - // See https://github.com/fitzgen/generational-arena/issues/30 - if let Some((i, _)) = sound_instances.iter().next() { - sound_instances.remove(i); - } sound_instances.clear(); } diff --git a/core/src/loader.rs b/core/src/loader.rs index c509a022c5f4..ed8fa72002cc 100644 --- a/core/src/loader.rs +++ b/core/src/loader.rs @@ -33,7 +33,7 @@ use crate::{avm2_stub_method, avm2_stub_method_context}; use encoding_rs::UTF_8; use gc_arena::{Collect, GcCell}; use ruffle_render::utils::{determine_jpeg_tag_format, JpegTagFormat}; -use slotmap::{DefaultKey, SlotMap}; +use slotmap::{new_key_type, SlotMap}; use std::borrow::Borrow; use std::fmt; use std::sync::{Arc, Mutex, Weak}; @@ -42,7 +42,9 @@ use swf::read::{extract_swz, read_compression_type}; use thiserror::Error; use url::{form_urlencoded, ParseError, Url}; -pub type Handle = DefaultKey; +new_key_type! { + pub struct LoaderHandle; +} /// The depth of AVM1 movies that AVM2 loads. const LOADER_INSERTED_AVM1_DEPTH: i32 = -0xF000; @@ -224,7 +226,7 @@ impl From> for Error { } /// Holds all in-progress loads for the player. -pub struct LoadManager<'gc>(SlotMap>); +pub struct LoadManager<'gc>(SlotMap>); unsafe impl<'gc> Collect for LoadManager<'gc> { fn trace(&self, cc: &gc_arena::Collection) { @@ -237,7 +239,7 @@ unsafe impl<'gc> Collect for LoadManager<'gc> { impl<'gc> LoadManager<'gc> { /// Construct a new `LoadManager`. pub fn new() -> Self { - Self(SlotMap::new()) + Self(SlotMap::with_key()) } /// Add a new loader to the `LoadManager`. @@ -249,7 +251,7 @@ impl<'gc> LoadManager<'gc> { /// invalidated). This can be done with remove_loader. /// Movie loaders are removed automatically after the loader status is set /// accordingly. - pub fn add_loader(&mut self, loader: Loader<'gc>) -> Handle { + pub fn add_loader(&mut self, loader: Loader<'gc>) -> LoaderHandle { let handle = self.0.insert(loader); match self.get_loader_mut(handle).unwrap() { Loader::RootMovie { self_handle, .. } @@ -272,17 +274,17 @@ impl<'gc> LoadManager<'gc> { /// Remove a completed loader. /// This is used to remove a loader after the loading or unloading process has completed. - pub fn remove_loader(&mut self, handle: Handle) { + pub fn remove_loader(&mut self, handle: LoaderHandle) { self.0.remove(handle); } /// Retrieve a loader by handle. - pub fn get_loader(&self, handle: Handle) -> Option<&Loader<'gc>> { + pub fn get_loader(&self, handle: LoaderHandle) -> Option<&Loader<'gc>> { self.0.get(handle) } /// Retrieve a loader by handle for mutation. - pub fn get_loader_mut(&mut self, handle: Handle) -> Option<&mut Loader<'gc>> { + pub fn get_loader_mut(&mut self, handle: LoaderHandle) -> Option<&mut Loader<'gc>> { self.0.get_mut(handle) } @@ -648,14 +650,14 @@ pub enum Loader<'gc> { RootMovie { /// The handle to refer to this loader instance. #[collect(require_static)] - self_handle: Option, + self_handle: Option, }, /// Loader that is loading a new movie into a MovieClip. Movie { /// The handle to refer to this loader instance. #[collect(require_static)] - self_handle: Option, + self_handle: Option, /// The target movie clip to load the movie into. target_clip: DisplayObject<'gc>, @@ -689,7 +691,7 @@ pub enum Loader<'gc> { Form { /// The handle to refer to this loader instance. #[collect(require_static)] - self_handle: Option, + self_handle: Option, /// The target AVM1 object to load form data into. target_object: Object<'gc>, @@ -699,7 +701,7 @@ pub enum Loader<'gc> { LoadVars { /// The handle to refer to this loader instance. #[collect(require_static)] - self_handle: Option, + self_handle: Option, /// The target AVM1 object to load form data into. target_object: Object<'gc>, @@ -710,7 +712,7 @@ pub enum Loader<'gc> { LoadURLLoader { /// The handle to refer to this loader instance. #[collect(require_static)] - self_handle: Option, + self_handle: Option, /// The target `URLLoader` to load data into. target_object: Avm2Object<'gc>, @@ -720,7 +722,7 @@ pub enum Loader<'gc> { SoundAvm1 { /// The handle to refer to this loader instance. #[collect(require_static)] - self_handle: Option, + self_handle: Option, /// The target AVM1 object to load the audio into. target_object: SoundObject<'gc>, @@ -730,7 +732,7 @@ pub enum Loader<'gc> { SoundAvm2 { /// The handle to refer to this loader instance. #[collect(require_static)] - self_handle: Option, + self_handle: Option, /// The target AVM1 object to load the audio into. target_object: Avm2Object<'gc>, @@ -740,7 +742,7 @@ pub enum Loader<'gc> { NetStream { /// The handle to refer to this loader instance. #[collect(require_static)] - self_handle: Option, + self_handle: Option, /// The stream to buffer data into. target_stream: NetStream<'gc>, @@ -750,7 +752,7 @@ pub enum Loader<'gc> { MovieUnloader { /// The handle to refer to this loader instance. #[collect(require_static)] - self_handle: Option, + self_handle: Option, /// The target MovieClip to unload. target_clip: DisplayObject<'gc>, @@ -760,7 +762,7 @@ pub enum Loader<'gc> { FileDialog { /// The handle to refer to this loader instance. #[collect(require_static)] - self_handle: Option, + self_handle: Option, /// The target AVM1 object to select a file path from. target_object: Object<'gc>, @@ -770,7 +772,7 @@ pub enum Loader<'gc> { FileDialogAvm2 { /// The handle to refer to this loader instance. #[collect(require_static)] - self_handle: Option, + self_handle: Option, /// The target AVM2 object to set to the selected file path. target_object: FileReferenceObject<'gc>, @@ -780,7 +782,7 @@ pub enum Loader<'gc> { SaveFileDialog { /// The handle to refer to this loader instance. #[collect(require_static)] - self_handle: Option, + self_handle: Option, /// The target AVM2 object to select a save location for. target_object: FileReferenceObject<'gc>, @@ -790,7 +792,7 @@ pub enum Loader<'gc> { DownloadFileDialog { /// The handle to refer to this loader instance. #[collect(require_static)] - self_handle: Option, + self_handle: Option, /// The target AVM1 object to select a file path from. target_object: Object<'gc>, @@ -800,7 +802,7 @@ pub enum Loader<'gc> { UploadFile { /// The handle to refer to this loader instance. #[collect(require_static)] - self_handle: Option, + self_handle: Option, /// The target AVM1 object to select a file path from. target_object: Object<'gc>, @@ -819,7 +821,7 @@ impl<'gc> Loader<'gc> { /// /// Returns any AVM errors encountered while sending events to user code. fn preload_tick( - handle: Handle, + handle: LoaderHandle, context: &mut UpdateContext<'_, 'gc>, limit: &mut ExecutionLimit, status: u16, @@ -1067,7 +1069,7 @@ impl<'gc> Loader<'gc> { } pub fn movie_loader_bytes( - handle: Handle, + handle: LoaderHandle, uc: &mut UpdateContext<'_, 'gc>, bytes: Vec, ) -> Result<(), Error> { @@ -1706,7 +1708,10 @@ impl<'gc> Loader<'gc> { } /// Report a movie loader start event to script code. - fn movie_loader_start(handle: Handle, uc: &mut UpdateContext<'_, 'gc>) -> Result<(), Error> { + fn movie_loader_start( + handle: LoaderHandle, + uc: &mut UpdateContext<'_, 'gc>, + ) -> Result<(), Error> { let me = uc.load_manager.get_loader_mut(handle); if me.is_none() { return Err(Error::Cancelled); @@ -1748,7 +1753,7 @@ impl<'gc> Loader<'gc> { /// Load data into a movie loader. fn movie_loader_data( - handle: Handle, + handle: LoaderHandle, uc: &mut UpdateContext<'_, 'gc>, data: &[u8], url: String, @@ -2094,7 +2099,7 @@ impl<'gc> Loader<'gc> { /// /// The current and total length are always reported as compressed lengths. fn movie_loader_progress( - handle: Handle, + handle: LoaderHandle, uc: &mut UpdateContext<'_, 'gc>, cur_len: usize, total_len: usize, @@ -2160,7 +2165,7 @@ impl<'gc> Loader<'gc> { /// Report a movie loader completion to script code. fn movie_loader_complete( - handle: Handle, + handle: LoaderHandle, uc: &mut UpdateContext<'_, 'gc>, dobj: Option>, status: u16, @@ -2329,7 +2334,7 @@ impl<'gc> Loader<'gc> { /// This is an associated function because we cannot borrow both the update /// context and one of it's loaders. fn movie_loader_error( - handle: Handle, + handle: LoaderHandle, uc: &mut UpdateContext<'_, 'gc>, msg: AvmString<'gc>, status: u16, diff --git a/core/src/local_connection.rs b/core/src/local_connection.rs index b1bffb7f4d81..842ec6693f29 100644 --- a/core/src/local_connection.rs +++ b/core/src/local_connection.rs @@ -2,9 +2,11 @@ use crate::avm1::Object as Avm1Object; use crate::avm2::object::LocalConnectionObject; use crate::string::AvmString; use gc_arena::Collect; -use slotmap::{DefaultKey, SlotMap}; +use slotmap::{new_key_type, SlotMap}; -pub type LocalConnectionHandle = DefaultKey; +new_key_type! { + pub struct LocalConnectionHandle; +} #[derive(Collect)] #[collect(no_drop)] @@ -55,7 +57,7 @@ unsafe impl<'gc> Collect for LocalConnections<'gc> { impl<'gc> LocalConnections<'gc> { pub fn empty() -> Self { Self { - connections: SlotMap::new(), + connections: SlotMap::with_key(), } } diff --git a/core/src/net_connection.rs b/core/src/net_connection.rs index e2c648bc6c94..504208a37efd 100644 --- a/core/src/net_connection.rs +++ b/core/src/net_connection.rs @@ -10,12 +10,14 @@ use crate::Player; use flash_lso::packet::{Header, Message, Packet}; use flash_lso::types::{AMFVersion, Value as AmfValue}; use gc_arena::{Collect, DynamicRoot, Rootable}; -use slotmap::{DefaultKey, SlotMap}; +use slotmap::{new_key_type, SlotMap}; use std::fmt::{Debug, Formatter}; use std::rc::Rc; use std::sync::{Mutex, Weak}; -pub type NetConnectionHandle = DefaultKey; +new_key_type! { + pub struct NetConnectionHandle; +} #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum ResponderCallback { @@ -90,7 +92,7 @@ unsafe impl<'gc> Collect for NetConnections<'gc> { impl<'gc> Default for NetConnections<'gc> { fn default() -> Self { Self { - connections: SlotMap::new(), + connections: SlotMap::with_key(), } } } diff --git a/core/src/socket.rs b/core/src/socket.rs index 1a91446a2912..b1033c0bcf97 100644 --- a/core/src/socket.rs +++ b/core/src/socket.rs @@ -13,13 +13,15 @@ use crate::{ }; use async_channel::{unbounded, Receiver, Sender as AsyncSender, Sender}; use gc_arena::Collect; -use slotmap::{DefaultKey, SlotMap}; +use slotmap::{new_key_type, SlotMap}; use std::{ cell::{Cell, RefCell}, time::Duration, }; -pub type SocketHandle = DefaultKey; +new_key_type! { + pub struct SocketHandle; +} #[derive(Copy, Clone, Collect)] #[collect(no_drop)] @@ -81,7 +83,7 @@ impl<'gc> Sockets<'gc> { let (sender, receiver) = unbounded(); Self { - sockets: SlotMap::new(), + sockets: SlotMap::with_key(), receiver, sender, } diff --git a/core/src/streams.rs b/core/src/streams.rs index 62d7c4de784f..1c1d900c63d6 100644 --- a/core/src/streams.rs +++ b/core/src/streams.rs @@ -434,7 +434,7 @@ impl<'gc> NetStream<'gc> { } if let Some(sound) = write.sound_instance { - context.stop_sounds_with_handle(sound); + context.stop_sound(sound); context.audio.stop_sound(sound); write.sound_instance = None; diff --git a/desktop/src/executor.rs b/desktop/src/executor.rs index f8c892d6f755..75c49d9677d2 100644 --- a/desktop/src/executor.rs +++ b/desktop/src/executor.rs @@ -5,11 +5,16 @@ use crate::task::Task; use async_channel::{unbounded, Receiver, Sender}; use ruffle_core::backend::navigator::OwnedFuture; use ruffle_core::loader::Error; -use slotmap::{DefaultKey, SlotMap}; +use slotmap::{new_key_type, SlotMap}; use std::sync::{Arc, Mutex, Weak}; use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker}; use winit::event_loop::EventLoopProxy; +new_key_type! { + // This is what we would call `TaskHandle` everywhere else, but that name is already taken. + struct TaskKey; +} + /// Executor context passed to event sources. /// /// All task handles are identical and interchangeable. Cloning a `TaskHandle` @@ -17,7 +22,7 @@ use winit::event_loop::EventLoopProxy; #[derive(Clone)] struct TaskHandle { /// The arena handle for a given task. - handle: DefaultKey, + handle: TaskKey, /// The executor the task belongs to. /// @@ -28,7 +33,7 @@ struct TaskHandle { impl TaskHandle { /// Construct a handle to a given task. - fn for_task(task: DefaultKey, executor: Weak>) -> Self { + fn for_task(task: TaskKey, executor: Weak>) -> Self { Self { handle: task, executor, @@ -128,7 +133,7 @@ impl TaskHandle { pub struct WinitAsyncExecutor { /// List of all spawned tasks. - task_queue: SlotMap, + task_queue: SlotMap, /// Source of tasks sent to us by the `NavigatorBackend`. channel: Receiver>, @@ -152,7 +157,7 @@ impl WinitAsyncExecutor { let (send, recv) = unbounded(); let new_self = Arc::new_cyclic(|self_ref| { Mutex::new(Self { - task_queue: SlotMap::new(), + task_queue: SlotMap::with_key(), channel: recv, self_ref: self_ref.clone(), event_loop: event_loop.clone(), @@ -200,7 +205,7 @@ impl WinitAsyncExecutor { } /// Mark a task as ready to proceed. - fn wake(&mut self, task: DefaultKey) { + fn wake(&mut self, task: TaskKey) { if let Some(task) = self.task_queue.get_mut(task) { if !task.is_completed() { task.set_ready(); diff --git a/video/software/src/backend.rs b/video/software/src/backend.rs index d5d8b3ba3ac0..14923b088dd5 100644 --- a/video/software/src/backend.rs +++ b/video/software/src/backend.rs @@ -23,7 +23,7 @@ impl Default for SoftwareVideoBackend { impl SoftwareVideoBackend { pub fn new() -> Self { Self { - streams: SlotMap::new(), + streams: SlotMap::with_key(), } } } diff --git a/video/src/lib.rs b/video/src/lib.rs index fb7885fa5056..ea9385d74750 100644 --- a/video/src/lib.rs +++ b/video/src/lib.rs @@ -1,10 +1,12 @@ #![deny(clippy::unwrap_used)] -use slotmap::DefaultKey; +use slotmap::new_key_type; pub mod backend; pub mod error; pub mod frame; pub mod null; -pub type VideoStreamHandle = DefaultKey; +new_key_type! { + pub struct VideoStreamHandle; +} diff --git a/video/src/null.rs b/video/src/null.rs index f51d3faedb35..0588c9cedeb6 100644 --- a/video/src/null.rs +++ b/video/src/null.rs @@ -22,7 +22,7 @@ pub struct NullVideoBackend { impl NullVideoBackend { pub fn new() -> Self { Self { - streams: SlotMap::new(), + streams: SlotMap::with_key(), } } } diff --git a/web/LICENSE.md b/web/LICENSE.md index 8af4c898f8e7..414fbcff23de 100644 --- a/web/LICENSE.md +++ b/web/LICENSE.md @@ -359,7 +359,6 @@ Ruffle depends on third-party libraries with compatible licenses. | [fxhash](https://github.com/cbreeden/fxhash) | [Apache-2.0](#Apache-20)/[MIT](#MIT) | Copyright (c) cbreeden | | [gc-arena](https://github.com/kyren/gc-arena) | [MIT](#MIT) | Copyright (c) kyren | | [gc-arena-derive](https://github.com/kyren/gc-arena) | [MIT](#MIT) | Copyright (c) kyren | -| [generational-arena](https://github.com/fitzgen/generational-arena) | [MPL-2.0](#MPL-20) | Copyright (c) Nick Fitzgerald | | [getrandom](https://github.com/rust-random/getrandom) | [Apache-2.0](#Apache-20)/[MIT](#MIT) | Copyright 2018 Developers of the Rand project Copyright (c) 2014 The Rust Project Developers | | [gfx-auxil](https://github.com/gfx-rs/gfx) | [Apache-2.0](#Apache-20)/[MIT](#MIT) | Copyright (c) The Gfx-rs Developers | | [gfx-backend-dx11](https://github.com/gfx-rs/gfx) | [Apache-2.0](#Apache-20)/[MIT](#MIT) | Copyright (c) The Gfx-rs Developers | @@ -527,7 +526,7 @@ Ruffle depends on third-party libraries with compatible licenses. | [sid](https://github.com/nical/sid) | [Apache-2.0](#Apache-20)/[MIT](#MIT) | Copyright (c) Nicolas Silva | | [slab](https://github.com/carllerche/slab) | [MIT](#MIT) | Copyright (c) 2019 Carl Lerche | | [slice-deque](https://github.com/gnzlbg/slice_deque) | [Apache-2.0](#Apache-20)/[MIT](#MIT) | Copyright (c) 2017 Gonzalo Brito Gadeschi Copyright (c) 2017 The Rust Project Developers | -| [slotmap](https://github.com/orlp/slotmap) | [Zlib](#Zlib) | Copyright (c) 2018 Orson Peters | +| [slotmap](https://github.com/orlp/slotmap) | [Zlib](#Zlib) | Copyright (c) 2021 Orson Peters | | [sluice](https://github.com/sagebind/sluice) | [MIT](#MIT) | Copyright (c) 2017 Stephen M. Coakley | | [smallvec](https://github.com/servo/rust-smallvec) | [Apache-2.0](#Apache-20)/[MIT](#MIT) | Copyright (c) 2018 The Servo Project Developers | | [smithay-client-toolkit](https://github.com/smithay/client-toolkit) | [MIT](#MIT) | Copyright (c) 2018 Victor Berger |