diff --git a/core/src/avm2/error.rs b/core/src/avm2/error.rs index f758b772f..15ab20826 100644 --- a/core/src/avm2/error.rs +++ b/core/src/avm2/error.rs @@ -210,6 +210,17 @@ pub fn eof_error<'gc>( error_constructor(activation, class, message, code) } +#[inline(never)] +#[cold] +pub fn error<'gc>( + activation: &mut Activation<'_, 'gc>, + message: &str, + code: u32, +) -> Result, Error<'gc>> { + let class = activation.avm2().classes().error; + error_constructor(activation, class, message, code) +} + fn error_constructor<'gc>( activation: &mut Activation<'_, 'gc>, class: ClassObject<'gc>, diff --git a/core/src/avm2/globals.rs b/core/src/avm2/globals.rs index d0d8f4e8e..92b713f88 100644 --- a/core/src/avm2/globals.rs +++ b/core/src/avm2/globals.rs @@ -111,6 +111,7 @@ pub struct SystemClasses<'gc> { pub verifyerror: ClassObject<'gc>, pub ioerror: ClassObject<'gc>, pub eoferror: ClassObject<'gc>, + pub error: ClassObject<'gc>, pub uncaughterrorevents: ClassObject<'gc>, pub statictext: ClassObject<'gc>, pub textlinemetrics: ClassObject<'gc>, @@ -218,6 +219,7 @@ impl<'gc> SystemClasses<'gc> { verifyerror: object, ioerror: object, eoferror: object, + error: object, uncaughterrorevents: object, statictext: object, textlinemetrics: object, @@ -606,6 +608,7 @@ fn load_playerglobal<'gc>( activation, script, [ + ("", "Error", error), ("", "ArgumentError", argumenterror), ("", "RangeError", rangeerror), ("", "ReferenceError", referenceerror), diff --git a/core/src/avm2/globals/flash/display/LoaderInfo.as b/core/src/avm2/globals/flash/display/LoaderInfo.as index 4f5cbc81c..869980e0d 100644 --- a/core/src/avm2/globals/flash/display/LoaderInfo.as +++ b/core/src/avm2/globals/flash/display/LoaderInfo.as @@ -30,5 +30,7 @@ package flash.display { public native function get parameters():Object; public native function get sharedEvents():EventDispatcher; public native function get uncaughtErrorEvents():UncaughtErrorEvents; + public native function get sameDomain():Boolean; + public native function get childAllowsParent():Boolean; } } diff --git a/core/src/avm2/globals/flash/display/loader_info.rs b/core/src/avm2/globals/flash/display/loader_info.rs index 638ce4284..ffd49d45c 100644 --- a/core/src/avm2/globals/flash/display/loader_info.rs +++ b/core/src/avm2/globals/flash/display/loader_info.rs @@ -2,6 +2,7 @@ use crate::avm2::activation::Activation; use crate::avm2::bytearray::Endian; +use crate::avm2::error::error; use crate::avm2::object::{DomainObject, LoaderStream, Object, TObject}; use crate::avm2::value::Value; use crate::avm2::{AvmString, Error}; @@ -11,7 +12,6 @@ use swf::{write_swf, Compression}; pub use crate::avm2::object::loader_info_allocator; -// FIXME - Throw an actual 'Error' with the proper code const INSUFFICIENT: &str = "Error #2099: The loading object is not sufficiently loaded to provide this information."; @@ -41,7 +41,7 @@ pub fn get_action_script_version<'gc>( { match &*loader_stream { LoaderStream::NotYetLoaded(_, _, _) => { - return Err(INSUFFICIENT.into()); + return Err(Error::AvmError(error(_activation, INSUFFICIENT, 2099)?)); } LoaderStream::Swf(movie, _) => { let version = if movie.is_action_script_3() { 3 } else { 2 }; @@ -195,7 +195,7 @@ pub fn get_frame_rate<'gc>( { match &*loader_stream { LoaderStream::NotYetLoaded(_, _, _) => { - return Err("Error: The stage's loader info does not have a frame rate".into()) + return Err(Error::AvmError(error(_activation, INSUFFICIENT, 2099)?)); } LoaderStream::Swf(root, _) => { return Ok(root.frame_rate().to_f64().into()); @@ -220,7 +220,7 @@ pub fn get_height<'gc>( { match &*loader_stream { LoaderStream::NotYetLoaded(_, _, _) => { - return Err("Error: The stage's loader info does not have a height".into()) + return Err(Error::AvmError(error(_activation, INSUFFICIENT, 2099)?)); } LoaderStream::Swf(root, _) => { return Ok(root.height().to_pixels().into()); @@ -242,19 +242,9 @@ pub fn get_is_url_inaccessible<'gc>( Ok(false.into()) } -/// `parentAllowsChild` getter -pub fn get_parent_allows_child<'gc>( +/// `sameDomain` getter +pub fn get_same_domain<'gc>( activation: &mut Activation<'_, 'gc>, - _this: Option>, - _args: &[Value<'gc>], -) -> Result, Error<'gc>> { - avm2_stub_getter!(activation, "flash.display.LoaderInfo", "parentAllowsChild"); - Ok(false.into()) -} - -/// `swfVersion` getter -pub fn get_swf_version<'gc>( - _activation: &mut Activation<'_, 'gc>, this: Option>, _args: &[Value<'gc>], ) -> Result, Error<'gc>> { @@ -265,7 +255,84 @@ pub fn get_swf_version<'gc>( { match &*loader_stream { LoaderStream::NotYetLoaded(_, _, _) => { - return Err("Error: The stage's loader info does not have a SWF version".into()) + return Err(Error::AvmError(error(activation, INSUFFICIENT, 2099)?)); + } + LoaderStream::Swf(_root, _) => { + avm2_stub_getter!(activation, "flash.display.LoaderInfo", "sameDomain"); + return Ok(false.into()); + } + } + } + } + + Ok(Value::Undefined) +} + +/// `childAllowsParent` getter +pub fn get_child_allows_parent<'gc>( + activation: &mut Activation<'_, 'gc>, + this: Option>, + _args: &[Value<'gc>], +) -> Result, Error<'gc>> { + if let Some(this) = this { + if let Some(loader_stream) = this + .as_loader_info_object() + .and_then(|o| o.as_loader_stream()) + { + match &*loader_stream { + LoaderStream::NotYetLoaded(_, _, _) => { + return Err(Error::AvmError(error(activation, INSUFFICIENT, 2099)?)); + } + LoaderStream::Swf(_root, _) => { + avm2_stub_getter!(activation, "flash.display.LoaderInfo", "childAllowsParent"); + return Ok(false.into()); + } + } + } + } + + Ok(Value::Undefined) +} + +/// `parentAllowsChild` getter +pub fn get_parent_allows_child<'gc>( + activation: &mut Activation<'_, 'gc>, + this: Option>, + _args: &[Value<'gc>], +) -> Result, Error<'gc>> { + if let Some(this) = this { + if let Some(loader_stream) = this + .as_loader_info_object() + .and_then(|o| o.as_loader_stream()) + { + match &*loader_stream { + LoaderStream::NotYetLoaded(_, _, _) => { + return Err(Error::AvmError(error(activation, INSUFFICIENT, 2099)?)); + } + LoaderStream::Swf(_root, _) => { + avm2_stub_getter!(activation, "flash.display.LoaderInfo", "parentAllowsChild"); + return Ok(false.into()); + } + } + } + } + Ok(Value::Undefined) +} + +/// `swfVersion` getter +pub fn get_swf_version<'gc>( + activation: &mut Activation<'_, 'gc>, + this: Option>, + _args: &[Value<'gc>], +) -> Result, Error<'gc>> { + if let Some(this) = this { + if let Some(loader_stream) = this + .as_loader_info_object() + .and_then(|o| o.as_loader_stream()) + { + match &*loader_stream { + LoaderStream::NotYetLoaded(_, _, _) => { + return Err(Error::AvmError(error(activation, INSUFFICIENT, 2099)?)); } LoaderStream::Swf(root, _) => { return Ok(root.version().into()); @@ -312,7 +379,7 @@ pub fn get_width<'gc>( { match &*loader_stream { LoaderStream::NotYetLoaded(_, _, _) => { - return Err("Error: The stage's loader info does not have a width".into()) + return Err(Error::AvmError(error(_activation, INSUFFICIENT, 2099)?)); } LoaderStream::Swf(root, _) => { return Ok(root.width().to_pixels().into());