avm1: Made avm1::Error an actual error type, and removed all calls that throw incorrect errors in avm1

This commit is contained in:
Nathan Adams 2020-06-20 14:57:53 +02:00 committed by Mike Welsh
parent ad07520af3
commit a36e2105a3
49 changed files with 201 additions and 114 deletions

View File

@ -47,7 +47,7 @@ pub mod xml_object;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
use crate::avm1::error::ExecutionError; use crate::avm1::error::{Error, ExecutionError};
use crate::avm1::listeners::SystemListener; use crate::avm1::listeners::SystemListener;
use crate::avm1::value::f64_to_wrapping_u32; use crate::avm1::value::f64_to_wrapping_u32;
pub use activation::Activation; pub use activation::Activation;
@ -115,8 +115,6 @@ unsafe impl<'gc> gc_arena::Collect for Avm1<'gc> {
} }
} }
type Error = Box<dyn std::error::Error>;
impl<'gc> Avm1<'gc> { impl<'gc> Avm1<'gc> {
pub fn new(gc_context: MutationContext<'gc, '_>, player_version: u8) -> Self { pub fn new(gc_context: MutationContext<'gc, '_>, player_version: u8) -> Self {
let (prototypes, globals, system_listeners) = create_globals(gc_context); let (prototypes, globals, system_listeners) = create_globals(gc_context);
@ -1066,7 +1064,7 @@ impl<'gc> Avm1<'gc> {
action: swf::avm1::types::Action, action: swf::avm1::types::Action,
) -> Result<(), Error> { ) -> Result<(), Error> {
log::error!("Unknown AVM1 opcode: {:?}", action); log::error!("Unknown AVM1 opcode: {:?}", action);
Err("Unknown op".into()) Ok(())
} }
fn action_add(&mut self, _context: &mut UpdateContext) -> Result<(), Error> { 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 {:?}", "Invalid method name, expected string but found {:?}",
method_name method_name
) );
.into())
} }
} }
@ -1700,7 +1698,8 @@ impl<'gc> Avm1<'gc> {
) -> Result<(), Error> { ) -> Result<(), Error> {
if target.starts_with("_level") && target.len() > 6 { if target.starts_with("_level") && target.len() > 6 {
let url = url.to_string(); let url = url.to_string();
let level_id = target[6..].parse::<u32>()?; match target[6..].parse::<u32>() {
Ok(level_id) => {
let fetch = context.navigator.fetch(&url, RequestOptions::get()); let fetch = context.navigator.fetch(&url, RequestOptions::get());
let level = self.resolve_level(level_id, context); let level = self.resolve_level(level_id, context);
@ -1711,6 +1710,13 @@ impl<'gc> Avm1<'gc> {
None, None,
); );
context.navigator.spawn_future(process); context.navigator.spawn_future(process);
}
Err(e) => log::warn!(
"Couldn't parse level id {} for action_get_url: {}",
target,
e
),
}
return Ok(()); return Ok(());
} }
@ -2015,8 +2021,11 @@ impl<'gc> Avm1<'gc> {
) -> Result<(), Error> { ) -> Result<(), Error> {
// TODO(Herschel): Results on incorrect operands? // TODO(Herschel): Results on incorrect operands?
use std::convert::TryFrom; use std::convert::TryFrom;
let val = char::try_from(self.pop().coerce_to_f64(self, context)? as u32)?; let result = char::try_from(self.pop().coerce_to_f64(self, context)? as u32);
self.push(val.to_string()); 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(()) Ok(())
} }
@ -2254,7 +2263,8 @@ impl<'gc> Avm1<'gc> {
} }
fn action_push_duplicate(&mut self, _context: &mut UpdateContext) -> Result<(), Error> { 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); self.push(val);
Ok(()) Ok(())
} }
@ -2290,7 +2300,9 @@ impl<'gc> Avm1<'gc> {
fn action_return(&mut self, context: &mut UpdateContext<'_, 'gc, '_>) -> Result<(), Error> { fn action_return(&mut self, context: &mut UpdateContext<'_, 'gc, '_>) -> Result<(), Error> {
let return_value = self.pop(); 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(()) Ok(())
} }
@ -2496,8 +2508,9 @@ impl<'gc> Avm1<'gc> {
context: &mut UpdateContext<'_, 'gc, '_>, context: &mut UpdateContext<'_, 'gc, '_>,
register: u8, register: u8,
) -> Result<(), Error> { ) -> Result<(), Error> {
// Does NOT pop the value from the stack. // The value must remain on the stack.
let val = self.stack.last().ok_or("Stack underflow")?.clone(); let val = self.pop();
self.push(val.clone());
self.set_current_register(register, val, context); self.set_current_register(register, val, context);
Ok(()) Ok(())
@ -2606,7 +2619,8 @@ impl<'gc> Avm1<'gc> {
// TODO(Herschel) // TODO(Herschel)
let _clip = self.pop().coerce_to_object(self, context); let _clip = self.pop().coerce_to_object(self, context);
self.push(Value::Undefined); 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> { fn toggle_quality(&mut self, _context: &mut UpdateContext) -> Result<(), Error> {
@ -2664,7 +2678,7 @@ impl<'gc> Avm1<'gc> {
if !loaded { if !loaded {
// Note that the offset is given in # of actions, NOT in bytes. // Note that the offset is given in # of actions, NOT in bytes.
// Read the actions and toss them away. // Read the actions and toss them away.
skip_actions(r, num_actions_to_skip)?; skip_actions(r, num_actions_to_skip);
} }
Ok(()) Ok(())
} }
@ -2681,7 +2695,7 @@ impl<'gc> Avm1<'gc> {
if !loaded { if !loaded {
// Note that the offset is given in # of actions, NOT in bytes. // Note that the offset is given in # of actions, NOT in bytes.
// Read the actions and toss them away. // Read the actions and toss them away.
skip_actions(r, num_actions_to_skip)?; skip_actions(r, num_actions_to_skip);
} }
Ok(()) 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 /// Utility function used by `Avm1::action_wait_for_frame` and
/// `Avm1::action_wait_for_frame_2`. /// `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 { 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. /// Starts draggining this display object, making it follow the cursor.

View File

@ -1,9 +1,10 @@
//! Activation records //! Activation records
use crate::avm1::error::Error;
use crate::avm1::error::ExecutionError; use crate::avm1::error::ExecutionError;
use crate::avm1::return_value::ReturnValue; use crate::avm1::return_value::ReturnValue;
use crate::avm1::scope::Scope; use crate::avm1::scope::Scope;
use crate::avm1::{Avm1, Error, Object, Value}; use crate::avm1::{Avm1, Object, Value};
use crate::context::UpdateContext; use crate::context::UpdateContext;
use crate::display_object::DisplayObject; use crate::display_object::DisplayObject;
use crate::tag_utils::SwfSlice; use crate::tag_utils::SwfSlice;

View File

@ -207,7 +207,7 @@ mod tests {
_this: Object<'gc>, _this: Object<'gc>,
_args: &[Value<'gc>], _args: &[Value<'gc>],
) -> Result<ReturnValue<'gc>, Error> { ) -> Result<ReturnValue<'gc>, Error> {
Err("Error message!".into()) Err(Error::PrototypeRecursionLimit)
} }
#[test] #[test]
@ -331,7 +331,7 @@ mod tests {
); );
assert_eq!( assert_eq!(
VariableDumper::dump(&object.into(), " ", avm, context), 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(()) Ok(())
}) })

View File

@ -1,5 +1,11 @@
use thiserror::Error; use thiserror::Error;
#[derive(Error, Debug)]
pub enum Error {
#[error("Prototype recursion limit has been exceeded")]
PrototypeRecursionLimit,
}
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum ExecutionError { pub enum ExecutionError {
#[error("Couldn't parse SWF")] #[error("Couldn't parse SWF")]
@ -15,5 +21,5 @@ pub enum ExecutionError {
AlreadyExecutingFrame, AlreadyExecutingFrame,
#[error("Script error")] #[error("Script error")]
ScriptError(Box<dyn std::error::Error>), ScriptError(#[from] Error),
} }

View File

@ -1,6 +1,7 @@
//! FSCommand handling //! FSCommand handling
use crate::avm1::{Avm1, Error, UpdateContext}; use crate::avm1::error::Error;
use crate::avm1::{Avm1, UpdateContext};
/// Parse an FSCommand URL. /// Parse an FSCommand URL.
pub fn parse(url: &str) -> Option<&str> { pub fn parse(url: &str) -> Option<&str> {

View File

@ -1,12 +1,13 @@
//! Code relating to executable functions + calling conventions. //! Code relating to executable functions + calling conventions.
use crate::avm1::activation::Activation; use crate::avm1::activation::Activation;
use crate::avm1::error::Error;
use crate::avm1::property::{Attribute, Attribute::*}; use crate::avm1::property::{Attribute, Attribute::*};
use crate::avm1::return_value::ReturnValue; use crate::avm1::return_value::ReturnValue;
use crate::avm1::scope::Scope; use crate::avm1::scope::Scope;
use crate::avm1::super_object::SuperObject; use crate::avm1::super_object::SuperObject;
use crate::avm1::value::Value; 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::display_object::{DisplayObject, TDisplayObject};
use crate::tag_utils::SwfSlice; use crate::tag_utils::SwfSlice;
use enumset::EnumSet; use enumset::EnumSet;

View File

@ -1,8 +1,9 @@
use crate::avm1::error::Error;
use crate::avm1::fscommand; use crate::avm1::fscommand;
use crate::avm1::function::{Executable, FunctionObject}; use crate::avm1::function::{Executable, FunctionObject};
use crate::avm1::listeners::SystemListeners; use crate::avm1::listeners::SystemListeners;
use crate::avm1::return_value::ReturnValue; 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::backend::navigator::NavigationMethod;
use enumset::EnumSet; use enumset::EnumSet;
use gc_arena::MutationContext; use gc_arena::MutationContext;

View File

@ -1,9 +1,10 @@
//! Array class //! Array class
use crate::avm1::error::Error;
use crate::avm1::function::{Executable, FunctionObject}; use crate::avm1::function::{Executable, FunctionObject};
use crate::avm1::property::Attribute; use crate::avm1::property::Attribute;
use crate::avm1::return_value::ReturnValue; 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 enumset::EnumSet;
use gc_arena::MutationContext; use gc_arena::MutationContext;
use smallvec::alloc::borrow::Cow; use smallvec::alloc::borrow::Cow;

View File

@ -1,9 +1,10 @@
//! `Boolean` class impl //! `Boolean` class impl
use crate::avm1::error::Error;
use crate::avm1::function::{Executable, FunctionObject}; use crate::avm1::function::{Executable, FunctionObject};
use crate::avm1::return_value::ReturnValue; use crate::avm1::return_value::ReturnValue;
use crate::avm1::value_object::ValueObject; 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 crate::context::UpdateContext;
use enumset::EnumSet; use enumset::EnumSet;
use gc_arena::MutationContext; use gc_arena::MutationContext;

View File

@ -1,8 +1,9 @@
//! Button/SimpleButton prototype //! Button/SimpleButton prototype
use crate::avm1::error::Error;
use crate::avm1::globals::display_object; use crate::avm1::globals::display_object;
use crate::avm1::return_value::ReturnValue; 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; use gc_arena::MutationContext;
pub fn create_proto<'gc>( pub fn create_proto<'gc>(

View File

@ -3,9 +3,10 @@
//! TODO: This should change when `ColorTransform` changes to match Flash's representation //! TODO: This should change when `ColorTransform` changes to match Flash's representation
//! (See GitHub #193) //! (See GitHub #193)
use crate::avm1::error::Error;
use crate::avm1::property::Attribute::*; use crate::avm1::property::Attribute::*;
use crate::avm1::return_value::ReturnValue; 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 crate::display_object::{DisplayObject, TDisplayObject};
use enumset::EnumSet; use enumset::EnumSet;
use gc_arena::MutationContext; use gc_arena::MutationContext;

View File

@ -1,9 +1,10 @@
//! DisplayObject common methods //! DisplayObject common methods
use crate::avm1::error::Error;
use crate::avm1::function::Executable; use crate::avm1::function::Executable;
use crate::avm1::property::Attribute::*; use crate::avm1::property::Attribute::*;
use crate::avm1::return_value::ReturnValue; 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 crate::display_object::{DisplayObject, TDisplayObject};
use enumset::EnumSet; use enumset::EnumSet;
use gc_arena::MutationContext; use gc_arena::MutationContext;

View File

@ -1,7 +1,8 @@
//! Function prototype //! Function prototype
use crate::avm1::error::Error;
use crate::avm1::return_value::ReturnValue; 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 enumset::EnumSet;
use gc_arena::MutationContext; use gc_arena::MutationContext;

View File

@ -1,6 +1,7 @@
use crate::avm1::error::Error;
use crate::avm1::property::Attribute; use crate::avm1::property::Attribute;
use crate::avm1::return_value::ReturnValue; 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 crate::events::KeyCode;
use gc_arena::MutationContext; use gc_arena::MutationContext;

View File

@ -1,7 +1,8 @@
use crate::avm1::error::Error;
use crate::avm1::object::Object; use crate::avm1::object::Object;
use crate::avm1::property::Attribute::*; use crate::avm1::property::Attribute::*;
use crate::avm1::return_value::ReturnValue; 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 gc_arena::MutationContext;
use rand::Rng; use rand::Rng;
use std::f64::{INFINITY, NAN, NEG_INFINITY}; use std::f64::{INFINITY, NAN, NEG_INFINITY};

View File

@ -1,8 +1,9 @@
//! flash.geom.Matrix //! flash.geom.Matrix
use crate::avm1::error::Error;
use crate::avm1::function::{Executable, FunctionObject}; use crate::avm1::function::{Executable, FunctionObject};
use crate::avm1::return_value::ReturnValue; 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 crate::context::UpdateContext;
use enumset::EnumSet; use enumset::EnumSet;
use gc_arena::MutationContext; use gc_arena::MutationContext;

View File

@ -1,7 +1,8 @@
use crate::avm1::error::Error;
use crate::avm1::listeners::Listeners; use crate::avm1::listeners::Listeners;
use crate::avm1::property::Attribute; use crate::avm1::property::Attribute;
use crate::avm1::return_value::ReturnValue; 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; use gc_arena::MutationContext;

View File

@ -1,10 +1,11 @@
//! MovieClip prototype //! MovieClip prototype
use crate::avm1::error::Error;
use crate::avm1::globals::display_object::{self, AVM_DEPTH_BIAS, AVM_MAX_DEPTH}; 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::globals::matrix::gradient_object_to_matrix;
use crate::avm1::property::Attribute::*; use crate::avm1::property::Attribute::*;
use crate::avm1::return_value::ReturnValue; 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::backend::navigator::NavigationMethod;
use crate::display_object::{DisplayObject, EditText, MovieClip, TDisplayObject}; use crate::display_object::{DisplayObject, EditText, MovieClip, TDisplayObject};
use crate::prelude::*; use crate::prelude::*;

View File

@ -1,10 +1,11 @@
//! `MovieClipLoader` impl //! `MovieClipLoader` impl
use crate::avm1::error::Error;
use crate::avm1::object::TObject; use crate::avm1::object::TObject;
use crate::avm1::property::Attribute; use crate::avm1::property::Attribute;
use crate::avm1::return_value::ReturnValue; use crate::avm1::return_value::ReturnValue;
use crate::avm1::script_object::ScriptObject; 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::backend::navigator::RequestOptions;
use crate::display_object::{DisplayObject, TDisplayObject}; use crate::display_object::{DisplayObject, TDisplayObject};
use enumset::EnumSet; use enumset::EnumSet;

View File

@ -1,10 +1,11 @@
//! `Number` class impl //! `Number` class impl
use crate::avm1::error::Error;
use crate::avm1::function::{Executable, FunctionObject}; use crate::avm1::function::{Executable, FunctionObject};
use crate::avm1::property::Attribute::*; use crate::avm1::property::Attribute::*;
use crate::avm1::return_value::ReturnValue; use crate::avm1::return_value::ReturnValue;
use crate::avm1::value_object::ValueObject; 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 crate::context::UpdateContext;
use enumset::EnumSet; use enumset::EnumSet;
use gc_arena::MutationContext; use gc_arena::MutationContext;

View File

@ -1,8 +1,9 @@
//! Object prototype //! Object prototype
use crate::avm1::error::Error;
use crate::avm1::function::{Executable, FunctionObject}; use crate::avm1::function::{Executable, FunctionObject};
use crate::avm1::property::Attribute::{self, *}; use crate::avm1::property::Attribute::{self, *};
use crate::avm1::return_value::ReturnValue; 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 crate::character::Character;
use enumset::EnumSet; use enumset::EnumSet;
use gc_arena::MutationContext; use gc_arena::MutationContext;
@ -228,18 +229,15 @@ pub fn as_set_prop_flags<'gc>(
_: Object<'gc>, _: Object<'gc>,
args: &[Value<'gc>], args: &[Value<'gc>],
) -> Result<ReturnValue<'gc>, Error> { ) -> Result<ReturnValue<'gc>, Error> {
//This exists because `.into` won't work inline let mut object = if let Some(object) = args.get(0).map(|v| v.coerce_to_object(avm, ac)) {
let my_error: Result<ReturnValue<'gc>, Error> = object
Err("ASSetPropFlags called without object to apply to!".into()); } else {
let my_error_2: Result<ReturnValue<'gc>, Error> = log::warn!("ASSetPropFlags called without object to apply to!");
Err("ASSetPropFlags called without object list!".into()); return Ok(Value::Undefined.into());
};
let mut object = args let properties = match args.get(1) {
.get(0) Some(Value::Object(ob)) => {
.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) => {
//Convert to native array. //Convert to native array.
//TODO: Can we make this an iterator? //TODO: Can we make this an iterator?
let mut array = vec![]; let mut array = vec![];
@ -254,8 +252,12 @@ pub fn as_set_prop_flags<'gc>(
Some(array) Some(array)
} }
Value::String(s) => Some(s.split(',').map(String::from).collect()), Some(Value::String(s)) => Some(s.split(',').map(String::from).collect()),
_ => None, Some(_) => None,
None => {
log::warn!("ASSetPropFlags called without object list!");
return Ok(Value::Undefined.into());
}
}; };
let set_attributes = EnumSet::<Attribute>::from_u128( let set_attributes = EnumSet::<Attribute>::from_u128(

View File

@ -1,9 +1,10 @@
//! flash.geom.Point //! flash.geom.Point
use crate::avm1::error::Error;
use crate::avm1::function::{Executable, FunctionObject}; use crate::avm1::function::{Executable, FunctionObject};
use crate::avm1::property::Attribute; use crate::avm1::property::Attribute;
use crate::avm1::return_value::ReturnValue; 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 crate::context::UpdateContext;
use enumset::EnumSet; use enumset::EnumSet;
use gc_arena::MutationContext; use gc_arena::MutationContext;

View File

@ -1,10 +1,11 @@
//! flash.geom.Rectangle //! flash.geom.Rectangle
use crate::avm1::error::Error;
use crate::avm1::function::{Executable, FunctionObject}; use crate::avm1::function::{Executable, FunctionObject};
use crate::avm1::globals::point::{construct_new_point, point_to_object, value_to_point}; use crate::avm1::globals::point::{construct_new_point, point_to_object, value_to_point};
use crate::avm1::property::Attribute; use crate::avm1::property::Attribute;
use crate::avm1::return_value::ReturnValue; 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 crate::context::UpdateContext;
use enumset::EnumSet; use enumset::EnumSet;
use gc_arena::MutationContext; use gc_arena::MutationContext;

View File

@ -1,10 +1,11 @@
//! AVM1 Sound object //! AVM1 Sound object
//! TODO: Sound position, transform, loadSound //! TODO: Sound position, transform, loadSound
use crate::avm1::error::Error;
use crate::avm1::function::Executable; use crate::avm1::function::Executable;
use crate::avm1::property::Attribute::*; use crate::avm1::property::Attribute::*;
use crate::avm1::return_value::ReturnValue; 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::character::Character;
use crate::display_object::TDisplayObject; use crate::display_object::TDisplayObject;
use gc_arena::MutationContext; use gc_arena::MutationContext;

View File

@ -1,10 +1,11 @@
//! Stage object //! Stage object
//! //!
//! TODO: This is a very rough stub with not much implementation. //! TODO: This is a very rough stub with not much implementation.
use crate::avm1::error::Error;
use crate::avm1::function::Executable; use crate::avm1::function::Executable;
use crate::avm1::property::Attribute; use crate::avm1::property::Attribute;
use crate::avm1::return_value::ReturnValue; 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; use gc_arena::MutationContext;

View File

@ -1,10 +1,11 @@
//! `String` class impl //! `String` class impl
use crate::avm1::error::Error;
use crate::avm1::function::{Executable, FunctionObject}; use crate::avm1::function::{Executable, FunctionObject};
use crate::avm1::property::Attribute::*; use crate::avm1::property::Attribute::*;
use crate::avm1::return_value::ReturnValue; use crate::avm1::return_value::ReturnValue;
use crate::avm1::value_object::ValueObject; 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::context::UpdateContext;
use crate::string_utils; use crate::string_utils;
use enumset::EnumSet; use enumset::EnumSet;

View File

@ -1,7 +1,8 @@
use crate::avm1::error::Error;
use crate::avm1::function::Executable; use crate::avm1::function::Executable;
use crate::avm1::object::Object; use crate::avm1::object::Object;
use crate::avm1::return_value::ReturnValue; 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 crate::context::UpdateContext;
use core::fmt; use core::fmt;
use enumset::{EnumSet, EnumSetType}; use enumset::{EnumSet, EnumSetType};

View File

@ -1,8 +1,9 @@
use crate::avm1::error::Error;
use crate::avm1::function::Executable; use crate::avm1::function::Executable;
use crate::avm1::globals::system::SystemCapabilities; use crate::avm1::globals::system::SystemCapabilities;
use crate::avm1::object::Object; use crate::avm1::object::Object;
use crate::avm1::return_value::ReturnValue; 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 crate::context::UpdateContext;
use enumset::EnumSet; use enumset::EnumSet;
use gc_arena::MutationContext; use gc_arena::MutationContext;

View File

@ -1,9 +1,10 @@
use crate::avm1::error::Error;
use crate::avm1::listeners::Listeners; use crate::avm1::listeners::Listeners;
use crate::avm1::object::Object; use crate::avm1::object::Object;
use crate::avm1::property::Attribute; use crate::avm1::property::Attribute;
use crate::avm1::property::Attribute::{DontDelete, DontEnum, ReadOnly}; use crate::avm1::property::Attribute::{DontDelete, DontEnum, ReadOnly};
use crate::avm1::return_value::ReturnValue; 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 crate::context::UpdateContext;
use gc_arena::MutationContext; use gc_arena::MutationContext;
use std::convert::Into; use std::convert::Into;

View File

@ -1,7 +1,8 @@
use crate::avm1::error::Error;
use crate::avm1::function::Executable; use crate::avm1::function::Executable;
use crate::avm1::object::Object; use crate::avm1::object::Object;
use crate::avm1::return_value::ReturnValue; 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 crate::context::UpdateContext;
use enumset::EnumSet; use enumset::EnumSet;
use gc_arena::MutationContext; use gc_arena::MutationContext;

View File

@ -1,8 +1,9 @@
use crate::avm1::error::Error;
use crate::avm1::function::Executable; use crate::avm1::function::Executable;
use crate::avm1::globals::display_object; use crate::avm1::globals::display_object;
use crate::avm1::property::Attribute::*; use crate::avm1::property::Attribute::*;
use crate::avm1::return_value::ReturnValue; 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::display_object::{EditText, TDisplayObject};
use crate::font::TextFormat; use crate::font::TextFormat;
use gc_arena::MutationContext; use gc_arena::MutationContext;

View File

@ -1,7 +1,8 @@
//! `TextFormat` impl //! `TextFormat` impl
use crate::avm1::error::Error;
use crate::avm1::return_value::ReturnValue; 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; use gc_arena::MutationContext;
fn map_defined_to_string<'gc>( fn map_defined_to_string<'gc>(

View File

@ -1,11 +1,12 @@
//! XML/XMLNode global classes //! XML/XMLNode global classes
use crate::avm1::error::Error;
use crate::avm1::function::Executable; use crate::avm1::function::Executable;
use crate::avm1::property::Attribute::*; use crate::avm1::property::Attribute::*;
use crate::avm1::return_value::ReturnValue; use crate::avm1::return_value::ReturnValue;
use crate::avm1::script_object::ScriptObject; use crate::avm1::script_object::ScriptObject;
use crate::avm1::xml_object::XMLObject; 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::backend::navigator::RequestOptions;
use crate::xml; use crate::xml;
use crate::xml::{XMLDocument, XMLNode}; use crate::xml::{XMLDocument, XMLNode};
@ -55,7 +56,7 @@ pub fn xmlnode_constructor<'gc>(
this.as_xml_node(), this.as_xml_node(),
) { ) {
(Some(Ok(1)), Some(Ok(ref strval)), Some(ref mut this_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); xmlelement.introduce_script_object(ac.gc_context, this);
this_node.swap(ac.gc_context, xmlelement); this_node.swap(ac.gc_context, xmlelement);
} }
@ -84,7 +85,9 @@ pub fn xmlnode_append_child<'gc>(
) { ) {
if let Ok(None) = child_xmlnode.parent() { if let Ok(None) = child_xmlnode.parent() {
let position = xmlnode.children_len(); 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 Ok(None) = child_xmlnode.parent() {
if let Some(position) = xmlnode.child_position(insertpoint_xmlnode) { 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); xmlnode.introduce_script_object(ac.gc_context, this);
this_node.swap(ac.gc_context, xmlnode); 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)) => { (None, Some(ref mut this_node)) => {
let xmldoc = XMLDocument::new(ac.gc_context); let xmldoc = XMLDocument::new(ac.gc_context);
@ -722,7 +732,7 @@ pub fn xml_create_element<'gc>(
.get(0) .get(0)
.map(|v| v.coerce_to_string(avm, ac).unwrap_or_default()) .map(|v| v.coerce_to_string(avm, ac).unwrap_or_default())
.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)); 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); xml_node.introduce_script_object(ac.gc_context, object);

View File

@ -1,5 +1,6 @@
use crate::avm1::error::Error;
use crate::avm1::return_value::ReturnValue; 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}; use gc_arena::{Collect, MutationContext};

View File

@ -1,5 +1,6 @@
//! Object trait to expose objects to AVM //! Object trait to expose objects to AVM
use crate::avm1::error::Error;
use crate::avm1::function::{Executable, FunctionObject}; use crate::avm1::function::{Executable, FunctionObject};
use crate::avm1::property::Attribute; use crate::avm1::property::Attribute;
use crate::avm1::return_value::ReturnValue; 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_attributes_object::XMLAttributesObject;
use crate::avm1::xml_idmap_object::XMLIDMapObject; use crate::avm1::xml_idmap_object::XMLIDMapObject;
use crate::avm1::xml_object::XMLObject; 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::display_object::DisplayObject;
use crate::xml::XMLNode; use crate::xml::XMLNode;
use enumset::EnumSet; use enumset::EnumSet;
@ -458,7 +459,7 @@ pub fn search_prototype<'gc>(
while proto.is_some() { while proto.is_some() {
if depth == 255 { 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) { if proto.unwrap().has_own_property(avm, context, name) {

View File

@ -1,9 +1,10 @@
//! User-defined properties //! User-defined properties
use self::Attribute::*; use self::Attribute::*;
use crate::avm1::error::Error;
use crate::avm1::function::Executable; use crate::avm1::function::Executable;
use crate::avm1::return_value::ReturnValue; 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 core::fmt;
use enumset::{EnumSet, EnumSetType}; use enumset::{EnumSet, EnumSetType};

View File

@ -1,7 +1,9 @@
//! Return value enum //! Return value enum
use crate::avm1::activation::Activation; 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 crate::context::UpdateContext;
use gc_arena::{Collect, GcCell}; use gc_arena::{Collect, GcCell};
use std::borrow::Cow; use std::borrow::Cow;
@ -93,7 +95,18 @@ impl<'gc> ReturnValue<'gc> {
match self { match self {
Immediate(val) => Ok(val), Immediate(val) => Ok(val),
ResultOf(frame) => { 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()) Ok(avm.pop())
} }

View File

@ -1,7 +1,8 @@
//! Represents AVM1 scope chain resolution. //! Represents AVM1 scope chain resolution.
use crate::avm1::error::Error;
use crate::avm1::return_value::ReturnValue; 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 enumset::EnumSet;
use gc_arena::{GcCell, MutationContext}; use gc_arena::{GcCell, MutationContext};
use std::cell::Ref; use std::cell::Ref;

View File

@ -1,7 +1,8 @@
use crate::avm1::error::Error;
use crate::avm1::function::{Executable, FunctionObject, NativeFunction}; use crate::avm1::function::{Executable, FunctionObject, NativeFunction};
use crate::avm1::property::{Attribute, Property}; use crate::avm1::property::{Attribute, Property};
use crate::avm1::return_value::ReturnValue; 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 crate::property_map::{Entry, PropertyMap};
use core::fmt; use core::fmt;
use enumset::EnumSet; use enumset::EnumSet;

View File

@ -1,9 +1,10 @@
//! AVM1 object type to represent Sound objects. //! AVM1 object type to represent Sound objects.
use crate::avm1::error::Error;
use crate::avm1::function::Executable; use crate::avm1::function::Executable;
use crate::avm1::property::Attribute; use crate::avm1::property::Attribute;
use crate::avm1::return_value::ReturnValue; 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::backend::audio::{SoundHandle, SoundInstanceHandle};
use crate::context::UpdateContext; use crate::context::UpdateContext;
use crate::display_object::DisplayObject; use crate::display_object::DisplayObject;

View File

@ -1,10 +1,11 @@
//! AVM1 object type to represent objects on the stage. //! AVM1 object type to represent objects on the stage.
use crate::avm1::error::Error;
use crate::avm1::function::Executable; use crate::avm1::function::Executable;
use crate::avm1::object::search_prototype; use crate::avm1::object::search_prototype;
use crate::avm1::property::Attribute; use crate::avm1::property::Attribute;
use crate::avm1::return_value::ReturnValue; 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::context::UpdateContext;
use crate::display_object::{DisplayObject, MovieClip}; use crate::display_object::{DisplayObject, MovieClip};
use crate::property_map::PropertyMap; use crate::property_map::PropertyMap;

View File

@ -1,11 +1,12 @@
//! Special object that implements `super` //! Special object that implements `super`
use crate::avm1::error::Error;
use crate::avm1::function::Executable; use crate::avm1::function::Executable;
use crate::avm1::object::search_prototype; use crate::avm1::object::search_prototype;
use crate::avm1::property::Attribute; use crate::avm1::property::Attribute;
use crate::avm1::return_value::ReturnValue; use crate::avm1::return_value::ReturnValue;
use crate::avm1::script_object::TYPE_OF_OBJECT; 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::context::UpdateContext;
use crate::display_object::DisplayObject; use crate::display_object::DisplayObject;
use enumset::EnumSet; use enumset::EnumSet;

View File

@ -1,5 +1,6 @@
use crate::avm1::error::Error;
use crate::avm1::value_object::ValueObject; 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::borrow::Cow;
use std::f64::NAN; use std::f64::NAN;
@ -591,13 +592,14 @@ pub fn f64_to_wrapping_i32(n: f64) -> i32 {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::avm1::error::Error;
use crate::avm1::function::{Executable, FunctionObject}; use crate::avm1::function::{Executable, FunctionObject};
use crate::avm1::globals::create_globals; use crate::avm1::globals::create_globals;
use crate::avm1::object::{Object, TObject}; use crate::avm1::object::{Object, TObject};
use crate::avm1::return_value::ReturnValue; use crate::avm1::return_value::ReturnValue;
use crate::avm1::script_object::ScriptObject; use crate::avm1::script_object::ScriptObject;
use crate::avm1::test_utils::with_avm; use crate::avm1::test_utils::with_avm;
use crate::avm1::{Avm1, Error, Value}; use crate::avm1::{Avm1, Value};
use crate::context::UpdateContext; use crate::context::UpdateContext;
use enumset::EnumSet; use enumset::EnumSet;
use std::f64::{INFINITY, NAN, NEG_INFINITY}; use std::f64::{INFINITY, NAN, NEG_INFINITY};

View File

@ -1,10 +1,11 @@
//! Object impl for boxed values //! Object impl for boxed values
use crate::avm1::error::Error;
use crate::avm1::function::Executable; use crate::avm1::function::Executable;
use crate::avm1::object::{ObjectPtr, TObject}; use crate::avm1::object::{ObjectPtr, TObject};
use crate::avm1::property::Attribute; use crate::avm1::property::Attribute;
use crate::avm1::return_value::ReturnValue; 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 enumset::EnumSet;
use gc_arena::{Collect, GcCell, MutationContext}; use gc_arena::{Collect, GcCell, MutationContext};
use std::borrow::Cow; use std::borrow::Cow;

View File

@ -1,10 +1,11 @@
//! AVM1 object type to represent the attributes of XML nodes //! AVM1 object type to represent the attributes of XML nodes
use crate::avm1::error::Error;
use crate::avm1::function::Executable; use crate::avm1::function::Executable;
use crate::avm1::object::{ObjectPtr, TObject}; use crate::avm1::object::{ObjectPtr, TObject};
use crate::avm1::property::Attribute; use crate::avm1::property::Attribute;
use crate::avm1::return_value::ReturnValue; 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 crate::xml::{XMLName, XMLNode};
use enumset::EnumSet; use enumset::EnumSet;
use gc_arena::{Collect, MutationContext}; use gc_arena::{Collect, MutationContext};
@ -110,13 +111,14 @@ impl<'gc> TObject<'gc> for XMLAttributesObject<'gc> {
#[allow(clippy::new_ret_no_self)] #[allow(clippy::new_ret_no_self)]
fn new( fn new(
&self, &self,
_avm: &mut Avm1<'gc>, avm: &mut Avm1<'gc>,
_context: &mut UpdateContext<'_, 'gc, '_>, context: &mut UpdateContext<'_, 'gc, '_>,
_this: Object<'gc>, _this: Object<'gc>,
_args: &[Value<'gc>], _args: &[Value<'gc>],
) -> Result<Object<'gc>, Error> { ) -> Result<Object<'gc>, Error> {
//TODO: `new xmlnode.attributes()` returns undefined, not an object //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( fn delete(

View File

@ -1,10 +1,11 @@
//! AVM1 object type to represent the attributes of XML nodes //! AVM1 object type to represent the attributes of XML nodes
use crate::avm1::error::Error;
use crate::avm1::function::Executable; use crate::avm1::function::Executable;
use crate::avm1::object::{ObjectPtr, TObject}; use crate::avm1::object::{ObjectPtr, TObject};
use crate::avm1::property::Attribute; use crate::avm1::property::Attribute;
use crate::avm1::return_value::ReturnValue; 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 crate::xml::{XMLDocument, XMLNode};
use enumset::EnumSet; use enumset::EnumSet;
use gc_arena::{Collect, MutationContext}; use gc_arena::{Collect, MutationContext};
@ -107,13 +108,14 @@ impl<'gc> TObject<'gc> for XMLIDMapObject<'gc> {
#[allow(clippy::new_ret_no_self)] #[allow(clippy::new_ret_no_self)]
fn new( fn new(
&self, &self,
_avm: &mut Avm1<'gc>, avm: &mut Avm1<'gc>,
_context: &mut UpdateContext<'_, 'gc, '_>, context: &mut UpdateContext<'_, 'gc, '_>,
_this: Object<'gc>, _this: Object<'gc>,
_args: &[Value<'gc>], _args: &[Value<'gc>],
) -> Result<Object<'gc>, Error> { ) -> Result<Object<'gc>, Error> {
//TODO: `new xmlnode.attributes()` returns undefined, not an object //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( fn delete(

View File

@ -1,10 +1,11 @@
//! AVM1 object type to represent XML nodes //! AVM1 object type to represent XML nodes
use crate::avm1::error::Error;
use crate::avm1::function::Executable; use crate::avm1::function::Executable;
use crate::avm1::object::{ObjectPtr, TObject}; use crate::avm1::object::{ObjectPtr, TObject};
use crate::avm1::property::Attribute; use crate::avm1::property::Attribute;
use crate::avm1::return_value::ReturnValue; 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 crate::xml::{XMLDocument, XMLNode};
use enumset::EnumSet; use enumset::EnumSet;
use gc_arena::{Collect, MutationContext}; use gc_arena::{Collect, MutationContext};

View File

@ -2,8 +2,6 @@
use crate::avm1::{Avm1, Object, ScriptObject, TObject, Value}; use crate::avm1::{Avm1, Object, ScriptObject, TObject, Value};
use crate::context::UpdateContext; use crate::context::UpdateContext;
type Error = Box<dyn std::error::Error>;
/// A set of text formatting options to be applied to some part, or the whole /// A set of text formatting options to be applied to some part, or the whole
/// of, a given text field. /// of, a given text field.
/// ///
@ -65,7 +63,7 @@ fn getstr_from_avm1_object<'gc>(
name: &str, name: &str,
avm1: &mut Avm1<'gc>, avm1: &mut Avm1<'gc>,
uc: &mut UpdateContext<'_, 'gc, '_>, uc: &mut UpdateContext<'_, 'gc, '_>,
) -> Result<Option<String>, Error> { ) -> Result<Option<String>, crate::avm1::error::Error> {
Ok(match object.get(name, avm1, uc)? { Ok(match object.get(name, avm1, uc)? {
Value::Undefined => None, Value::Undefined => None,
Value::Null => None, Value::Null => None,
@ -78,7 +76,7 @@ fn getfloat_from_avm1_object<'gc>(
name: &str, name: &str,
avm1: &mut Avm1<'gc>, avm1: &mut Avm1<'gc>,
uc: &mut UpdateContext<'_, 'gc, '_>, uc: &mut UpdateContext<'_, 'gc, '_>,
) -> Result<Option<f64>, Error> { ) -> Result<Option<f64>, crate::avm1::error::Error> {
Ok(match object.get(name, avm1, uc)? { Ok(match object.get(name, avm1, uc)? {
Value::Undefined => None, Value::Undefined => None,
Value::Null => None, Value::Null => None,
@ -91,7 +89,7 @@ fn getbool_from_avm1_object<'gc>(
name: &str, name: &str,
avm1: &mut Avm1<'gc>, avm1: &mut Avm1<'gc>,
uc: &mut UpdateContext<'_, 'gc, '_>, uc: &mut UpdateContext<'_, 'gc, '_>,
) -> Result<Option<bool>, Error> { ) -> Result<Option<bool>, crate::avm1::error::Error> {
Ok(match object.get(name, avm1, uc)? { Ok(match object.get(name, avm1, uc)? {
Value::Undefined => None, Value::Undefined => None,
Value::Null => None, Value::Null => None,
@ -105,7 +103,7 @@ impl TextFormat {
object1: Object<'gc>, object1: Object<'gc>,
avm1: &mut Avm1<'gc>, avm1: &mut Avm1<'gc>,
uc: &mut UpdateContext<'_, 'gc, '_>, uc: &mut UpdateContext<'_, 'gc, '_>,
) -> Result<Self, Error> { ) -> Result<Self, crate::avm1::error::Error> {
Ok(Self { Ok(Self {
font: getstr_from_avm1_object(object1, "font", avm1, uc)?, font: getstr_from_avm1_object(object1, "font", avm1, uc)?,
size: getfloat_from_avm1_object(object1, "size", avm1, uc)?, size: getfloat_from_avm1_object(object1, "size", avm1, uc)?,
@ -142,7 +140,7 @@ impl TextFormat {
&self, &self,
avm1: &mut Avm1<'gc>, avm1: &mut Avm1<'gc>,
uc: &mut UpdateContext<'_, 'gc, '_>, uc: &mut UpdateContext<'_, 'gc, '_>,
) -> Result<Object<'gc>, Error> { ) -> Result<Object<'gc>, crate::avm1::error::Error> {
let object = ScriptObject::object(uc.gc_context, Some(avm1.prototypes().text_format)); let object = ScriptObject::object(uc.gc_context, Some(avm1.prototypes().text_format));
object.set( object.set(

View File

@ -164,8 +164,8 @@ impl<'gc> XMLNode<'gc> {
mc: MutationContext<'gc, '_>, mc: MutationContext<'gc, '_>,
element_name: &str, element_name: &str,
document: XMLDocument<'gc>, document: XMLDocument<'gc>,
) -> Result<Self, Error> { ) -> Self {
Ok(XMLNode(GcCell::allocate( XMLNode(GcCell::allocate(
mc, mc,
XMLNodeData::Element { XMLNodeData::Element {
script_object: None, script_object: None,
@ -178,7 +178,7 @@ impl<'gc> XMLNode<'gc> {
attributes_script_object: None, attributes_script_object: None,
children: Vec::new(), children: Vec::new(),
}, },
))) ))
} }
/// Construct a new XML root node. /// Construct a new XML root node.