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`.
This commit is contained in:
parent
6fe44c3862
commit
22fedf4dca
|
@ -79,31 +79,21 @@ pub fn application_domain<'gc>(
|
|||
) -> Result<Value<'gc>, 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,17 +39,9 @@ pub fn current_domain<'gc>(
|
|||
) -> Result<Value<'gc>, 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<Value<'gc>, 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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Object<'gc>>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
domain: Domain<'gc>,
|
||||
) -> Object<'gc> {
|
||||
let base = ScriptObjectData::base_new(base_proto, ScriptObjectClass::ClassInstance(constr));
|
||||
) -> Result<Object<'gc>, 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<Object<'gc>, 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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue