avm2: Script scopes should hold the domains they are a part of.
Also, this means we have a `TObject` representation for domains now.
This commit is contained in:
parent
6a736b0d2b
commit
1792939212
|
@ -6,8 +6,8 @@ use crate::avm2::domain::Domain;
|
|||
use crate::avm2::method::NativeMethod;
|
||||
use crate::avm2::names::{Namespace, QName};
|
||||
use crate::avm2::object::{
|
||||
implicit_deriver, ArrayObject, FunctionObject, NamespaceObject, Object, PrimitiveObject,
|
||||
ScriptObject, StageObject, TObject,
|
||||
implicit_deriver, ArrayObject, DomainObject, FunctionObject, NamespaceObject, Object,
|
||||
PrimitiveObject, ScriptObject, StageObject, TObject,
|
||||
};
|
||||
use crate::avm2::scope::Scope;
|
||||
use crate::avm2::script::Script;
|
||||
|
@ -270,7 +270,7 @@ pub fn load_player_globals<'gc>(
|
|||
domain: GcCell<'gc, Domain<'gc>>,
|
||||
) -> Result<(), Error> {
|
||||
let mc = activation.context.gc_context;
|
||||
let gs = ScriptObject::bare_object(mc);
|
||||
let gs = DomainObject::from_domain(mc, None, domain);
|
||||
let script = Script::empty_script(mc, gs);
|
||||
|
||||
// public / root package
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
use crate::avm2::activation::Activation;
|
||||
use crate::avm2::array::ArrayStorage;
|
||||
use crate::avm2::class::Class;
|
||||
use crate::avm2::domain::Domain;
|
||||
use crate::avm2::function::Executable;
|
||||
use crate::avm2::names::{Multiname, Namespace, QName};
|
||||
use crate::avm2::scope::Scope;
|
||||
|
@ -18,6 +19,7 @@ use std::fmt::Debug;
|
|||
|
||||
mod array_object;
|
||||
mod custom_object;
|
||||
mod domain_object;
|
||||
mod function_object;
|
||||
mod namespace_object;
|
||||
mod primitive_object;
|
||||
|
@ -25,6 +27,7 @@ mod script_object;
|
|||
mod stage_object;
|
||||
|
||||
pub use crate::avm2::object::array_object::ArrayObject;
|
||||
pub use crate::avm2::object::domain_object::DomainObject;
|
||||
pub use crate::avm2::object::function_object::{implicit_deriver, FunctionObject};
|
||||
pub use crate::avm2::object::namespace_object::NamespaceObject;
|
||||
pub use crate::avm2::object::primitive_object::PrimitiveObject;
|
||||
|
@ -43,6 +46,7 @@ pub use crate::avm2::object::stage_object::StageObject;
|
|||
NamespaceObject(NamespaceObject<'gc>),
|
||||
ArrayObject(ArrayObject<'gc>),
|
||||
StageObject(StageObject<'gc>),
|
||||
DomainObject(DomainObject<'gc>),
|
||||
}
|
||||
)]
|
||||
pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy {
|
||||
|
@ -682,7 +686,14 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
/// coercions happen by defining `toString` in a downstream class or
|
||||
/// prototype; this is then picked up by the VM runtime when doing
|
||||
/// coercions.
|
||||
fn to_string(&self, mc: MutationContext<'gc, '_>) -> Result<Value<'gc>, Error>;
|
||||
fn to_string(&self, mc: MutationContext<'gc, '_>) -> Result<Value<'gc>, Error> {
|
||||
let class_name = self
|
||||
.as_proto_class()
|
||||
.map(|c| c.read().name().local_name())
|
||||
.unwrap_or_else(|| "Object".into());
|
||||
|
||||
Ok(AvmString::new(mc, format!("[object {}]", class_name)).into())
|
||||
}
|
||||
|
||||
/// Implement the result of calling `Object.prototype.toLocaleString` on this
|
||||
/// object class.
|
||||
|
@ -823,6 +834,11 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
///
|
||||
/// If not, then this function does nothing.
|
||||
fn init_display_object(&self, _mc: MutationContext<'gc, '_>, _obj: DisplayObject<'gc>) {}
|
||||
|
||||
/// Unwrap this object as an ApplicationDomain.
|
||||
fn as_application_domain(&self) -> Option<GcCell<'gc, Domain<'gc>>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub enum ObjectPtr {}
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
//! Application Domain objects for scripts
|
||||
|
||||
use crate::avm2::activation::Activation;
|
||||
use crate::avm2::class::Class;
|
||||
use crate::avm2::domain::Domain;
|
||||
use crate::avm2::names::{Namespace, QName};
|
||||
use crate::avm2::object::script_object::{ScriptObjectClass, ScriptObjectData};
|
||||
use crate::avm2::object::{Object, ObjectPtr, TObject};
|
||||
use crate::avm2::scope::Scope;
|
||||
use crate::avm2::string::AvmString;
|
||||
use crate::avm2::traits::Trait;
|
||||
use crate::avm2::value::Value;
|
||||
use crate::avm2::Error;
|
||||
use crate::{impl_avm2_custom_object, impl_avm2_custom_object_properties};
|
||||
use gc_arena::{Collect, GcCell, MutationContext};
|
||||
|
||||
#[derive(Clone, Collect, Debug, Copy)]
|
||||
#[collect(no_drop)]
|
||||
pub struct DomainObject<'gc>(GcCell<'gc, DomainObjectData<'gc>>);
|
||||
|
||||
#[derive(Clone, Collect, Debug)]
|
||||
#[collect(no_drop)]
|
||||
pub struct DomainObjectData<'gc> {
|
||||
/// Base script object
|
||||
base: ScriptObjectData<'gc>,
|
||||
|
||||
/// The domain this object holds
|
||||
domain: GcCell<'gc, Domain<'gc>>,
|
||||
}
|
||||
|
||||
impl<'gc> DomainObject<'gc> {
|
||||
pub fn from_domain(
|
||||
mc: MutationContext<'gc, '_>,
|
||||
base_proto: Option<Object<'gc>>,
|
||||
domain: GcCell<'gc, Domain<'gc>>,
|
||||
) -> Object<'gc> {
|
||||
let base = ScriptObjectData::base_new(base_proto, ScriptObjectClass::NoClass);
|
||||
|
||||
DomainObject(GcCell::allocate(mc, DomainObjectData { base, domain })).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> TObject<'gc> for DomainObject<'gc> {
|
||||
impl_avm2_custom_object!(base);
|
||||
impl_avm2_custom_object_properties!(base);
|
||||
|
||||
fn as_application_domain(&self) -> Option<GcCell<'gc, Domain<'gc>>> {
|
||||
Some(self.0.read().domain)
|
||||
}
|
||||
|
||||
fn value_of(&self, _mc: MutationContext<'gc, '_>) -> Result<Value<'gc>, Error> {
|
||||
let this: Object<'gc> = Object::DomainObject(*self);
|
||||
|
||||
Ok(this.into())
|
||||
}
|
||||
|
||||
fn construct(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Object<'gc>, Error> {
|
||||
let this: Object<'gc> = Object::DomainObject(*self);
|
||||
let parent_domain = if let Some(parent_domain) = args
|
||||
.get(0)
|
||||
.cloned()
|
||||
.unwrap_or(Value::Undefined)
|
||||
.coerce_to_object(activation)?
|
||||
.as_application_domain()
|
||||
{
|
||||
parent_domain
|
||||
} else {
|
||||
activation.context.avm2.global_domain()
|
||||
};
|
||||
|
||||
Ok(DomainObject::from_domain(
|
||||
activation.context.gc_context,
|
||||
Some(this),
|
||||
Domain::movie_domain(activation.context.gc_context, parent_domain),
|
||||
))
|
||||
}
|
||||
|
||||
fn derive(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
_class: GcCell<'gc, Class<'gc>>,
|
||||
_scope: Option<GcCell<'gc, Scope<'gc>>>,
|
||||
) -> Result<Object<'gc>, Error> {
|
||||
let this: Object<'gc> = Object::DomainObject(*self);
|
||||
Ok(DomainObject::from_domain(
|
||||
activation.context.gc_context,
|
||||
Some(this),
|
||||
activation.context.avm2.global_domain(),
|
||||
))
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
use crate::avm2::class::Class;
|
||||
use crate::avm2::domain::Domain;
|
||||
use crate::avm2::method::{BytecodeMethod, Method};
|
||||
use crate::avm2::object::{Object, ScriptObject};
|
||||
use crate::avm2::object::{DomainObject, Object};
|
||||
use crate::avm2::string::AvmString;
|
||||
use crate::avm2::traits::Trait;
|
||||
use crate::avm2::value::Value;
|
||||
|
@ -139,9 +139,11 @@ impl<'gc> TranslationUnit<'gc> {
|
|||
return Ok(*scripts);
|
||||
}
|
||||
|
||||
let domain = read.domain;
|
||||
|
||||
drop(read);
|
||||
|
||||
let global = ScriptObject::object(mc, avm2.prototypes().global);
|
||||
let global = DomainObject::from_domain(mc, Some(avm2.prototypes().global), domain);
|
||||
|
||||
let script = Script::from_abc_index(self, script_index, global, mc)?;
|
||||
self.0.write(mc).scripts.insert(script_index, script);
|
||||
|
@ -149,9 +151,7 @@ impl<'gc> TranslationUnit<'gc> {
|
|||
script.write(mc).load_traits(self, script_index, avm2, mc)?;
|
||||
|
||||
for traitdef in script.read().traits()? {
|
||||
self.0
|
||||
.read()
|
||||
.domain
|
||||
domain
|
||||
.write(mc)
|
||||
.export_definition(traitdef.name().clone(), script)?;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue