diff --git a/core/src/avm1.rs b/core/src/avm1.rs index f2f3aa636..6f60753b8 100644 --- a/core/src/avm1.rs +++ b/core/src/avm1.rs @@ -47,7 +47,7 @@ pub mod xml_object; #[cfg(test)] mod tests; -use crate::avm1::error::ExecutionError; +use crate::avm1::error::{Error, ExecutionError}; use crate::avm1::listeners::SystemListener; use crate::avm1::value::f64_to_wrapping_u32; pub use activation::Activation; @@ -115,8 +115,6 @@ unsafe impl<'gc> gc_arena::Collect for Avm1<'gc> { } } -type Error = Box; - impl<'gc> Avm1<'gc> { pub fn new(gc_context: MutationContext<'gc, '_>, player_version: u8) -> Self { let (prototypes, globals, system_listeners) = create_globals(gc_context); @@ -1066,7 +1064,7 @@ impl<'gc> Avm1<'gc> { action: swf::avm1::types::Action, ) -> Result<(), Error> { log::error!("Unknown AVM1 opcode: {:?}", action); - Err("Unknown op".into()) + Ok(()) } fn action_add(&mut self, _context: &mut UpdateContext) -> Result<(), Error> { @@ -1300,11 +1298,11 @@ impl<'gc> Avm1<'gc> { } } _ => { - return Err(format!( + self.push(Value::Undefined); + log::warn!( "Invalid method name, expected string but found {:?}", method_name - ) - .into()) + ); } } @@ -1700,17 +1698,25 @@ impl<'gc> Avm1<'gc> { ) -> Result<(), Error> { if target.starts_with("_level") && target.len() > 6 { let url = url.to_string(); - let level_id = target[6..].parse::()?; - let fetch = context.navigator.fetch(&url, RequestOptions::get()); - let level = self.resolve_level(level_id, context); + match target[6..].parse::() { + Ok(level_id) => { + let fetch = context.navigator.fetch(&url, RequestOptions::get()); + let level = self.resolve_level(level_id, context); - let process = context.load_manager.load_movie_into_clip( - context.player.clone().unwrap(), - level, - fetch, - None, - ); - context.navigator.spawn_future(process); + let process = context.load_manager.load_movie_into_clip( + context.player.clone().unwrap(), + level, + fetch, + None, + ); + context.navigator.spawn_future(process); + } + Err(e) => log::warn!( + "Couldn't parse level id {} for action_get_url: {}", + target, + e + ), + } return Ok(()); } @@ -2015,8 +2021,11 @@ impl<'gc> Avm1<'gc> { ) -> Result<(), Error> { // TODO(Herschel): Results on incorrect operands? use std::convert::TryFrom; - let val = char::try_from(self.pop().coerce_to_f64(self, context)? as u32)?; - self.push(val.to_string()); + let result = char::try_from(self.pop().coerce_to_f64(self, context)? as u32); + match result { + Ok(val) => self.push(val.to_string()), + Err(e) => log::warn!("Couldn't parse char for action_mb_ascii_to_char: {}", e), + } Ok(()) } @@ -2254,7 +2263,8 @@ impl<'gc> Avm1<'gc> { } fn action_push_duplicate(&mut self, _context: &mut UpdateContext) -> Result<(), Error> { - let val = self.stack.last().ok_or("Stack underflow")?.clone(); + let val = self.pop(); + self.push(val.clone()); self.push(val); Ok(()) } @@ -2290,7 +2300,9 @@ impl<'gc> Avm1<'gc> { fn action_return(&mut self, context: &mut UpdateContext<'_, 'gc, '_>) -> Result<(), Error> { let return_value = self.pop(); - self.retire_stack_frame(context, return_value)?; + if let Err(e) = self.retire_stack_frame(context, return_value) { + log::warn!("Couldn't return from stack frame: {}", e); + } Ok(()) } @@ -2496,8 +2508,9 @@ impl<'gc> Avm1<'gc> { context: &mut UpdateContext<'_, 'gc, '_>, register: u8, ) -> Result<(), Error> { - // Does NOT pop the value from the stack. - let val = self.stack.last().ok_or("Stack underflow")?.clone(); + // The value must remain on the stack. + let val = self.pop(); + self.push(val.clone()); self.set_current_register(register, val, context); Ok(()) @@ -2606,7 +2619,8 @@ impl<'gc> Avm1<'gc> { // TODO(Herschel) let _clip = self.pop().coerce_to_object(self, context); self.push(Value::Undefined); - Err("Unimplemented action: TargetPath".into()) + log::warn!("Unimplemented action: TargetPath"); + Ok(()) } fn toggle_quality(&mut self, _context: &mut UpdateContext) -> Result<(), Error> { @@ -2664,7 +2678,7 @@ impl<'gc> Avm1<'gc> { if !loaded { // Note that the offset is given in # of actions, NOT in bytes. // Read the actions and toss them away. - skip_actions(r, num_actions_to_skip)?; + skip_actions(r, num_actions_to_skip); } Ok(()) } @@ -2681,7 +2695,7 @@ impl<'gc> Avm1<'gc> { if !loaded { // Note that the offset is given in # of actions, NOT in bytes. // Read the actions and toss them away. - skip_actions(r, num_actions_to_skip)?; + skip_actions(r, num_actions_to_skip); } Ok(()) } @@ -2723,12 +2737,12 @@ pub fn is_swf_case_sensitive(swf_version: u8) -> bool { /// Utility function used by `Avm1::action_wait_for_frame` and /// `Avm1::action_wait_for_frame_2`. -fn skip_actions(reader: &mut Reader<'_>, num_actions_to_skip: u8) -> Result<(), Error> { +fn skip_actions(reader: &mut Reader<'_>, num_actions_to_skip: u8) { for _ in 0..num_actions_to_skip { - reader.read_action()?; + if let Err(e) = reader.read_action() { + log::warn!("Couldn't skip action: {}", e); + } } - - Ok(()) } /// Starts draggining this display object, making it follow the cursor. diff --git a/core/src/avm1/activation.rs b/core/src/avm1/activation.rs index 6485e37f0..07bb984b1 100644 --- a/core/src/avm1/activation.rs +++ b/core/src/avm1/activation.rs @@ -1,9 +1,10 @@ //! Activation records +use crate::avm1::error::Error; use crate::avm1::error::ExecutionError; use crate::avm1::return_value::ReturnValue; use crate::avm1::scope::Scope; -use crate::avm1::{Avm1, Error, Object, Value}; +use crate::avm1::{Avm1, Object, Value}; use crate::context::UpdateContext; use crate::display_object::DisplayObject; use crate::tag_utils::SwfSlice; diff --git a/core/src/avm1/debug.rs b/core/src/avm1/debug.rs index a42b3c8c9..2c35601df 100644 --- a/core/src/avm1/debug.rs +++ b/core/src/avm1/debug.rs @@ -207,7 +207,7 @@ mod tests { _this: Object<'gc>, _args: &[Value<'gc>], ) -> Result, Error> { - Err("Error message!".into()) + Err(Error::PrototypeRecursionLimit) } #[test] @@ -331,7 +331,7 @@ mod tests { ); assert_eq!( VariableDumper::dump(&object.into(), " ", avm, context), - "[object #0] {\n broken_value: Error: \"Error message!\"\n}" + "[object #0] {\n broken_value: Error: \"Prototype recursion limit has been exceeded\"\n}" ); Ok(()) }) diff --git a/core/src/avm1/error.rs b/core/src/avm1/error.rs index d27cd82cc..36c6073b1 100644 --- a/core/src/avm1/error.rs +++ b/core/src/avm1/error.rs @@ -1,5 +1,11 @@ use thiserror::Error; +#[derive(Error, Debug)] +pub enum Error { + #[error("Prototype recursion limit has been exceeded")] + PrototypeRecursionLimit, +} + #[derive(Error, Debug)] pub enum ExecutionError { #[error("Couldn't parse SWF")] @@ -15,5 +21,5 @@ pub enum ExecutionError { AlreadyExecutingFrame, #[error("Script error")] - ScriptError(Box), + ScriptError(#[from] Error), } diff --git a/core/src/avm1/fscommand.rs b/core/src/avm1/fscommand.rs index 5c83a8b4e..b50408464 100644 --- a/core/src/avm1/fscommand.rs +++ b/core/src/avm1/fscommand.rs @@ -1,6 +1,7 @@ //! FSCommand handling -use crate::avm1::{Avm1, Error, UpdateContext}; +use crate::avm1::error::Error; +use crate::avm1::{Avm1, UpdateContext}; /// Parse an FSCommand URL. pub fn parse(url: &str) -> Option<&str> { diff --git a/core/src/avm1/function.rs b/core/src/avm1/function.rs index 81d638270..00e5ff138 100644 --- a/core/src/avm1/function.rs +++ b/core/src/avm1/function.rs @@ -1,12 +1,13 @@ //! Code relating to executable functions + calling conventions. use crate::avm1::activation::Activation; +use crate::avm1::error::Error; use crate::avm1::property::{Attribute, Attribute::*}; use crate::avm1::return_value::ReturnValue; use crate::avm1::scope::Scope; use crate::avm1::super_object::SuperObject; use crate::avm1::value::Value; -use crate::avm1::{Avm1, Error, Object, ObjectPtr, ScriptObject, TObject, UpdateContext}; +use crate::avm1::{Avm1, Object, ObjectPtr, ScriptObject, TObject, UpdateContext}; use crate::display_object::{DisplayObject, TDisplayObject}; use crate::tag_utils::SwfSlice; use enumset::EnumSet; diff --git a/core/src/avm1/globals.rs b/core/src/avm1/globals.rs index 921ff6f8b..3de3e0d59 100644 --- a/core/src/avm1/globals.rs +++ b/core/src/avm1/globals.rs @@ -1,8 +1,9 @@ +use crate::avm1::error::Error; use crate::avm1::fscommand; use crate::avm1::function::{Executable, FunctionObject}; use crate::avm1::listeners::SystemListeners; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, Object, ScriptObject, TObject, UpdateContext, Value}; +use crate::avm1::{Avm1, Object, ScriptObject, TObject, UpdateContext, Value}; use crate::backend::navigator::NavigationMethod; use enumset::EnumSet; use gc_arena::MutationContext; diff --git a/core/src/avm1/globals/array.rs b/core/src/avm1/globals/array.rs index b49b379c1..eea2d7ace 100644 --- a/core/src/avm1/globals/array.rs +++ b/core/src/avm1/globals/array.rs @@ -1,9 +1,10 @@ //! Array class +use crate::avm1::error::Error; use crate::avm1::function::{Executable, FunctionObject}; use crate::avm1::property::Attribute; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, Object, ScriptObject, TObject, UpdateContext, Value}; +use crate::avm1::{Avm1, Object, ScriptObject, TObject, UpdateContext, Value}; use enumset::EnumSet; use gc_arena::MutationContext; use smallvec::alloc::borrow::Cow; diff --git a/core/src/avm1/globals/boolean.rs b/core/src/avm1/globals/boolean.rs index 21254b90a..3d8c4c967 100644 --- a/core/src/avm1/globals/boolean.rs +++ b/core/src/avm1/globals/boolean.rs @@ -1,9 +1,10 @@ //! `Boolean` class impl +use crate::avm1::error::Error; use crate::avm1::function::{Executable, FunctionObject}; use crate::avm1::return_value::ReturnValue; use crate::avm1::value_object::ValueObject; -use crate::avm1::{Avm1, Error, Object, TObject, Value}; +use crate::avm1::{Avm1, Object, TObject, Value}; use crate::context::UpdateContext; use enumset::EnumSet; use gc_arena::MutationContext; diff --git a/core/src/avm1/globals/button.rs b/core/src/avm1/globals/button.rs index 6211b27fc..cb54aa57b 100644 --- a/core/src/avm1/globals/button.rs +++ b/core/src/avm1/globals/button.rs @@ -1,8 +1,9 @@ //! Button/SimpleButton prototype +use crate::avm1::error::Error; use crate::avm1::globals::display_object; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, Object, ScriptObject, UpdateContext, Value}; +use crate::avm1::{Avm1, Object, ScriptObject, UpdateContext, Value}; use gc_arena::MutationContext; pub fn create_proto<'gc>( diff --git a/core/src/avm1/globals/color.rs b/core/src/avm1/globals/color.rs index 69847feb8..94df46a83 100644 --- a/core/src/avm1/globals/color.rs +++ b/core/src/avm1/globals/color.rs @@ -3,9 +3,10 @@ //! TODO: This should change when `ColorTransform` changes to match Flash's representation //! (See GitHub #193) +use crate::avm1::error::Error; use crate::avm1::property::Attribute::*; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, Object, ScriptObject, TObject, UpdateContext, Value}; +use crate::avm1::{Avm1, Object, ScriptObject, TObject, UpdateContext, Value}; use crate::display_object::{DisplayObject, TDisplayObject}; use enumset::EnumSet; use gc_arena::MutationContext; diff --git a/core/src/avm1/globals/display_object.rs b/core/src/avm1/globals/display_object.rs index 02ebb21ee..f99c70223 100644 --- a/core/src/avm1/globals/display_object.rs +++ b/core/src/avm1/globals/display_object.rs @@ -1,9 +1,10 @@ //! DisplayObject common methods +use crate::avm1::error::Error; use crate::avm1::function::Executable; use crate::avm1::property::Attribute::*; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, Object, ScriptObject, TObject, UpdateContext, Value}; +use crate::avm1::{Avm1, Object, ScriptObject, TObject, UpdateContext, Value}; use crate::display_object::{DisplayObject, TDisplayObject}; use enumset::EnumSet; use gc_arena::MutationContext; diff --git a/core/src/avm1/globals/function.rs b/core/src/avm1/globals/function.rs index 5bad43309..e7f9971e8 100644 --- a/core/src/avm1/globals/function.rs +++ b/core/src/avm1/globals/function.rs @@ -1,7 +1,8 @@ //! Function prototype +use crate::avm1::error::Error; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, Object, ScriptObject, TObject, UpdateContext, Value}; +use crate::avm1::{Avm1, Object, ScriptObject, TObject, UpdateContext, Value}; use enumset::EnumSet; use gc_arena::MutationContext; diff --git a/core/src/avm1/globals/key.rs b/core/src/avm1/globals/key.rs index a10da8171..ec6f19280 100644 --- a/core/src/avm1/globals/key.rs +++ b/core/src/avm1/globals/key.rs @@ -1,6 +1,7 @@ +use crate::avm1::error::Error; use crate::avm1::property::Attribute; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, Object, ScriptObject, TObject, UpdateContext, Value}; +use crate::avm1::{Avm1, Object, ScriptObject, TObject, UpdateContext, Value}; use crate::events::KeyCode; use gc_arena::MutationContext; diff --git a/core/src/avm1/globals/math.rs b/core/src/avm1/globals/math.rs index 906649086..92fa22276 100644 --- a/core/src/avm1/globals/math.rs +++ b/core/src/avm1/globals/math.rs @@ -1,7 +1,8 @@ +use crate::avm1::error::Error; use crate::avm1::object::Object; use crate::avm1::property::Attribute::*; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, ScriptObject, TObject, UpdateContext, Value}; +use crate::avm1::{Avm1, ScriptObject, TObject, UpdateContext, Value}; use gc_arena::MutationContext; use rand::Rng; use std::f64::{INFINITY, NAN, NEG_INFINITY}; diff --git a/core/src/avm1/globals/matrix.rs b/core/src/avm1/globals/matrix.rs index 28b967cc3..807d5f8b5 100644 --- a/core/src/avm1/globals/matrix.rs +++ b/core/src/avm1/globals/matrix.rs @@ -1,8 +1,9 @@ //! flash.geom.Matrix +use crate::avm1::error::Error; use crate::avm1::function::{Executable, FunctionObject}; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, Object, ScriptObject, TObject, Value}; +use crate::avm1::{Avm1, Object, ScriptObject, TObject, Value}; use crate::context::UpdateContext; use enumset::EnumSet; use gc_arena::MutationContext; diff --git a/core/src/avm1/globals/mouse.rs b/core/src/avm1/globals/mouse.rs index 5419f74b1..5b326bc40 100644 --- a/core/src/avm1/globals/mouse.rs +++ b/core/src/avm1/globals/mouse.rs @@ -1,7 +1,8 @@ +use crate::avm1::error::Error; use crate::avm1::listeners::Listeners; use crate::avm1::property::Attribute; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, Object, ScriptObject, TObject, UpdateContext, Value}; +use crate::avm1::{Avm1, Object, ScriptObject, TObject, UpdateContext, Value}; use gc_arena::MutationContext; diff --git a/core/src/avm1/globals/movie_clip.rs b/core/src/avm1/globals/movie_clip.rs index 451054be4..f9c9846ff 100644 --- a/core/src/avm1/globals/movie_clip.rs +++ b/core/src/avm1/globals/movie_clip.rs @@ -1,10 +1,11 @@ //! MovieClip prototype +use crate::avm1::error::Error; use crate::avm1::globals::display_object::{self, AVM_DEPTH_BIAS, AVM_MAX_DEPTH}; use crate::avm1::globals::matrix::gradient_object_to_matrix; use crate::avm1::property::Attribute::*; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, Object, ScriptObject, TObject, UpdateContext, Value}; +use crate::avm1::{Avm1, Object, ScriptObject, TObject, UpdateContext, Value}; use crate::backend::navigator::NavigationMethod; use crate::display_object::{DisplayObject, EditText, MovieClip, TDisplayObject}; use crate::prelude::*; diff --git a/core/src/avm1/globals/movie_clip_loader.rs b/core/src/avm1/globals/movie_clip_loader.rs index 1337a532c..6056c79d8 100644 --- a/core/src/avm1/globals/movie_clip_loader.rs +++ b/core/src/avm1/globals/movie_clip_loader.rs @@ -1,10 +1,11 @@ //! `MovieClipLoader` impl +use crate::avm1::error::Error; use crate::avm1::object::TObject; use crate::avm1::property::Attribute; use crate::avm1::return_value::ReturnValue; use crate::avm1::script_object::ScriptObject; -use crate::avm1::{Avm1, Error, Object, UpdateContext, Value}; +use crate::avm1::{Avm1, Object, UpdateContext, Value}; use crate::backend::navigator::RequestOptions; use crate::display_object::{DisplayObject, TDisplayObject}; use enumset::EnumSet; diff --git a/core/src/avm1/globals/number.rs b/core/src/avm1/globals/number.rs index 27b4bdeb2..13a5b2175 100644 --- a/core/src/avm1/globals/number.rs +++ b/core/src/avm1/globals/number.rs @@ -1,10 +1,11 @@ //! `Number` class impl +use crate::avm1::error::Error; use crate::avm1::function::{Executable, FunctionObject}; use crate::avm1::property::Attribute::*; use crate::avm1::return_value::ReturnValue; use crate::avm1::value_object::ValueObject; -use crate::avm1::{Avm1, Error, Object, TObject, Value}; +use crate::avm1::{Avm1, Object, TObject, Value}; use crate::context::UpdateContext; use enumset::EnumSet; use gc_arena::MutationContext; diff --git a/core/src/avm1/globals/object.rs b/core/src/avm1/globals/object.rs index f265f15d0..9568b41fb 100644 --- a/core/src/avm1/globals/object.rs +++ b/core/src/avm1/globals/object.rs @@ -1,8 +1,9 @@ //! Object prototype +use crate::avm1::error::Error; use crate::avm1::function::{Executable, FunctionObject}; use crate::avm1::property::Attribute::{self, *}; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, Object, TObject, UpdateContext, Value}; +use crate::avm1::{Avm1, Object, TObject, UpdateContext, Value}; use crate::character::Character; use enumset::EnumSet; use gc_arena::MutationContext; @@ -228,18 +229,15 @@ pub fn as_set_prop_flags<'gc>( _: Object<'gc>, args: &[Value<'gc>], ) -> Result, Error> { - //This exists because `.into` won't work inline - let my_error: Result, Error> = - Err("ASSetPropFlags called without object to apply to!".into()); - let my_error_2: Result, Error> = - Err("ASSetPropFlags called without object list!".into()); + let mut object = if let Some(object) = args.get(0).map(|v| v.coerce_to_object(avm, ac)) { + object + } else { + log::warn!("ASSetPropFlags called without object to apply to!"); + return Ok(Value::Undefined.into()); + }; - let mut object = args - .get(0) - .ok_or_else(|| my_error.unwrap_err())? - .coerce_to_object(avm, ac); - let properties = match args.get(1).ok_or_else(|| my_error_2.unwrap_err())? { - Value::Object(ob) => { + let properties = match args.get(1) { + Some(Value::Object(ob)) => { //Convert to native array. //TODO: Can we make this an iterator? let mut array = vec![]; @@ -254,8 +252,12 @@ pub fn as_set_prop_flags<'gc>( Some(array) } - Value::String(s) => Some(s.split(',').map(String::from).collect()), - _ => None, + Some(Value::String(s)) => Some(s.split(',').map(String::from).collect()), + Some(_) => None, + None => { + log::warn!("ASSetPropFlags called without object list!"); + return Ok(Value::Undefined.into()); + } }; let set_attributes = EnumSet::::from_u128( diff --git a/core/src/avm1/globals/point.rs b/core/src/avm1/globals/point.rs index 28369fd6a..11f294d10 100644 --- a/core/src/avm1/globals/point.rs +++ b/core/src/avm1/globals/point.rs @@ -1,9 +1,10 @@ //! flash.geom.Point +use crate::avm1::error::Error; use crate::avm1::function::{Executable, FunctionObject}; use crate::avm1::property::Attribute; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, Object, ScriptObject, TObject, Value}; +use crate::avm1::{Avm1, Object, ScriptObject, TObject, Value}; use crate::context::UpdateContext; use enumset::EnumSet; use gc_arena::MutationContext; diff --git a/core/src/avm1/globals/rectangle.rs b/core/src/avm1/globals/rectangle.rs index 098048168..3c6681e20 100644 --- a/core/src/avm1/globals/rectangle.rs +++ b/core/src/avm1/globals/rectangle.rs @@ -1,10 +1,11 @@ //! flash.geom.Rectangle +use crate::avm1::error::Error; use crate::avm1::function::{Executable, FunctionObject}; use crate::avm1::globals::point::{construct_new_point, point_to_object, value_to_point}; use crate::avm1::property::Attribute; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, Object, ScriptObject, TObject, Value}; +use crate::avm1::{Avm1, Object, ScriptObject, TObject, Value}; use crate::context::UpdateContext; use enumset::EnumSet; use gc_arena::MutationContext; diff --git a/core/src/avm1/globals/sound.rs b/core/src/avm1/globals/sound.rs index 578ef9504..6f0fc2498 100644 --- a/core/src/avm1/globals/sound.rs +++ b/core/src/avm1/globals/sound.rs @@ -1,10 +1,11 @@ //! AVM1 Sound object //! TODO: Sound position, transform, loadSound +use crate::avm1::error::Error; use crate::avm1::function::Executable; use crate::avm1::property::Attribute::*; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, Object, SoundObject, TObject, UpdateContext, Value}; +use crate::avm1::{Avm1, Object, SoundObject, TObject, UpdateContext, Value}; use crate::character::Character; use crate::display_object::TDisplayObject; use gc_arena::MutationContext; diff --git a/core/src/avm1/globals/stage.rs b/core/src/avm1/globals/stage.rs index de6876a8f..df389365a 100644 --- a/core/src/avm1/globals/stage.rs +++ b/core/src/avm1/globals/stage.rs @@ -1,10 +1,11 @@ //! Stage object //! //! TODO: This is a very rough stub with not much implementation. +use crate::avm1::error::Error; use crate::avm1::function::Executable; use crate::avm1::property::Attribute; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, Object, ScriptObject, TObject, UpdateContext, Value}; +use crate::avm1::{Avm1, Object, ScriptObject, TObject, UpdateContext, Value}; use gc_arena::MutationContext; diff --git a/core/src/avm1/globals/string.rs b/core/src/avm1/globals/string.rs index e9d5f304d..7557a45db 100644 --- a/core/src/avm1/globals/string.rs +++ b/core/src/avm1/globals/string.rs @@ -1,10 +1,11 @@ //! `String` class impl +use crate::avm1::error::Error; use crate::avm1::function::{Executable, FunctionObject}; use crate::avm1::property::Attribute::*; use crate::avm1::return_value::ReturnValue; use crate::avm1::value_object::ValueObject; -use crate::avm1::{Avm1, Error, Object, ScriptObject, TObject, Value}; +use crate::avm1::{Avm1, Object, ScriptObject, TObject, Value}; use crate::context::UpdateContext; use crate::string_utils; use enumset::EnumSet; diff --git a/core/src/avm1/globals/system.rs b/core/src/avm1/globals/system.rs index b4909d723..e2a59c51a 100644 --- a/core/src/avm1/globals/system.rs +++ b/core/src/avm1/globals/system.rs @@ -1,7 +1,8 @@ +use crate::avm1::error::Error; use crate::avm1::function::Executable; use crate::avm1::object::Object; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, ScriptObject, TObject, Value}; +use crate::avm1::{Avm1, ScriptObject, TObject, Value}; use crate::context::UpdateContext; use core::fmt; use enumset::{EnumSet, EnumSetType}; diff --git a/core/src/avm1/globals/system_capabilities.rs b/core/src/avm1/globals/system_capabilities.rs index 8f658dc16..3dd0f0b65 100644 --- a/core/src/avm1/globals/system_capabilities.rs +++ b/core/src/avm1/globals/system_capabilities.rs @@ -1,8 +1,9 @@ +use crate::avm1::error::Error; use crate::avm1::function::Executable; use crate::avm1::globals::system::SystemCapabilities; use crate::avm1::object::Object; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, ScriptObject, TObject, Value}; +use crate::avm1::{Avm1, ScriptObject, TObject, Value}; use crate::context::UpdateContext; use enumset::EnumSet; use gc_arena::MutationContext; diff --git a/core/src/avm1/globals/system_ime.rs b/core/src/avm1/globals/system_ime.rs index af7da07b0..f987f0298 100644 --- a/core/src/avm1/globals/system_ime.rs +++ b/core/src/avm1/globals/system_ime.rs @@ -1,9 +1,10 @@ +use crate::avm1::error::Error; use crate::avm1::listeners::Listeners; use crate::avm1::object::Object; use crate::avm1::property::Attribute; use crate::avm1::property::Attribute::{DontDelete, DontEnum, ReadOnly}; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, ScriptObject, TObject, Value}; +use crate::avm1::{Avm1, ScriptObject, TObject, Value}; use crate::context::UpdateContext; use gc_arena::MutationContext; use std::convert::Into; diff --git a/core/src/avm1/globals/system_security.rs b/core/src/avm1/globals/system_security.rs index cafdd34a2..60a4b85e6 100644 --- a/core/src/avm1/globals/system_security.rs +++ b/core/src/avm1/globals/system_security.rs @@ -1,7 +1,8 @@ +use crate::avm1::error::Error; use crate::avm1::function::Executable; use crate::avm1::object::Object; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, ScriptObject, TObject, Value}; +use crate::avm1::{Avm1, ScriptObject, TObject, Value}; use crate::context::UpdateContext; use enumset::EnumSet; use gc_arena::MutationContext; diff --git a/core/src/avm1/globals/text_field.rs b/core/src/avm1/globals/text_field.rs index 4725221f4..abd59fcdd 100644 --- a/core/src/avm1/globals/text_field.rs +++ b/core/src/avm1/globals/text_field.rs @@ -1,8 +1,9 @@ +use crate::avm1::error::Error; use crate::avm1::function::Executable; use crate::avm1::globals::display_object; use crate::avm1::property::Attribute::*; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, Object, ScriptObject, TObject, UpdateContext, Value}; +use crate::avm1::{Avm1, Object, ScriptObject, TObject, UpdateContext, Value}; use crate::display_object::{EditText, TDisplayObject}; use crate::font::TextFormat; use gc_arena::MutationContext; diff --git a/core/src/avm1/globals/text_format.rs b/core/src/avm1/globals/text_format.rs index d1de7009c..21eab70d0 100644 --- a/core/src/avm1/globals/text_format.rs +++ b/core/src/avm1/globals/text_format.rs @@ -1,7 +1,8 @@ //! `TextFormat` impl +use crate::avm1::error::Error; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, Object, ScriptObject, TObject, UpdateContext, Value}; +use crate::avm1::{Avm1, Object, ScriptObject, TObject, UpdateContext, Value}; use gc_arena::MutationContext; fn map_defined_to_string<'gc>( diff --git a/core/src/avm1/globals/xml.rs b/core/src/avm1/globals/xml.rs index 902f8f4be..1c38a2618 100644 --- a/core/src/avm1/globals/xml.rs +++ b/core/src/avm1/globals/xml.rs @@ -1,11 +1,12 @@ //! XML/XMLNode global classes +use crate::avm1::error::Error; use crate::avm1::function::Executable; use crate::avm1::property::Attribute::*; use crate::avm1::return_value::ReturnValue; use crate::avm1::script_object::ScriptObject; use crate::avm1::xml_object::XMLObject; -use crate::avm1::{Avm1, Error, Object, TObject, UpdateContext, Value}; +use crate::avm1::{Avm1, Object, TObject, UpdateContext, Value}; use crate::backend::navigator::RequestOptions; use crate::xml; use crate::xml::{XMLDocument, XMLNode}; @@ -55,7 +56,7 @@ pub fn xmlnode_constructor<'gc>( this.as_xml_node(), ) { (Some(Ok(1)), Some(Ok(ref strval)), Some(ref mut this_node)) => { - let mut xmlelement = XMLNode::new_element(ac.gc_context, strval, blank_document)?; + let mut xmlelement = XMLNode::new_element(ac.gc_context, strval, blank_document); xmlelement.introduce_script_object(ac.gc_context, this); this_node.swap(ac.gc_context, xmlelement); } @@ -84,7 +85,9 @@ pub fn xmlnode_append_child<'gc>( ) { if let Ok(None) = child_xmlnode.parent() { let position = xmlnode.children_len(); - xmlnode.insert_child(ac.gc_context, position, child_xmlnode)?; + if let Err(e) = xmlnode.insert_child(ac.gc_context, position, child_xmlnode) { + log::warn!("Couldn't insert_child inside of XMLNode.appendChild: {}", e); + } } } @@ -106,7 +109,12 @@ pub fn xmlnode_insert_before<'gc>( ) { if let Ok(None) = child_xmlnode.parent() { if let Some(position) = xmlnode.child_position(insertpoint_xmlnode) { - xmlnode.insert_child(ac.gc_context, position, child_xmlnode)?; + if let Err(e) = xmlnode.insert_child(ac.gc_context, position, child_xmlnode) { + log::warn!( + "Couldn't insert_child inside of XMLNode.insertBefore: {}", + e + ); + } } } } @@ -691,7 +699,9 @@ pub fn xml_constructor<'gc>( xmlnode.introduce_script_object(ac.gc_context, this); this_node.swap(ac.gc_context, xmlnode); - this_node.replace_with_str(ac.gc_context, string)?; + if let Err(e) = this_node.replace_with_str(ac.gc_context, string) { + log::warn!("Couldn't replace_with_str inside of XML constructor: {}", e); + } } (None, Some(ref mut this_node)) => { let xmldoc = XMLDocument::new(ac.gc_context); @@ -722,7 +732,7 @@ pub fn xml_create_element<'gc>( .get(0) .map(|v| v.coerce_to_string(avm, ac).unwrap_or_default()) .unwrap_or_default(); - let mut xml_node = XMLNode::new_element(ac.gc_context, &nodename, document)?; + let mut xml_node = XMLNode::new_element(ac.gc_context, &nodename, document); let object = XMLObject::from_xml_node(ac.gc_context, xml_node, Some(avm.prototypes().xml_node)); xml_node.introduce_script_object(ac.gc_context, object); diff --git a/core/src/avm1/listeners.rs b/core/src/avm1/listeners.rs index 37db1a6b9..680695fa4 100644 --- a/core/src/avm1/listeners.rs +++ b/core/src/avm1/listeners.rs @@ -1,5 +1,6 @@ +use crate::avm1::error::Error; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, Object, ScriptObject, TObject, UpdateContext, Value}; +use crate::avm1::{Avm1, Object, ScriptObject, TObject, UpdateContext, Value}; use gc_arena::{Collect, MutationContext}; diff --git a/core/src/avm1/object.rs b/core/src/avm1/object.rs index bf46f24a9..9cb0a0487 100644 --- a/core/src/avm1/object.rs +++ b/core/src/avm1/object.rs @@ -1,5 +1,6 @@ //! Object trait to expose objects to AVM +use crate::avm1::error::Error; use crate::avm1::function::{Executable, FunctionObject}; use crate::avm1::property::Attribute; use crate::avm1::return_value::ReturnValue; @@ -8,7 +9,7 @@ use crate::avm1::value_object::ValueObject; use crate::avm1::xml_attributes_object::XMLAttributesObject; use crate::avm1::xml_idmap_object::XMLIDMapObject; use crate::avm1::xml_object::XMLObject; -use crate::avm1::{Avm1, Error, ScriptObject, SoundObject, StageObject, UpdateContext, Value}; +use crate::avm1::{Avm1, ScriptObject, SoundObject, StageObject, UpdateContext, Value}; use crate::display_object::DisplayObject; use crate::xml::XMLNode; use enumset::EnumSet; @@ -458,7 +459,7 @@ pub fn search_prototype<'gc>( while proto.is_some() { if depth == 255 { - return Err("Encountered an excessively deep prototype chain.".into()); + return Err(Error::PrototypeRecursionLimit); } if proto.unwrap().has_own_property(avm, context, name) { diff --git a/core/src/avm1/property.rs b/core/src/avm1/property.rs index 5c6d666b5..b81d950d4 100644 --- a/core/src/avm1/property.rs +++ b/core/src/avm1/property.rs @@ -1,9 +1,10 @@ //! User-defined properties use self::Attribute::*; +use crate::avm1::error::Error; use crate::avm1::function::Executable; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, Object, UpdateContext, Value}; +use crate::avm1::{Avm1, Object, UpdateContext, Value}; use core::fmt; use enumset::{EnumSet, EnumSetType}; diff --git a/core/src/avm1/return_value.rs b/core/src/avm1/return_value.rs index 803c90965..7b5f2cc04 100644 --- a/core/src/avm1/return_value.rs +++ b/core/src/avm1/return_value.rs @@ -1,7 +1,9 @@ //! Return value enum use crate::avm1::activation::Activation; -use crate::avm1::{Avm1, Error, Object, Value}; +use crate::avm1::error::Error; +use crate::avm1::error::ExecutionError; +use crate::avm1::{Avm1, Object, Value}; use crate::context::UpdateContext; use gc_arena::{Collect, GcCell}; use std::borrow::Cow; @@ -93,7 +95,18 @@ impl<'gc> ReturnValue<'gc> { match self { Immediate(val) => Ok(val), ResultOf(frame) => { - avm.run_current_frame(context, frame)?; + match avm.run_current_frame(context, frame) { + Err(ExecutionError::ScriptError(e)) => { + return Err(e); + } + Err(e) => { + log::warn!( + "Couldn't resolve value, encountered an avm1 execution error: {}", + e + ); + } + _ => {} + } Ok(avm.pop()) } diff --git a/core/src/avm1/scope.rs b/core/src/avm1/scope.rs index 41c9469e6..dcd2d152b 100644 --- a/core/src/avm1/scope.rs +++ b/core/src/avm1/scope.rs @@ -1,7 +1,8 @@ //! Represents AVM1 scope chain resolution. +use crate::avm1::error::Error; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, Object, ScriptObject, TObject, UpdateContext, Value}; +use crate::avm1::{Avm1, Object, ScriptObject, TObject, UpdateContext, Value}; use enumset::EnumSet; use gc_arena::{GcCell, MutationContext}; use std::cell::Ref; diff --git a/core/src/avm1/script_object.rs b/core/src/avm1/script_object.rs index bd6e218d4..a286ab1ee 100644 --- a/core/src/avm1/script_object.rs +++ b/core/src/avm1/script_object.rs @@ -1,7 +1,8 @@ +use crate::avm1::error::Error; use crate::avm1::function::{Executable, FunctionObject, NativeFunction}; use crate::avm1::property::{Attribute, Property}; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, Object, ObjectPtr, TObject, UpdateContext, Value}; +use crate::avm1::{Avm1, Object, ObjectPtr, TObject, UpdateContext, Value}; use crate::property_map::{Entry, PropertyMap}; use core::fmt; use enumset::EnumSet; diff --git a/core/src/avm1/sound_object.rs b/core/src/avm1/sound_object.rs index 2e7d4d75d..d51e7af0a 100644 --- a/core/src/avm1/sound_object.rs +++ b/core/src/avm1/sound_object.rs @@ -1,9 +1,10 @@ //! AVM1 object type to represent Sound objects. +use crate::avm1::error::Error; use crate::avm1::function::Executable; use crate::avm1::property::Attribute; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, Object, ObjectPtr, ScriptObject, TObject, Value}; +use crate::avm1::{Avm1, Object, ObjectPtr, ScriptObject, TObject, Value}; use crate::backend::audio::{SoundHandle, SoundInstanceHandle}; use crate::context::UpdateContext; use crate::display_object::DisplayObject; diff --git a/core/src/avm1/stage_object.rs b/core/src/avm1/stage_object.rs index 96ad927f6..446d5706f 100644 --- a/core/src/avm1/stage_object.rs +++ b/core/src/avm1/stage_object.rs @@ -1,10 +1,11 @@ //! AVM1 object type to represent objects on the stage. +use crate::avm1::error::Error; use crate::avm1::function::Executable; use crate::avm1::object::search_prototype; use crate::avm1::property::Attribute; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, Object, ObjectPtr, ScriptObject, TDisplayObject, TObject, Value}; +use crate::avm1::{Avm1, Object, ObjectPtr, ScriptObject, TDisplayObject, TObject, Value}; use crate::context::UpdateContext; use crate::display_object::{DisplayObject, MovieClip}; use crate::property_map::PropertyMap; diff --git a/core/src/avm1/super_object.rs b/core/src/avm1/super_object.rs index 5ecd8733c..640134b95 100644 --- a/core/src/avm1/super_object.rs +++ b/core/src/avm1/super_object.rs @@ -1,11 +1,12 @@ //! Special object that implements `super` +use crate::avm1::error::Error; use crate::avm1::function::Executable; use crate::avm1::object::search_prototype; use crate::avm1::property::Attribute; use crate::avm1::return_value::ReturnValue; use crate::avm1::script_object::TYPE_OF_OBJECT; -use crate::avm1::{Avm1, Error, Object, ObjectPtr, ScriptObject, TObject, Value}; +use crate::avm1::{Avm1, Object, ObjectPtr, ScriptObject, TObject, Value}; use crate::context::UpdateContext; use crate::display_object::DisplayObject; use enumset::EnumSet; diff --git a/core/src/avm1/value.rs b/core/src/avm1/value.rs index 5572393ff..cb3ccec36 100644 --- a/core/src/avm1/value.rs +++ b/core/src/avm1/value.rs @@ -1,5 +1,6 @@ +use crate::avm1::error::Error; use crate::avm1::value_object::ValueObject; -use crate::avm1::{Avm1, Error, Object, TObject, UpdateContext}; +use crate::avm1::{Avm1, Object, TObject, UpdateContext}; use std::borrow::Cow; use std::f64::NAN; @@ -591,13 +592,14 @@ pub fn f64_to_wrapping_i32(n: f64) -> i32 { #[cfg(test)] mod test { + use crate::avm1::error::Error; use crate::avm1::function::{Executable, FunctionObject}; use crate::avm1::globals::create_globals; use crate::avm1::object::{Object, TObject}; use crate::avm1::return_value::ReturnValue; use crate::avm1::script_object::ScriptObject; use crate::avm1::test_utils::with_avm; - use crate::avm1::{Avm1, Error, Value}; + use crate::avm1::{Avm1, Value}; use crate::context::UpdateContext; use enumset::EnumSet; use std::f64::{INFINITY, NAN, NEG_INFINITY}; diff --git a/core/src/avm1/value_object.rs b/core/src/avm1/value_object.rs index bf81ccc46..b1b2d565c 100644 --- a/core/src/avm1/value_object.rs +++ b/core/src/avm1/value_object.rs @@ -1,10 +1,11 @@ //! Object impl for boxed values +use crate::avm1::error::Error; use crate::avm1::function::Executable; use crate::avm1::object::{ObjectPtr, TObject}; use crate::avm1::property::Attribute; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, Object, ScriptObject, UpdateContext, Value}; +use crate::avm1::{Avm1, Object, ScriptObject, UpdateContext, Value}; use enumset::EnumSet; use gc_arena::{Collect, GcCell, MutationContext}; use std::borrow::Cow; diff --git a/core/src/avm1/xml_attributes_object.rs b/core/src/avm1/xml_attributes_object.rs index 4ca0e9744..918bcb968 100644 --- a/core/src/avm1/xml_attributes_object.rs +++ b/core/src/avm1/xml_attributes_object.rs @@ -1,10 +1,11 @@ //! AVM1 object type to represent the attributes of XML nodes +use crate::avm1::error::Error; use crate::avm1::function::Executable; use crate::avm1::object::{ObjectPtr, TObject}; use crate::avm1::property::Attribute; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, Object, ScriptObject, UpdateContext, Value}; +use crate::avm1::{Avm1, Object, ScriptObject, UpdateContext, Value}; use crate::xml::{XMLName, XMLNode}; use enumset::EnumSet; use gc_arena::{Collect, MutationContext}; @@ -110,13 +111,14 @@ impl<'gc> TObject<'gc> for XMLAttributesObject<'gc> { #[allow(clippy::new_ret_no_self)] fn new( &self, - _avm: &mut Avm1<'gc>, - _context: &mut UpdateContext<'_, 'gc, '_>, + avm: &mut Avm1<'gc>, + context: &mut UpdateContext<'_, 'gc, '_>, _this: Object<'gc>, _args: &[Value<'gc>], ) -> Result, Error> { //TODO: `new xmlnode.attributes()` returns undefined, not an object - Err("Cannot create new XML Attributes object".into()) + log::warn!("Cannot create new XML Attributes object"); + Ok(Value::Undefined.coerce_to_object(avm, context)) } fn delete( diff --git a/core/src/avm1/xml_idmap_object.rs b/core/src/avm1/xml_idmap_object.rs index 18dc836dc..2e8560705 100644 --- a/core/src/avm1/xml_idmap_object.rs +++ b/core/src/avm1/xml_idmap_object.rs @@ -1,10 +1,11 @@ //! AVM1 object type to represent the attributes of XML nodes +use crate::avm1::error::Error; use crate::avm1::function::Executable; use crate::avm1::object::{ObjectPtr, TObject}; use crate::avm1::property::Attribute; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, Object, ScriptObject, UpdateContext, Value}; +use crate::avm1::{Avm1, Object, ScriptObject, UpdateContext, Value}; use crate::xml::{XMLDocument, XMLNode}; use enumset::EnumSet; use gc_arena::{Collect, MutationContext}; @@ -107,13 +108,14 @@ impl<'gc> TObject<'gc> for XMLIDMapObject<'gc> { #[allow(clippy::new_ret_no_self)] fn new( &self, - _avm: &mut Avm1<'gc>, - _context: &mut UpdateContext<'_, 'gc, '_>, + avm: &mut Avm1<'gc>, + context: &mut UpdateContext<'_, 'gc, '_>, _this: Object<'gc>, _args: &[Value<'gc>], ) -> Result, Error> { //TODO: `new xmlnode.attributes()` returns undefined, not an object - Err("Cannot create new XML Attributes object".into()) + log::warn!("Cannot create new XML Attributes object"); + Ok(Value::Undefined.coerce_to_object(avm, context)) } fn delete( diff --git a/core/src/avm1/xml_object.rs b/core/src/avm1/xml_object.rs index 09be03a5f..ea6566627 100644 --- a/core/src/avm1/xml_object.rs +++ b/core/src/avm1/xml_object.rs @@ -1,10 +1,11 @@ //! AVM1 object type to represent XML nodes +use crate::avm1::error::Error; use crate::avm1::function::Executable; use crate::avm1::object::{ObjectPtr, TObject}; use crate::avm1::property::Attribute; use crate::avm1::return_value::ReturnValue; -use crate::avm1::{Avm1, Error, Object, ScriptObject, UpdateContext, Value}; +use crate::avm1::{Avm1, Object, ScriptObject, UpdateContext, Value}; use crate::xml::{XMLDocument, XMLNode}; use enumset::EnumSet; use gc_arena::{Collect, MutationContext}; diff --git a/core/src/font/text_format.rs b/core/src/font/text_format.rs index be79537c5..e010364d9 100644 --- a/core/src/font/text_format.rs +++ b/core/src/font/text_format.rs @@ -2,8 +2,6 @@ use crate::avm1::{Avm1, Object, ScriptObject, TObject, Value}; use crate::context::UpdateContext; -type Error = Box; - /// A set of text formatting options to be applied to some part, or the whole /// of, a given text field. /// @@ -65,7 +63,7 @@ fn getstr_from_avm1_object<'gc>( name: &str, avm1: &mut Avm1<'gc>, uc: &mut UpdateContext<'_, 'gc, '_>, -) -> Result, Error> { +) -> Result, crate::avm1::error::Error> { Ok(match object.get(name, avm1, uc)? { Value::Undefined => None, Value::Null => None, @@ -78,7 +76,7 @@ fn getfloat_from_avm1_object<'gc>( name: &str, avm1: &mut Avm1<'gc>, uc: &mut UpdateContext<'_, 'gc, '_>, -) -> Result, Error> { +) -> Result, crate::avm1::error::Error> { Ok(match object.get(name, avm1, uc)? { Value::Undefined => None, Value::Null => None, @@ -91,7 +89,7 @@ fn getbool_from_avm1_object<'gc>( name: &str, avm1: &mut Avm1<'gc>, uc: &mut UpdateContext<'_, 'gc, '_>, -) -> Result, Error> { +) -> Result, crate::avm1::error::Error> { Ok(match object.get(name, avm1, uc)? { Value::Undefined => None, Value::Null => None, @@ -105,7 +103,7 @@ impl TextFormat { object1: Object<'gc>, avm1: &mut Avm1<'gc>, uc: &mut UpdateContext<'_, 'gc, '_>, - ) -> Result { + ) -> Result { Ok(Self { font: getstr_from_avm1_object(object1, "font", avm1, uc)?, size: getfloat_from_avm1_object(object1, "size", avm1, uc)?, @@ -142,7 +140,7 @@ impl TextFormat { &self, avm1: &mut Avm1<'gc>, uc: &mut UpdateContext<'_, 'gc, '_>, - ) -> Result, Error> { + ) -> Result, crate::avm1::error::Error> { let object = ScriptObject::object(uc.gc_context, Some(avm1.prototypes().text_format)); object.set( diff --git a/core/src/xml/tree.rs b/core/src/xml/tree.rs index 3403d9db9..2b4742924 100644 --- a/core/src/xml/tree.rs +++ b/core/src/xml/tree.rs @@ -164,8 +164,8 @@ impl<'gc> XMLNode<'gc> { mc: MutationContext<'gc, '_>, element_name: &str, document: XMLDocument<'gc>, - ) -> Result { - Ok(XMLNode(GcCell::allocate( + ) -> Self { + XMLNode(GcCell::allocate( mc, XMLNodeData::Element { script_object: None, @@ -178,7 +178,7 @@ impl<'gc> XMLNode<'gc> { attributes_script_object: None, children: Vec::new(), }, - ))) + )) } /// Construct a new XML root node.