From 22fedf4dca05e5cf567f8bb2b95fb4f20c5f79cc Mon Sep 17 00:00:00 2001 From: David Wendt Date: Mon, 31 May 2021 17:32:27 -0400 Subject: [PATCH] avm2: Make all domain object construction (save for the global domain) pull the constructor and call it in `from_domain`. This also adds `DomainObject::script_global`, which does the same thing but picks the `global` class instead of `ApplicationDomain`. --- .../avm2/globals/flash/display/loaderinfo.rs | 22 ++----- .../flash/system/application_domain.rs | 21 +----- core/src/avm2/object/domain_object.rs | 65 +++++++++++++------ core/src/avm2/script.rs | 8 +-- 4 files changed, 56 insertions(+), 60 deletions(-) diff --git a/core/src/avm2/globals/flash/display/loaderinfo.rs b/core/src/avm2/globals/flash/display/loaderinfo.rs index e31e49d7f..231bfb0dc 100644 --- a/core/src/avm2/globals/flash/display/loaderinfo.rs +++ b/core/src/avm2/globals/flash/display/loaderinfo.rs @@ -79,31 +79,21 @@ pub fn application_domain<'gc>( ) -> Result, Error> { if let Some(this) = this { if let Some(loader_stream) = this.as_loader_stream() { - let appdomain_proto = activation.avm2().prototypes().application_domain; - let appdomain_constr = activation.avm2().constructors().application_domain; - match &*loader_stream { LoaderStream::Stage => { return Ok(DomainObject::from_domain( - activation.context.gc_context, - appdomain_constr, - Some(appdomain_proto), + activation, activation.context.avm2.global_domain(), - ) + )? .into()); } LoaderStream::Swf(movie, _) => { - let library = activation + let domain = activation .context .library - .library_for_movie_mut(movie.clone()); - return Ok(DomainObject::from_domain( - activation.context.gc_context, - appdomain_constr, - Some(appdomain_proto), - library.avm2_domain(), - ) - .into()); + .library_for_movie_mut(movie.clone()) + .avm2_domain(); + return Ok(DomainObject::from_domain(activation, domain)?.into()); } } } diff --git a/core/src/avm2/globals/flash/system/application_domain.rs b/core/src/avm2/globals/flash/system/application_domain.rs index 7679b018c..f22592f94 100644 --- a/core/src/avm2/globals/flash/system/application_domain.rs +++ b/core/src/avm2/globals/flash/system/application_domain.rs @@ -39,17 +39,9 @@ pub fn current_domain<'gc>( ) -> Result, Error> { let globals = activation.scope().map(|s| s.read().globals()); let appdomain = globals.and_then(|g| g.as_application_domain()); - let appdomain_proto = activation.avm2().prototypes().application_domain; - let appdomain_constr = activation.avm2().constructors().application_domain; if let Some(appdomain) = appdomain { - return Ok(DomainObject::from_domain( - activation.context.gc_context, - appdomain_constr, - Some(appdomain_proto), - appdomain, - ) - .into()); + return Ok(DomainObject::from_domain(activation, appdomain)?.into()); } Ok(Value::Undefined) @@ -63,16 +55,7 @@ pub fn parent_domain<'gc>( ) -> Result, Error> { if let Some(appdomain) = this.and_then(|this| this.as_application_domain()) { if let Some(parent_domain) = appdomain.parent_domain() { - let appdomain_proto = activation.avm2().prototypes().application_domain; - let appdomain_constr = activation.avm2().constructors().application_domain; - - return Ok(DomainObject::from_domain( - activation.context.gc_context, - appdomain_constr, - Some(appdomain_proto), - parent_domain, - ) - .into()); + return Ok(DomainObject::from_domain(activation, parent_domain)?.into()); } } diff --git a/core/src/avm2/object/domain_object.rs b/core/src/avm2/object/domain_object.rs index 8620e6739..c6d180e43 100644 --- a/core/src/avm2/object/domain_object.rs +++ b/core/src/avm2/object/domain_object.rs @@ -28,8 +28,13 @@ pub fn appdomain_deriver<'gc>( .globals() .as_application_domain() .ok_or("Constructor scope must have an appdomain at the bottom of it's scope stack")?; + let base = ScriptObjectData::base_new(Some(proto), ScriptObjectClass::ClassInstance(constr)); - DomainObject::derive(constr, proto, domain, activation.context.gc_context) + Ok(DomainObject(GcCell::allocate( + activation.context.gc_context, + DomainObjectData { base, domain }, + )) + .into()) } #[derive(Clone, Collect, Debug, Copy)] @@ -58,28 +63,53 @@ impl<'gc> DomainObject<'gc> { DomainObject(GcCell::allocate(mc, DomainObjectData { base, domain })).into() } + /// Create a new object for a given domain. + /// + /// This function will call instance initializers. You do not need to do so + /// yourself. pub fn from_domain( - mc: MutationContext<'gc, '_>, - constr: Object<'gc>, - base_proto: Option>, + activation: &mut Activation<'_, 'gc, '_>, domain: Domain<'gc>, - ) -> Object<'gc> { - let base = ScriptObjectData::base_new(base_proto, ScriptObjectClass::ClassInstance(constr)); + ) -> Result, Error> { + let constr = activation.avm2().constructors().application_domain; + let proto = activation.avm2().prototypes().application_domain; + let base = + ScriptObjectData::base_new(Some(proto), ScriptObjectClass::ClassInstance(constr)); + let this = DomainObject(GcCell::allocate( + activation.context.gc_context, + DomainObjectData { base, domain }, + )) + .into(); - DomainObject(GcCell::allocate(mc, DomainObjectData { base, domain })).into() + constr.call_initializer(Some(this), &[], activation, Some(constr))?; + + Ok(this) } - /// Construct a primitive subclass. - pub fn derive( - constr: Object<'gc>, - base_proto: Object<'gc>, + /// Create a new object for a given script's global scope. + /// + /// The `domain` object will serve as the scope of last resort should the + /// global scope not have a particular name defined. + /// + /// This function will call instance initializers. You do not need to do so + /// yourself. + pub fn script_global( + activation: &mut Activation<'_, 'gc, '_>, domain: Domain<'gc>, - mc: MutationContext<'gc, '_>, ) -> Result, Error> { + let constr = activation.avm2().constructors().global; + let proto = activation.avm2().prototypes().global; let base = - ScriptObjectData::base_new(Some(base_proto), ScriptObjectClass::ClassInstance(constr)); + ScriptObjectData::base_new(Some(proto), ScriptObjectClass::ClassInstance(constr)); + let this = DomainObject(GcCell::allocate( + activation.context.gc_context, + DomainObjectData { base, domain }, + )) + .into(); - Ok(DomainObject(GcCell::allocate(mc, DomainObjectData { base, domain })).into()) + constr.call_initializer(Some(this), &[], activation, Some(constr))?; + + Ok(this) } } @@ -107,11 +137,6 @@ impl<'gc> TObject<'gc> for DomainObject<'gc> { )? .coerce_to_object(activation)?; - Ok(DomainObject::from_domain( - activation.context.gc_context, - constr, - Some(this), - activation.context.avm2.global_domain(), - )) + appdomain_deriver(constr, this, activation) } } diff --git a/core/src/avm2/script.rs b/core/src/avm2/script.rs index 486dedcea..9525ffdea 100644 --- a/core/src/avm2/script.rs +++ b/core/src/avm2/script.rs @@ -146,11 +146,9 @@ impl<'gc> TranslationUnit<'gc> { drop(read); - let global_proto = uc.avm2.prototypes().global; - let global_constr = uc.avm2.constructors().global; - - let global = - DomainObject::from_domain(uc.gc_context, global_constr, Some(global_proto), domain); + let mut activation = Activation::from_nothing(uc.reborrow()); + let global = DomainObject::script_global(&mut activation, domain)?; + drop(activation); let mut script = Script::from_abc_index(self, script_index, global, uc.gc_context)?; self.0