Replace most manual `Collect` impls with `#[derive(Collect)]`
* Replace most unsafe impls with Collect. * Switch to local gc-arena fork.
This commit is contained in:
parent
809d0a9245
commit
6050dd8204
|
@ -1395,8 +1395,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "gc-arena"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7262a3f0bd866ed41d13f7a5147d5fe2278f6860aeab66bd72e9f2f770fc3e8"
|
||||
source = "git+https://github.com/ruffle-rs/gc-arena#4931b3bc25b2b74174ff5eb9c34ae0dda732778b"
|
||||
dependencies = [
|
||||
"gc-arena-derive",
|
||||
]
|
||||
|
@ -1404,8 +1403,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "gc-arena-derive"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f5a1fd9d509709237f7673fe8fa4a2fcf8136bf5bd43b67bab6af267a9850524"
|
||||
source = "git+https://github.com/ruffle-rs/gc-arena#4931b3bc25b2b74174ff5eb9c34ae0dda732778b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
|
@ -9,8 +9,8 @@ license = "MIT OR Apache-2.0"
|
|||
bitstream-io = "1.0.0"
|
||||
flate2 = "1.0.20"
|
||||
fnv = "1.0.7"
|
||||
gc-arena = "0.2.0"
|
||||
gc-arena-derive = "0.2.0"
|
||||
gc-arena = { git = "https://github.com/ruffle-rs/gc-arena" }
|
||||
gc-arena-derive = { git = "https://github.com/ruffle-rs/gc-arena" }
|
||||
generational-arena = "0.2.8"
|
||||
gif = "0.11.1"
|
||||
indexmap = "1.6.1"
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::avm1::globals::create_globals;
|
|||
use crate::avm1::object::{search_prototype, stage_object};
|
||||
use crate::context::UpdateContext;
|
||||
use crate::prelude::*;
|
||||
use gc_arena::{GcCell, MutationContext};
|
||||
use gc_arena::{Collect, GcCell, MutationContext};
|
||||
|
||||
use swf::avm1::read::Reader;
|
||||
|
||||
|
@ -76,6 +76,8 @@ macro_rules! avm_error {
|
|||
)
|
||||
}
|
||||
|
||||
#[derive(Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub struct Avm1<'gc> {
|
||||
/// The Flash Player version we're emulating.
|
||||
player_version: u8,
|
||||
|
@ -119,22 +121,6 @@ pub struct Avm1<'gc> {
|
|||
pub debug_output: bool,
|
||||
}
|
||||
|
||||
unsafe impl<'gc> gc_arena::Collect for Avm1<'gc> {
|
||||
#[inline]
|
||||
fn trace(&self, cc: gc_arena::CollectionContext) {
|
||||
self.globals.trace(cc);
|
||||
self.constant_pool.trace(cc);
|
||||
//self.system_listeners.trace(cc);
|
||||
self.prototypes.trace(cc);
|
||||
self.display_properties.trace(cc);
|
||||
self.stack.trace(cc);
|
||||
|
||||
for register in &self.registers {
|
||||
register.trace(cc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> Avm1<'gc> {
|
||||
pub fn new(gc_context: MutationContext<'gc, '_>, player_version: u8) -> Self {
|
||||
let (prototypes, globals, broadcaster_functions) = create_globals(gc_context);
|
||||
|
|
|
@ -77,18 +77,13 @@ macro_rules! implement_utc_getters {
|
|||
};
|
||||
}
|
||||
|
||||
#[derive(Collect)]
|
||||
#[collect(require_static)]
|
||||
enum YearType {
|
||||
Full,
|
||||
Adjust(Box<dyn Fn(i64) -> i64>),
|
||||
}
|
||||
|
||||
unsafe impl Collect for YearType {
|
||||
#[inline]
|
||||
fn needs_trace() -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl YearType {
|
||||
fn adjust(&self, year: i64) -> i64 {
|
||||
match self {
|
||||
|
|
|
@ -10,20 +10,17 @@ use std::fmt;
|
|||
#[collect(no_drop)]
|
||||
pub struct DateObject<'gc>(GcCell<'gc, DateObjectData<'gc>>);
|
||||
|
||||
#[derive(Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub struct DateObjectData<'gc> {
|
||||
/// The underlying script object.
|
||||
base: ScriptObject<'gc>,
|
||||
|
||||
/// The DateTime represented by this object
|
||||
#[collect(require_static)]
|
||||
date_time: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
unsafe impl<'gc> Collect for DateObjectData<'gc> {
|
||||
fn trace(&self, cc: gc_arena::CollectionContext) {
|
||||
self.base.trace(cc);
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for DateObject<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let this = self.0.read();
|
||||
|
|
|
@ -72,6 +72,8 @@ impl<'gc> Watcher<'gc> {
|
|||
#[collect(no_drop)]
|
||||
pub struct ScriptObject<'gc>(GcCell<'gc, ScriptObjectData<'gc>>);
|
||||
|
||||
#[derive(Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub struct ScriptObjectData<'gc> {
|
||||
prototype: Option<Object<'gc>>,
|
||||
values: PropertyMap<Property<'gc>>,
|
||||
|
@ -81,16 +83,6 @@ pub struct ScriptObjectData<'gc> {
|
|||
watchers: PropertyMap<Watcher<'gc>>,
|
||||
}
|
||||
|
||||
unsafe impl<'gc> Collect for ScriptObjectData<'gc> {
|
||||
fn trace(&self, cc: gc_arena::CollectionContext) {
|
||||
self.prototype.trace(cc);
|
||||
self.values.trace(cc);
|
||||
self.array.trace(cc);
|
||||
self.interfaces.trace(cc);
|
||||
self.watchers.trace(cc);
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for ScriptObjectData<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("Object")
|
||||
|
|
|
@ -14,6 +14,8 @@ use std::fmt;
|
|||
#[collect(no_drop)]
|
||||
pub struct SoundObject<'gc>(GcCell<'gc, SoundObjectData<'gc>>);
|
||||
|
||||
#[derive(Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub struct SoundObjectData<'gc> {
|
||||
/// The underlying script object.
|
||||
///
|
||||
|
@ -22,9 +24,11 @@ pub struct SoundObjectData<'gc> {
|
|||
base: ScriptObject<'gc>,
|
||||
|
||||
/// The sound that is attached to this object.
|
||||
#[collect(require_static)]
|
||||
sound: Option<SoundHandle>,
|
||||
|
||||
/// The instance of the last played sound on this object.
|
||||
#[collect(require_static)]
|
||||
sound_instance: Option<SoundInstanceHandle>,
|
||||
|
||||
/// Sounds in AVM1 are tied to a specific movie clip.
|
||||
|
@ -37,13 +41,6 @@ pub struct SoundObjectData<'gc> {
|
|||
duration: u32,
|
||||
}
|
||||
|
||||
unsafe impl<'gc> Collect for SoundObjectData<'gc> {
|
||||
fn trace(&self, cc: gc_arena::CollectionContext) {
|
||||
self.base.trace(cc);
|
||||
self.owner.trace(cc);
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for SoundObject<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let this = self.0.read();
|
||||
|
|
|
@ -4,10 +4,13 @@ use crate::avm1::object::Object;
|
|||
use crate::avm1::Value;
|
||||
use bitflags::bitflags;
|
||||
use core::fmt;
|
||||
use gc_arena::Collect;
|
||||
|
||||
bitflags! {
|
||||
/// Attributes of properties in the AVM runtime.
|
||||
/// The values are significant and should match the order used by `object::as_set_prop_flags`.
|
||||
#[derive(Collect)]
|
||||
#[collect(require_static)]
|
||||
pub struct Attribute: u8 {
|
||||
const DONT_ENUM = 1 << 0;
|
||||
const DONT_DELETE = 1 << 1;
|
||||
|
@ -16,7 +19,8 @@ bitflags! {
|
|||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub enum Property<'gc> {
|
||||
Virtual {
|
||||
get: Object<'gc>,
|
||||
|
@ -108,18 +112,6 @@ impl<'gc> Property<'gc> {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<'gc> gc_arena::Collect for Property<'gc> {
|
||||
fn trace(&self, cc: gc_arena::CollectionContext) {
|
||||
match self {
|
||||
Property::Virtual { get, set, .. } => {
|
||||
get.trace(cc);
|
||||
set.trace(cc);
|
||||
}
|
||||
Property::Stored { value, .. } => value.trace(cc),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Property<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
|
|
|
@ -5,11 +5,12 @@ use crate::avm1::callable_value::CallableValue;
|
|||
use crate::avm1::error::Error;
|
||||
use crate::avm1::property::Attribute;
|
||||
use crate::avm1::{Object, ScriptObject, TObject, Value};
|
||||
use gc_arena::{GcCell, MutationContext};
|
||||
use gc_arena::{Collect, GcCell, MutationContext};
|
||||
use std::cell::Ref;
|
||||
|
||||
/// Indicates what kind of scope a scope is.
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Collect)]
|
||||
#[collect(require_static)]
|
||||
pub enum ScopeClass {
|
||||
/// Scope represents global scope.
|
||||
Global,
|
||||
|
@ -28,21 +29,14 @@ pub enum ScopeClass {
|
|||
}
|
||||
|
||||
/// Represents a scope chain for an AVM1 activation.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub struct Scope<'gc> {
|
||||
parent: Option<GcCell<'gc, Scope<'gc>>>,
|
||||
class: ScopeClass,
|
||||
values: Object<'gc>,
|
||||
}
|
||||
|
||||
unsafe impl<'gc> gc_arena::Collect for Scope<'gc> {
|
||||
#[inline]
|
||||
fn trace(&self, cc: gc_arena::CollectionContext) {
|
||||
self.parent.trace(cc);
|
||||
self.values.trace(cc);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> Scope<'gc> {
|
||||
/// Construct a global scope (one without a parent).
|
||||
pub fn from_global_object(globals: Object<'gc>) -> Scope<'gc> {
|
||||
|
|
|
@ -6,9 +6,11 @@ use crate::ecma_conversions::{
|
|||
f64_to_string, f64_to_wrapping_i16, f64_to_wrapping_i32, f64_to_wrapping_u16,
|
||||
f64_to_wrapping_u32,
|
||||
};
|
||||
use gc_arena::Collect;
|
||||
use std::borrow::Cow;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy, Collect)]
|
||||
#[collect(no_drop)]
|
||||
#[allow(dead_code)]
|
||||
pub enum Value<'gc> {
|
||||
Undefined,
|
||||
|
@ -94,16 +96,6 @@ impl<'gc> From<usize> for Value<'gc> {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<'gc> gc_arena::Collect for Value<'gc> {
|
||||
fn trace(&self, cc: gc_arena::CollectionContext) {
|
||||
match self {
|
||||
Value::String(string) => string.trace(cc),
|
||||
Value::Object(object) => object.trace(cc),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Value<'_> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
|
|
|
@ -5,12 +5,14 @@ use crate::avm2::return_value::ReturnValue;
|
|||
use crate::avm2::value::Value;
|
||||
use crate::avm2::Error;
|
||||
use bitflags::bitflags;
|
||||
use gc_arena::{Collect, CollectionContext};
|
||||
use gc_arena::Collect;
|
||||
|
||||
bitflags! {
|
||||
/// Attributes of properties in the AVM runtime.
|
||||
///
|
||||
/// TODO: Replace with AVM2 properties for traits
|
||||
#[derive(Collect)]
|
||||
#[collect(require_static)]
|
||||
pub struct Attribute: u8 {
|
||||
const DONT_DELETE = 1 << 0;
|
||||
const READ_ONLY = 1 << 1;
|
||||
|
@ -18,7 +20,8 @@ bitflags! {
|
|||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub enum Property<'gc> {
|
||||
Virtual {
|
||||
get: Option<Object<'gc>>,
|
||||
|
@ -35,19 +38,6 @@ pub enum Property<'gc> {
|
|||
},
|
||||
}
|
||||
|
||||
unsafe impl<'gc> Collect for Property<'gc> {
|
||||
fn trace(&self, cc: CollectionContext) {
|
||||
match self {
|
||||
Property::Virtual { get, set, .. } => {
|
||||
get.trace(cc);
|
||||
set.trace(cc);
|
||||
}
|
||||
Property::Stored { value, .. } => value.trace(cc),
|
||||
Property::Slot { .. } => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> Property<'gc> {
|
||||
/// Create a new stored property.
|
||||
pub fn new_stored(value: impl Into<Value<'gc>>) -> Self {
|
||||
|
|
|
@ -3,10 +3,11 @@
|
|||
use crate::avm2::property::Attribute;
|
||||
use crate::avm2::value::Value;
|
||||
use crate::avm2::Error;
|
||||
use gc_arena::{Collect, CollectionContext};
|
||||
use gc_arena::Collect;
|
||||
|
||||
/// Represents a single slot on an object.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub enum Slot<'gc> {
|
||||
/// An unoccupied slot.
|
||||
///
|
||||
|
@ -23,15 +24,6 @@ pub enum Slot<'gc> {
|
|||
},
|
||||
}
|
||||
|
||||
unsafe impl<'gc> Collect for Slot<'gc> {
|
||||
fn trace(&self, cc: CollectionContext) {
|
||||
match self {
|
||||
Self::Unoccupied => {}
|
||||
Self::Occupied { value, .. } => value.trace(cc),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> Default for Slot<'gc> {
|
||||
fn default() -> Self {
|
||||
Self::Unoccupied
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::{
|
|||
},
|
||||
};
|
||||
use downcast_rs::Downcast;
|
||||
use gc_arena::{Collect, CollectionContext};
|
||||
use gc_arena::Collect;
|
||||
use generational_arena::{Arena, Index};
|
||||
|
||||
pub mod decoders;
|
||||
|
@ -165,6 +165,8 @@ impl Default for NullAudioBackend {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub struct AudioManager<'gc> {
|
||||
/// The list of actively playing sounds.
|
||||
sounds: Vec<SoundInstance<'gc>>,
|
||||
|
@ -370,20 +372,16 @@ impl<'gc> Default for AudioManager<'gc> {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<'gc> Collect for AudioManager<'gc> {
|
||||
fn trace(&self, cc: CollectionContext) {
|
||||
for sound in &self.sounds {
|
||||
sound.trace(cc);
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub struct SoundInstance<'gc> {
|
||||
/// The handle to the sound instance in the audio backend.
|
||||
#[collect(require_static)]
|
||||
instance: SoundInstanceHandle,
|
||||
|
||||
/// The handle to the sound definition in the audio backend.
|
||||
/// This will be `None` for stream sounds.
|
||||
#[collect(require_static)]
|
||||
sound: Option<SoundHandle>,
|
||||
|
||||
/// The display object that this sound is playing in, if any.
|
||||
|
@ -394,13 +392,6 @@ pub struct SoundInstance<'gc> {
|
|||
pub avm1_object: Option<SoundObject<'gc>>,
|
||||
}
|
||||
|
||||
unsafe impl<'gc> Collect for SoundInstance<'gc> {
|
||||
fn trace(&self, cc: CollectionContext) {
|
||||
self.display_object.trace(cc);
|
||||
self.avm1_object.trace(cc);
|
||||
}
|
||||
}
|
||||
|
||||
/// A sound transform for a playing sound, for use by audio backends.
|
||||
/// This differs from `display_object::SoundTranform` by being
|
||||
/// already converted to `f32` and having `volume` baked in.
|
||||
|
|
|
@ -3,8 +3,10 @@ use crate::display_object::{
|
|||
Bitmap, Button, EditText, Graphic, MorphShape, MovieClip, Text, Video,
|
||||
};
|
||||
use crate::font::Font;
|
||||
use gc_arena::Collect;
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub enum Character<'gc> {
|
||||
EditText(EditText<'gc>),
|
||||
Graphic(Graphic<'gc>),
|
||||
|
@ -14,24 +16,6 @@ pub enum Character<'gc> {
|
|||
Font(Font<'gc>),
|
||||
MorphShape(MorphShape<'gc>),
|
||||
Text(Text<'gc>),
|
||||
Sound(SoundHandle),
|
||||
Sound(#[collect(require_static)] SoundHandle),
|
||||
Video(Video<'gc>),
|
||||
}
|
||||
|
||||
unsafe impl<'gc> gc_arena::Collect for Character<'gc> {
|
||||
#[inline]
|
||||
fn trace(&self, cc: gc_arena::CollectionContext) {
|
||||
match self {
|
||||
Character::EditText(c) => c.trace(cc),
|
||||
Character::Graphic(c) => c.trace(cc),
|
||||
Character::MovieClip(c) => c.trace(cc),
|
||||
Character::Bitmap(c) => c.trace(cc),
|
||||
Character::Button(c) => c.trace(cc),
|
||||
Character::Font(c) => c.trace(cc),
|
||||
Character::MorphShape(c) => c.trace(cc),
|
||||
Character::Text(c) => c.trace(cc),
|
||||
Character::Sound(c) => c.trace(cc),
|
||||
Character::Video(c) => c.trace(cc),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -291,6 +291,8 @@ impl<'a, 'gc, 'gc_context> UpdateContext<'a, 'gc, 'gc_context> {
|
|||
}
|
||||
|
||||
/// A queued ActionScript call.
|
||||
#[derive(Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub struct QueuedActions<'gc> {
|
||||
/// The movie clip this ActionScript is running on.
|
||||
pub clip: DisplayObject<'gc>,
|
||||
|
@ -302,14 +304,6 @@ pub struct QueuedActions<'gc> {
|
|||
pub is_unload: bool,
|
||||
}
|
||||
|
||||
unsafe impl<'gc> Collect for QueuedActions<'gc> {
|
||||
#[inline]
|
||||
fn trace(&self, cc: gc_arena::CollectionContext) {
|
||||
self.clip.trace(cc);
|
||||
self.action_type.trace(cc);
|
||||
}
|
||||
}
|
||||
|
||||
/// Action and gotos need to be queued up to execute at the end of the frame.
|
||||
pub struct ActionQueue<'gc> {
|
||||
/// Each priority is kept in a separate bucket.
|
||||
|
@ -400,7 +394,8 @@ pub struct RenderContext<'a, 'gc> {
|
|||
}
|
||||
|
||||
/// The type of action being run.
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub enum ActionType<'gc> {
|
||||
/// Normal frame or event actions.
|
||||
Normal { bytecode: SwfSlice },
|
||||
|
@ -494,22 +489,3 @@ impl fmt::Debug for ActionType<'_> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'gc> Collect for ActionType<'gc> {
|
||||
#[inline]
|
||||
fn trace(&self, cc: gc_arena::CollectionContext) {
|
||||
match self {
|
||||
ActionType::Construct { constructor, .. } => {
|
||||
constructor.trace(cc);
|
||||
}
|
||||
ActionType::Method { object, args, .. } => {
|
||||
object.trace(cc);
|
||||
args.trace(cc);
|
||||
}
|
||||
ActionType::NotifyListeners { args, .. } => {
|
||||
args.trace(cc);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,8 @@ pub use movie_clip::{MovieClip, Scene};
|
|||
pub use text::Text;
|
||||
pub use video::Video;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub struct DisplayObjectBase<'gc> {
|
||||
parent: Option<DisplayObject<'gc>>,
|
||||
place_frame: u16,
|
||||
|
@ -105,17 +106,6 @@ impl<'gc> Default for DisplayObjectBase<'gc> {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<'gc> Collect for DisplayObjectBase<'gc> {
|
||||
#[inline]
|
||||
fn trace(&self, cc: gc_arena::CollectionContext) {
|
||||
self.parent.trace(cc);
|
||||
self.prev_sibling.trace(cc);
|
||||
self.next_sibling.trace(cc);
|
||||
self.masker.trace(cc);
|
||||
self.maskee.trace(cc);
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl<'gc> DisplayObjectBase<'gc> {
|
||||
/// Reset all properties that would be adjusted by a movie load.
|
||||
|
@ -1491,7 +1481,8 @@ bitflags! {
|
|||
/// Every value is a percentage (0-100), but out of range values are allowed.
|
||||
/// In AVM1, this is returned by `Sound.getTransform`.
|
||||
/// In AVM2, this is returned by `Sprite.soundTransform`.
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Collect)]
|
||||
#[collect(require_static)]
|
||||
pub struct SoundTransform {
|
||||
pub volume: i32,
|
||||
pub left_to_left: i32,
|
||||
|
|
|
@ -18,7 +18,8 @@ use swf::ButtonActionCondition;
|
|||
#[collect(no_drop)]
|
||||
pub struct Button<'gc>(GcCell<'gc, ButtonData<'gc>>);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub struct ButtonData<'gc> {
|
||||
base: DisplayObjectBase<'gc>,
|
||||
static_data: GcCell<'gc, ButtonStatic>,
|
||||
|
@ -567,20 +568,8 @@ impl<'gc> ButtonData<'gc> {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<'gc> gc_arena::Collect for ButtonData<'gc> {
|
||||
#[inline]
|
||||
fn trace(&self, cc: gc_arena::CollectionContext) {
|
||||
self.container.trace(cc);
|
||||
for child in self.hit_area.values() {
|
||||
child.trace(cc);
|
||||
}
|
||||
self.base.trace(cc);
|
||||
self.static_data.trace(cc);
|
||||
self.object.trace(cc);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Collect)]
|
||||
#[collect(require_static)]
|
||||
#[allow(dead_code)]
|
||||
enum ButtonState {
|
||||
Up,
|
||||
|
@ -595,7 +584,8 @@ struct ButtonAction {
|
|||
key_code: Option<ButtonKeyCode>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Collect)]
|
||||
#[collect(require_static)]
|
||||
enum ButtonTracking {
|
||||
Push,
|
||||
Menu,
|
||||
|
@ -603,7 +593,8 @@ enum ButtonTracking {
|
|||
|
||||
/// Static data shared between all instances of a button.
|
||||
#[allow(dead_code)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Collect)]
|
||||
#[collect(require_static)]
|
||||
struct ButtonStatic {
|
||||
swf: Arc<SwfMovie>,
|
||||
id: CharacterId,
|
||||
|
@ -616,10 +607,3 @@ struct ButtonStatic {
|
|||
down_to_over_sound: Option<swf::ButtonSound>,
|
||||
over_to_up_sound: Option<swf::ButtonSound>,
|
||||
}
|
||||
|
||||
unsafe impl gc_arena::Collect for ButtonStatic {
|
||||
#[inline]
|
||||
fn needs_trace() -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1625,7 +1625,8 @@ struct EditTextStatic {
|
|||
swf: Arc<SwfMovie>,
|
||||
text: EditTextStaticData,
|
||||
}
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Collect)]
|
||||
#[collect(require_static)]
|
||||
struct EditTextStaticData {
|
||||
id: CharacterId,
|
||||
bounds: swf::Rectangle,
|
||||
|
@ -1649,25 +1650,13 @@ struct EditTextStaticData {
|
|||
is_device_font: bool,
|
||||
}
|
||||
|
||||
unsafe impl<'gc> Collect for EditTextStaticData {
|
||||
fn needs_trace() -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone, Debug, Collect)]
|
||||
#[collect(require_static)]
|
||||
pub struct TextSelection {
|
||||
from: usize,
|
||||
to: usize,
|
||||
}
|
||||
|
||||
unsafe impl Collect for TextSelection {
|
||||
#[inline]
|
||||
fn needs_trace() -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl TextSelection {
|
||||
pub fn for_position(position: usize) -> Self {
|
||||
Self {
|
||||
|
|
|
@ -11,7 +11,8 @@ use std::sync::Arc;
|
|||
#[collect(no_drop)]
|
||||
pub struct Graphic<'gc>(GcCell<'gc, GraphicData<'gc>>);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub struct GraphicData<'gc> {
|
||||
base: DisplayObjectBase<'gc>,
|
||||
static_data: gc_arena::Gc<'gc, GraphicStatic>,
|
||||
|
@ -97,25 +98,13 @@ impl<'gc> TDisplayObject<'gc> for Graphic<'gc> {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<'gc> gc_arena::Collect for GraphicData<'gc> {
|
||||
fn trace(&self, cc: gc_arena::CollectionContext) {
|
||||
self.base.trace(cc);
|
||||
self.static_data.trace(cc);
|
||||
}
|
||||
}
|
||||
|
||||
/// Static data shared between all instances of a graphic.
|
||||
#[allow(dead_code)]
|
||||
#[derive(Collect)]
|
||||
#[collect(require_static)]
|
||||
struct GraphicStatic {
|
||||
id: CharacterId,
|
||||
shape: swf::Shape,
|
||||
render_handle: ShapeHandle,
|
||||
bounds: BoundingBox,
|
||||
}
|
||||
|
||||
unsafe impl<'gc> gc_arena::Collect for GraphicStatic {
|
||||
#[inline]
|
||||
fn needs_trace() -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,8 @@ use swf::Twips;
|
|||
#[collect(no_drop)]
|
||||
pub struct MorphShape<'gc>(GcCell<'gc, MorphShapeData<'gc>>);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub struct MorphShapeData<'gc> {
|
||||
base: DisplayObjectBase<'gc>,
|
||||
static_data: Gc<'gc, MorphShapeStatic>,
|
||||
|
@ -96,14 +97,6 @@ impl<'gc> TDisplayObject<'gc> for MorphShape<'gc> {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<'gc> gc_arena::Collect for MorphShapeData<'gc> {
|
||||
#[inline]
|
||||
fn trace(&self, cc: gc_arena::CollectionContext) {
|
||||
self.base.trace(cc);
|
||||
self.static_data.trace(cc);
|
||||
}
|
||||
}
|
||||
|
||||
/// A precalculated intermediate frame for a morph shape.
|
||||
struct Frame {
|
||||
shape_handle: ShapeHandle,
|
||||
|
@ -113,6 +106,8 @@ struct Frame {
|
|||
|
||||
/// Static data shared between all instances of a morph shape.
|
||||
#[allow(dead_code)]
|
||||
#[derive(Collect)]
|
||||
#[collect(require_static)]
|
||||
pub struct MorphShapeStatic {
|
||||
id: CharacterId,
|
||||
start: swf::MorphShape,
|
||||
|
@ -307,13 +302,6 @@ impl MorphShapeStatic {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<'gc> gc_arena::Collect for MorphShapeStatic {
|
||||
#[inline]
|
||||
fn needs_trace() -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
// Interpolation functions
|
||||
// These interpolate between two SWF shape structures.
|
||||
// a + b should = 1.0
|
||||
|
|
|
@ -47,12 +47,14 @@ type FrameNumber = u16;
|
|||
#[collect(no_drop)]
|
||||
pub struct MovieClip<'gc>(GcCell<'gc, MovieClipData<'gc>>);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub struct MovieClipData<'gc> {
|
||||
base: DisplayObjectBase<'gc>,
|
||||
static_data: Gc<'gc, MovieClipStatic>,
|
||||
tag_stream_pos: u64,
|
||||
current_frame: FrameNumber,
|
||||
#[collect(require_static)]
|
||||
audio_stream: Option<SoundInstanceHandle>,
|
||||
container: ChildContainer<'gc>,
|
||||
object: Option<AvmObject<'gc>>,
|
||||
|
@ -68,18 +70,6 @@ pub struct MovieClipData<'gc> {
|
|||
use_hand_cursor: bool,
|
||||
}
|
||||
|
||||
unsafe impl<'gc> Collect for MovieClipData<'gc> {
|
||||
#[inline]
|
||||
fn trace(&self, cc: gc_arena::CollectionContext) {
|
||||
self.container.trace(cc);
|
||||
self.base.trace(cc);
|
||||
self.static_data.trace(cc);
|
||||
self.object.trace(cc);
|
||||
self.avm2_constructor.trace(cc);
|
||||
self.frame_scripts.trace(cc);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> MovieClip<'gc> {
|
||||
#[allow(dead_code)]
|
||||
pub fn new(swf: SwfSlice, gc_context: MutationContext<'gc, '_>) -> Self {
|
||||
|
@ -3204,6 +3194,8 @@ impl<'a> GotoPlaceObject<'a> {
|
|||
|
||||
bitflags! {
|
||||
/// Boolean state flags used by `MovieClip`.
|
||||
#[derive(Collect)]
|
||||
#[collect(require_static)]
|
||||
struct MovieClipFlags: u8 {
|
||||
/// Whether this `MovieClip` has run its initial frame.
|
||||
const INITIALIZED = 1 << 0;
|
||||
|
@ -3221,7 +3213,8 @@ bitflags! {
|
|||
|
||||
/// Actions that are attached to a `MovieClip` event in
|
||||
/// an `onClipEvent`/`on` handler.
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Collect)]
|
||||
#[collect(require_static)]
|
||||
pub struct ClipAction {
|
||||
/// The event that triggers this handler.
|
||||
event: ClipEvent,
|
||||
|
|
|
@ -12,7 +12,8 @@ use std::sync::Arc;
|
|||
#[collect(no_drop)]
|
||||
pub struct Text<'gc>(GcCell<'gc, TextData<'gc>>);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub struct TextData<'gc> {
|
||||
base: DisplayObjectBase<'gc>,
|
||||
static_data: gc_arena::Gc<'gc, TextStatic>,
|
||||
|
@ -194,17 +195,10 @@ impl<'gc> TDisplayObject<'gc> for Text<'gc> {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<'gc> gc_arena::Collect for TextData<'gc> {
|
||||
#[inline]
|
||||
fn trace(&self, cc: gc_arena::CollectionContext) {
|
||||
self.base.trace(cc);
|
||||
self.static_data.trace(cc);
|
||||
}
|
||||
}
|
||||
|
||||
/// Static data shared between all instances of a text object.
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Collect)]
|
||||
#[collect(require_static)]
|
||||
struct TextStatic {
|
||||
swf: Arc<SwfMovie>,
|
||||
id: CharacterId,
|
||||
|
@ -212,10 +206,3 @@ struct TextStatic {
|
|||
text_transform: Matrix,
|
||||
text_blocks: Vec<swf::TextRecord>,
|
||||
}
|
||||
|
||||
unsafe impl<'gc> gc_arena::Collect for TextStatic {
|
||||
#[inline]
|
||||
fn needs_trace() -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::avm1::{
|
|||
AvmString as Avm1String, Object as Avm1Object, ScriptObject as Avm1ScriptObject,
|
||||
};
|
||||
use crate::context::UpdateContext;
|
||||
use gc_arena::{Collect, CollectionContext};
|
||||
use gc_arena::Collect;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
/// An intermediate format of representing shared data between ActionScript and elsewhere.
|
||||
|
@ -252,19 +252,14 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Default, Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub struct ExternalInterface<'gc> {
|
||||
#[collect(require_static)]
|
||||
providers: Vec<Box<dyn ExternalInterfaceProvider>>,
|
||||
callbacks: BTreeMap<String, Callback<'gc>>,
|
||||
}
|
||||
|
||||
unsafe impl Collect for ExternalInterface<'_> {
|
||||
#[inline]
|
||||
fn trace(&self, cc: CollectionContext) {
|
||||
self.callbacks.trace(cc);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> ExternalInterface<'gc> {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
|
|
|
@ -259,7 +259,8 @@ impl<'gc> Default for LoadManager<'gc> {
|
|||
}
|
||||
|
||||
/// The completion status of a `Loader` loading a movie.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Collect)]
|
||||
#[collect(require_static)]
|
||||
pub enum LoaderStatus {
|
||||
/// The movie hasn't been loaded yet.
|
||||
Pending,
|
||||
|
@ -270,16 +271,20 @@ pub enum LoaderStatus {
|
|||
}
|
||||
|
||||
/// A struct that holds garbage-collected pointers for asynchronous code.
|
||||
#[derive(Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub enum Loader<'gc> {
|
||||
/// Loader that is loading the root movie of a player.
|
||||
RootMovie {
|
||||
/// The handle to refer to this loader instance.
|
||||
#[collect(require_static)]
|
||||
self_handle: Option<Handle>,
|
||||
},
|
||||
|
||||
/// 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<Handle>,
|
||||
|
||||
/// The target movie clip to load the movie into.
|
||||
|
@ -303,6 +308,7 @@ pub enum Loader<'gc> {
|
|||
/// Loader that is loading form data into an AVM1 object scope.
|
||||
Form {
|
||||
/// The handle to refer to this loader instance.
|
||||
#[collect(require_static)]
|
||||
self_handle: Option<Handle>,
|
||||
|
||||
/// The target AVM1 object to load form data into.
|
||||
|
@ -312,6 +318,7 @@ pub enum Loader<'gc> {
|
|||
/// Loader that is loading form data into an AVM1 LoadVars object.
|
||||
LoadVars {
|
||||
/// The handle to refer to this loader instance.
|
||||
#[collect(require_static)]
|
||||
self_handle: Option<Handle>,
|
||||
|
||||
/// The target AVM1 object to load form data into.
|
||||
|
@ -321,6 +328,7 @@ pub enum Loader<'gc> {
|
|||
/// Loader that is loading XML data into an XML tree.
|
||||
Xml {
|
||||
/// The handle to refer to this loader instance.
|
||||
#[collect(require_static)]
|
||||
self_handle: Option<Handle>,
|
||||
|
||||
/// The active movie clip at the time of load invocation.
|
||||
|
@ -336,25 +344,6 @@ pub enum Loader<'gc> {
|
|||
},
|
||||
}
|
||||
|
||||
unsafe impl<'gc> Collect for Loader<'gc> {
|
||||
fn trace(&self, cc: CollectionContext) {
|
||||
match self {
|
||||
Loader::RootMovie { .. } => {}
|
||||
Loader::Movie {
|
||||
target_clip,
|
||||
target_broadcaster,
|
||||
..
|
||||
} => {
|
||||
target_clip.trace(cc);
|
||||
target_broadcaster.trace(cc);
|
||||
}
|
||||
Loader::Form { target_object, .. } => target_object.trace(cc),
|
||||
Loader::LoadVars { target_object, .. } => target_object.trace(cc),
|
||||
Loader::Xml { target_node, .. } => target_node.trace(cc),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> Loader<'gc> {
|
||||
/// Set the loader handle for this loader.
|
||||
///
|
||||
|
|
|
@ -1491,19 +1491,17 @@ impl Player {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub struct DragObject<'gc> {
|
||||
/// The display object being dragged.
|
||||
pub display_object: DisplayObject<'gc>,
|
||||
|
||||
/// The offset from the mouse position to the center of the clip.
|
||||
#[collect(require_static)]
|
||||
pub offset: (Twips, Twips),
|
||||
|
||||
/// The bounding rectangle where the clip will be maintained.
|
||||
#[collect(require_static)]
|
||||
pub constraint: BoundingBox,
|
||||
}
|
||||
|
||||
unsafe impl<'gc> gc_arena::Collect for DragObject<'gc> {
|
||||
fn trace(&self, cc: gc_arena::CollectionContext) {
|
||||
self.display_object.trace(cc);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Error types used in XML handling
|
||||
|
||||
use gc_arena::{Collect, CollectionContext};
|
||||
use gc_arena::Collect;
|
||||
use quick_xml::Error as QXError;
|
||||
use std::error::Error as StdError;
|
||||
use std::fmt::Error as FmtError;
|
||||
|
@ -77,14 +77,10 @@ impl From<QXError> for Error {
|
|||
/// We can't clone `quick_xml` errors, nor can we clone several of the error
|
||||
/// types it wraps over, so this creates an RC boxed version of the error that
|
||||
/// can then be used elsewhere.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Collect)]
|
||||
#[collect(require_static)]
|
||||
pub struct ParseError(Rc<QXError>);
|
||||
|
||||
unsafe impl Collect for ParseError {
|
||||
/// ParseError does not contain GC pointers.
|
||||
fn trace(&self, _cc: CollectionContext<'_>) {}
|
||||
}
|
||||
|
||||
impl ParseError {
|
||||
///Convert a quick_xml error into a `ParseError`.
|
||||
pub fn from_quickxml_error(err: QXError) -> Self {
|
||||
|
|
Loading…
Reference in New Issue