From 620820be9ecc8c6de8e358128cc48173781640d9 Mon Sep 17 00:00:00 2001 From: = Date: Sat, 20 Aug 2022 22:36:51 +0200 Subject: [PATCH] core: Replaced tag_utils Error with an actual Error enum --- core/src/avm2.rs | 5 +- core/src/display_object/movie_clip.rs | 12 +--- core/src/loader.rs | 80 +++++++++++++++------------ core/src/tag_utils.rs | 31 ++++++++++- 4 files changed, 80 insertions(+), 48 deletions(-) diff --git a/core/src/avm2.rs b/core/src/avm2.rs index 759d61bdc..cb844748c 100644 --- a/core/src/avm2.rs +++ b/core/src/avm2.rs @@ -267,7 +267,7 @@ impl<'gc> Avm2<'gc> { domain: Domain<'gc>, reader: &mut SwfStream<'_>, tag_len: usize, - ) -> Result<(), Error> { + ) -> Result<(), crate::tag_utils::Error> { let start = reader.as_slice(); // Queue the actions. // TODO: The tag reader parses the entire ABC file, instead of just @@ -282,7 +282,8 @@ impl<'gc> Avm2<'gc> { let slice = swf.resize_to_reader(reader, tag_len - num_read); if !slice.is_empty() { - Avm2::load_abc(slice, &name, is_lazy_initialize, context, domain)?; + Avm2::load_abc(slice, &name, is_lazy_initialize, context, domain) + .map_err(|e| crate::tag_utils::Error::InvalidABC(e.to_string()))?; } Ok(()) diff --git a/core/src/display_object/movie_clip.rs b/core/src/display_object/movie_clip.rs index 5fd079cdb..434b6d2ad 100644 --- a/core/src/display_object/movie_clip.rs +++ b/core/src/display_object/movie_clip.rs @@ -34,7 +34,7 @@ use crate::events::{ButtonKeyCode, ClipEvent, ClipEventResult}; use crate::font::Font; use crate::prelude::*; use crate::string::{AvmString, WStr, WString}; -use crate::tag_utils::{self, DecodeResult, SwfMovie, SwfSlice, SwfStream}; +use crate::tag_utils::{self, DecodeResult, Error, SwfMovie, SwfSlice, SwfStream}; use crate::vminterface::{AvmObject, Instantiator}; use gc_arena::{Collect, Gc, GcCell, MutationContext}; use smallvec::SmallVec; @@ -589,9 +589,7 @@ impl<'gc> MovieClip<'gc> { context: &mut UpdateContext<'_, 'gc, '_>, reader: &mut SwfStream<'_>, ) -> DecodeResult { - let movie = self - .movie() - .ok_or("Attempted to set symbol classes on movie without any")?; + let movie = self.movie().ok_or(Error::NoSymbolClasses)?; let mut activation = Avm2Activation::from_nothing(context.reborrow()); let num_symbols = reader.read_u16()?; @@ -2633,11 +2631,7 @@ impl<'gc, 'a> MovieClipData<'gc> { Ok(()) } - _ => Err(format!( - "Attempted to preload video frames into non-video character {}", - vframe.stream_id - ) - .into()), + _ => Err(Error::PreloadVideoIntoInvalidCharacter(vframe.stream_id)), } } diff --git a/core/src/loader.rs b/core/src/loader.rs index 431535973..f8414da3f 100644 --- a/core/src/loader.rs +++ b/core/src/loader.rs @@ -134,6 +134,11 @@ pub enum Error { // the GC arena). We're losing info here. How do we fix that? #[error("Error running avm1 script: {0}")] Avm1Error(String), + + // TODO: We can't support lifetimes on this error object yet (or we'll need some backends inside + // the GC arena). We're losing info here. How do we fix that? + #[error("Error running avm2 script: {0}")] + Avm2Error(String), } impl From> for Error { @@ -579,10 +584,8 @@ impl<'gc> Loader<'gc> { event_handler { let mut loader = loader_info - .get_property( - &Multiname::public("loader"), - &mut activation, - )? + .get_property(&Multiname::public("loader"), &mut activation) + .map_err(|e| Error::Avm2Error(e.to_string()))? .as_object() .unwrap() .as_display_object() @@ -879,16 +882,18 @@ impl<'gc> Loader<'gc> { // FIXME - Match the exact error message generated by Flash let io_error_evt_cls = activation.avm2().classes().ioerrorevent; - let io_error_evt = io_error_evt_cls.construct( - &mut activation, - &[ - "ioError".into(), - false.into(), - false.into(), - "Error #2032: Stream Error".into(), - 2032.into(), - ], - )?; + let io_error_evt = io_error_evt_cls + .construct( + &mut activation, + &[ + "ioError".into(), + false.into(), + false.into(), + "Error #2032: Stream Error".into(), + 2032.into(), + ], + ) + .map_err(|e| Error::Avm2Error(e.to_string()))?; if let Err(e) = Avm2::dispatch_event(uc, io_error_evt, target) { log::error!( @@ -990,16 +995,21 @@ impl<'gc> Loader<'gc> { Some(MovieLoaderEventHandler::Avm2LoaderInfo(loader_info)) => { let mut activation = Avm2Activation::from_nothing(uc.reborrow()); - let progress_evt = activation.avm2().classes().progressevent.construct( - &mut activation, - &[ - "progress".into(), - false.into(), - false.into(), - cur_len.into(), - total_len.into(), - ], - )?; + let progress_evt = activation + .avm2() + .classes() + .progressevent + .construct( + &mut activation, + &[ + "progress".into(), + false.into(), + false.into(), + cur_len.into(), + total_len.into(), + ], + ) + .map_err(|e| Error::Avm2Error(e.to_string()))?; if let Err(e) = Avm2::dispatch_event(uc, progress_evt, loader_info) { log::error!( @@ -1101,16 +1111,18 @@ impl<'gc> Loader<'gc> { // FIXME - Match the exact error message generated by Flash let io_error_evt_cls = activation.avm2().classes().ioerrorevent; - let io_error_evt = io_error_evt_cls.construct( - &mut activation, - &[ - "ioError".into(), - false.into(), - false.into(), - "Movie loader error".into(), - 0.into(), - ], - )?; + let io_error_evt = io_error_evt_cls + .construct( + &mut activation, + &[ + "ioError".into(), + false.into(), + false.into(), + "Movie loader error".into(), + 0.into(), + ], + ) + .map_err(|e| Error::Avm2Error(e.to_string()))?; if let Err(e) = Avm2::dispatch_event(uc, io_error_evt, loader_info) { log::error!( diff --git a/core/src/tag_utils.rs b/core/src/tag_utils.rs index d9e135cf8..f1dc1581f 100644 --- a/core/src/tag_utils.rs +++ b/core/src/tag_utils.rs @@ -1,8 +1,33 @@ use gc_arena::Collect; use std::sync::Arc; -use swf::{Fixed8, HeaderExt, Rectangle, TagCode, Twips}; +use swf::{CharacterId, Fixed8, HeaderExt, Rectangle, TagCode, Twips}; +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum Error { + #[error("Couldn't read SWF")] + InvalidSwf(#[from] swf::error::Error), + + #[error("Couldn't register bitmap")] + InvalidBitmap(#[from] ruffle_render::error::Error), + + #[error("Attempted to set symbol classes on movie without any")] + NoSymbolClasses, + + #[error("Attempted to preload video frames into non-video character {0}")] + PreloadVideoIntoInvalidCharacter(CharacterId), + + #[error("IO Error")] + IOError(#[from] std::io::Error), + + #[error("Invalid SWF url")] + InvalidSwfUrl, + + // TODO: Replace avm2 errors with something more substantial + #[error("Invalid ABC: {0}")] + InvalidABC(String), +} -pub type Error = Box; pub type DecodeResult = Result<(), Error>; pub type SwfStream<'a> = swf::read::Reader<'a>; @@ -57,7 +82,7 @@ impl SwfMovie { let data = std::fs::read(&path)?; let abs_path = path.as_ref().canonicalize()?; - let url = url::Url::from_file_path(abs_path).map_err(|()| "Invalid SWF URL")?; + let url = url::Url::from_file_path(abs_path).map_err(|()| Error::InvalidSwfUrl)?; Self::from_data(&data, Some(url.into()), loader_url) }