avm1: Add impl_custom_object!() macro to simplify custom object types
This commit is contained in:
parent
eb94cc54b2
commit
180891c58e
|
@ -22,6 +22,7 @@ use std::borrow::Cow;
|
|||
use std::fmt::Debug;
|
||||
|
||||
pub mod color_transform_object;
|
||||
mod custom_object;
|
||||
pub mod script_object;
|
||||
pub mod shared_object;
|
||||
pub mod sound_object;
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
use crate::avm1::error::Error;
|
||||
use crate::avm1::function::Executable;
|
||||
use crate::avm1::property::Attribute;
|
||||
use crate::avm1::{Object, ObjectPtr, ScriptObject, TObject, Value};
|
||||
use crate::avm1::{Object, ScriptObject, TObject, Value};
|
||||
use crate::context::UpdateContext;
|
||||
use enumset::EnumSet;
|
||||
use crate::impl_custom_object_without_set;
|
||||
use gc_arena::{Collect, GcCell, MutationContext};
|
||||
|
||||
use crate::avm1::activation::Activation;
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
|
||||
/// A ColorTransform
|
||||
|
@ -93,22 +90,10 @@ impl<'gc> ColorTransformObject<'gc> {
|
|||
[set_blue_offset, get_blue_offset, blue_offset],
|
||||
[set_alpha_offset, get_alpha_offset, alpha_offset],
|
||||
);
|
||||
|
||||
fn base(self) -> ScriptObject<'gc> {
|
||||
self.0.read().base
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> TObject<'gc> for ColorTransformObject<'gc> {
|
||||
fn get_local(
|
||||
&self,
|
||||
name: &str,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
self.base().get_local(name, activation, context, this)
|
||||
}
|
||||
impl_custom_object_without_set!(base);
|
||||
|
||||
fn set(
|
||||
&self,
|
||||
|
@ -117,7 +102,8 @@ impl<'gc> TObject<'gc> for ColorTransformObject<'gc> {
|
|||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
) -> Result<(), Error<'gc>> {
|
||||
self.base().internal_set(
|
||||
let base = self.0.read().base;
|
||||
base.internal_set(
|
||||
name,
|
||||
value,
|
||||
activation,
|
||||
|
@ -127,27 +113,8 @@ impl<'gc> TObject<'gc> for ColorTransformObject<'gc> {
|
|||
)
|
||||
}
|
||||
|
||||
fn call(
|
||||
&self,
|
||||
name: &str,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
base_proto: Option<Object<'gc>>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
self.base()
|
||||
.call(name, activation, context, this, base_proto, args)
|
||||
}
|
||||
|
||||
fn call_setter(
|
||||
&self,
|
||||
name: &str,
|
||||
value: Value<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
) -> Option<Executable<'gc>> {
|
||||
self.base().call_setter(name, value, activation, context)
|
||||
fn as_color_transform_object(&self) -> Option<ColorTransformObject<'gc>> {
|
||||
Some(*self)
|
||||
}
|
||||
|
||||
#[allow(clippy::new_ret_no_self)]
|
||||
|
@ -164,185 +131,4 @@ impl<'gc> TObject<'gc> for ColorTransformObject<'gc> {
|
|||
)
|
||||
.into())
|
||||
}
|
||||
|
||||
fn delete(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: &str,
|
||||
) -> bool {
|
||||
self.base().delete(activation, gc_context, name)
|
||||
}
|
||||
|
||||
fn proto(&self) -> Option<Object<'gc>> {
|
||||
self.base().proto()
|
||||
}
|
||||
|
||||
fn set_proto(&self, gc_context: MutationContext<'gc, '_>, prototype: Option<Object<'gc>>) {
|
||||
self.base().set_proto(gc_context, prototype);
|
||||
}
|
||||
|
||||
fn define_value(
|
||||
&self,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: &str,
|
||||
value: Value<'gc>,
|
||||
attributes: EnumSet<Attribute>,
|
||||
) {
|
||||
self.base()
|
||||
.define_value(gc_context, name, value, attributes)
|
||||
}
|
||||
|
||||
fn set_attributes(
|
||||
&mut self,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: Option<&str>,
|
||||
set_attributes: EnumSet<Attribute>,
|
||||
clear_attributes: EnumSet<Attribute>,
|
||||
) {
|
||||
self.base()
|
||||
.set_attributes(gc_context, name, set_attributes, clear_attributes)
|
||||
}
|
||||
|
||||
fn add_property(
|
||||
&self,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: &str,
|
||||
get: Executable<'gc>,
|
||||
set: Option<Executable<'gc>>,
|
||||
attributes: EnumSet<Attribute>,
|
||||
) {
|
||||
self.base()
|
||||
.add_property(gc_context, name, get, set, attributes)
|
||||
}
|
||||
|
||||
fn add_property_with_case(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: &str,
|
||||
get: Executable<'gc>,
|
||||
set: Option<Executable<'gc>>,
|
||||
attributes: EnumSet<Attribute>,
|
||||
) {
|
||||
self.base()
|
||||
.add_property_with_case(activation, gc_context, name, get, set, attributes)
|
||||
}
|
||||
|
||||
fn set_watcher(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: Cow<str>,
|
||||
callback: Executable<'gc>,
|
||||
user_data: Value<'gc>,
|
||||
) {
|
||||
self.base()
|
||||
.set_watcher(activation, gc_context, name, callback, user_data);
|
||||
}
|
||||
|
||||
fn remove_watcher(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: Cow<str>,
|
||||
) -> bool {
|
||||
self.base().remove_watcher(activation, gc_context, name)
|
||||
}
|
||||
|
||||
fn has_property(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
name: &str,
|
||||
) -> bool {
|
||||
self.base().has_property(activation, context, name)
|
||||
}
|
||||
|
||||
fn has_own_property(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
name: &str,
|
||||
) -> bool {
|
||||
self.base().has_own_property(activation, context, name)
|
||||
}
|
||||
|
||||
fn has_own_virtual(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
name: &str,
|
||||
) -> bool {
|
||||
self.base().has_own_virtual(activation, context, name)
|
||||
}
|
||||
|
||||
fn is_property_enumerable(&self, activation: &mut Activation<'_, 'gc>, name: &str) -> bool {
|
||||
self.base().is_property_enumerable(activation, name)
|
||||
}
|
||||
|
||||
fn get_keys(&self, activation: &mut Activation<'_, 'gc>) -> Vec<String> {
|
||||
self.base().get_keys(activation)
|
||||
}
|
||||
|
||||
fn as_string(&self) -> Cow<str> {
|
||||
Cow::Owned(self.base().as_string().into_owned())
|
||||
}
|
||||
|
||||
fn type_of(&self) -> &'static str {
|
||||
self.base().type_of()
|
||||
}
|
||||
|
||||
fn interfaces(&self) -> Vec<Object<'gc>> {
|
||||
self.base().interfaces()
|
||||
}
|
||||
|
||||
fn set_interfaces(
|
||||
&mut self,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
iface_list: Vec<Object<'gc>>,
|
||||
) {
|
||||
self.base().set_interfaces(gc_context, iface_list)
|
||||
}
|
||||
|
||||
fn as_script_object(&self) -> Option<ScriptObject<'gc>> {
|
||||
Some(self.base())
|
||||
}
|
||||
|
||||
fn as_color_transform_object(&self) -> Option<ColorTransformObject<'gc>> {
|
||||
Some(*self)
|
||||
}
|
||||
|
||||
fn as_ptr(&self) -> *const ObjectPtr {
|
||||
self.0.as_ptr() as *const ObjectPtr
|
||||
}
|
||||
|
||||
fn length(&self) -> usize {
|
||||
self.base().length()
|
||||
}
|
||||
|
||||
fn array(&self) -> Vec<Value<'gc>> {
|
||||
self.base().array()
|
||||
}
|
||||
|
||||
fn set_length(&self, gc_context: MutationContext<'gc, '_>, length: usize) {
|
||||
self.base().set_length(gc_context, length)
|
||||
}
|
||||
|
||||
fn array_element(&self, index: usize) -> Value<'gc> {
|
||||
self.base().array_element(index)
|
||||
}
|
||||
|
||||
fn set_array_element(
|
||||
&self,
|
||||
index: usize,
|
||||
value: Value<'gc>,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
) -> usize {
|
||||
self.base().set_array_element(index, value, gc_context)
|
||||
}
|
||||
|
||||
fn delete_array_element(&self, index: usize, gc_context: MutationContext<'gc, '_>) {
|
||||
self.base().delete_array_element(index, gc_context)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,281 @@
|
|||
#[macro_export]
|
||||
macro_rules! impl_custom_object_without_set {
|
||||
($field:ident) => {
|
||||
fn get_local(
|
||||
&self,
|
||||
name: &str,
|
||||
activation: &mut crate::avm1::Activation<'_, 'gc>,
|
||||
context: &mut crate::context::UpdateContext<'_, 'gc, '_>,
|
||||
this: crate::avm1::Object<'gc>,
|
||||
) -> Result<crate::avm1::Value<'gc>, crate::avm1::Error<'gc>> {
|
||||
self.0
|
||||
.read()
|
||||
.$field
|
||||
.get_local(name, activation, context, this)
|
||||
}
|
||||
|
||||
fn call(
|
||||
&self,
|
||||
name: &str,
|
||||
activation: &mut crate::avm1::Activation<'_, 'gc>,
|
||||
context: &mut crate::context::UpdateContext<'_, 'gc, '_>,
|
||||
this: crate::avm1::Object<'gc>,
|
||||
base_proto: Option<crate::avm1::Object<'gc>>,
|
||||
args: &[crate::avm1::Value<'gc>],
|
||||
) -> Result<crate::avm1::Value<'gc>, crate::avm1::Error<'gc>> {
|
||||
self.0
|
||||
.read()
|
||||
.$field
|
||||
.call(name, activation, context, this, base_proto, args)
|
||||
}
|
||||
|
||||
fn call_setter(
|
||||
&self,
|
||||
name: &str,
|
||||
value: crate::avm1::Value<'gc>,
|
||||
activation: &mut crate::avm1::Activation<'_, 'gc>,
|
||||
context: &mut crate::context::UpdateContext<'_, 'gc, '_>,
|
||||
) -> Option<crate::avm1::function::Executable<'gc>> {
|
||||
self.0
|
||||
.read()
|
||||
.$field
|
||||
.call_setter(name, value, activation, context)
|
||||
}
|
||||
|
||||
fn delete(
|
||||
&self,
|
||||
activation: &mut crate::avm1::Activation<'_, 'gc>,
|
||||
gc_context: gc_arena::MutationContext<'gc, '_>,
|
||||
name: &str,
|
||||
) -> bool {
|
||||
self.0.read().$field.delete(activation, gc_context, name)
|
||||
}
|
||||
|
||||
fn proto(&self) -> Option<crate::avm1::Object<'gc>> {
|
||||
self.0.read().$field.proto()
|
||||
}
|
||||
|
||||
fn set_proto(
|
||||
&self,
|
||||
gc_context: gc_arena::MutationContext<'gc, '_>,
|
||||
prototype: Option<crate::avm1::Object<'gc>>,
|
||||
) {
|
||||
self.0.read().$field.set_proto(gc_context, prototype);
|
||||
}
|
||||
|
||||
fn define_value(
|
||||
&self,
|
||||
gc_context: gc_arena::MutationContext<'gc, '_>,
|
||||
name: &str,
|
||||
value: crate::avm1::Value<'gc>,
|
||||
attributes: enumset::EnumSet<crate::avm1::property::Attribute>,
|
||||
) {
|
||||
self.0
|
||||
.read()
|
||||
.$field
|
||||
.define_value(gc_context, name, value, attributes)
|
||||
}
|
||||
|
||||
fn set_attributes(
|
||||
&mut self,
|
||||
gc_context: gc_arena::MutationContext<'gc, '_>,
|
||||
name: Option<&str>,
|
||||
set_attributes: enumset::EnumSet<crate::avm1::property::Attribute>,
|
||||
clear_attributes: enumset::EnumSet<crate::avm1::property::Attribute>,
|
||||
) {
|
||||
self.0.write(gc_context).$field.set_attributes(
|
||||
gc_context,
|
||||
name,
|
||||
set_attributes,
|
||||
clear_attributes,
|
||||
)
|
||||
}
|
||||
|
||||
fn add_property(
|
||||
&self,
|
||||
gc_context: gc_arena::MutationContext<'gc, '_>,
|
||||
name: &str,
|
||||
get: crate::avm1::function::Executable<'gc>,
|
||||
set: Option<crate::avm1::function::Executable<'gc>>,
|
||||
attributes: enumset::EnumSet<crate::avm1::property::Attribute>,
|
||||
) {
|
||||
self.0
|
||||
.read()
|
||||
.$field
|
||||
.add_property(gc_context, name, get, set, attributes)
|
||||
}
|
||||
|
||||
fn add_property_with_case(
|
||||
&self,
|
||||
activation: &mut crate::avm1::Activation<'_, 'gc>,
|
||||
gc_context: gc_arena::MutationContext<'gc, '_>,
|
||||
name: &str,
|
||||
get: crate::avm1::function::Executable<'gc>,
|
||||
set: Option<crate::avm1::function::Executable<'gc>>,
|
||||
attributes: enumset::EnumSet<crate::avm1::property::Attribute>,
|
||||
) {
|
||||
self.0
|
||||
.read()
|
||||
.$field
|
||||
.add_property_with_case(activation, gc_context, name, get, set, attributes)
|
||||
}
|
||||
|
||||
fn has_property(
|
||||
&self,
|
||||
activation: &mut crate::avm1::Activation<'_, 'gc>,
|
||||
context: &mut crate::context::UpdateContext<'_, 'gc, '_>,
|
||||
name: &str,
|
||||
) -> bool {
|
||||
self.0.read().$field.has_property(activation, context, name)
|
||||
}
|
||||
|
||||
fn has_own_property(
|
||||
&self,
|
||||
activation: &mut crate::avm1::Activation<'_, 'gc>,
|
||||
context: &mut crate::context::UpdateContext<'_, 'gc, '_>,
|
||||
name: &str,
|
||||
) -> bool {
|
||||
self.0
|
||||
.read()
|
||||
.$field
|
||||
.has_own_property(activation, context, name)
|
||||
}
|
||||
|
||||
fn has_own_virtual(
|
||||
&self,
|
||||
activation: &mut crate::avm1::Activation<'_, 'gc>,
|
||||
context: &mut crate::context::UpdateContext<'_, 'gc, '_>,
|
||||
name: &str,
|
||||
) -> bool {
|
||||
self.0
|
||||
.read()
|
||||
.$field
|
||||
.has_own_virtual(activation, context, name)
|
||||
}
|
||||
|
||||
fn is_property_enumerable(
|
||||
&self,
|
||||
activation: &mut crate::avm1::Activation<'_, 'gc>,
|
||||
name: &str,
|
||||
) -> bool {
|
||||
self.0
|
||||
.read()
|
||||
.$field
|
||||
.is_property_enumerable(activation, name)
|
||||
}
|
||||
|
||||
fn get_keys(&self, activation: &mut crate::avm1::Activation<'_, 'gc>) -> Vec<String> {
|
||||
self.0.read().$field.get_keys(activation)
|
||||
}
|
||||
|
||||
fn as_string(&self) -> std::borrow::Cow<str> {
|
||||
std::borrow::Cow::Owned(self.0.read().$field.as_string().into_owned())
|
||||
}
|
||||
|
||||
fn type_of(&self) -> &'static str {
|
||||
self.0.read().$field.type_of()
|
||||
}
|
||||
|
||||
fn interfaces(&self) -> Vec<crate::avm1::Object<'gc>> {
|
||||
self.0.read().$field.interfaces()
|
||||
}
|
||||
|
||||
fn set_interfaces(
|
||||
&mut self,
|
||||
gc_context: gc_arena::MutationContext<'gc, '_>,
|
||||
iface_list: Vec<crate::avm1::Object<'gc>>,
|
||||
) {
|
||||
self.0
|
||||
.write(gc_context)
|
||||
.$field
|
||||
.set_interfaces(gc_context, iface_list)
|
||||
}
|
||||
|
||||
fn as_script_object(&self) -> Option<ScriptObject<'gc>> {
|
||||
Some(self.0.read().$field)
|
||||
}
|
||||
|
||||
fn as_ptr(&self) -> *const crate::avm1::ObjectPtr {
|
||||
self.0.as_ptr() as *const crate::avm1::ObjectPtr
|
||||
}
|
||||
|
||||
fn length(&self) -> usize {
|
||||
self.0.read().$field.length()
|
||||
}
|
||||
|
||||
fn array(&self) -> Vec<crate::avm1::Value<'gc>> {
|
||||
self.0.read().$field.array()
|
||||
}
|
||||
|
||||
fn set_length(&self, gc_context: gc_arena::MutationContext<'gc, '_>, length: usize) {
|
||||
self.0.read().$field.set_length(gc_context, length)
|
||||
}
|
||||
|
||||
fn array_element(&self, index: usize) -> crate::avm1::Value<'gc> {
|
||||
self.0.read().$field.array_element(index)
|
||||
}
|
||||
|
||||
fn set_array_element(
|
||||
&self,
|
||||
index: usize,
|
||||
value: crate::avm1::Value<'gc>,
|
||||
gc_context: gc_arena::MutationContext<'gc, '_>,
|
||||
) -> usize {
|
||||
self.0
|
||||
.read()
|
||||
.$field
|
||||
.set_array_element(index, value, gc_context)
|
||||
}
|
||||
|
||||
fn delete_array_element(
|
||||
&self,
|
||||
index: usize,
|
||||
gc_context: gc_arena::MutationContext<'gc, '_>,
|
||||
) {
|
||||
self.0.read().$field.delete_array_element(index, gc_context)
|
||||
}
|
||||
|
||||
fn set_watcher(
|
||||
&self,
|
||||
activation: &mut crate::avm1::Activation<'_, 'gc>,
|
||||
gc_context: gc_arena::MutationContext<'gc, '_>,
|
||||
name: std::borrow::Cow<str>,
|
||||
callback: crate::avm1::function::Executable<'gc>,
|
||||
user_data: crate::avm1::Value<'gc>,
|
||||
) {
|
||||
self.0
|
||||
.read()
|
||||
.$field
|
||||
.set_watcher(activation, gc_context, name, callback, user_data);
|
||||
}
|
||||
|
||||
fn remove_watcher(
|
||||
&self,
|
||||
activation: &mut crate::avm1::Activation<'_, 'gc>,
|
||||
gc_context: gc_arena::MutationContext<'gc, '_>,
|
||||
name: std::borrow::Cow<str>,
|
||||
) -> bool {
|
||||
self.0
|
||||
.read()
|
||||
.$field
|
||||
.remove_watcher(activation, gc_context, name)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_custom_object {
|
||||
($field:ident) => {
|
||||
crate::impl_custom_object_without_set!($field);
|
||||
|
||||
fn set(
|
||||
&self,
|
||||
name: &str,
|
||||
value: crate::avm1::Value<'gc>,
|
||||
activation: &mut crate::avm1::Activation<'_, 'gc>,
|
||||
context: &mut crate::context::UpdateContext<'_, 'gc, '_>,
|
||||
) -> Result<(), crate::avm1::Error<'gc>> {
|
||||
self.0.read().$field.set(name, value, activation, context)
|
||||
}
|
||||
};
|
||||
}
|
|
@ -1,15 +1,10 @@
|
|||
use crate::avm1::activation::Activation;
|
||||
use crate::avm1::error::Error;
|
||||
use crate::avm1::function::Executable;
|
||||
use crate::avm1::object::sound_object::SoundObject;
|
||||
use crate::avm1::property::Attribute;
|
||||
use crate::avm1::{Object, ObjectPtr, ScriptObject, TObject, Value};
|
||||
use crate::context::UpdateContext;
|
||||
use crate::display_object::DisplayObject;
|
||||
use enumset::EnumSet;
|
||||
use crate::impl_custom_object;
|
||||
use gc_arena::{Collect, GcCell, MutationContext};
|
||||
|
||||
use std::borrow::Cow;
|
||||
use crate::avm1::activation::Activation;
|
||||
use crate::avm1::error::Error;
|
||||
use crate::avm1::{Object, ScriptObject, TObject, Value};
|
||||
use crate::context::UpdateContext;
|
||||
use std::fmt;
|
||||
|
||||
/// A SharedObject
|
||||
|
@ -63,54 +58,10 @@ impl<'gc> SharedObject<'gc> {
|
|||
.cloned()
|
||||
.unwrap_or_else(|| "".to_string())
|
||||
}
|
||||
|
||||
fn base(self) -> ScriptObject<'gc> {
|
||||
self.0.read().base
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> TObject<'gc> for SharedObject<'gc> {
|
||||
fn get_local(
|
||||
&self,
|
||||
name: &str,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
self.base().get_local(name, activation, context, this)
|
||||
}
|
||||
|
||||
fn set(
|
||||
&self,
|
||||
name: &str,
|
||||
value: Value<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
) -> Result<(), Error<'gc>> {
|
||||
self.base().set(name, value, activation, context)
|
||||
}
|
||||
fn call(
|
||||
&self,
|
||||
name: &str,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
base_proto: Option<Object<'gc>>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
self.base()
|
||||
.call(name, activation, context, this, base_proto, args)
|
||||
}
|
||||
|
||||
fn call_setter(
|
||||
&self,
|
||||
name: &str,
|
||||
value: Value<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
) -> Option<Executable<'gc>> {
|
||||
self.base().call_setter(name, value, activation, context)
|
||||
}
|
||||
impl_custom_object!(base);
|
||||
|
||||
#[allow(clippy::new_ret_no_self)]
|
||||
fn new(
|
||||
|
@ -127,196 +78,7 @@ impl<'gc> TObject<'gc> for SharedObject<'gc> {
|
|||
.into())
|
||||
}
|
||||
|
||||
fn delete(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: &str,
|
||||
) -> bool {
|
||||
self.base().delete(activation, gc_context, name)
|
||||
}
|
||||
|
||||
fn proto(&self) -> Option<Object<'gc>> {
|
||||
self.base().proto()
|
||||
}
|
||||
|
||||
fn set_proto(&self, gc_context: MutationContext<'gc, '_>, prototype: Option<Object<'gc>>) {
|
||||
self.base().set_proto(gc_context, prototype);
|
||||
}
|
||||
|
||||
fn define_value(
|
||||
&self,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: &str,
|
||||
value: Value<'gc>,
|
||||
attributes: EnumSet<Attribute>,
|
||||
) {
|
||||
self.base()
|
||||
.define_value(gc_context, name, value, attributes)
|
||||
}
|
||||
|
||||
fn set_attributes(
|
||||
&mut self,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: Option<&str>,
|
||||
set_attributes: EnumSet<Attribute>,
|
||||
clear_attributes: EnumSet<Attribute>,
|
||||
) {
|
||||
self.base()
|
||||
.set_attributes(gc_context, name, set_attributes, clear_attributes)
|
||||
}
|
||||
|
||||
fn add_property(
|
||||
&self,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: &str,
|
||||
get: Executable<'gc>,
|
||||
set: Option<Executable<'gc>>,
|
||||
attributes: EnumSet<Attribute>,
|
||||
) {
|
||||
self.base()
|
||||
.add_property(gc_context, name, get, set, attributes)
|
||||
}
|
||||
|
||||
fn add_property_with_case(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: &str,
|
||||
get: Executable<'gc>,
|
||||
set: Option<Executable<'gc>>,
|
||||
attributes: EnumSet<Attribute>,
|
||||
) {
|
||||
self.base()
|
||||
.add_property_with_case(activation, gc_context, name, get, set, attributes)
|
||||
}
|
||||
|
||||
fn set_watcher(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: Cow<str>,
|
||||
callback: Executable<'gc>,
|
||||
user_data: Value<'gc>,
|
||||
) {
|
||||
self.base()
|
||||
.set_watcher(activation, gc_context, name, callback, user_data);
|
||||
}
|
||||
|
||||
fn remove_watcher(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: Cow<str>,
|
||||
) -> bool {
|
||||
self.base().remove_watcher(activation, gc_context, name)
|
||||
}
|
||||
|
||||
fn has_property(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
name: &str,
|
||||
) -> bool {
|
||||
self.base().has_property(activation, context, name)
|
||||
}
|
||||
|
||||
fn has_own_property(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
name: &str,
|
||||
) -> bool {
|
||||
self.base().has_own_property(activation, context, name)
|
||||
}
|
||||
|
||||
fn has_own_virtual(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
name: &str,
|
||||
) -> bool {
|
||||
self.base().has_own_virtual(activation, context, name)
|
||||
}
|
||||
|
||||
fn is_property_enumerable(&self, activation: &mut Activation<'_, 'gc>, name: &str) -> bool {
|
||||
self.base().is_property_enumerable(activation, name)
|
||||
}
|
||||
|
||||
fn get_keys(&self, activation: &mut Activation<'_, 'gc>) -> Vec<String> {
|
||||
self.base().get_keys(activation)
|
||||
}
|
||||
|
||||
fn as_string(&self) -> Cow<str> {
|
||||
Cow::Owned(self.base().as_string().into_owned())
|
||||
}
|
||||
|
||||
fn type_of(&self) -> &'static str {
|
||||
self.base().type_of()
|
||||
}
|
||||
|
||||
fn interfaces(&self) -> Vec<Object<'gc>> {
|
||||
self.base().interfaces()
|
||||
}
|
||||
|
||||
fn set_interfaces(
|
||||
&mut self,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
iface_list: Vec<Object<'gc>>,
|
||||
) {
|
||||
self.base().set_interfaces(gc_context, iface_list)
|
||||
}
|
||||
|
||||
fn as_script_object(&self) -> Option<ScriptObject<'gc>> {
|
||||
Some(self.base())
|
||||
}
|
||||
|
||||
fn as_display_object(&self) -> Option<DisplayObject<'gc>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn as_executable(&self) -> Option<Executable<'gc>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn as_sound_object(&self) -> Option<SoundObject<'gc>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn as_shared_object(&self) -> Option<SharedObject<'gc>> {
|
||||
Some(*self)
|
||||
}
|
||||
|
||||
fn as_ptr(&self) -> *const ObjectPtr {
|
||||
self.0.as_ptr() as *const ObjectPtr
|
||||
}
|
||||
|
||||
fn length(&self) -> usize {
|
||||
self.base().length()
|
||||
}
|
||||
|
||||
fn array(&self) -> Vec<Value<'gc>> {
|
||||
self.base().array()
|
||||
}
|
||||
|
||||
fn set_length(&self, gc_context: MutationContext<'gc, '_>, length: usize) {
|
||||
self.base().set_length(gc_context, length)
|
||||
}
|
||||
|
||||
fn array_element(&self, index: usize) -> Value<'gc> {
|
||||
self.base().array_element(index)
|
||||
}
|
||||
|
||||
fn set_array_element(
|
||||
&self,
|
||||
index: usize,
|
||||
value: Value<'gc>,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
) -> usize {
|
||||
self.base().set_array_element(index, value, gc_context)
|
||||
}
|
||||
|
||||
fn delete_array_element(&self, index: usize, gc_context: MutationContext<'gc, '_>) {
|
||||
self.base().delete_array_element(index, gc_context)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,15 +2,12 @@
|
|||
|
||||
use crate::avm1::activation::Activation;
|
||||
use crate::avm1::error::Error;
|
||||
use crate::avm1::function::Executable;
|
||||
use crate::avm1::property::Attribute;
|
||||
use crate::avm1::{Object, ObjectPtr, ScriptObject, TObject, Value};
|
||||
use crate::avm1::{Object, ScriptObject, TObject, Value};
|
||||
use crate::backend::audio::{SoundHandle, SoundInstanceHandle};
|
||||
use crate::context::UpdateContext;
|
||||
use crate::display_object::DisplayObject;
|
||||
use enumset::EnumSet;
|
||||
use crate::impl_custom_object;
|
||||
use gc_arena::{Collect, GcCell, MutationContext};
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
|
||||
/// A SounObject that is tied to a sound from the AudioBackend.
|
||||
|
@ -124,54 +121,10 @@ impl<'gc> SoundObject<'gc> {
|
|||
pub fn set_position(self, gc_context: MutationContext<'gc, '_>, position: u32) {
|
||||
self.0.write(gc_context).position = position;
|
||||
}
|
||||
|
||||
fn base(self) -> ScriptObject<'gc> {
|
||||
self.0.read().base
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> TObject<'gc> for SoundObject<'gc> {
|
||||
fn get_local(
|
||||
&self,
|
||||
name: &str,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
self.base().get_local(name, activation, context, this)
|
||||
}
|
||||
|
||||
fn set(
|
||||
&self,
|
||||
name: &str,
|
||||
value: Value<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
) -> Result<(), Error<'gc>> {
|
||||
self.base().set(name, value, activation, context)
|
||||
}
|
||||
fn call(
|
||||
&self,
|
||||
name: &str,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
base_proto: Option<Object<'gc>>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
self.base()
|
||||
.call(name, activation, context, this, base_proto, args)
|
||||
}
|
||||
|
||||
fn call_setter(
|
||||
&self,
|
||||
name: &str,
|
||||
value: Value<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
) -> Option<Executable<'gc>> {
|
||||
self.base().call_setter(name, value, activation, context)
|
||||
}
|
||||
impl_custom_object!(base);
|
||||
|
||||
#[allow(clippy::new_ret_no_self)]
|
||||
fn new(
|
||||
|
@ -187,192 +140,7 @@ impl<'gc> TObject<'gc> for SoundObject<'gc> {
|
|||
)
|
||||
}
|
||||
|
||||
fn delete(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: &str,
|
||||
) -> bool {
|
||||
self.base().delete(activation, gc_context, name)
|
||||
}
|
||||
|
||||
fn proto(&self) -> Option<Object<'gc>> {
|
||||
self.base().proto()
|
||||
}
|
||||
|
||||
fn set_proto(&self, gc_context: MutationContext<'gc, '_>, prototype: Option<Object<'gc>>) {
|
||||
self.base().set_proto(gc_context, prototype);
|
||||
}
|
||||
|
||||
fn define_value(
|
||||
&self,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: &str,
|
||||
value: Value<'gc>,
|
||||
attributes: EnumSet<Attribute>,
|
||||
) {
|
||||
self.base()
|
||||
.define_value(gc_context, name, value, attributes)
|
||||
}
|
||||
|
||||
fn set_attributes(
|
||||
&mut self,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: Option<&str>,
|
||||
set_attributes: EnumSet<Attribute>,
|
||||
clear_attributes: EnumSet<Attribute>,
|
||||
) {
|
||||
self.base()
|
||||
.set_attributes(gc_context, name, set_attributes, clear_attributes)
|
||||
}
|
||||
|
||||
fn add_property(
|
||||
&self,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: &str,
|
||||
get: Executable<'gc>,
|
||||
set: Option<Executable<'gc>>,
|
||||
attributes: EnumSet<Attribute>,
|
||||
) {
|
||||
self.base()
|
||||
.add_property(gc_context, name, get, set, attributes)
|
||||
}
|
||||
|
||||
fn add_property_with_case(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: &str,
|
||||
get: Executable<'gc>,
|
||||
set: Option<Executable<'gc>>,
|
||||
attributes: EnumSet<Attribute>,
|
||||
) {
|
||||
self.base()
|
||||
.add_property_with_case(activation, gc_context, name, get, set, attributes)
|
||||
}
|
||||
|
||||
fn set_watcher(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: Cow<str>,
|
||||
callback: Executable<'gc>,
|
||||
user_data: Value<'gc>,
|
||||
) {
|
||||
self.base()
|
||||
.set_watcher(activation, gc_context, name, callback, user_data);
|
||||
}
|
||||
|
||||
fn remove_watcher(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: Cow<str>,
|
||||
) -> bool {
|
||||
self.base().remove_watcher(activation, gc_context, name)
|
||||
}
|
||||
|
||||
fn has_property(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
name: &str,
|
||||
) -> bool {
|
||||
self.base().has_property(activation, context, name)
|
||||
}
|
||||
|
||||
fn has_own_property(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
name: &str,
|
||||
) -> bool {
|
||||
self.base().has_own_property(activation, context, name)
|
||||
}
|
||||
|
||||
fn has_own_virtual(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
name: &str,
|
||||
) -> bool {
|
||||
self.base().has_own_virtual(activation, context, name)
|
||||
}
|
||||
|
||||
fn is_property_enumerable(&self, activation: &mut Activation<'_, 'gc>, name: &str) -> bool {
|
||||
self.base().is_property_enumerable(activation, name)
|
||||
}
|
||||
|
||||
fn get_keys(&self, activation: &mut Activation<'_, 'gc>) -> Vec<String> {
|
||||
self.base().get_keys(activation)
|
||||
}
|
||||
|
||||
fn as_string(&self) -> Cow<str> {
|
||||
Cow::Owned(self.base().as_string().into_owned())
|
||||
}
|
||||
|
||||
fn type_of(&self) -> &'static str {
|
||||
self.base().type_of()
|
||||
}
|
||||
|
||||
fn interfaces(&self) -> Vec<Object<'gc>> {
|
||||
self.base().interfaces()
|
||||
}
|
||||
|
||||
fn set_interfaces(
|
||||
&mut self,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
iface_list: Vec<Object<'gc>>,
|
||||
) {
|
||||
self.base().set_interfaces(gc_context, iface_list)
|
||||
}
|
||||
|
||||
fn as_script_object(&self) -> Option<ScriptObject<'gc>> {
|
||||
Some(self.base())
|
||||
}
|
||||
|
||||
fn as_display_object(&self) -> Option<DisplayObject<'gc>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn as_executable(&self) -> Option<Executable<'gc>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn as_sound_object(&self) -> Option<SoundObject<'gc>> {
|
||||
Some(*self)
|
||||
}
|
||||
|
||||
fn as_ptr(&self) -> *const ObjectPtr {
|
||||
self.0.as_ptr() as *const ObjectPtr
|
||||
}
|
||||
|
||||
fn length(&self) -> usize {
|
||||
self.base().length()
|
||||
}
|
||||
|
||||
fn array(&self) -> Vec<Value<'gc>> {
|
||||
self.base().array()
|
||||
}
|
||||
|
||||
fn set_length(&self, gc_context: MutationContext<'gc, '_>, length: usize) {
|
||||
self.base().set_length(gc_context, length)
|
||||
}
|
||||
|
||||
fn array_element(&self, index: usize) -> Value<'gc> {
|
||||
self.base().array_element(index)
|
||||
}
|
||||
|
||||
fn set_array_element(
|
||||
&self,
|
||||
index: usize,
|
||||
value: Value<'gc>,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
) -> usize {
|
||||
self.base().set_array_element(index, value, gc_context)
|
||||
}
|
||||
|
||||
fn delete_array_element(&self, index: usize, gc_context: MutationContext<'gc, '_>) {
|
||||
self.base().delete_array_element(index, gc_context)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,10 @@
|
|||
|
||||
use crate::avm1::activation::Activation;
|
||||
use crate::avm1::error::Error;
|
||||
use crate::avm1::function::Executable;
|
||||
use crate::avm1::object::{ObjectPtr, TObject};
|
||||
use crate::avm1::property::Attribute;
|
||||
use crate::avm1::object::TObject;
|
||||
use crate::avm1::{Object, ScriptObject, UpdateContext, Value};
|
||||
use enumset::EnumSet;
|
||||
use crate::impl_custom_object;
|
||||
use gc_arena::{Collect, GcCell, MutationContext};
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
|
||||
/// An Object that serves as a box for a primitive value.
|
||||
|
@ -132,55 +129,7 @@ impl fmt::Debug for ValueObject<'_> {
|
|||
}
|
||||
|
||||
impl<'gc> TObject<'gc> for ValueObject<'gc> {
|
||||
fn get_local(
|
||||
&self,
|
||||
name: &str,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
self.0
|
||||
.read()
|
||||
.base
|
||||
.get_local(name, activation, context, this)
|
||||
}
|
||||
|
||||
fn set(
|
||||
&self,
|
||||
name: &str,
|
||||
value: Value<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
) -> Result<(), Error<'gc>> {
|
||||
self.0.read().base.set(name, value, activation, context)
|
||||
}
|
||||
fn call(
|
||||
&self,
|
||||
name: &str,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
base_proto: Option<Object<'gc>>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
self.0
|
||||
.read()
|
||||
.base
|
||||
.call(name, activation, context, this, base_proto, args)
|
||||
}
|
||||
|
||||
fn call_setter(
|
||||
&self,
|
||||
name: &str,
|
||||
value: Value<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
) -> Option<Executable<'gc>> {
|
||||
self.0
|
||||
.read()
|
||||
.base
|
||||
.call_setter(name, value, activation, context)
|
||||
}
|
||||
impl_custom_object!(base);
|
||||
|
||||
#[allow(clippy::new_ret_no_self)]
|
||||
fn new(
|
||||
|
@ -193,210 +142,7 @@ impl<'gc> TObject<'gc> for ValueObject<'gc> {
|
|||
Ok(ValueObject::empty_box(context.gc_context, Some(this)))
|
||||
}
|
||||
|
||||
fn delete(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: &str,
|
||||
) -> bool {
|
||||
self.0.read().base.delete(activation, gc_context, name)
|
||||
}
|
||||
|
||||
fn add_property(
|
||||
&self,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: &str,
|
||||
get: Executable<'gc>,
|
||||
set: Option<Executable<'gc>>,
|
||||
attributes: EnumSet<Attribute>,
|
||||
) {
|
||||
self.0
|
||||
.read()
|
||||
.base
|
||||
.add_property(gc_context, name, get, set, attributes)
|
||||
}
|
||||
|
||||
fn add_property_with_case(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: &str,
|
||||
get: Executable<'gc>,
|
||||
set: Option<Executable<'gc>>,
|
||||
attributes: EnumSet<Attribute>,
|
||||
) {
|
||||
self.0
|
||||
.read()
|
||||
.base
|
||||
.add_property_with_case(activation, gc_context, name, get, set, attributes)
|
||||
}
|
||||
|
||||
fn set_watcher(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: Cow<str>,
|
||||
callback: Executable<'gc>,
|
||||
user_data: Value<'gc>,
|
||||
) {
|
||||
self.0
|
||||
.read()
|
||||
.base
|
||||
.set_watcher(activation, gc_context, name, callback, user_data);
|
||||
}
|
||||
|
||||
fn remove_watcher(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: Cow<str>,
|
||||
) -> bool {
|
||||
self.0
|
||||
.write(gc_context)
|
||||
.base
|
||||
.remove_watcher(activation, gc_context, name)
|
||||
}
|
||||
|
||||
fn define_value(
|
||||
&self,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: &str,
|
||||
value: Value<'gc>,
|
||||
attributes: EnumSet<Attribute>,
|
||||
) {
|
||||
self.0
|
||||
.read()
|
||||
.base
|
||||
.define_value(gc_context, name, value, attributes)
|
||||
}
|
||||
|
||||
fn set_attributes(
|
||||
&mut self,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: Option<&str>,
|
||||
set_attributes: EnumSet<Attribute>,
|
||||
clear_attributes: EnumSet<Attribute>,
|
||||
) {
|
||||
self.0.write(gc_context).base.set_attributes(
|
||||
gc_context,
|
||||
name,
|
||||
set_attributes,
|
||||
clear_attributes,
|
||||
)
|
||||
}
|
||||
|
||||
fn proto(&self) -> Option<Object<'gc>> {
|
||||
self.0.read().base.proto()
|
||||
}
|
||||
|
||||
fn set_proto(&self, gc_context: MutationContext<'gc, '_>, prototype: Option<Object<'gc>>) {
|
||||
self.0
|
||||
.write(gc_context)
|
||||
.base
|
||||
.set_proto(gc_context, prototype);
|
||||
}
|
||||
|
||||
fn has_property(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
name: &str,
|
||||
) -> bool {
|
||||
self.0.read().base.has_property(activation, context, name)
|
||||
}
|
||||
|
||||
fn has_own_property(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
name: &str,
|
||||
) -> bool {
|
||||
self.0
|
||||
.read()
|
||||
.base
|
||||
.has_own_property(activation, context, name)
|
||||
}
|
||||
|
||||
fn has_own_virtual(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
name: &str,
|
||||
) -> bool {
|
||||
self.0
|
||||
.read()
|
||||
.base
|
||||
.has_own_virtual(activation, context, name)
|
||||
}
|
||||
|
||||
fn is_property_enumerable(&self, activation: &mut Activation<'_, 'gc>, name: &str) -> bool {
|
||||
self.0.read().base.is_property_enumerable(activation, name)
|
||||
}
|
||||
|
||||
fn get_keys(&self, activation: &mut Activation<'_, 'gc>) -> Vec<String> {
|
||||
self.0.read().base.get_keys(activation)
|
||||
}
|
||||
|
||||
fn as_string(&self) -> Cow<str> {
|
||||
Cow::Owned(self.0.read().base.as_string().into_owned())
|
||||
}
|
||||
|
||||
fn type_of(&self) -> &'static str {
|
||||
self.0.read().base.type_of()
|
||||
}
|
||||
|
||||
fn interfaces(&self) -> Vec<Object<'gc>> {
|
||||
self.0.read().base.interfaces()
|
||||
}
|
||||
|
||||
fn set_interfaces(&mut self, context: MutationContext<'gc, '_>, iface_list: Vec<Object<'gc>>) {
|
||||
self.0
|
||||
.write(context)
|
||||
.base
|
||||
.set_interfaces(context, iface_list)
|
||||
}
|
||||
|
||||
fn as_script_object(&self) -> Option<ScriptObject<'gc>> {
|
||||
Some(self.0.read().base)
|
||||
}
|
||||
|
||||
fn as_value_object(&self) -> Option<ValueObject<'gc>> {
|
||||
Some(*self)
|
||||
}
|
||||
|
||||
fn as_ptr(&self) -> *const ObjectPtr {
|
||||
self.0.read().base.as_ptr() as *const ObjectPtr
|
||||
}
|
||||
|
||||
fn length(&self) -> usize {
|
||||
self.0.read().base.length()
|
||||
}
|
||||
|
||||
fn array(&self) -> Vec<Value<'gc>> {
|
||||
self.0.read().base.array()
|
||||
}
|
||||
|
||||
fn set_length(&self, gc_context: MutationContext<'gc, '_>, length: usize) {
|
||||
self.0.read().base.set_length(gc_context, length)
|
||||
}
|
||||
|
||||
fn array_element(&self, index: usize) -> Value<'gc> {
|
||||
self.0.read().base.array_element(index)
|
||||
}
|
||||
|
||||
fn set_array_element(
|
||||
&self,
|
||||
index: usize,
|
||||
value: Value<'gc>,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
) -> usize {
|
||||
self.0
|
||||
.read()
|
||||
.base
|
||||
.set_array_element(index, value, gc_context)
|
||||
}
|
||||
|
||||
fn delete_array_element(&self, index: usize, gc_context: MutationContext<'gc, '_>) {
|
||||
self.0.read().base.delete_array_element(index, gc_context)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,20 +2,24 @@
|
|||
|
||||
use crate::avm1::activation::Activation;
|
||||
use crate::avm1::error::Error;
|
||||
use crate::avm1::function::Executable;
|
||||
use crate::avm1::object::{ObjectPtr, TObject};
|
||||
use crate::avm1::property::Attribute;
|
||||
use crate::avm1::object::TObject;
|
||||
use crate::avm1::{Object, ScriptObject, UpdateContext, Value};
|
||||
use crate::impl_custom_object;
|
||||
use crate::xml::{XMLDocument, XMLNode};
|
||||
use enumset::EnumSet;
|
||||
use gc_arena::{Collect, MutationContext};
|
||||
use std::borrow::Cow;
|
||||
use gc_arena::{Collect, GcCell, MutationContext};
|
||||
use std::fmt;
|
||||
|
||||
/// A ScriptObject that is inherently tied to an XML node.
|
||||
#[derive(Clone, Copy, Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub struct XMLObject<'gc>(ScriptObject<'gc>, XMLNode<'gc>);
|
||||
pub struct XMLObject<'gc>(GcCell<'gc, XMLObjectData<'gc>>);
|
||||
|
||||
#[derive(Clone, Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub struct XMLObjectData<'gc> {
|
||||
base: ScriptObject<'gc>,
|
||||
node: XMLNode<'gc>,
|
||||
}
|
||||
|
||||
impl<'gc> XMLObject<'gc> {
|
||||
/// Construct a new XML node and object pair.
|
||||
|
@ -26,7 +30,14 @@ impl<'gc> XMLObject<'gc> {
|
|||
let empty_document = XMLDocument::new(gc_context);
|
||||
let mut xml_node = XMLNode::new_text(gc_context, "", empty_document);
|
||||
let base_object = ScriptObject::object(gc_context, proto);
|
||||
let object = XMLObject(base_object, xml_node).into();
|
||||
let object = XMLObject(GcCell::allocate(
|
||||
gc_context,
|
||||
XMLObjectData {
|
||||
base: base_object,
|
||||
node: xml_node,
|
||||
},
|
||||
))
|
||||
.into();
|
||||
|
||||
xml_node.introduce_script_object(gc_context, object);
|
||||
|
||||
|
@ -39,66 +50,29 @@ impl<'gc> XMLObject<'gc> {
|
|||
xml_node: XMLNode<'gc>,
|
||||
proto: Option<Object<'gc>>,
|
||||
) -> Object<'gc> {
|
||||
XMLObject(ScriptObject::object(gc_context, proto), xml_node).into()
|
||||
}
|
||||
|
||||
fn base(&self) -> ScriptObject<'gc> {
|
||||
match self {
|
||||
XMLObject(base, ..) => *base,
|
||||
}
|
||||
XMLObject(GcCell::allocate(
|
||||
gc_context,
|
||||
XMLObjectData {
|
||||
base: ScriptObject::object(gc_context, proto),
|
||||
node: xml_node,
|
||||
},
|
||||
))
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for XMLObject<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
XMLObject(base, node) => f.debug_tuple("XMLObject").field(base).field(node).finish(),
|
||||
}
|
||||
let this = self.0.read();
|
||||
f.debug_struct("XMLObject")
|
||||
.field("base", &this.base)
|
||||
.field("node", &this.node)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> TObject<'gc> for XMLObject<'gc> {
|
||||
fn get_local(
|
||||
&self,
|
||||
name: &str,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
self.base().get_local(name, activation, context, this)
|
||||
}
|
||||
|
||||
fn set(
|
||||
&self,
|
||||
name: &str,
|
||||
value: Value<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
) -> Result<(), Error<'gc>> {
|
||||
self.base().set(name, value, activation, context)
|
||||
}
|
||||
fn call(
|
||||
&self,
|
||||
name: &str,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
base_proto: Option<Object<'gc>>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
self.base()
|
||||
.call(name, activation, context, this, base_proto, args)
|
||||
}
|
||||
|
||||
fn call_setter(
|
||||
&self,
|
||||
name: &str,
|
||||
value: Value<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
) -> Option<Executable<'gc>> {
|
||||
self.base().call_setter(name, value, activation, context)
|
||||
}
|
||||
impl_custom_object!(base);
|
||||
|
||||
#[allow(clippy::new_ret_no_self)]
|
||||
fn new(
|
||||
|
@ -111,182 +85,7 @@ impl<'gc> TObject<'gc> for XMLObject<'gc> {
|
|||
Ok(XMLObject::empty_node(context.gc_context, Some(this)))
|
||||
}
|
||||
|
||||
fn delete(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: &str,
|
||||
) -> bool {
|
||||
self.base().delete(activation, gc_context, name)
|
||||
}
|
||||
|
||||
fn add_property(
|
||||
&self,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: &str,
|
||||
get: Executable<'gc>,
|
||||
set: Option<Executable<'gc>>,
|
||||
attributes: EnumSet<Attribute>,
|
||||
) {
|
||||
self.base()
|
||||
.add_property(gc_context, name, get, set, attributes)
|
||||
}
|
||||
|
||||
fn add_property_with_case(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: &str,
|
||||
get: Executable<'gc>,
|
||||
set: Option<Executable<'gc>>,
|
||||
attributes: EnumSet<Attribute>,
|
||||
) {
|
||||
self.base()
|
||||
.add_property_with_case(activation, gc_context, name, get, set, attributes)
|
||||
}
|
||||
|
||||
fn set_watcher(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: Cow<str>,
|
||||
callback: Executable<'gc>,
|
||||
user_data: Value<'gc>,
|
||||
) {
|
||||
self.base()
|
||||
.set_watcher(activation, gc_context, name, callback, user_data);
|
||||
}
|
||||
|
||||
fn remove_watcher(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: Cow<str>,
|
||||
) -> bool {
|
||||
self.base().remove_watcher(activation, gc_context, name)
|
||||
}
|
||||
|
||||
fn define_value(
|
||||
&self,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: &str,
|
||||
value: Value<'gc>,
|
||||
attributes: EnumSet<Attribute>,
|
||||
) {
|
||||
self.base()
|
||||
.define_value(gc_context, name, value, attributes)
|
||||
}
|
||||
|
||||
fn set_attributes(
|
||||
&mut self,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
name: Option<&str>,
|
||||
set_attributes: EnumSet<Attribute>,
|
||||
clear_attributes: EnumSet<Attribute>,
|
||||
) {
|
||||
self.base()
|
||||
.set_attributes(gc_context, name, set_attributes, clear_attributes)
|
||||
}
|
||||
|
||||
fn proto(&self) -> Option<Object<'gc>> {
|
||||
self.base().proto()
|
||||
}
|
||||
|
||||
fn set_proto(&self, gc_context: MutationContext<'gc, '_>, prototype: Option<Object<'gc>>) {
|
||||
self.base().set_proto(gc_context, prototype);
|
||||
}
|
||||
|
||||
fn has_property(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
name: &str,
|
||||
) -> bool {
|
||||
self.base().has_property(activation, context, name)
|
||||
}
|
||||
|
||||
fn has_own_property(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
name: &str,
|
||||
) -> bool {
|
||||
self.base().has_own_property(activation, context, name)
|
||||
}
|
||||
|
||||
fn has_own_virtual(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
name: &str,
|
||||
) -> bool {
|
||||
self.base().has_own_virtual(activation, context, name)
|
||||
}
|
||||
|
||||
fn is_property_enumerable(&self, activation: &mut Activation<'_, 'gc>, name: &str) -> bool {
|
||||
self.base().is_property_enumerable(activation, name)
|
||||
}
|
||||
|
||||
fn get_keys(&self, activation: &mut Activation<'_, 'gc>) -> Vec<String> {
|
||||
self.base().get_keys(activation)
|
||||
}
|
||||
|
||||
fn as_string(&self) -> Cow<str> {
|
||||
Cow::Owned(self.base().as_string().into_owned())
|
||||
}
|
||||
|
||||
fn type_of(&self) -> &'static str {
|
||||
self.base().type_of()
|
||||
}
|
||||
|
||||
fn interfaces(&self) -> Vec<Object<'gc>> {
|
||||
self.base().interfaces()
|
||||
}
|
||||
|
||||
fn set_interfaces(&mut self, context: MutationContext<'gc, '_>, iface_list: Vec<Object<'gc>>) {
|
||||
self.base().set_interfaces(context, iface_list)
|
||||
}
|
||||
|
||||
fn as_script_object(&self) -> Option<ScriptObject<'gc>> {
|
||||
Some(self.base())
|
||||
}
|
||||
|
||||
fn as_xml_node(&self) -> Option<XMLNode<'gc>> {
|
||||
match self {
|
||||
XMLObject(_base, node) => Some(*node),
|
||||
}
|
||||
}
|
||||
|
||||
fn as_ptr(&self) -> *const ObjectPtr {
|
||||
self.base().as_ptr() as *const ObjectPtr
|
||||
}
|
||||
|
||||
fn length(&self) -> usize {
|
||||
self.base().length()
|
||||
}
|
||||
|
||||
fn array(&self) -> Vec<Value<'gc>> {
|
||||
self.base().array()
|
||||
}
|
||||
|
||||
fn set_length(&self, gc_context: MutationContext<'gc, '_>, length: usize) {
|
||||
self.base().set_length(gc_context, length)
|
||||
}
|
||||
|
||||
fn array_element(&self, index: usize) -> Value<'gc> {
|
||||
self.base().array_element(index)
|
||||
}
|
||||
|
||||
fn set_array_element(
|
||||
&self,
|
||||
index: usize,
|
||||
value: Value<'gc>,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
) -> usize {
|
||||
self.base().set_array_element(index, value, gc_context)
|
||||
}
|
||||
|
||||
fn delete_array_element(&self, index: usize, gc_context: MutationContext<'gc, '_>) {
|
||||
self.base().delete_array_element(index, gc_context)
|
||||
Some(self.0.read().node)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue