avm2: make Namespace a GC type

This commit is contained in:
Adrian Wielgosik 2023-02-09 17:54:38 +01:00 committed by Adrian Wielgosik
parent 4e0dce2efa
commit e0e653e463
72 changed files with 1227 additions and 980 deletions

View File

@ -56,7 +56,7 @@ pub use crate::avm2::domain::Domain;
pub use crate::avm2::error::Error;
pub use crate::avm2::globals::flash::ui::context_menu::make_context_menu_state;
pub use crate::avm2::multiname::Multiname;
pub use crate::avm2::namespace::Namespace;
pub use crate::avm2::namespace::{Namespace, NamespaceData};
pub use crate::avm2::object::{
ArrayObject, ClassObject, EventObject, Object, ScriptObject, SoundChannelObject, StageObject,
TObject,
@ -87,6 +87,13 @@ pub struct Avm2<'gc> {
/// System classes.
system_classes: Option<SystemClasses<'gc>>,
pub public_namespace: Namespace<'gc>,
pub as3_namespace: Namespace<'gc>,
pub vector_public_namespace: Namespace<'gc>,
pub vector_internal_namespace: Namespace<'gc>,
pub proxy_namespace: Namespace<'gc>,
pub ruffle_private_namespace: Namespace<'gc>,
#[collect(require_static)]
native_method_table: &'static [Option<(&'static str, NativeMethodImpl)>],
@ -121,6 +128,17 @@ impl<'gc> Avm2<'gc> {
call_stack: GcCell::allocate(mc, CallStack::new()),
globals,
system_classes: None,
public_namespace: Namespace::package("", mc),
as3_namespace: Namespace::package("http://adobe.com/AS3/2006/builtin", mc),
vector_public_namespace: Namespace::package("__AS3__.vec", mc),
vector_internal_namespace: Namespace::internal("__AS3__.vec", mc),
proxy_namespace: Namespace::package(
"http://www.adobe.com/2006/actionscript/flash/proxy",
mc,
),
ruffle_private_namespace: Namespace::private("", mc),
native_method_table: Default::default(),
native_instance_allocator_table: Default::default(),
native_instance_init_table: Default::default(),

View File

@ -492,18 +492,14 @@ impl<'a, 'gc> Activation<'a, 'gc> {
unreachable!();
};
let mut args_object = ArrayObject::from_storage(&mut activation, args_array)?;
let args_object = ArrayObject::from_storage(&mut activation, args_array)?;
if method
.method()
.flags
.contains(AbcMethodFlags::NEED_ARGUMENTS)
{
args_object.set_property(
&Multiname::public("callee"),
callee.into(),
&mut activation,
)?;
args_object.set_string_property_local("callee", callee.into(), &mut activation)?;
}
*activation
@ -647,11 +643,6 @@ impl<'a, 'gc> Activation<'a, 'gc> {
self.context.avm2
}
/// Set the return value.
pub fn set_return_value(&mut self, value: Value<'gc>) {
self.return_value = Some(value);
}
/// Get the class that defined the currently-executing method, if it
/// exists.
///
@ -781,7 +772,9 @@ impl<'a, 'gc> Activation<'a, 'gc> {
method: Gc<'gc, BytecodeMethod<'gc>>,
index: Index<AbcNamespace>,
) -> Result<Namespace<'gc>, Error<'gc>> {
Namespace::from_abc_namespace(method.translation_unit(), index, self.context.gc_context)
method
.translation_unit()
.pool_namespace(index, self.context.gc_context)
}
/// Retrieve a multiname from the current constant pool.
@ -1667,7 +1660,7 @@ impl<'a, 'gc> Activation<'a, 'gc> {
}
let name = name_value.coerce_to_string(self)?;
let multiname = Multiname::public(name);
let multiname = Multiname::new(self.avm2().public_namespace, name);
let has_prop = obj.has_property_via_in(self, &multiname)?;
self.push_stack(has_prop);
@ -1897,11 +1890,7 @@ impl<'a, 'gc> Activation<'a, 'gc> {
let value = self.pop_stack();
let name = self.pop_stack();
object.set_property(
&Multiname::public(name.coerce_to_string(self)?),
value,
self,
)?;
object.set_public_property(name.coerce_to_string(self)?, value, self)?;
}
self.push_stack(object);

View File

@ -2,7 +2,6 @@ use crate::avm2::bytearray::ByteArrayStorage;
use crate::avm2::object::{ByteArrayObject, TObject};
use crate::avm2::ArrayObject;
use crate::avm2::ArrayStorage;
use crate::avm2::Multiname;
use crate::avm2::{Activation, Error, Object, Value};
use crate::string::AvmString;
use enumset::EnumSet;
@ -101,7 +100,7 @@ pub fn recursive_serialize<'gc>(
let name = obj
.get_enumerant_name(index, activation)?
.coerce_to_string(activation)?;
let value = obj.get_property(&Multiname::public(name), activation)?;
let value = obj.get_public_property(name, activation)?;
if let Some(value) = serialize_value(activation, value, amf_version) {
elements.push(Element::new(name.to_utf8_lossy(), value));
@ -138,11 +137,8 @@ pub fn deserialize_value<'gc>(
let mut array = ArrayObject::from_storage(activation, storage)?;
// Now let's add each element as a property
for element in elements {
array.set_property(
&Multiname::public(AvmString::new_utf8(
activation.context.gc_context,
element.name(),
)),
array.set_public_property(
AvmString::new_utf8(activation.context.gc_context, element.name()),
deserialize_value(activation, element.value())?,
activation,
)?;
@ -172,11 +168,8 @@ pub fn deserialize_value<'gc>(
.construct(activation, &[])?;
for entry in elements {
let value = deserialize_value(activation, entry.value())?;
obj.set_property(
&Multiname::public(AvmString::new_utf8(
activation.context.gc_context,
entry.name(),
)),
obj.set_public_property(
AvmString::new_utf8(activation.context.gc_context, entry.name()),
value,
activation,
)?;
@ -227,11 +220,8 @@ pub fn deserialize_lso<'gc>(
.construct(activation, &[])?;
for child in &lso.body {
obj.set_property(
&Multiname::public(AvmString::new_utf8(
activation.context.gc_context,
&child.name,
)),
obj.set_public_property(
AvmString::new_utf8(activation.context.gc_context, &child.name),
deserialize_value(activation, child.value())?,
activation,
)?;

View File

@ -260,11 +260,7 @@ impl<'gc> Class<'gc> {
};
let protected_namespace = if let Some(ns) = &abc_instance.protected_namespace {
Some(Namespace::from_abc_namespace(
unit,
*ns,
activation.context.gc_context,
)?)
Some(unit.pool_namespace(*ns, activation.context.gc_context)?)
} else {
None
};
@ -472,7 +468,7 @@ impl<'gc> Class<'gc> {
Ok(GcCell::allocate(
activation.context.gc_context,
Self {
name: QName::dynamic_name(name),
name: QName::new(activation.avm2().public_namespace, name),
params: Vec::new(),
super_class: None,
attributes: ClassAttributes::empty(),
@ -526,52 +522,55 @@ impl<'gc> Class<'gc> {
}
#[inline(never)]
pub fn define_public_constant_string_class_traits(
pub fn define_constant_number_class_traits(
&mut self,
items: &[(&'static str, &'static str)],
namespace: Namespace<'gc>,
items: &[(&'static str, f64)],
activation: &mut Activation<'_, 'gc>,
) {
for &(name, value) in items {
self.define_class_trait(Trait::from_const(
QName::new(Namespace::public(), name),
Multiname::public("String"),
QName::new(namespace, name),
Multiname::new(activation.avm2().public_namespace, "Number"),
Some(value.into()),
));
}
}
#[inline(never)]
pub fn define_public_constant_number_class_traits(&mut self, items: &[(&'static str, f64)]) {
pub fn define_constant_uint_class_traits(
&mut self,
namespace: Namespace<'gc>,
items: &[(&'static str, u32)],
activation: &mut Activation<'_, 'gc>,
) {
for &(name, value) in items {
self.define_class_trait(Trait::from_const(
QName::new(Namespace::public(), name),
Multiname::public("Number"),
QName::new(namespace, name),
Multiname::new(activation.avm2().public_namespace, "uint"),
Some(value.into()),
));
}
}
#[inline(never)]
pub fn define_public_constant_uint_class_traits(&mut self, items: &[(&'static str, u32)]) {
pub fn define_constant_int_class_traits(
&mut self,
namespace: Namespace<'gc>,
items: &[(&'static str, i32)],
activation: &mut Activation<'_, 'gc>,
) {
for &(name, value) in items {
self.define_class_trait(Trait::from_const(
QName::new(Namespace::public(), name),
Multiname::public("uint"),
QName::new(namespace, name),
Multiname::new(activation.avm2().public_namespace, "int"),
Some(value.into()),
));
}
}
#[inline(never)]
pub fn define_public_constant_int_class_traits(&mut self, items: &[(&'static str, i32)]) {
for &(name, value) in items {
self.define_class_trait(Trait::from_const(
QName::new(Namespace::public(), name),
Multiname::public("int"),
Some(value.into()),
));
}
}
#[inline(never)]
pub fn define_public_builtin_class_properties(
pub fn define_builtin_class_properties(
&mut self,
mc: MutationContext<'gc, '_>,
namespace: Namespace<'gc>,
items: &[(
&'static str,
Option<NativeMethodImpl>,
@ -581,88 +580,51 @@ impl<'gc> Class<'gc> {
for &(name, getter, setter) in items {
if let Some(getter) = getter {
self.define_class_trait(Trait::from_getter(
QName::new(Namespace::public(), name),
QName::new(namespace, name),
Method::from_builtin(getter, name, mc),
));
}
if let Some(setter) = setter {
self.define_class_trait(Trait::from_setter(
QName::new(Namespace::public(), name),
QName::new(namespace, name),
Method::from_builtin(setter, name, mc),
));
}
}
}
#[inline(never)]
pub fn define_public_builtin_instance_methods(
pub fn define_builtin_instance_methods(
&mut self,
mc: MutationContext<'gc, '_>,
namespace: Namespace<'gc>,
items: &[(&'static str, NativeMethodImpl)],
) {
for &(name, value) in items {
self.define_instance_trait(Trait::from_method(
QName::new(Namespace::public(), name),
QName::new(namespace, name),
Method::from_builtin(value, name, mc),
));
}
}
#[inline(never)]
pub fn define_as3_builtin_class_methods(
pub fn define_builtin_class_methods(
&mut self,
mc: MutationContext<'gc, '_>,
namespace: Namespace<'gc>,
items: &[(&'static str, NativeMethodImpl)],
) {
for &(name, value) in items {
self.define_class_trait(Trait::from_method(
QName::new(Namespace::as3_namespace(), name),
QName::new(namespace, name),
Method::from_builtin(value, name, mc),
));
}
}
#[inline(never)]
pub fn define_as3_builtin_instance_methods(
&mut self,
mc: MutationContext<'gc, '_>,
items: &[(&'static str, NativeMethodImpl)],
) {
for &(name, value) in items {
self.define_instance_trait(Trait::from_method(
QName::new(Namespace::as3_namespace(), name),
Method::from_builtin(value, name, mc),
));
}
}
#[inline(never)]
pub fn define_ns_builtin_instance_methods(
&mut self,
mc: MutationContext<'gc, '_>,
ns: &'static str,
items: &[(&'static str, NativeMethodImpl)],
) {
for &(name, value) in items {
self.define_instance_trait(Trait::from_method(
QName::new(Namespace::Namespace(ns.into()), name),
Method::from_builtin(value, name, mc),
));
}
}
#[inline(never)]
pub fn define_public_builtin_class_methods(
&mut self,
mc: MutationContext<'gc, '_>,
items: &[(&'static str, NativeMethodImpl)],
) {
for &(name, value) in items {
self.define_class_trait(Trait::from_method(
QName::new(Namespace::public(), name),
Method::from_builtin(value, name, mc),
));
}
}
#[inline(never)]
pub fn define_public_builtin_instance_properties(
pub fn define_builtin_instance_properties(
&mut self,
mc: MutationContext<'gc, '_>,
namespace: Namespace<'gc>,
items: &[(
&'static str,
Option<NativeMethodImpl>,
@ -672,74 +634,34 @@ impl<'gc> Class<'gc> {
for &(name, getter, setter) in items {
if let Some(getter) = getter {
self.define_instance_trait(Trait::from_getter(
QName::new(Namespace::public(), name),
QName::new(namespace, name),
Method::from_builtin(getter, name, mc),
));
}
if let Some(setter) = setter {
self.define_instance_trait(Trait::from_setter(
QName::new(Namespace::public(), name),
QName::new(namespace, name),
Method::from_builtin(setter, name, mc),
));
}
}
}
#[inline(never)]
pub fn define_public_slot_number_instance_traits(
pub fn define_slot_number_instance_traits(
&mut self,
namespace: Namespace<'gc>,
items: &[(&'static str, Option<f64>)],
activation: &mut Activation<'_, 'gc>,
) {
for &(name, value) in items {
self.define_instance_trait(Trait::from_slot(
QName::new(Namespace::public(), name),
Multiname::public("Number"),
QName::new(namespace, name),
Multiname::new(activation.avm2().public_namespace, "Number"),
value.map(|v| v.into()),
));
}
}
#[inline(never)]
pub fn define_public_slot_instance_traits(
&mut self,
items: &[(&'static str, &'static str, &'static str)],
) {
for &(name, type_ns, type_name) in items {
self.define_instance_trait(Trait::from_slot(
QName::new(Namespace::public(), name),
Multiname::new(Namespace::Namespace(type_ns.into()), type_name),
None,
));
}
}
#[inline(never)]
pub fn define_public_slot_instance_traits_type_multiname(
&mut self,
items: &[(&'static str, Multiname<'gc>)],
) {
for (name, type_name) in items {
self.define_instance_trait(Trait::from_slot(
QName::new(Namespace::public(), *name),
type_name.clone(),
None,
));
}
}
#[inline(never)]
pub fn define_private_slot_instance_traits(
&mut self,
items: &[(&'static str, &'static str, &'static str, &'static str)],
) {
for &(ns, name, type_ns, type_name) in items {
self.define_instance_trait(Trait::from_slot(
QName::new(Namespace::Private(ns.into()), name),
Multiname::new(Namespace::Namespace(type_ns.into()), type_name),
None,
));
}
}
/// Define a trait on the class.
///
/// Class traits will be accessible as properties on the class object.

View File

@ -5,7 +5,6 @@ use crate::avm2::object::{Object, TObject};
use crate::avm2::value::Value;
use crate::avm2::Error;
use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::display_object::TDisplayObject;
use crate::string::AvmString;
use fnv::FnvHashMap;
@ -342,8 +341,6 @@ impl<'gc> Hash for EventHandler<'gc> {
}
}
pub const NS_EVENT_DISPATCHER: &str = "https://ruffle.rs/AS3/impl/EventDispatcher/";
/// Retrieve the parent of a given `EventDispatcher`.
///
/// `EventDispatcher` does not provide a generic way for it's subclasses to
@ -381,7 +378,7 @@ pub fn dispatch_event_to_target<'gc>(
);
let dispatch_list = dispatcher
.get_property(
&Multiname::new(Namespace::private(NS_EVENT_DISPATCHER), "dispatch_list"),
&Multiname::new(activation.avm2().ruffle_private_namespace, "dispatch_list"),
activation,
)?
.as_object();
@ -438,7 +435,7 @@ pub fn dispatch_event<'gc>(
) -> Result<bool, Error<'gc>> {
let target = this
.get_property(
&Multiname::new(Namespace::private(NS_EVENT_DISPATCHER), "target"),
&Multiname::new(activation.avm2().ruffle_private_namespace, "target"),
activation,
)?
.as_object()

View File

@ -39,11 +39,6 @@ mod vector;
mod xml;
mod xml_list;
pub(crate) const NS_RUFFLE_INTERNAL: &str = "https://ruffle.rs/AS3/impl/";
pub(crate) const NS_VECTOR: &str = "__AS3__.vec";
pub use flash::utils::NS_FLASH_PROXY;
/// This structure represents all system builtin classes.
#[derive(Clone, Collect)]
#[collect(no_drop)]
@ -217,7 +212,10 @@ fn function<'gc>(
let (_, mut global, mut domain) = script.init();
let mc = activation.context.gc_context;
let scope = activation.create_scopechain();
let qname = QName::new(Namespace::package(package), name);
let qname = QName::new(
Namespace::package(package, activation.context.gc_context),
name,
);
let method = Method::from_builtin(nf, name, mc);
let as3fn = FunctionObject::from_method(activation, method, scope, None, None).into();
domain.export_definition(qname, script, mc)?;
@ -250,9 +248,9 @@ fn dynamic_class<'gc>(
/// This function returns the class object and class prototype as a class, which
/// may be stored in `SystemClasses`
fn class<'gc>(
activation: &mut Activation<'_, 'gc>,
class_def: GcCell<'gc, Class<'gc>>,
script: Script<'gc>,
activation: &mut Activation<'_, 'gc>,
) -> Result<ClassObject<'gc>, Error<'gc>> {
let (_, mut global, mut domain) = script.init();
@ -299,7 +297,7 @@ fn class<'gc>(
macro_rules! avm2_system_class {
($field:ident, $activation:ident, $class:expr, $script:expr) => {
let class_object = class($activation, $class, $script)?;
let class_object = class($class, $script, $activation)?;
let sc = $activation.avm2().system_classes.as_mut().unwrap();
sc.$field = class_object;
@ -341,20 +339,20 @@ pub fn load_player_globals<'gc>(
//
// Hence, this ridiculously complicated dance of classdef, type allocation,
// and partial initialization.
let object_classdef = object::create_class(mc);
let object_classdef = object::create_class(activation);
let object_class = ClassObject::from_class_partial(activation, object_classdef, None)?;
let object_proto = ScriptObject::custom_object(mc, Some(object_class), None);
let fn_classdef = function::create_class(mc);
let fn_classdef = function::create_class(activation);
let fn_class = ClassObject::from_class_partial(activation, fn_classdef, Some(object_class))?;
let fn_proto = ScriptObject::custom_object(mc, Some(fn_class), Some(object_proto));
let class_classdef = class::create_class(mc);
let class_classdef = class::create_class(activation);
let class_class =
ClassObject::from_class_partial(activation, class_classdef, Some(object_class))?;
let class_proto = ScriptObject::custom_object(mc, Some(object_class), Some(object_proto));
let global_classdef = global_scope::create_class(mc);
let global_classdef = global_scope::create_class(activation);
let global_class =
ClassObject::from_class_partial(activation, global_classdef, Some(object_class))?;
let global_proto = ScriptObject::custom_object(mc, Some(object_class), Some(object_proto));
@ -405,14 +403,24 @@ pub fn load_player_globals<'gc>(
// After this point, it is safe to initialize any other classes.
// Make sure to initialize superclasses *before* their subclasses!
avm2_system_class!(string, activation, string::create_class(mc), script);
avm2_system_class!(boolean, activation, boolean::create_class(mc), script);
avm2_system_class!(number, activation, number::create_class(mc), script);
avm2_system_class!(int, activation, int::create_class(mc), script);
avm2_system_class!(uint, activation, uint::create_class(mc), script);
avm2_system_class!(namespace, activation, namespace::create_class(mc), script);
avm2_system_class!(qname, activation, qname::create_class(mc), script);
avm2_system_class!(array, activation, array::create_class(mc), script);
avm2_system_class!(string, activation, string::create_class(activation), script);
avm2_system_class!(
boolean,
activation,
boolean::create_class(activation),
script
);
avm2_system_class!(number, activation, number::create_class(activation), script);
avm2_system_class!(int, activation, int::create_class(activation), script);
avm2_system_class!(uint, activation, uint::create_class(activation), script);
avm2_system_class!(
namespace,
activation,
namespace::create_class(activation),
script
);
avm2_system_class!(qname, activation, qname::create_class(activation), script);
avm2_system_class!(array, activation, array::create_class(activation), script);
function(activation, "", "trace", toplevel::trace, script)?;
function(
@ -456,105 +464,105 @@ pub fn load_player_globals<'gc>(
function(activation, "", "parseFloat", toplevel::parse_float, script)?;
function(activation, "", "escape", toplevel::escape, script)?;
avm2_system_class!(regexp, activation, regexp::create_class(mc), script);
avm2_system_class!(vector, activation, vector::create_class(mc), script);
avm2_system_class!(regexp, activation, regexp::create_class(activation), script);
avm2_system_class!(vector, activation, vector::create_class(activation), script);
avm2_system_class!(date, activation, date::create_class(mc), script);
avm2_system_class!(date, activation, date::create_class(activation), script);
// package `flash.system`
avm2_system_class!(
application_domain,
activation,
flash::system::application_domain::create_class(mc),
flash::system::application_domain::create_class(activation),
script
);
class(
activation,
flash::events::ieventdispatcher::create_interface(mc),
flash::events::ieventdispatcher::create_interface(activation),
script,
activation,
)?;
avm2_system_class!(
eventdispatcher,
activation,
flash::events::eventdispatcher::create_class(mc),
flash::events::eventdispatcher::create_class(activation),
script
);
// package `flash.display`
class(
activation,
flash::display::ibitmapdrawable::create_interface(mc),
flash::display::ibitmapdrawable::create_interface(activation),
script,
activation,
)?;
avm2_system_class!(
display_object,
activation,
flash::display::displayobject::create_class(mc),
flash::display::displayobject::create_class(activation),
script
);
avm2_system_class!(
shape,
activation,
flash::display::shape::create_class(mc),
flash::display::shape::create_class(activation),
script
);
class(
activation,
flash::display::interactiveobject::create_class(mc),
flash::display::interactiveobject::create_class(activation),
script,
activation,
)?;
avm2_system_class!(
simplebutton,
activation,
flash::display::simplebutton::create_class(mc),
flash::display::simplebutton::create_class(activation),
script
);
class(
activation,
flash::display::displayobjectcontainer::create_class(mc),
flash::display::displayobjectcontainer::create_class(activation),
script,
activation,
)?;
avm2_system_class!(
sprite,
activation,
flash::display::sprite::create_class(mc),
flash::display::sprite::create_class(activation),
script
);
avm2_system_class!(
movieclip,
activation,
flash::display::movieclip::create_class(mc),
flash::display::movieclip::create_class(activation),
script
);
avm2_system_class!(
graphics,
activation,
flash::display::graphics::create_class(mc),
flash::display::graphics::create_class(activation),
script
);
avm2_system_class!(
loaderinfo,
activation,
flash::display::loaderinfo::create_class(mc),
flash::display::loaderinfo::create_class(activation),
script
);
avm2_system_class!(
stage,
activation,
flash::display::stage::create_class(mc),
flash::display::stage::create_class(activation),
script
);
avm2_system_class!(
bitmap,
activation,
flash::display::bitmap::create_class(mc),
flash::display::bitmap::create_class(activation),
script
);
avm2_system_class!(
bitmapdata,
activation,
flash::display::bitmapdata::create_class(mc),
flash::display::bitmapdata::create_class(activation),
script
);
@ -564,25 +572,29 @@ pub fn load_player_globals<'gc>(
avm2_system_class!(
video,
activation,
flash::media::video::create_class(mc),
script
);
class(activation, flash::media::sound::create_class(mc), script)?;
avm2_system_class!(
soundtransform,
activation,
flash::media::soundtransform::create_class(mc),
flash::media::video::create_class(activation),
script
);
class(
activation,
flash::media::soundmixer::create_class(mc),
flash::media::sound::create_class(activation),
script,
activation,
)?;
avm2_system_class!(
soundtransform,
activation,
flash::media::soundtransform::create_class(activation),
script
);
class(
flash::media::soundmixer::create_class(activation),
script,
activation,
)?;
avm2_system_class!(
soundchannel,
activation,
flash::media::soundchannel::create_class(mc),
flash::media::soundchannel::create_class(activation),
script
);
@ -590,16 +602,20 @@ pub fn load_player_globals<'gc>(
avm2_system_class!(
textfield,
activation,
flash::text::textfield::create_class(mc),
flash::text::textfield::create_class(activation),
script
);
avm2_system_class!(
textformat,
activation,
flash::text::textformat::create_class(mc),
flash::text::textformat::create_class(activation),
script
);
class(activation, flash::text::font::create_class(mc), script)?;
class(
flash::text::font::create_class(activation),
script,
activation,
)?;
// Inside this call, the macro `avm2_system_classes_playerglobal`
// triggers classloading. Therefore, we run `load_playerglobal`
@ -652,7 +668,7 @@ fn load_playerglobal<'gc>(
macro_rules! avm2_system_classes_playerglobal {
($activation:expr, $script:expr, [$(($package:expr, $class_name:expr, $field:ident)),* $(,)?]) => {
$(
let name = Multiname::new(Namespace::package($package), $class_name);
let name = Multiname::new(Namespace::package($package, activation.context.gc_context), $class_name);
let class_object = activation.resolve_class(&name)?;
let sc = $activation.avm2().system_classes.as_mut().unwrap();
sc.$field = class_object;

View File

@ -8,11 +8,10 @@ use crate::avm2::object::{array_allocator, ArrayObject, Object, TObject};
use crate::avm2::value::Value;
use crate::avm2::Error;
use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::avm2::QName;
use crate::string::AvmString;
use bitflags::bitflags;
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
use std::cmp::{min, Ordering};
use std::mem::swap;
@ -135,11 +134,8 @@ pub fn resolve_array_hole<'gc>(
}
if let Some(proto) = this.proto() {
proto.get_property(
&Multiname::public(AvmString::new_utf8(
activation.context.gc_context,
i.to_string(),
)),
proto.get_public_property(
AvmString::new_utf8(activation.context.gc_context, i.to_string()),
activation,
)
} else {
@ -213,7 +209,7 @@ pub fn to_locale_string<'gc>(
) -> Result<Value<'gc>, Error<'gc>> {
join_inner(act, this, &[",".into()], |v, activation| {
if let Ok(o) = v.coerce_to_object(activation) {
o.call_property(&Multiname::public("toLocaleString"), &[], activation)
o.call_public_property("toLocaleString", &[], activation)
} else {
Ok(v)
}
@ -270,7 +266,7 @@ impl<'gc> ArrayIter<'gc> {
end_index: u32,
) -> Result<Self, Error<'gc>> {
let length = array_object
.get_property(&Multiname::public("length"), activation)?
.get_public_property("length", activation)?
.coerce_to_u32(activation)?;
Ok(Self {
@ -295,11 +291,8 @@ impl<'gc> ArrayIter<'gc> {
Some(
self.array_object
.get_property(
&Multiname::public(AvmString::new_utf8(
activation.context.gc_context,
i.to_string(),
)),
.get_public_property(
AvmString::new_utf8(activation.context.gc_context, i.to_string()),
activation,
)
.map(|val| (i, val)),
@ -324,11 +317,8 @@ impl<'gc> ArrayIter<'gc> {
Some(
self.array_object
.get_property(
&Multiname::public(AvmString::new_utf8(
activation.context.gc_context,
i.to_string(),
)),
.get_public_property(
AvmString::new_utf8(activation.context.gc_context, i.to_string()),
activation,
)
.map(|val| (i, val)),
@ -1145,12 +1135,10 @@ pub fn sort_on<'gc>(
// it's treated as if the field's value was undefined.
// TODO: verify this and fix it
let a_object = a.coerce_to_object(activation)?;
let a_field =
a_object.get_property(&Multiname::public(*field_name), activation)?;
let a_field = a_object.get_public_property(*field_name, activation)?;
let b_object = b.coerce_to_object(activation)?;
let b_field =
b_object.get_property(&Multiname::public(*field_name), activation)?;
let b_field = b_object.get_public_property(*field_name, activation)?;
let ord = if options.contains(SortOptions::NUMERIC) {
compare_numeric(activation, a_field, b_field)?
@ -1183,10 +1171,11 @@ pub fn sort_on<'gc>(
}
/// Construct `Array`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::public(), "Array"),
Some(Multiname::public("Object")),
QName::new(activation.avm2().public_namespace, "Array"),
Some(Multiname::new(activation.avm2().public_namespace, "Object")),
Method::from_builtin(instance_init, "<Array instance initializer>", mc),
Method::from_builtin(class_init, "<Array class initializer>", mc),
mc,
@ -1202,14 +1191,22 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("toLocaleString", to_locale_string),
("valueOf", value_of),
];
write.define_public_builtin_instance_methods(mc, PUBLIC_INSTANCE_METHODS);
write.define_builtin_instance_methods(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_METHODS,
);
const PUBLIC_INSTANCE_PROPERTIES: &[(
&str,
Option<NativeMethodImpl>,
Option<NativeMethodImpl>,
)] = &[("length", Some(length), Some(set_length))];
write.define_public_builtin_instance_properties(mc, PUBLIC_INSTANCE_PROPERTIES);
write.define_builtin_instance_properties(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_PROPERTIES,
);
const AS3_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] = &[
("concat", concat),
@ -1231,7 +1228,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("sort", sort),
("sortOn", sort_on),
];
write.define_as3_builtin_instance_methods(mc, AS3_INSTANCE_METHODS);
write.define_builtin_instance_methods(
mc,
activation.avm2().as3_namespace,
AS3_INSTANCE_METHODS,
);
const CONSTANTS: &[(&str, u32)] = &[
(
@ -1246,7 +1247,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
),
("UNIQUESORT", SortOptions::UNIQUE_SORT.bits() as u32),
];
write.define_public_constant_uint_class_traits(CONSTANTS);
write.define_constant_uint_class_traits(
activation.avm2().public_namespace,
CONSTANTS,
activation,
);
class
}

View File

@ -7,9 +7,8 @@ use crate::avm2::object::{primitive_allocator, FunctionObject, Object, TObject};
use crate::avm2::value::Value;
use crate::avm2::Error;
use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::avm2::QName;
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
/// Implements `Boolean`'s instance initializer.
fn instance_init<'gc>(
@ -58,8 +57,8 @@ fn class_init<'gc>(
let this_class = this.as_class_object().unwrap();
let boolean_proto = this_class.prototype();
boolean_proto.set_property_local(
&Multiname::public("toString"),
boolean_proto.set_string_property_local(
"toString",
FunctionObject::from_method(
activation,
Method::from_builtin(to_string, "toString", gc_context),
@ -70,8 +69,8 @@ fn class_init<'gc>(
.into(),
activation,
)?;
boolean_proto.set_property_local(
&Multiname::public("valueOf"),
boolean_proto.set_string_property_local(
"valueOf",
FunctionObject::from_method(
activation,
Method::from_builtin(value_of, "valueOf", gc_context),
@ -124,10 +123,11 @@ fn value_of<'gc>(
}
/// Construct `Boolean`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::public(), "Boolean"),
Some(Multiname::public("Object")),
QName::new(activation.avm2().public_namespace, "Boolean"),
Some(Multiname::new(activation.avm2().public_namespace, "Object")),
Method::from_builtin(instance_init, "<Boolean instance initializer>", mc),
Method::from_builtin(class_init, "<Boolean class initializer>", mc),
mc,
@ -144,7 +144,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
const AS3_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] =
&[("toString", to_string), ("valueOf", value_of)];
write.define_as3_builtin_instance_methods(mc, AS3_INSTANCE_METHODS);
write.define_builtin_instance_methods(
mc,
activation.avm2().as3_namespace,
AS3_INSTANCE_METHODS,
);
class
}

View File

@ -7,9 +7,8 @@ use crate::avm2::object::{Object, TObject};
use crate::avm2::value::Value;
use crate::avm2::Error;
use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::avm2::QName;
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
/// Implements `Class`'s instance initializer.
///
@ -46,10 +45,11 @@ fn prototype<'gc>(
}
/// Construct `Class`'s class.
pub fn create_class<'gc>(gc_context: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let gc_context = activation.context.gc_context;
let class_class = Class::new(
QName::new(Namespace::public(), "Class"),
Some(Multiname::public("Object")),
QName::new(activation.avm2().public_namespace, "Class"),
Some(Multiname::new(activation.avm2().public_namespace, "Object")),
Method::from_builtin(instance_init, "<Class instance initializer>", gc_context),
Method::from_builtin(class_init, "<Class class initializer>", gc_context),
gc_context,
@ -62,7 +62,11 @@ pub fn create_class<'gc>(gc_context: MutationContext<'gc, '_>) -> GcCell<'gc, Cl
Option<NativeMethodImpl>,
Option<NativeMethodImpl>,
)] = &[("prototype", Some(prototype), None)];
write.define_public_builtin_instance_properties(gc_context, PUBLIC_INSTANCE_PROPERTIES);
write.define_builtin_instance_properties(
gc_context,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_PROPERTIES,
);
class_class
}

View File

@ -7,12 +7,11 @@ use crate::avm2::object::{date_allocator, DateObject, FunctionObject, Object, TO
use crate::avm2::value::Value;
use crate::avm2::Error;
use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::avm2::QName;
use crate::locale::{get_current_date_time, get_timezone};
use crate::string::{utils as string_utils, AvmString, WStr};
use chrono::{DateTime, Datelike, Duration, FixedOffset, LocalResult, TimeZone, Timelike, Utc};
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
use num_traits::ToPrimitive;
// All of these methods will be defined as both
@ -302,8 +301,8 @@ pub fn class_init<'gc>(
let date_proto = this_class.prototype();
for (name, method) in PUBLIC_INSTANCE_AND_PROTO_METHODS {
date_proto.set_property_local(
&Multiname::public(*name),
date_proto.set_string_property_local(
*name,
FunctionObject::from_method(
activation,
Method::from_builtin(*method, name, gc_context),
@ -1326,10 +1325,11 @@ pub fn parse<'gc>(
}
/// Construct `Date`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::public(), "Date"),
Some(Multiname::public("Object")),
QName::new(activation.avm2().public_namespace, "Date"),
Some(Multiname::new(activation.avm2().public_namespace, "Object")),
Method::from_builtin(instance_init, "<Date instance initializer>", mc),
Method::from_builtin(class_init, "<Date class initializer>", mc),
mc,
@ -1366,13 +1366,24 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("dayUTC", Some(day_utc), None),
("timezoneOffset", Some(timezone_offset), None),
];
write.define_public_builtin_instance_properties(mc, PUBLIC_INSTANCE_PROPERTIES);
write.define_as3_builtin_instance_methods(mc, PUBLIC_INSTANCE_AND_PROTO_METHODS);
write.define_builtin_instance_properties(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_PROPERTIES,
);
write.define_builtin_instance_methods(
mc,
activation.avm2().as3_namespace,
PUBLIC_INSTANCE_AND_PROTO_METHODS,
);
const PUBLIC_CLASS_METHODS: &[(&str, NativeMethodImpl)] = &[("UTC", utc), ("parse", parse)];
write.define_as3_builtin_class_methods(mc, PUBLIC_CLASS_METHODS);
write.define_builtin_class_methods(
mc,
activation.avm2().public_namespace,
PUBLIC_CLASS_METHODS,
);
class
}

View File

@ -15,7 +15,7 @@ use crate::bitmap::bitmap_data::BitmapData;
use crate::character::Character;
use crate::display_object::{Bitmap, TDisplayObject};
use crate::{avm2_stub_getter, avm2_stub_setter};
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
/// Implements `flash.display.Bitmap`'s instance constructor.
pub fn instance_init<'gc>(
@ -94,11 +94,7 @@ pub fn instance_init<'gc>(
);
};
this.set_property(
&Multiname::public("bitmapData"),
bd_object.into(),
activation,
)?;
this.set_public_property("bitmapData", bd_object.into(), activation)?;
bitmap.set_smoothing(activation.context.gc_context, smoothing);
} else {
@ -229,11 +225,12 @@ pub fn set_smoothing<'gc>(
}
/// Construct `Bitmap`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::package("flash.display"), "Bitmap"),
QName::new(Namespace::package("flash.display", mc), "Bitmap"),
Some(Multiname::new(
Namespace::package("flash.display"),
Namespace::package("flash.display", mc),
"DisplayObject",
)),
Method::from_builtin(instance_init, "<Bitmap instance initializer>", mc),
@ -258,7 +255,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
),
("smoothing", Some(smoothing), Some(set_smoothing)),
];
write.define_public_builtin_instance_properties(mc, PUBLIC_INSTANCE_PROPERTIES);
write.define_builtin_instance_properties(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_PROPERTIES,
);
class
}

View File

@ -18,7 +18,7 @@ use crate::bitmap::is_size_valid;
use crate::character::Character;
use crate::display_object::Bitmap;
use crate::swf::BlendMode;
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
use ruffle_render::filters::{BlurFilter, ColorMatrixFilter, Filter};
use ruffle_render::transform::Transform;
use std::str::FromStr;
@ -219,16 +219,16 @@ pub fn copy_pixels<'gc>(
.coerce_to_object(activation)?;
let src_min_x = source_rect
.get_property(&Multiname::public("x"), activation)?
.get_public_property("x", activation)?
.coerce_to_i32(activation)?;
let src_min_y = source_rect
.get_property(&Multiname::public("y"), activation)?
.get_public_property("y", activation)?
.coerce_to_i32(activation)?;
let src_width = source_rect
.get_property(&Multiname::public("width"), activation)?
.get_public_property("width", activation)?
.coerce_to_i32(activation)?;
let src_height = source_rect
.get_property(&Multiname::public("height"), activation)?
.get_public_property("height", activation)?
.coerce_to_i32(activation)?;
let dest_point = args
@ -237,10 +237,10 @@ pub fn copy_pixels<'gc>(
.coerce_to_object(activation)?;
let dest_x = dest_point
.get_property(&Multiname::public("x"), activation)?
.get_public_property("x", activation)?
.coerce_to_i32(activation)?;
let dest_y = dest_point
.get_property(&Multiname::public("y"), activation)?
.get_public_property("y", activation)?
.coerce_to_i32(activation)?;
if let Some(src_bitmap) = source_bitmap.as_bitmap_data() {
@ -277,10 +277,10 @@ pub fn copy_pixels<'gc>(
.coerce_to_object(activation)
{
x = alpha_point
.get_property(&Multiname::public("x"), activation)?
.get_public_property("x", activation)?
.coerce_to_i32(activation)?;
y = alpha_point
.get_property(&Multiname::public("y"), activation)?
.get_public_property("y", activation)?
.coerce_to_i32(activation)?;
}
@ -333,16 +333,16 @@ pub fn get_pixels<'gc>(
.unwrap_or(&Value::Undefined)
.coerce_to_object(activation)?;
let x = rectangle
.get_property(&Multiname::public("x"), activation)?
.get_public_property("x", activation)?
.coerce_to_i32(activation)?;
let y = rectangle
.get_property(&Multiname::public("y"), activation)?
.get_public_property("y", activation)?
.coerce_to_i32(activation)?;
let width = rectangle
.get_property(&Multiname::public("width"), activation)?
.get_public_property("width", activation)?
.coerce_to_i32(activation)?;
let height = rectangle
.get_property(&Multiname::public("height"), activation)?
.get_public_property("height", activation)?
.coerce_to_i32(activation)?;
let bytearray = ByteArrayObject::from_storage(
activation,
@ -469,16 +469,16 @@ pub fn set_pixels<'gc>(
.coerce_to_object(activation)?;
if let Some(bitmap_data) = this.and_then(|t| t.as_bitmap_data()) {
let x = rectangle
.get_property(&Multiname::public("x"), activation)?
.get_public_property("x", activation)?
.coerce_to_u32(activation)?;
let y = rectangle
.get_property(&Multiname::public("y"), activation)?
.get_public_property("y", activation)?
.coerce_to_u32(activation)?;
let width = rectangle
.get_property(&Multiname::public("width"), activation)?
.get_public_property("width", activation)?
.coerce_to_u32(activation)?;
let height = rectangle
.get_property(&Multiname::public("height"), activation)?
.get_public_property("height", activation)?
.coerce_to_u32(activation)?;
let ba_read = bytearray
@ -532,10 +532,10 @@ pub fn copy_channel<'gc>(
.coerce_to_object(activation)?;
let dest_x = dest_point
.get_property(&Multiname::public("x"), activation)?
.get_public_property("x", activation)?
.coerce_to_u32(activation)?;
let dest_y = dest_point
.get_property(&Multiname::public("y"), activation)?
.get_public_property("y", activation)?
.coerce_to_u32(activation)?;
let source_channel = args
@ -551,16 +551,16 @@ pub fn copy_channel<'gc>(
if let Some(source_bitmap) = source_bitmap.as_bitmap_data() {
//TODO: what if source is disposed
let src_min_x = source_rect
.get_property(&Multiname::public("x"), activation)?
.get_public_property("x", activation)?
.coerce_to_u32(activation)?;
let src_min_y = source_rect
.get_property(&Multiname::public("y"), activation)?
.get_public_property("y", activation)?
.coerce_to_u32(activation)?;
let src_width = source_rect
.get_property(&Multiname::public("width"), activation)?
.get_public_property("width", activation)?
.coerce_to_u32(activation)?;
let src_height = source_rect
.get_property(&Multiname::public("height"), activation)?
.get_public_property("height", activation)?
.coerce_to_u32(activation)?;
let src_max_x = src_min_x + src_width;
let src_max_y = src_min_y + src_height;
@ -660,16 +660,16 @@ pub fn color_transform<'gc>(
// TODO: Re-use `object_to_rectangle` in `movie_clip.rs`.
let rectangle = rectangle.coerce_to_object(activation)?;
let x = rectangle
.get_property(&Multiname::public("x"), activation)?
.get_public_property("x", activation)?
.coerce_to_i32(activation)?;
let y = rectangle
.get_property(&Multiname::public("y"), activation)?
.get_public_property("y", activation)?
.coerce_to_i32(activation)?;
let width = rectangle
.get_property(&Multiname::public("width"), activation)?
.get_public_property("width", activation)?
.coerce_to_i32(activation)?;
let height = rectangle
.get_property(&Multiname::public("height"), activation)?
.get_public_property("height", activation)?
.coerce_to_i32(activation)?;
let x_min = x.max(0) as u32;
@ -828,16 +828,16 @@ pub fn fill_rect<'gc>(
if let Some(bitmap_data) = this.and_then(|this| this.as_bitmap_data()) {
let x = rectangle
.get_property(&Multiname::public("x"), activation)?
.get_public_property("x", activation)?
.coerce_to_u32(activation)?;
let y = rectangle
.get_property(&Multiname::public("y"), activation)?
.get_public_property("y", activation)?
.coerce_to_u32(activation)?;
let width = rectangle
.get_property(&Multiname::public("width"), activation)?
.get_public_property("width", activation)?
.coerce_to_u32(activation)?;
let height = rectangle
.get_property(&Multiname::public("height"), activation)?
.get_public_property("height", activation)?
.coerce_to_u32(activation)?;
bitmap_data.write(activation.context.gc_context).fill_rect(
@ -942,10 +942,10 @@ pub fn apply_filter<'gc>(
})?;
let dest_point = (
dest_point
.get_property(&Multiname::public("x"), activation)?
.get_public_property("x", activation)?
.coerce_to_u32(activation)?,
dest_point
.get_property(&Multiname::public("x"), activation)?
.get_public_property("x", activation)?
.coerce_to_u32(activation)?,
);
let filter = args[3]
@ -954,46 +954,27 @@ pub fn apply_filter<'gc>(
Error::from(format!("TypeError: Error #1034: Type Coercion failed: cannot convert {} to flash.filters.BitmapFilter.", args[1].coerce_to_string(activation).unwrap_or_default()))
})?;
let bevel_filter = activation.resolve_class(&Multiname::new(
Namespace::package("flash.filters"),
"BevelFilter",
))?;
let bitmap_filter = activation.resolve_class(&Multiname::new(
Namespace::package("flash.filters"),
"BitmapFilter",
))?;
let blur_filter = activation.resolve_class(&Multiname::new(
Namespace::package("flash.filters"),
"BlurFilter",
))?;
let color_matrix_filter = activation.resolve_class(&Multiname::new(
Namespace::package("flash.filters"),
"ColorMatrixFilter",
))?;
let convolution_filter = activation.resolve_class(&Multiname::new(
Namespace::package("flash.filters"),
"ConvolutionFilter",
))?;
let displacement_map_filter = activation.resolve_class(&Multiname::new(
Namespace::package("flash.filters"),
"DisplacementMapFilter",
))?;
let drop_shadow_filter = activation.resolve_class(&Multiname::new(
Namespace::package("flash.filters"),
"DropShadowFilter",
))?;
let glow_filter = activation.resolve_class(&Multiname::new(
Namespace::package("flash.filters"),
"GlowFilter",
))?;
let gradient_bevel_filter = activation.resolve_class(&Multiname::new(
Namespace::package("flash.filters"),
"GradientBevelFilter",
))?;
let gradient_glow_filter = activation.resolve_class(&Multiname::new(
Namespace::package("flash.filters"),
"GradientGlowFilter",
))?;
let filters_namespace = Namespace::package("flash.filters", activation.context.gc_context);
let bevel_filter =
activation.resolve_class(&Multiname::new(filters_namespace, "BevelFilter"))?;
let bitmap_filter =
activation.resolve_class(&Multiname::new(filters_namespace, "BitmapFilter"))?;
let blur_filter =
activation.resolve_class(&Multiname::new(filters_namespace, "BlurFilter"))?;
let color_matrix_filter =
activation.resolve_class(&Multiname::new(filters_namespace, "ColorMatrixFilter"))?;
let convolution_filter =
activation.resolve_class(&Multiname::new(filters_namespace, "ConvolutionFilter"))?;
let displacement_map_filter = activation
.resolve_class(&Multiname::new(filters_namespace, "DisplacementMapFilter"))?;
let drop_shadow_filter =
activation.resolve_class(&Multiname::new(filters_namespace, "DropShadowFilter"))?;
let glow_filter =
activation.resolve_class(&Multiname::new(filters_namespace, "GlowFilter"))?;
let gradient_bevel_filter =
activation.resolve_class(&Multiname::new(filters_namespace, "GradientBevelFilter"))?;
let gradient_glow_filter =
activation.resolve_class(&Multiname::new(filters_namespace, "GradientGlowFilter"))?;
// let shader_filter = activation.resolve_class(&Multiname::new(
// Namespace::package("flash.filters"),
// "ShaderFilter",
@ -1001,7 +982,7 @@ pub fn apply_filter<'gc>(
let filter = if filter.is_of_type(color_matrix_filter, activation) {
let mut matrix = [0.0; 20];
if let Some(object) = filter
.get_property(&Multiname::public("matrix"), activation)?
.get_public_property("matrix", activation)?
.as_object()
{
if let Some(array) = object.as_array_storage() {
@ -1017,13 +998,13 @@ pub fn apply_filter<'gc>(
Filter::ColorMatrixFilter(ColorMatrixFilter { matrix })
} else if filter.is_of_type(blur_filter, activation) {
let blur_x = filter
.get_property(&Multiname::public("blurX"), activation)?
.get_public_property("blurX", activation)?
.coerce_to_number(activation)?;
let blur_y = filter
.get_property(&Multiname::public("blurY"), activation)?
.get_public_property("blurY", activation)?
.coerce_to_number(activation)?;
let quality = filter
.get_property(&Multiname::public("quality"), activation)?
.get_public_property("quality", activation)?
.coerce_to_u32(activation)?;
Filter::BlurFilter(BlurFilter {
blur_x: blur_x as f32,
@ -1207,10 +1188,10 @@ pub fn perlin_noise<'gc>(
if let Some(offsets) = offsets.as_array_storage() {
if let Some(Value::Object(e)) = offsets.get(i) {
let x = e
.get_property(&Multiname::public("x"), activation)?
.get_public_property("x", activation)?
.coerce_to_number(activation)?;
let y = e
.get_property(&Multiname::public("y"), activation)?
.get_public_property("y", activation)?
.coerce_to_number(activation)?;
Ok((x, y))
} else {
@ -1245,10 +1226,11 @@ pub fn perlin_noise<'gc>(
}
/// Construct `BitmapData`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::package("flash.display"), "BitmapData"),
Some(Multiname::new(Namespace::package(""), "Object")),
QName::new(Namespace::package("flash.display", mc), "BitmapData"),
Some(Multiname::new(activation.avm2().public_namespace, "Object")),
Method::from_builtin(instance_init, "<BitmapData instance initializer>", mc),
Method::from_builtin(class_init, "<BitmapData class initializer>", mc),
mc,
@ -1260,7 +1242,7 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
write.set_instance_allocator(bitmapdata_allocator);
write.implements(Multiname::new(
Namespace::package("flash.display"),
Namespace::package("flash.display", mc),
"IBitmapDrawable",
));
@ -1274,7 +1256,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("rect", Some(rect), None),
("transparent", Some(transparent), None),
];
write.define_public_builtin_instance_properties(mc, PUBLIC_INSTANCE_PROPERTIES);
write.define_builtin_instance_properties(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_PROPERTIES,
);
const PUBLIC_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] = &[
("getPixels", get_pixels),
@ -1299,7 +1285,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("clone", clone),
("perlinNoise", perlin_noise),
];
write.define_public_builtin_instance_methods(mc, PUBLIC_INSTANCE_METHODS);
write.define_builtin_instance_methods(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_METHODS,
);
class
}

View File

@ -18,7 +18,7 @@ use crate::string::AvmString;
use crate::types::{Degrees, Percent};
use crate::vminterface::Instantiator;
use crate::{avm2_stub_getter, avm2_stub_setter};
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
use std::str::FromStr;
use swf::Twips;
use swf::{BlendMode, Rectangle};
@ -285,8 +285,9 @@ pub fn set_filters<'gc>(
if let Some(filters_array) = new_filters.as_array_object() {
if let Some(filters_storage) = filters_array.as_array_storage() {
let filter_class =
Multiname::new(Namespace::package("flash.filters"), "BitmapFilter");
let filters_namespace =
Namespace::package("flash.filters", activation.context.gc_context);
let filter_class = Multiname::new(filters_namespace, "BitmapFilter");
let filter_class_object = activation.resolve_class(&filter_class)?;
@ -769,10 +770,10 @@ pub fn set_transform<'gc>(
// FIXME - consider 3D matrix and pixel bounds
let matrix = transform
.get_property(&Multiname::public("matrix"), activation)?
.get_public_property("matrix", activation)?
.coerce_to_object(activation)?;
let color_transform = transform
.get_property(&Multiname::public("colorTransform"), activation)?
.get_public_property("colorTransform", activation)?
.coerce_to_object(activation)?;
let matrix =
@ -867,7 +868,7 @@ pub fn object_to_rectangle<'gc>(
let mut values = [0.0; 4];
for (&name, value) in NAMES.iter().zip(&mut values) {
*value = object
.get_property(&Multiname::public(name), activation)?
.get_public_property(name, activation)?
.coerce_to_number(activation)?;
}
let [x, y, width, height] = values;
@ -921,10 +922,10 @@ fn local_to_global<'gc>(
.unwrap_or(&Value::Undefined)
.coerce_to_object(activation)?;
let x = point
.get_property(&Multiname::public("x"), activation)?
.get_public_property("x", activation)?
.coerce_to_number(activation)?;
let y = point
.get_property(&Multiname::public("y"), activation)?
.get_public_property("y", activation)?
.coerce_to_number(activation)?;
let (out_x, out_y) = dobj.local_to_global((Twips::from_pixels(x), Twips::from_pixels(y)));
@ -953,10 +954,10 @@ fn global_to_local<'gc>(
.unwrap_or(&Value::Undefined)
.coerce_to_object(activation)?;
let x = point
.get_property(&Multiname::public("x"), activation)?
.get_public_property("x", activation)?
.coerce_to_number(activation)?;
let y = point
.get_property(&Multiname::public("y"), activation)?
.get_public_property("y", activation)?
.coerce_to_number(activation)?;
let (out_x, out_y) = dobj.global_to_local((Twips::from_pixels(x), Twips::from_pixels(y)));
@ -1106,11 +1107,12 @@ pub fn set_opaque_background<'gc>(
}
/// Construct `DisplayObject`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::package("flash.display"), "DisplayObject"),
QName::new(Namespace::package("flash.display", mc), "DisplayObject"),
Some(Multiname::new(
Namespace::package("flash.events"),
Namespace::package("flash.events", mc),
"EventDispatcher",
)),
Method::from_builtin(instance_init, "<DisplayObject instance initializer>", mc),
@ -1128,7 +1130,7 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
));
write.implements(Multiname::new(
Namespace::package("flash.display"),
Namespace::package("flash.display", mc),
"IBitmapDrawable",
));
@ -1174,7 +1176,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
Some(set_cache_as_bitmap),
),
];
write.define_public_builtin_instance_properties(mc, PUBLIC_INSTANCE_PROPERTIES);
write.define_builtin_instance_properties(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_PROPERTIES,
);
const PUBLIC_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] = &[
("hitTestPoint", hit_test_point),
@ -1184,7 +1190,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("getBounds", get_bounds),
("getRect", get_rect),
];
write.define_public_builtin_instance_methods(mc, PUBLIC_INSTANCE_METHODS);
write.define_builtin_instance_methods(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_METHODS,
);
class
}

View File

@ -12,7 +12,7 @@ use crate::avm2::{ArrayObject, ArrayStorage, Error};
use crate::context::UpdateContext;
use crate::display_object::{DisplayObject, TDisplayObject, TDisplayObjectContainer};
use crate::{avm2_stub_getter, avm2_stub_method, avm2_stub_setter};
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
use std::cmp::min;
/// Implements `flash.display.DisplayObjectContainer`'s instance constructor.
@ -640,14 +640,15 @@ pub fn set_tab_children<'gc>(
}
/// Construct `DisplayObjectContainer`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(
Namespace::package("flash.display"),
Namespace::package("flash.display", mc),
"DisplayObjectContainer",
),
Some(Multiname::new(
Namespace::package("flash.display"),
Namespace::package("flash.display", mc),
"InteractiveObject",
)),
Method::from_builtin(
@ -680,7 +681,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
),
("tabChildren", Some(tab_children), Some(set_tab_children)),
];
write.define_public_builtin_instance_properties(mc, PUBLIC_INSTANCE_PROPERTIES);
write.define_builtin_instance_properties(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_PROPERTIES,
);
const PUBLIC_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] = &[
("getChildAt", get_child_at),
@ -702,7 +707,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
are_inaccessible_objects_under_point,
),
];
write.define_public_builtin_instance_methods(mc, PUBLIC_INSTANCE_METHODS);
write.define_builtin_instance_methods(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_METHODS,
);
class
}

View File

@ -13,7 +13,7 @@ use crate::avm2_stub_method;
use crate::display_object::TDisplayObject;
use crate::drawing::Drawing;
use crate::string::WStr;
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
use ruffle_render::shape_utils::DrawCommand;
use std::f64::consts::FRAC_1_SQRT_2;
use swf::{Color, FillStyle, Fixed8, LineCapStyle, LineJoinStyle, LineStyle, Twips};
@ -788,10 +788,11 @@ fn draw_ellipse<'gc>(
}
/// Construct `Graphics`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::package("flash.display"), "Graphics"),
Some(Multiname::public("Object")),
QName::new(Namespace::package("flash.display", mc), "Graphics"),
Some(Multiname::new(activation.avm2().public_namespace, "Object")),
Method::from_builtin(instance_init, "<Graphics instance initializer>", mc),
Method::from_builtin(class_init, "<Graphics class initializer>", mc),
mc,
@ -822,7 +823,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("drawCircle", draw_circle),
("drawEllipse", draw_ellipse),
];
write.define_public_builtin_instance_methods(mc, PUBLIC_INSTANCE_METHODS);
write.define_builtin_instance_methods(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_METHODS,
);
class
}

View File

@ -8,7 +8,7 @@ use crate::avm2::value::Value;
use crate::avm2::Error;
use crate::avm2::Namespace;
use crate::avm2::QName;
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
/// Emulates attempts to execute bodiless methods.
pub fn bodiless_method<'gc>(
@ -29,9 +29,10 @@ pub fn class_init<'gc>(
}
/// Construct `IBitmapDrawable`'s class.
pub fn create_interface<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_interface<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::package("flash.display"), "IBitmapDrawable"),
QName::new(Namespace::package("flash.display", mc), "IBitmapDrawable"),
None,
Method::from_builtin(
bodiless_method,

View File

@ -11,7 +11,7 @@ use crate::avm2::Namespace;
use crate::avm2::QName;
use crate::display_object::{TDisplayObject, TInteractiveObject};
use crate::{avm2_stub_getter, avm2_stub_setter};
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
/// Implements `flash.display.InteractiveObject`'s instance constructor.
pub fn instance_init<'gc>(
@ -144,7 +144,10 @@ fn set_context_menu<'gc>(
.and_then(|t| t.as_display_object())
.and_then(|dobj| dobj.as_interactive())
{
let cls_name = Multiname::new(Namespace::package("flash.display"), "NativeMenu");
let cls_name = Multiname::new(
Namespace::package("flash.display", activation.context.gc_context),
"NativeMenu",
);
let cls = activation.resolve_class(&cls_name)?;
let value = args
.get(0)
@ -222,11 +225,12 @@ pub fn set_focus_rect<'gc>(
}
/// Construct `InteractiveObject`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::package("flash.display"), "InteractiveObject"),
QName::new(Namespace::package("flash.display", mc), "InteractiveObject"),
Some(Multiname::new(
Namespace::package("flash.display"),
Namespace::package("flash.display", mc),
"DisplayObject",
)),
Method::from_builtin(
@ -262,7 +266,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("tabIndex", Some(tab_index), Some(set_tab_index)),
("focusRect", Some(focus_rect), Some(set_focus_rect)),
];
write.define_public_builtin_instance_properties(mc, PUBLIC_INSTANCE_PROPERTIES);
write.define_builtin_instance_properties(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_PROPERTIES,
);
class
}

View File

@ -5,7 +5,6 @@ use crate::avm2::object::LoaderInfoObject;
use crate::avm2::object::TObject;
use crate::avm2::value::Value;
use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::avm2::{Error, Object};
use crate::backend::navigator::Request;
use crate::display_object::LoaderDisplay;
@ -40,7 +39,10 @@ pub fn init<'gc>(
false,
)?;
this.set_property(
&Multiname::new(Namespace::private(""), "_contentLoaderInfo"),
&Multiname::new(
activation.avm2().ruffle_private_namespace,
"_contentLoaderInfo",
),
loader_info.into(),
activation,
)?;
@ -61,7 +63,7 @@ pub fn load<'gc>(
.and_then(|v| v.coerce_to_object(activation).ok());
let url = url_request
.get_property(&Multiname::public("url"), activation)?
.get_public_property("url", activation)?
.coerce_to_string(activation)?;
// This is a dummy MovieClip, which will get overwritten in `Loader`
@ -72,7 +74,10 @@ pub fn load<'gc>(
let loader_info = this
.get_property(
&Multiname::new(Namespace::private(""), "_contentLoaderInfo"),
&Multiname::new(
activation.avm2().ruffle_private_namespace,
"_contentLoaderInfo",
),
activation,
)?
.as_object()
@ -112,7 +117,10 @@ pub fn load_bytes<'gc>(
let loader_info = this
.get_property(
&Multiname::new(Namespace::private(""), "_contentLoaderInfo"),
&Multiname::new(
activation.avm2().ruffle_private_namespace,
"_contentLoaderInfo",
),
activation,
)?
.as_object()

View File

@ -12,7 +12,7 @@ use crate::avm2::QName;
use crate::avm2::{AvmString, Error};
use crate::avm2_stub_getter;
use crate::display_object::TDisplayObject;
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
use swf::{write_swf, Compression};
// FIXME - Throw an actual 'Error' with the proper code
@ -470,7 +470,7 @@ pub fn parameters<'gc>(
for (k, v) in parameters.iter() {
let avm_k = AvmString::new_utf8(activation.context.gc_context, k);
let avm_v = AvmString::new_utf8(activation.context.gc_context, v);
params_obj.set_property(&Multiname::public(avm_k), avm_v.into(), activation)?;
params_obj.set_public_property(avm_k, avm_v.into(), activation)?;
}
return Ok(params_obj.into());
@ -505,11 +505,12 @@ pub fn uncaught_error_events<'gc>(
}
/// Construct `LoaderInfo`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::package("flash.display"), "LoaderInfo"),
QName::new(Namespace::package("flash.display", mc), "LoaderInfo"),
Some(Multiname::new(
Namespace::package("flash.events"),
Namespace::package("flash.events", mc),
"EventDispatcher",
)),
Method::from_builtin(instance_init, "<LoaderInfo instance initializer>", mc),
@ -552,7 +553,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("sharedEvents", Some(shared_events), None),
("uncaughtErrorEvents", Some(uncaught_error_events), None),
];
write.define_public_builtin_instance_properties(mc, PUBLIC_INSTANCE_PROPERTIES);
write.define_builtin_instance_properties(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_PROPERTIES,
);
class
}

View File

@ -12,7 +12,7 @@ use crate::avm2::Namespace;
use crate::avm2::QName;
use crate::display_object::{MovieClip, Scene, TDisplayObject};
use crate::string::{AvmString, WString};
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
/// Implements `flash.display.MovieClip`'s instance constructor.
pub fn instance_init<'gc>(
@ -545,11 +545,12 @@ pub fn next_scene<'gc>(
}
/// Construct `MovieClip`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::package("flash.display"), "MovieClip"),
QName::new(Namespace::package("flash.display", mc), "MovieClip"),
Some(Multiname::new(
Namespace::package("flash.display"),
Namespace::package("flash.display", mc),
"Sprite",
)),
Method::from_builtin(instance_init, "<MovieClip instance initializer>", mc),
@ -575,7 +576,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("isPlaying", Some(is_playing), None),
("totalFrames", Some(total_frames), None),
];
write.define_public_builtin_instance_properties(mc, PUBLIC_INSTANCE_PROPERTIES);
write.define_builtin_instance_properties(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_PROPERTIES,
);
const PUBLIC_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] = &[
("addFrameScript", add_frame_script),
@ -588,7 +593,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("prevScene", prev_scene),
("nextScene", next_scene),
];
write.define_public_builtin_instance_methods(mc, PUBLIC_INSTANCE_METHODS);
write.define_builtin_instance_methods(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_METHODS,
);
class
}

View File

@ -2,7 +2,6 @@
use crate::avm2::activation::Activation;
use crate::avm2::class::Class;
use crate::avm2::globals::NS_RUFFLE_INTERNAL;
use crate::avm2::method::{Method, NativeMethodImpl};
use crate::avm2::object::{Object, StageObject, TObject};
use crate::avm2::traits::Trait;
@ -12,7 +11,7 @@ use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::avm2::QName;
use crate::display_object::Graphic;
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
/// Implements `flash.display.Shape`'s instance constructor.
pub fn instance_init<'gc>(
@ -52,13 +51,13 @@ pub fn graphics<'gc>(
if let Some(dobj) = this.as_display_object() {
// Lazily initialize the `Graphics` object in a hidden property.
let graphics = match this.get_property(
&Multiname::new(Namespace::private(NS_RUFFLE_INTERNAL), "graphics"),
&Multiname::new(activation.avm2().ruffle_private_namespace, "graphics"),
activation,
)? {
Value::Undefined | Value::Null => {
let graphics = Value::from(StageObject::graphics(activation, dobj)?);
this.set_property(
&Multiname::new(Namespace::private(NS_RUFFLE_INTERNAL), "graphics"),
&Multiname::new(activation.avm2().ruffle_private_namespace, "graphics"),
graphics,
activation,
)?;
@ -74,11 +73,12 @@ pub fn graphics<'gc>(
}
/// Construct `Shape`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::package("flash.display"), "Shape"),
QName::new(Namespace::package("flash.display", mc), "Shape"),
Some(Multiname::new(
Namespace::package("flash.display"),
Namespace::package("flash.display", mc),
"DisplayObject",
)),
Method::from_builtin(instance_init, "<Shape instance initializer>", mc),
@ -93,12 +93,16 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
Option<NativeMethodImpl>,
Option<NativeMethodImpl>,
)] = &[("graphics", Some(graphics), None)];
write.define_public_builtin_instance_properties(mc, PUBLIC_INSTANCE_PROPERTIES);
write.define_builtin_instance_properties(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_PROPERTIES,
);
// Slot for lazy-initialized Graphics object.
write.define_instance_trait(Trait::from_slot(
QName::new(Namespace::private(NS_RUFFLE_INTERNAL), "graphics"),
Multiname::new(Namespace::package("flash.display"), "Graphics"),
QName::new(activation.avm2().ruffle_private_namespace, "graphics"),
Multiname::new(Namespace::package("flash.display", mc), "Graphics"),
None,
));

View File

@ -12,7 +12,7 @@ use crate::avm2::Namespace;
use crate::avm2::QName;
use crate::display_object::{Avm2Button, ButtonTracking, TDisplayObject};
use crate::vminterface::Instantiator;
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
use swf::ButtonState;
/// Implements `flash.display.SimpleButton`'s instance constructor.
@ -362,11 +362,12 @@ pub fn set_use_hand_cursor<'gc>(
}
/// Construct `SimpleButton`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::package("flash.display"), "SimpleButton"),
QName::new(Namespace::package("flash.display", mc), "SimpleButton"),
Some(Multiname::new(
Namespace::package("flash.display"),
Namespace::package("flash.display", mc),
"InteractiveObject",
)),
Method::from_builtin(instance_init, "<SimpleButton instance initializer>", mc),
@ -404,7 +405,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
Some(set_sound_transform),
),
];
write.define_public_builtin_instance_properties(mc, PUBLIC_INSTANCE_PROPERTIES);
write.define_builtin_instance_properties(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_PROPERTIES,
);
class
}

View File

@ -2,7 +2,6 @@
use crate::avm2::activation::Activation;
use crate::avm2::class::{Class, ClassAttributes};
use crate::avm2::globals::NS_RUFFLE_INTERNAL;
use crate::avm2::method::{Method, NativeMethodImpl};
use crate::avm2::object::{Object, StageObject, TObject};
use crate::avm2::traits::Trait;
@ -13,7 +12,7 @@ use crate::avm2::Namespace;
use crate::avm2::QName;
use crate::display_object::{MovieClip, SoundTransform, TDisplayObject};
use crate::tag_utils::SwfMovie;
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
use ruffle_render::bounding_box::BoundingBox;
use std::sync::Arc;
use swf::Twips;
@ -78,13 +77,13 @@ pub fn graphics<'gc>(
if let Some(dobj) = this.as_display_object() {
// Lazily initialize the `Graphics` object in a hidden property.
let graphics = match this.get_property(
&Multiname::new(Namespace::private(NS_RUFFLE_INTERNAL), "graphics"),
&Multiname::new(activation.avm2().ruffle_private_namespace, "graphics"),
activation,
)? {
Value::Undefined | Value::Null => {
let graphics = Value::from(StageObject::graphics(activation, dobj)?);
this.set_property(
&Multiname::new(Namespace::private(NS_RUFFLE_INTERNAL), "graphics"),
&Multiname::new(activation.avm2().ruffle_private_namespace, "graphics"),
graphics,
activation,
)?;
@ -196,19 +195,19 @@ pub fn start_drag<'gc>(
let constraint = if let Some(rect) = args.get(1) {
let rect = rect.coerce_to_object(activation)?;
let x = rect
.get_property(&Multiname::public("x"), activation)?
.get_public_property("x", activation)?
.coerce_to_number(activation)?;
let y = rect
.get_property(&Multiname::public("y"), activation)?
.get_public_property("y", activation)?
.coerce_to_number(activation)?;
let width = rect
.get_property(&Multiname::public("width"), activation)?
.get_public_property("width", activation)?
.coerce_to_number(activation)?;
let height = rect
.get_property(&Multiname::public("height"), activation)?
.get_public_property("height", activation)?
.coerce_to_number(activation)?;
// Normalize the bounds.
@ -300,11 +299,12 @@ pub fn set_use_hand_cursor<'gc>(
}
/// Construct `Sprite`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::package("flash.display"), "Sprite"),
QName::new(Namespace::package("flash.display", mc), "Sprite"),
Some(Multiname::new(
Namespace::package("flash.display"),
Namespace::package("flash.display", mc),
"DisplayObjectContainer",
)),
Method::from_builtin(instance_init, "<Sprite instance initializer>", mc),
@ -335,16 +335,27 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
Some(set_use_hand_cursor),
),
];
write.define_public_builtin_instance_properties(mc, PUBLIC_INSTANCE_PROPERTIES);
write.define_builtin_instance_properties(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_PROPERTIES,
);
const PUBLIC_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] =
&[("startDrag", start_drag), ("stopDrag", stop_drag)];
write.define_public_builtin_instance_methods(mc, PUBLIC_INSTANCE_METHODS);
write.define_builtin_instance_methods(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_METHODS,
);
// Slot for lazy-initialized Graphics object.
write.define_instance_trait(Trait::from_slot(
QName::new(Namespace::private(NS_RUFFLE_INTERNAL), "graphics"),
Multiname::new(Namespace::package("flash.display"), "Graphics"),
QName::new(activation.avm2().ruffle_private_namespace, "graphics"),
Multiname::new(
Namespace::package("flash.display", activation.context.gc_context),
"Graphics",
),
None,
));

View File

@ -14,7 +14,7 @@ use crate::avm2::{ArrayObject, ArrayStorage};
use crate::display_object::{StageDisplayState, TDisplayObject};
use crate::string::{AvmString, WString};
use crate::{avm2_stub_getter, avm2_stub_setter};
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
use swf::Color;
/// Implements `flash.display.Stage`'s instance constructor.
@ -762,11 +762,12 @@ pub fn set_full_screen_source_rect<'gc>(
}
/// Construct `Stage`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::package("flash.display"), "Stage"),
QName::new(Namespace::package("flash.display", mc), "Stage"),
Some(Multiname::new(
Namespace::package("flash.display"),
Namespace::package("flash.display", mc),
"DisplayObjectContainer",
)),
Method::from_builtin(instance_init, "<Stage instance initializer>", mc),
@ -820,7 +821,7 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
if let Some(getter) = getter {
write.define_instance_trait(
Trait::from_getter(
QName::new(Namespace::public(), name),
QName::new(activation.avm2().public_namespace, name),
Method::from_builtin(getter, name, mc),
)
.with_override(),
@ -829,7 +830,7 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
if let Some(setter) = setter {
write.define_instance_trait(
Trait::from_setter(
QName::new(Namespace::public(), name),
QName::new(activation.avm2().public_namespace, name),
Method::from_builtin(setter, name, mc),
)
.with_override(),
@ -876,10 +877,18 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("quality", Some(quality), Some(set_quality)),
("stage3Ds", Some(stage3ds), None),
];
write.define_public_builtin_instance_properties(mc, PUBLIC_INSTANCE_PROPERTIES);
write.define_builtin_instance_properties(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_PROPERTIES,
);
const PUBLIC_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] = &[("invalidate", invalidate)];
write.define_public_builtin_instance_methods(mc, PUBLIC_INSTANCE_METHODS);
write.define_builtin_instance_methods(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_METHODS,
);
class
}

View File

@ -1,6 +1,5 @@
use crate::avm2::object::Context3DObject;
use crate::avm2::object::TObject;
use crate::avm2::Multiname;
use crate::avm2::{Activation, Error, Object, Value};
@ -26,11 +25,7 @@ pub fn request_context3d_internal<'gc>(
// FIXME - fire this at least one frame later,
// since some seems to expect this (e.g. the adobe triangle example)
this.call_property(
&Multiname::public("dispatchEvent"),
&[event.into()],
activation,
)?;
this.call_public_property("dispatchEvent", &[event.into()], activation)?;
}
}
Ok(Value::Undefined)

View File

@ -4,7 +4,6 @@ use ruffle_render::backend::Context3DVertexBufferFormat;
use ruffle_render::backend::ProgramType;
use crate::avm2::Activation;
use crate::avm2::Multiname;
use crate::avm2::TObject;
use crate::avm2::Value;
use crate::avm2::{Error, Object};
@ -255,14 +254,14 @@ pub fn set_program_constants_from_matrix<'gc>(
// See https://github.com/openfl/openfl/blob/971a4c9e43b5472fd84d73920a2b7c1b3d8d9257/src/openfl/display3D/Context3D.hx#L1532-L1550
if user_transposedMatrix {
matrix = matrix
.call_property(&Multiname::public("clone"), &[], activation)?
.call_public_property("clone", &[], activation)?
.coerce_to_object(activation)?;
matrix.call_property(&Multiname::public("transpose"), &[], activation)?;
matrix.call_public_property("transpose", &[], activation)?;
}
let matrix_raw_data = matrix
.get_property(&Multiname::public("rawData"), activation)?
.get_public_property("rawData", activation)?
.coerce_to_object(activation)?;
let matrix_raw_data = matrix_raw_data
.as_vector_storage()

View File

@ -2,9 +2,7 @@
use crate::avm2::activation::Activation;
use crate::avm2::class::{Class, ClassAttributes};
use crate::avm2::events::{
dispatch_event as dispatch_event_internal, parent_of, NS_EVENT_DISPATCHER,
};
use crate::avm2::events::{dispatch_event as dispatch_event_internal, parent_of};
use crate::avm2::method::{Method, NativeMethodImpl};
use crate::avm2::object::{DispatchObject, Object, TObject};
use crate::avm2::traits::Trait;
@ -13,7 +11,7 @@ use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::avm2::QName;
use crate::avm2::{Avm2, Error};
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
/// Implements `flash.events.EventDispatcher`'s instance constructor.
pub fn instance_init<'gc>(
@ -27,7 +25,7 @@ pub fn instance_init<'gc>(
let target = args.get(0).cloned().unwrap_or(Value::Null);
this.init_property(
&Multiname::new(Namespace::private(NS_EVENT_DISPATCHER), "target"),
&Multiname::new(activation.avm2().ruffle_private_namespace, "target"),
target,
activation,
)?;
@ -46,14 +44,14 @@ fn dispatch_list<'gc>(
mut this: Object<'gc>,
) -> Result<Object<'gc>, Error<'gc>> {
match this.get_property(
&Multiname::new(Namespace::private(NS_EVENT_DISPATCHER), "dispatch_list"),
&Multiname::new(activation.avm2().ruffle_private_namespace, "dispatch_list"),
activation,
)? {
Value::Object(o) => Ok(o),
_ => {
let dispatch_list = DispatchObject::empty_list(activation.context.gc_context);
this.init_property(
&Multiname::new(Namespace::private(NS_EVENT_DISPATCHER), "dispatch_list"),
&Multiname::new(activation.avm2().ruffle_private_namespace, "dispatch_list"),
dispatch_list.into(),
activation,
)?;
@ -185,7 +183,7 @@ pub fn will_trigger<'gc>(
let target = this
.get_property(
&Multiname::new(Namespace::private(NS_EVENT_DISPATCHER), "target"),
&Multiname::new(activation.avm2().ruffle_private_namespace, "target"),
activation,
)?
.as_object()
@ -237,7 +235,7 @@ pub fn to_string<'gc>(
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
let object_proto = activation.avm2().classes().object.prototype();
let name = Multiname::public("toString");
let name = Multiname::new(activation.avm2().public_namespace, "toString");
object_proto
.get_property(&name, activation)?
.as_callable(activation, Some(&name), Some(object_proto))?
@ -245,10 +243,11 @@ pub fn to_string<'gc>(
}
/// Construct `EventDispatcher`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::package("flash.events"), "EventDispatcher"),
Some(Multiname::public("Object")),
QName::new(Namespace::package("flash.events", mc), "EventDispatcher"),
Some(Multiname::new(activation.avm2().public_namespace, "Object")),
Method::from_builtin(instance_init, "<EventDispatcher instance initializer>", mc),
Method::from_builtin(class_init, "<EventDispatcher class initializer>", mc),
mc,
@ -259,7 +258,7 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
write.set_attributes(ClassAttributes::SEALED);
write.implements(Multiname::new(
Namespace::package("flash.events"),
Namespace::package("flash.events", mc),
"IEventDispatcher",
));
@ -271,16 +270,20 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("dispatchEvent", dispatch_event),
("toString", to_string),
];
write.define_public_builtin_instance_methods(mc, PUBLIC_INSTANCE_METHODS);
write.define_builtin_instance_methods(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_METHODS,
);
write.define_instance_trait(Trait::from_slot(
QName::new(Namespace::private(NS_EVENT_DISPATCHER), "target"),
Multiname::public("Object"),
QName::new(activation.avm2().ruffle_private_namespace, "target"),
Multiname::new(activation.avm2().public_namespace, "Object"),
None,
));
write.define_instance_trait(Trait::from_slot(
QName::new(Namespace::private(NS_EVENT_DISPATCHER), "dispatch_list"),
Multiname::public("Object"),
QName::new(activation.avm2().ruffle_private_namespace, "dispatch_list"),
Multiname::new(activation.avm2().public_namespace, "Object"),
None,
));

View File

@ -8,7 +8,7 @@ use crate::avm2::value::Value;
use crate::avm2::Error;
use crate::avm2::Namespace;
use crate::avm2::QName;
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
/// Emulates attempts to execute bodiless methods.
pub fn bodiless_method<'gc>(
@ -29,9 +29,10 @@ pub fn class_init<'gc>(
}
/// Construct `IEventDispatcher`'s class.
pub fn create_interface<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_interface<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::package("flash.events"), "IEventDispatcher"),
QName::new(Namespace::package("flash.events", mc), "IEventDispatcher"),
None,
Method::from_builtin(
bodiless_method,
@ -53,7 +54,11 @@ pub fn create_interface<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<
("removeEventListener", bodiless_method),
("willTrigger", bodiless_method),
];
write.define_public_builtin_instance_methods(mc, PUBLIC_INSTANCE_METHODS);
write.define_builtin_instance_methods(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_METHODS,
);
class
}

View File

@ -2,7 +2,6 @@ use crate::avm2::activation::Activation;
use crate::avm2::object::{Object, TObject};
use crate::avm2::value::Value;
use crate::avm2::Error;
use crate::avm2::Multiname;
use crate::display_object::TDisplayObject;
use swf::Twips;
@ -15,7 +14,7 @@ pub fn get_stage_x<'gc>(
if let Some(this) = this {
if let Some(evt) = this.as_event() {
let local_x = this
.get_property(&Multiname::public("localX"), activation)?
.get_public_property("localX", activation)?
.coerce_to_number(activation)?;
if local_x.is_nan() {
@ -43,7 +42,7 @@ pub fn get_stage_y<'gc>(
if let Some(this) = this {
if let Some(evt) = this.as_event() {
let local_y = this
.get_property(&Multiname::public("localY"), activation)?
.get_public_property("localY", activation)?
.coerce_to_number(activation)?;
if local_y.is_nan() {

View File

@ -1,7 +1,7 @@
#![allow(non_snake_case)]
use crate::avm2::Multiname;
use crate::avm2::{Activation, Error, Namespace, Object, TObject, Value};
use crate::avm2::{Activation, Error, Object, TObject, Value};
use crate::avm2_stub_getter;
use crate::display_object::TDisplayObject;
use crate::prelude::{ColorTransform, DisplayObject, Matrix, Twips};
@ -14,7 +14,7 @@ fn get_display_object<'gc>(
) -> Result<DisplayObject<'gc>, Error<'gc>> {
Ok(this
.get_property(
&Multiname::new(Namespace::Private("".into()), "_displayObject"),
&Multiname::new(activation.avm2().ruffle_private_namespace, "_displayObject"),
activation,
)?
.as_object()
@ -29,7 +29,7 @@ pub fn init<'gc>(
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
this.unwrap().set_property(
&Multiname::new(Namespace::Private("".into()), "_displayObject"),
&Multiname::new(activation.avm2().ruffle_private_namespace, "_displayObject"),
args[0],
activation,
)?;
@ -145,28 +145,28 @@ pub fn object_to_color_transform<'gc>(
activation: &mut Activation<'_, 'gc>,
) -> Result<ColorTransform, Error<'gc>> {
let red_multiplier = object
.get_property(&Multiname::public("redMultiplier"), activation)?
.get_public_property("redMultiplier", activation)?
.coerce_to_number(activation)?;
let green_multiplier = object
.get_property(&Multiname::public("greenMultiplier"), activation)?
.get_public_property("greenMultiplier", activation)?
.coerce_to_number(activation)?;
let blue_multiplier = object
.get_property(&Multiname::public("blueMultiplier"), activation)?
.get_public_property("blueMultiplier", activation)?
.coerce_to_number(activation)?;
let alpha_multiplier = object
.get_property(&Multiname::public("alphaMultiplier"), activation)?
.get_public_property("alphaMultiplier", activation)?
.coerce_to_number(activation)?;
let red_offset = object
.get_property(&Multiname::public("redOffset"), activation)?
.get_public_property("redOffset", activation)?
.coerce_to_number(activation)?;
let green_offset = object
.get_property(&Multiname::public("greenOffset"), activation)?
.get_public_property("greenOffset", activation)?
.coerce_to_number(activation)?;
let blue_offset = object
.get_property(&Multiname::public("blueOffset"), activation)?
.get_public_property("blueOffset", activation)?
.coerce_to_number(activation)?;
let alpha_offset = object
.get_property(&Multiname::public("alphaOffset"), activation)?
.get_public_property("alphaOffset", activation)?
.coerce_to_number(activation)?;
Ok(ColorTransform {
r_mult: Fixed8::from_f64(red_multiplier),
@ -224,25 +224,25 @@ pub fn object_to_matrix<'gc>(
activation: &mut Activation<'_, 'gc>,
) -> Result<Matrix, Error<'gc>> {
let a = object
.get_property(&Multiname::public("a"), activation)?
.get_public_property("a", activation)?
.coerce_to_number(activation)? as f32;
let b = object
.get_property(&Multiname::public("b"), activation)?
.get_public_property("b", activation)?
.coerce_to_number(activation)? as f32;
let c = object
.get_property(&Multiname::public("c"), activation)?
.get_public_property("c", activation)?
.coerce_to_number(activation)? as f32;
let d = object
.get_property(&Multiname::public("d"), activation)?
.get_public_property("d", activation)?
.coerce_to_number(activation)? as f32;
let tx = Twips::from_pixels(
object
.get_property(&Multiname::public("tx"), activation)?
.get_public_property("tx", activation)?
.coerce_to_number(activation)?,
);
let ty = Twips::from_pixels(
object
.get_property(&Multiname::public("ty"), activation)?
.get_public_property("ty", activation)?
.coerce_to_number(activation)?,
);

View File

@ -13,7 +13,7 @@ use crate::backend::navigator::Request;
use crate::character::Character;
use crate::display_object::SoundTransform;
use crate::{avm2_stub_constructor, avm2_stub_getter, avm2_stub_method};
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
use swf::{SoundEvent, SoundInfo};
/// Implements `flash.media.Sound`'s instance constructor.
@ -221,7 +221,7 @@ pub fn load<'gc>(
};
let url = url_request
.get_property(&Multiname::public("url"), activation)?
.get_public_property("url", activation)?
.coerce_to_string(activation)?;
// TODO: context parameter currently unused.
@ -266,11 +266,12 @@ pub fn load_pcm_from_byte_array<'gc>(
}
/// Construct `Sound`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::package("flash.media"), "Sound"),
QName::new(Namespace::package("flash.media", mc), "Sound"),
Some(Multiname::new(
Namespace::package("flash.events"),
Namespace::package("flash.events", mc),
"EventDispatcher",
)),
Method::from_builtin(instance_init, "<Sound instance initializer>", mc),
@ -295,7 +296,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("url", Some(url), None),
("length", Some(length), None),
];
write.define_public_builtin_instance_properties(mc, PUBLIC_INSTANCE_PROPERTIES);
write.define_builtin_instance_properties(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_PROPERTIES,
);
const PUBLIC_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] = &[
("play", play),
@ -308,7 +313,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
),
("loadPCMFromByteArray", load_pcm_from_byte_array),
];
write.define_public_builtin_instance_methods(mc, PUBLIC_INSTANCE_METHODS);
write.define_builtin_instance_methods(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_METHODS,
);
class
}

View File

@ -10,7 +10,7 @@ use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::avm2::QName;
use crate::display_object::SoundTransform;
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
/// Implements `flash.media.SoundChannel`'s instance constructor.
pub fn instance_init<'gc>(
@ -131,11 +131,12 @@ pub fn stop<'gc>(
}
/// Construct `SoundChannel`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::package("flash.media"), "SoundChannel"),
QName::new(Namespace::package("flash.media", mc), "SoundChannel"),
Some(Multiname::new(
Namespace::package("flash.events"),
Namespace::package("flash.events", mc),
"EventDispatcher",
)),
Method::from_builtin(instance_init, "<SoundChannel instance initializer>", mc),
@ -162,10 +163,18 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
Some(set_sound_transform),
),
];
write.define_public_builtin_instance_properties(mc, PUBLIC_INSTANCE_PROPERTIES);
write.define_builtin_instance_properties(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_PROPERTIES,
);
const PUBLIC_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] = &[("stop", stop)];
write.define_public_builtin_instance_methods(mc, PUBLIC_INSTANCE_METHODS);
write.define_builtin_instance_methods(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_METHODS,
);
class
}

View File

@ -15,7 +15,7 @@ use crate::avm2::Namespace;
use crate::avm2::QName;
use crate::avm2_stub_getter;
use crate::display_object::SoundTransform;
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
/// Implements `flash.media.SoundMixer`'s instance constructor.
pub fn instance_init<'gc>(
@ -218,10 +218,11 @@ pub fn compute_spectrum<'gc>(
}
/// Construct `SoundMixer`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::package("flash.media"), "SoundMixer"),
Some(Multiname::public("Object")),
QName::new(Namespace::package("flash.media", mc), "SoundMixer"),
Some(Multiname::new(activation.avm2().public_namespace, "Object")),
Method::from_builtin(instance_init, "<SoundMixer instance initializer>", mc),
Method::from_builtin(class_init, "<SoundMixer class initializer>", mc),
mc,
@ -240,14 +241,22 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
),
("bufferTime", Some(buffer_time), Some(set_buffer_time)),
];
write.define_public_builtin_class_properties(mc, PUBLIC_CLASS_PROPERTIES);
write.define_builtin_class_properties(
mc,
activation.avm2().public_namespace,
PUBLIC_CLASS_PROPERTIES,
);
const PUBLIC_CLASS_METHODS: &[(&str, NativeMethodImpl)] = &[
("stopAll", stop_all),
("areSoundsInaccessible", are_sounds_inaccessible),
("computeSpectrum", compute_spectrum),
];
write.define_public_builtin_class_methods(mc, PUBLIC_CLASS_METHODS);
write.define_builtin_class_methods(
mc,
activation.avm2().public_namespace,
PUBLIC_CLASS_METHODS,
);
class
}

View File

@ -9,7 +9,7 @@ use crate::avm2::Error;
use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::avm2::QName;
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
/// Implements `flash.media.SoundTransform`'s instance constructor.
pub fn instance_init<'gc>(
@ -31,8 +31,8 @@ pub fn instance_init<'gc>(
.unwrap_or_else(|| 0.0.into())
.coerce_to_number(activation)?;
this.set_property(&Multiname::public("volume"), volume.into(), activation)?;
this.set_property(&Multiname::public("pan"), pan.into(), activation)?;
this.set_public_property("volume", volume.into(), activation)?;
this.set_public_property("pan", pan.into(), activation)?;
}
Ok(Value::Undefined)
@ -55,10 +55,10 @@ pub fn pan<'gc>(
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(this) = this {
let left_to_right = this
.get_property(&Multiname::public("leftToRight"), activation)?
.get_public_property("leftToRight", activation)?
.coerce_to_number(activation)?;
let right_to_left = this
.get_property(&Multiname::public("rightToLeft"), activation)?
.get_public_property("rightToLeft", activation)?
.coerce_to_number(activation)?;
if left_to_right != 0.0 || right_to_left != 0.0 {
@ -66,7 +66,7 @@ pub fn pan<'gc>(
}
let left_to_left = this
.get_property(&Multiname::public("leftToLeft"), activation)?
.get_public_property("leftToLeft", activation)?
.coerce_to_number(activation)?;
return Ok((1.0 - left_to_left.powf(2.0).abs()).into());
@ -88,28 +88,21 @@ pub fn set_pan<'gc>(
.unwrap_or(Value::Undefined)
.coerce_to_number(activation)?;
this.set_property(
&Multiname::public("leftToLeft"),
(1.0 - pan).sqrt().into(),
activation,
)?;
this.set_property(
&Multiname::public("rightToRight"),
(1.0 + pan).sqrt().into(),
activation,
)?;
this.set_property(&Multiname::public("leftToRight"), (0.0).into(), activation)?;
this.set_property(&Multiname::public("rightToLeft"), (0.0).into(), activation)?;
this.set_public_property("leftToLeft", (1.0 - pan).sqrt().into(), activation)?;
this.set_public_property("rightToRight", (1.0 + pan).sqrt().into(), activation)?;
this.set_public_property("leftToRight", (0.0).into(), activation)?;
this.set_public_property("rightToLeft", (0.0).into(), activation)?;
}
Ok(Value::Undefined)
}
/// Construct `SoundTransform`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::package("flash.media"), "SoundTransform"),
Some(Multiname::public("Object")),
QName::new(Namespace::package("flash.media", mc), "SoundTransform"),
Some(Multiname::new(activation.avm2().public_namespace, "Object")),
Method::from_builtin(instance_init, "<SoundTransform instance initializer>", mc),
Method::from_builtin(class_init, "<SoundTransform class initializer>", mc),
mc,
@ -124,7 +117,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
Option<NativeMethodImpl>,
Option<NativeMethodImpl>,
)] = &[("pan", Some(pan), Some(set_pan))];
write.define_public_builtin_instance_properties(mc, PUBLIC_INSTANCE_PROPERTIES);
write.define_builtin_instance_properties(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_PROPERTIES,
);
const PUBLIC_INSTANCE_SLOTS: &[(&str, Option<f64>)] = &[
("leftToLeft", None),
@ -133,7 +130,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("rightToRight", None),
("volume", None),
];
write.define_public_slot_number_instance_traits(PUBLIC_INSTANCE_SLOTS);
write.define_slot_number_instance_traits(
activation.avm2().public_namespace,
PUBLIC_INSTANCE_SLOTS,
activation,
);
class
}

View File

@ -9,7 +9,7 @@ use crate::avm2::Error;
use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::avm2::QName;
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
/// Implements `flash.media.Video`'s instance constructor.
pub fn instance_init<'gc>(
@ -34,11 +34,12 @@ pub fn class_init<'gc>(
}
/// Construct `Video`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::package("flash.media"), "Video"),
QName::new(Namespace::package("flash.media", mc), "Video"),
Some(Multiname::new(
Namespace::package("flash.display"),
Namespace::package("flash.display", mc),
"DisplayObject",
)),
Method::from_builtin(instance_init, "<Video instance initializer>", mc),

View File

@ -1,7 +1,7 @@
//! `flash.net` namespace
use crate::avm2::object::TObject;
use crate::avm2::{Activation, Error, Multiname, Object, Value};
use crate::avm2::{Activation, Error, Object, Value};
pub mod object_encoding;
pub mod shared_object;
@ -24,7 +24,7 @@ pub fn navigate_to_url<'gc>(
.coerce_to_string(activation)?;
let url = request
.get_property(&Multiname::public("url"), activation)?
.get_public_property("url", activation)?
.coerce_to_string(activation)?;
activation

View File

@ -141,7 +141,10 @@ pub fn get_local<'gc>(
let mut this = sharedobject_cls.construct(activation, &[])?;
// Set the internal name
let ruffle_name = Multiname::new(Namespace::Namespace("__ruffle__".into()), "_ruffleName");
let ruffle_name = Multiname::new(
Namespace::package("__ruffle__", activation.context.gc_context),
"_ruffleName",
);
this.set_property(
&ruffle_name,
AvmString::new_utf8(activation.context.gc_context, &full_name).into(),
@ -167,7 +170,7 @@ pub fn get_local<'gc>(
.into();
}
this.set_property(&Multiname::public("data"), data, activation)?;
this.set_public_property("data", data, activation)?;
activation
.context
.avm2_shared_objects
@ -183,10 +186,13 @@ pub fn flush<'gc>(
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(this) = this {
let data = this
.get_property(&Multiname::public("data"), activation)?
.get_public_property("data", activation)?
.coerce_to_object(activation)?;
let ruffle_name = Multiname::new(Namespace::Namespace("__ruffle__".into()), "_ruffleName");
let ruffle_name = Multiname::new(
Namespace::package("__ruffle__", activation.context.gc_context),
"_ruffleName",
);
let name = this
.get_property(&ruffle_name, activation)?
.coerce_to_string(activation)?;

View File

@ -3,7 +3,6 @@
use crate::avm2::activation::Activation;
use crate::avm2::object::TObject;
use crate::avm2::value::Value;
use crate::avm2::Multiname;
use crate::avm2::{Error, Object};
use crate::avm2_stub_method;
use crate::backend::navigator::{NavigationMethod, Request};
@ -23,7 +22,7 @@ pub fn load<'gc>(
};
let data_format = this
.get_property(&Multiname::public("dataFormat"), activation)?
.get_public_property("dataFormat", activation)?
.coerce_to_string(activation)?;
let data_format = if &data_format == b"binary" {
@ -48,11 +47,11 @@ fn spawn_fetch<'gc>(
data_format: DataFormat,
) -> Result<Value<'gc>, Error<'gc>> {
let url = url_request
.get_property(&Multiname::public("url"), activation)?
.get_public_property("url", activation)?
.coerce_to_string(activation)?;
let method_str = url_request
.get_property(&Multiname::public("method"), activation)?
.get_public_property("method", activation)?
.coerce_to_string(activation)?;
let method = NavigationMethod::from_method_str(&method_str).unwrap_or_else(|| {
@ -61,10 +60,10 @@ fn spawn_fetch<'gc>(
});
let content_type = url_request
.get_property(&Multiname::public("contentType"), activation)?
.get_public_property("contentType", activation)?
.coerce_to_string(activation)?;
let data = url_request.get_property(&Multiname::public("data"), activation)?;
let data = url_request.get_public_property("data", activation)?;
let data = if let Value::Null = data {
None
@ -80,7 +79,7 @@ fn spawn_fetch<'gc>(
if data.is_of_type(activation.avm2().classes().urlvariables, activation) {
if &*content_type == b"application/x-www-form-urlencoded" {
let data = data
.call_property(&Multiname::public("toString"), &[], activation)?
.call_public_property("toString", &[], activation)?
.coerce_to_string(activation)?
.to_string()
.into_bytes();

View File

@ -9,7 +9,7 @@ use crate::avm2::Error;
use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::avm2::QName;
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
/// Implements `flash.system.ApplicationDomain`'s instance constructor.
pub fn instance_init<'gc>(
@ -71,7 +71,7 @@ pub fn get_definition<'gc>(
.cloned()
.unwrap_or_else(|| "".into())
.coerce_to_string(activation)?;
let name = QName::from_qualified_name(name, activation.context.gc_context);
let name = QName::from_qualified_name(name, activation);
let (qname, mut defined_script) = match appdomain.get_defining_script(&name.into())? {
Some(data) => data,
None => {
@ -107,7 +107,7 @@ pub fn has_definition<'gc>(
.unwrap_or_else(|| "".into())
.coerce_to_string(activation)?;
let qname = QName::from_qualified_name(name, activation.context.gc_context);
let qname = QName::from_qualified_name(name, activation);
return Ok(appdomain.has_definition(qname).into());
}
@ -147,10 +147,11 @@ pub fn domain_memory<'gc>(
}
/// Construct `ApplicationDomain`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::package("flash.system"), "ApplicationDomain"),
Some(Multiname::public("Object")),
QName::new(Namespace::package("flash.system", mc), "ApplicationDomain"),
Some(Multiname::new(activation.avm2().public_namespace, "Object")),
Method::from_builtin(
instance_init,
"<ApplicationDomain instance initializer>",
@ -165,7 +166,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
const PUBLIC_CLASS_PROPERTIES: &[(&str, Option<NativeMethodImpl>, Option<NativeMethodImpl>)] =
&[("currentDomain", Some(current_domain), None)];
write.define_public_builtin_class_properties(mc, PUBLIC_CLASS_PROPERTIES);
write.define_builtin_class_properties(
mc,
activation.avm2().public_namespace,
PUBLIC_CLASS_PROPERTIES,
);
const PUBLIC_INSTANCE_PROPERTIES: &[(
&str,
@ -175,13 +180,21 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("domainMemory", Some(domain_memory), Some(set_domain_memory)),
("parentDomain", Some(parent_domain), None),
];
write.define_public_builtin_instance_properties(mc, PUBLIC_INSTANCE_PROPERTIES);
write.define_builtin_instance_properties(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_PROPERTIES,
);
const PUBLIC_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] = &[
("getDefinition", get_definition),
("hasDefinition", has_definition),
];
write.define_public_builtin_instance_methods(mc, PUBLIC_INSTANCE_METHODS);
write.define_builtin_instance_methods(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_METHODS,
);
class
}

View File

@ -12,7 +12,7 @@ use crate::avm2::{ArrayObject, ArrayStorage, Error};
use crate::avm2_stub_getter;
use crate::character::Character;
use crate::string::AvmString;
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
/// Implements `flash.text.Font`'s instance constructor.
pub fn instance_init<'gc>(
@ -177,10 +177,11 @@ pub fn register_font<'gc>(
}
/// Construct `Font`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::package("flash.text"), "Font"),
Some(Multiname::public("Object")),
QName::new(Namespace::package("flash.text", mc), "Font"),
Some(Multiname::new(activation.avm2().public_namespace, "Object")),
Method::from_builtin(instance_init, "<Font instance initializer>", mc),
Method::from_builtin(class_init, "<Font class initializer>", mc),
mc,
@ -199,16 +200,28 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("fontStyle", Some(font_style), None),
("fontType", Some(font_type), None),
];
write.define_public_builtin_instance_properties(mc, PUBLIC_INSTANCE_PROPERTIES);
write.define_builtin_instance_properties(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_PROPERTIES,
);
const PUBLIC_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] = &[("hasGlyphs", has_glyphs)];
write.define_public_builtin_instance_methods(mc, PUBLIC_INSTANCE_METHODS);
write.define_builtin_instance_methods(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_METHODS,
);
const PUBLIC_CLASS_METHODS: &[(&str, NativeMethodImpl)] = &[
("enumerateFonts", enumerate_fonts),
("registerFont", register_font),
];
write.define_public_builtin_class_methods(mc, PUBLIC_CLASS_METHODS);
write.define_builtin_class_methods(
mc,
activation.avm2().public_namespace,
PUBLIC_CLASS_METHODS,
);
class
}

View File

@ -14,7 +14,7 @@ use crate::html::TextFormat;
use crate::string::AvmString;
use crate::tag_utils::SwfMovie;
use crate::{avm2_stub_getter, avm2_stub_setter};
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
use std::sync::Arc;
use swf::Color;
@ -1296,11 +1296,12 @@ pub fn set_restrict<'gc>(
}
/// Construct `TextField`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::package("flash.text"), "TextField"),
QName::new(Namespace::package("flash.text", mc), "TextField"),
Some(Multiname::new(
Namespace::package("flash.display"),
Namespace::package("flash.display", mc),
"InteractiveObject",
)),
Method::from_builtin(instance_init, "<TextField instance initializer>", mc),
@ -1364,7 +1365,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("sharpness", Some(sharpness), Some(set_sharpness)),
("numLines", Some(num_lines), None),
];
write.define_public_builtin_instance_properties(mc, PUBLIC_INSTANCE_PROPERTIES);
write.define_builtin_instance_properties(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_PROPERTIES,
);
const PUBLIC_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] = &[
("appendText", append_text),
@ -1375,7 +1380,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("setTextFormat", set_text_format),
("getLineMetrics", get_line_metrics),
];
write.define_public_builtin_instance_methods(mc, PUBLIC_INSTANCE_METHODS);
write.define_builtin_instance_methods(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_METHODS,
);
class
}

View File

@ -12,7 +12,7 @@ use crate::avm2::QName;
use crate::ecma_conversions::round_to_even;
use crate::html::TextFormat;
use crate::string::{AvmString, WStr};
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
/// Implements `flash.text.TextFormat`'s instance constructor.
pub fn instance_init<'gc>(
@ -489,11 +489,8 @@ fn set_tab_stops<'gc>(
let tab_stops: Result<Vec<_>, Error<'gc>> = (0..length)
.map(|i| {
let element = object.get_property(
&Multiname::public(AvmString::new_utf8(
activation.context.gc_context,
i.to_string(),
)),
let element = object.get_public_property(
AvmString::new_utf8(activation.context.gc_context, i.to_string()),
activation,
)?;
Ok(round_to_even(element.coerce_to_number(activation)?).into())
@ -570,10 +567,11 @@ fn set_url<'gc>(
}
/// Construct `TextFormat`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::package("flash.text"), "TextFormat"),
Some(Multiname::public("Object")),
QName::new(Namespace::package("flash.text", mc), "TextFormat"),
Some(Multiname::new(activation.avm2().public_namespace, "Object")),
Method::from_builtin(instance_init, "<TextFormat instance initializer>", mc),
Method::from_builtin(class_init, "<TextFormat class initializer>", mc),
mc,
@ -640,7 +638,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
),
("url", Some(getter!(url)), Some(setter!(set_url))),
];
write.define_public_builtin_instance_properties(mc, PUBLIC_INSTANCE_PROPERTIES);
write.define_builtin_instance_properties(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_PROPERTIES,
);
class
}

View File

@ -1,5 +1,4 @@
use crate::avm2::activation::Activation;
use crate::avm2::multiname::Multiname;
use crate::avm2::object::{Object, TObject};
use crate::avm2::value::Value;
use crate::avm2::Error;
@ -11,26 +10,16 @@ pub fn hide_built_in_items<'gc>(
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(this) = this {
if let Value::Object(mut items) =
this.get_property(&Multiname::public("builtInItems"), activation)?
{
if let Value::Object(mut items) = this.get_public_property("builtInItems", activation)? {
// items is a ContextMenuBuiltInItems
items.set_property(
&Multiname::public("forwardAndBack"),
Value::Bool(false),
activation,
)?;
items.set_property(&Multiname::public("loop"), Value::Bool(false), activation)?;
items.set_property(&Multiname::public("play"), Value::Bool(false), activation)?;
items.set_property(&Multiname::public("print"), Value::Bool(false), activation)?;
items.set_property(
&Multiname::public("quality"),
Value::Bool(false),
activation,
)?;
items.set_property(&Multiname::public("rewind"), Value::Bool(false), activation)?;
items.set_property(&Multiname::public("save"), Value::Bool(false), activation)?;
items.set_property(&Multiname::public("zoom"), Value::Bool(false), activation)?;
items.set_public_property("forwardAndBack", Value::Bool(false), activation)?;
items.set_public_property("loop", Value::Bool(false), activation)?;
items.set_public_property("play", Value::Bool(false), activation)?;
items.set_public_property("print", Value::Bool(false), activation)?;
items.set_public_property("quality", Value::Bool(false), activation)?;
items.set_public_property("rewind", Value::Bool(false), activation)?;
items.set_public_property("save", Value::Bool(false), activation)?;
items.set_public_property("zoom", Value::Bool(false), activation)?;
}
}
@ -46,7 +35,7 @@ pub fn make_context_menu_state<'gc>(
macro_rules! check_bool {
( $obj:expr, $name:expr, $value:expr ) => {
matches!(
$obj.get_property(&Multiname::public($name), activation),
$obj.get_public_property($name, activation),
Ok(Value::Bool($value))
)
};
@ -54,9 +43,7 @@ pub fn make_context_menu_state<'gc>(
let mut builtin_items = context_menu::BuiltInItemFlags::for_stage(activation.context.stage);
if let Some(menu) = menu {
if let Ok(Value::Object(builtins)) =
menu.get_property(&Multiname::public("builtInItems"), activation)
{
if let Ok(Value::Object(builtins)) = menu.get_public_property("builtInItems", activation) {
if check_bool!(builtins, "zoom", false) {
builtin_items.zoom = false;
}
@ -84,8 +71,7 @@ pub fn make_context_menu_state<'gc>(
result.build_builtin_items(builtin_items, activation.context.stage);
if let Some(menu) = menu {
if let Ok(Value::Object(custom_items)) =
menu.get_property(&Multiname::public("customItems"), activation)
if let Ok(Value::Object(custom_items)) = menu.get_public_property("customItems", activation)
{
// note: this borrows the array, but it shouldn't be possible for
// AS to get invoked here and cause BorrowMutError
@ -94,7 +80,7 @@ pub fn make_context_menu_state<'gc>(
// this is a CustomMenuItem
if let Some(Value::Object(item)) = item {
let caption = if let Ok(Value::String(s)) =
item.get_property(&Multiname::public("caption"), activation)
item.get_public_property("caption", activation)
{
s
} else {

View File

@ -13,9 +13,6 @@ pub mod dictionary;
pub mod proxy;
pub mod timer;
/// `flash.utils.flash_proxy` namespace
pub const NS_FLASH_PROXY: &str = "http://www.adobe.com/2006/actionscript/flash/proxy";
/// Implements `flash.utils.getTimer`
pub fn get_timer<'gc>(
activation: &mut Activation<'_, 'gc>,
@ -260,6 +257,6 @@ pub fn get_definition_by_name<'gc>(
.get(0)
.unwrap_or(&Value::Undefined)
.coerce_to_string(activation)?;
let qname = QName::from_qualified_name(name, activation.context.gc_context);
let qname = QName::from_qualified_name(name, activation);
appdomain.get_defined_value(activation, qname)
}

View File

@ -4,7 +4,6 @@ use crate::avm2::activation::Activation;
use crate::avm2::object::TObject;
use crate::avm2::value::Value;
use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::avm2::{Error, Object};
use crate::timer::TimerCallback;
@ -17,7 +16,7 @@ pub fn stop<'gc>(
let mut this = this.expect("`this` should be set in native method!");
let id = this
.get_property(
&Multiname::new(Namespace::Private("".into()), "_timerId"),
&Multiname::new(activation.avm2().ruffle_private_namespace, "_timerId"),
activation,
)
.unwrap()
@ -26,7 +25,7 @@ pub fn stop<'gc>(
if id != -1 {
activation.context.timers.remove(id);
this.set_property(
&Multiname::new(Namespace::Private("".into()), "_timerId"),
&Multiname::new(activation.avm2().ruffle_private_namespace, "_timerId"),
(-1).into(),
activation,
)?;
@ -44,7 +43,7 @@ pub fn start<'gc>(
let mut this = this.expect("`this` should be set in native method!");
let id = this
.get_property(
&Multiname::new(Namespace::Private("".into()), "_timerId"),
&Multiname::new(activation.avm2().ruffle_private_namespace, "_timerId"),
activation,
)
.unwrap()
@ -52,7 +51,7 @@ pub fn start<'gc>(
let delay = this
.get_property(
&Multiname::new(Namespace::Private("".into()), "_delay"),
&Multiname::new(activation.avm2().ruffle_private_namespace, "_delay"),
activation,
)
.unwrap()
@ -61,7 +60,7 @@ pub fn start<'gc>(
if id == -1 {
let on_update = this
.get_property(
&Multiname::new(Namespace::Private("".into()), "onUpdate"),
&Multiname::new(activation.avm2().ruffle_private_namespace, "onUpdate"),
activation,
)?
.coerce_to_object(activation)?;
@ -74,7 +73,7 @@ pub fn start<'gc>(
false,
);
this.set_property(
&Multiname::new(Namespace::Private("".into()), "_timerId"),
&Multiname::new(activation.avm2().ruffle_private_namespace, "_timerId"),
id.into(),
activation,
)?;

View File

@ -8,9 +8,8 @@ use crate::avm2::object::{function_allocator, FunctionObject, Object, TObject};
use crate::avm2::value::Value;
use crate::avm2::Error;
use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::avm2::QName;
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
/// Implements `Function`'s instance initializer.
pub fn instance_init<'gc>(
@ -36,8 +35,8 @@ pub fn class_init<'gc>(
let this_class = this.as_class_object().unwrap();
let function_proto = this_class.prototype();
function_proto.set_property_local(
&Multiname::public("call"),
function_proto.set_string_property_local(
"call",
FunctionObject::from_method(
activation,
Method::from_builtin(call, "call", activation.context.gc_context),
@ -48,8 +47,8 @@ pub fn class_init<'gc>(
.into(),
activation,
)?;
function_proto.set_property_local(
&Multiname::public("apply"),
function_proto.set_string_property_local(
"apply",
FunctionObject::from_method(
activation,
Method::from_builtin(apply, "apply", activation.context.gc_context),
@ -181,10 +180,11 @@ fn set_prototype<'gc>(
}
/// Construct `Function`'s class.
pub fn create_class<'gc>(gc_context: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let gc_context = activation.context.gc_context;
let function_class = Class::new(
QName::new(Namespace::public(), "Function"),
Some(Multiname::public("Object")),
QName::new(activation.avm2().public_namespace, "Function"),
Some(Multiname::new(activation.avm2().public_namespace, "Object")),
Method::from_builtin(instance_init, "<Function instance initializer>", gc_context),
Method::from_builtin(class_init, "<Function class initializer>", gc_context),
gc_context,
@ -194,7 +194,11 @@ pub fn create_class<'gc>(gc_context: MutationContext<'gc, '_>) -> GcCell<'gc, Cl
// Fixed traits (in AS3 namespace)
const AS3_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] = &[("call", call), ("apply", apply)];
write.define_as3_builtin_instance_methods(gc_context, AS3_INSTANCE_METHODS);
write.define_builtin_instance_methods(
gc_context,
activation.avm2().as3_namespace,
AS3_INSTANCE_METHODS,
);
const PUBLIC_INSTANCE_PROPERTIES: &[(
&str,
@ -204,7 +208,11 @@ pub fn create_class<'gc>(gc_context: MutationContext<'gc, '_>) -> GcCell<'gc, Cl
("prototype", Some(prototype), Some(set_prototype)),
("length", Some(length), None),
];
write.define_public_builtin_instance_properties(gc_context, PUBLIC_INSTANCE_PROPERTIES);
write.define_builtin_instance_properties(
gc_context,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_PROPERTIES,
);
write.set_instance_allocator(function_allocator);

View File

@ -11,9 +11,8 @@ use crate::avm2::object::Object;
use crate::avm2::value::Value;
use crate::avm2::Error;
use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::avm2::QName;
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
/// Implements `global`'s instance constructor.
pub fn instance_init<'gc>(
@ -34,10 +33,11 @@ pub fn class_init<'gc>(
}
/// Construct `global`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
Class::new(
QName::new(Namespace::public(), "global"),
Some(Multiname::public("Object")),
QName::new(activation.avm2().public_namespace, "global"),
Some(Multiname::new(activation.avm2().public_namespace, "Object")),
Method::from_builtin(instance_init, "<global instance initializer>", mc),
Method::from_builtin(class_init, "<global class initializer>", mc),
mc,

View File

@ -7,10 +7,9 @@ use crate::avm2::method::{Method, NativeMethodImpl};
use crate::avm2::object::{primitive_allocator, FunctionObject, Object, TObject};
use crate::avm2::value::Value;
use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::avm2::QName;
use crate::avm2::{AvmString, Error};
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
/// Implements `int`'s instance initializer.
fn instance_init<'gc>(
@ -59,8 +58,8 @@ fn class_init<'gc>(
let this_class = this.as_class_object().unwrap();
let int_proto = this_class.prototype();
int_proto.set_property_local(
&Multiname::public("toExponential"),
int_proto.set_string_property_local(
"toExponential",
FunctionObject::from_method(
activation,
Method::from_builtin(to_exponential, "toExponential", gc_context),
@ -71,8 +70,8 @@ fn class_init<'gc>(
.into(),
activation,
)?;
int_proto.set_property_local(
&Multiname::public("toFixed"),
int_proto.set_string_property_local(
"toFixed",
FunctionObject::from_method(
activation,
Method::from_builtin(to_fixed, "toFixed", gc_context),
@ -83,8 +82,8 @@ fn class_init<'gc>(
.into(),
activation,
)?;
int_proto.set_property_local(
&Multiname::public("toPrecision"),
int_proto.set_string_property_local(
"toPrecision",
FunctionObject::from_method(
activation,
Method::from_builtin(to_precision, "toPrecision", gc_context),
@ -95,8 +94,8 @@ fn class_init<'gc>(
.into(),
activation,
)?;
int_proto.set_property_local(
&Multiname::public("toString"),
int_proto.set_string_property_local(
"toString",
FunctionObject::from_method(
activation,
Method::from_builtin(to_string, "toString", gc_context),
@ -107,8 +106,8 @@ fn class_init<'gc>(
.into(),
activation,
)?;
int_proto.set_property_local(
&Multiname::public("valueOf"),
int_proto.set_string_property_local(
"valueOf",
FunctionObject::from_method(
activation,
Method::from_builtin(value_of, "valueOf", gc_context),
@ -265,10 +264,11 @@ fn value_of<'gc>(
}
/// Construct `int`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::public(), "int"),
Some(Multiname::public("Object")),
QName::new(activation.avm2().public_namespace, "int"),
Some(Multiname::new(activation.avm2().public_namespace, "Object")),
Method::from_builtin(instance_init, "<int instance initializer>", mc),
Method::from_builtin(class_init, "<int class initializer>", mc),
mc,
@ -284,7 +284,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
));
const CLASS_CONSTANTS: &[(&str, i32)] = &[("MAX_VALUE", i32::MAX), ("MIN_VALUE", i32::MIN)];
write.define_public_constant_int_class_traits(CLASS_CONSTANTS);
write.define_constant_int_class_traits(
activation.avm2().public_namespace,
CLASS_CONSTANTS,
activation,
);
const AS3_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] = &[
("toExponential", to_exponential),
@ -293,7 +297,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("toString", to_string),
("valueOf", value_of),
];
write.define_as3_builtin_instance_methods(mc, AS3_INSTANCE_METHODS);
write.define_builtin_instance_methods(
mc,
activation.avm2().as3_namespace,
AS3_INSTANCE_METHODS,
);
class
}

View File

@ -6,7 +6,6 @@ use crate::avm2::globals::array::ArrayIter;
use crate::avm2::object::{ArrayObject, FunctionObject, Object, TObject};
use crate::avm2::value::Value;
use crate::avm2::Error;
use crate::avm2::Multiname;
use crate::ecma_conversions::f64_to_wrapping_i32;
use crate::string::{AvmString, Units};
use serde::Serialize;
@ -42,9 +41,9 @@ fn deserialize_json_inner<'gc>(
Some(reviver) => reviver.call(None, &[key.into(), val], activation)?,
};
if matches!(mapped_val, Value::Undefined) {
obj.delete_property(activation, &Multiname::public(key))?;
obj.delete_public_property(activation, key)?;
} else {
obj.set_property(&Multiname::public(key), mapped_val, activation)?;
obj.set_public_property(key, mapped_val, activation)?;
}
}
obj.into()
@ -119,7 +118,7 @@ impl<'gc> AvmSerializer<'gc> {
} else {
let obj = value.as_object().unwrap();
let to_json = obj
.get_property(&Multiname::public("toJSON"), activation)?
.get_public_property("toJSON", activation)?
.as_object()
.and_then(|obj| obj.as_function_object());
if let Some(to_json) = to_json {
@ -152,7 +151,7 @@ impl<'gc> AvmSerializer<'gc> {
while let Some(r) = iter.next(activation) {
let item = r?.1;
let key = item.coerce_to_string(activation)?;
let value = obj.get_property(&Multiname::public(key), activation)?;
let value = obj.get_public_property(key, activation)?;
let mapped = self.map_value(activation, || key, value)?;
if !matches!(mapped, Value::Undefined) {
js_obj.insert(
@ -168,7 +167,7 @@ impl<'gc> AvmSerializer<'gc> {
Value::Undefined => break,
name_val => {
let name = name_val.coerce_to_string(activation)?;
let value = obj.get_property(&Multiname::public(name), activation)?;
let value = obj.get_public_property(name, activation)?;
let mapped = self.map_value(activation, || name, value)?;
if !matches!(mapped, Value::Undefined) {
js_obj.insert(

View File

@ -7,10 +7,9 @@ use crate::avm2::object::{namespace_allocator, Object};
use crate::avm2::value::Value;
use crate::avm2::Error;
use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::avm2::QName;
use crate::avm2_stub_constructor;
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
/// Implements `Namespace`'s instance initializer.
pub fn instance_init<'gc>(
@ -54,10 +53,11 @@ pub fn class_init<'gc>(
}
/// Construct `Namespace`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::public(), "Namespace"),
Some(Multiname::public("Object")),
QName::new(activation.avm2().public_namespace, "Namespace"),
Some(Multiname::new(activation.avm2().public_namespace, "Object")),
Method::from_builtin(instance_init, "<Namespace instance initializer>", mc),
Method::from_builtin(class_init, "<Namespace class initializer>", mc),
mc,

View File

@ -6,10 +6,9 @@ use crate::avm2::method::{Method, NativeMethodImpl};
use crate::avm2::object::{primitive_allocator, FunctionObject, Object, TObject};
use crate::avm2::value::Value;
use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::avm2::QName;
use crate::avm2::{AvmString, Error};
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
/// Implements `Number`'s instance initializer.
fn instance_init<'gc>(
@ -58,8 +57,8 @@ fn class_init<'gc>(
let this_class = this.as_class_object().unwrap();
let number_proto = this_class.prototype();
number_proto.set_property_local(
&Multiname::public("toExponential"),
number_proto.set_string_property_local(
"toExponential",
FunctionObject::from_method(
activation,
Method::from_builtin(to_exponential, "toExponential", gc_context),
@ -70,8 +69,8 @@ fn class_init<'gc>(
.into(),
activation,
)?;
number_proto.set_property_local(
&Multiname::public("toFixed"),
number_proto.set_string_property_local(
"toFixed",
FunctionObject::from_method(
activation,
Method::from_builtin(to_fixed, "toFixed", gc_context),
@ -82,8 +81,8 @@ fn class_init<'gc>(
.into(),
activation,
)?;
number_proto.set_property_local(
&Multiname::public("toPrecision"),
number_proto.set_string_property_local(
"toPrecision",
FunctionObject::from_method(
activation,
Method::from_builtin(to_precision, "toPrecision", gc_context),
@ -94,8 +93,8 @@ fn class_init<'gc>(
.into(),
activation,
)?;
number_proto.set_property_local(
&Multiname::public("toString"),
number_proto.set_string_property_local(
"toString",
FunctionObject::from_method(
activation,
Method::from_builtin(to_string, "toString", gc_context),
@ -106,8 +105,8 @@ fn class_init<'gc>(
.into(),
activation,
)?;
number_proto.set_property_local(
&Multiname::public("valueOf"),
number_proto.set_string_property_local(
"valueOf",
FunctionObject::from_method(
activation,
Method::from_builtin(value_of, "valueOf", gc_context),
@ -351,10 +350,11 @@ fn value_of<'gc>(
}
/// Construct `Number`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::public(), "Number"),
Some(Multiname::public("Object")),
QName::new(activation.avm2().public_namespace, "Number"),
Some(Multiname::new(activation.avm2().public_namespace, "Object")),
Method::from_builtin(instance_init, "<Number instance initializer>", mc),
Method::from_builtin(class_init, "<Number class initializer>", mc),
mc,
@ -376,11 +376,19 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("NEGATIVE_INFINITY", f64::NEG_INFINITY),
("POSITIVE_INFINITY", f64::INFINITY),
];
write.define_public_constant_number_class_traits(CLASS_CONSTANTS);
write.define_constant_number_class_traits(
activation.avm2().public_namespace,
CLASS_CONSTANTS,
activation,
);
const PUBLIC_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] =
&[("toLocaleString", to_locale_string)];
write.define_public_builtin_instance_methods(mc, PUBLIC_INSTANCE_METHODS);
write.define_builtin_instance_methods(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_METHODS,
);
const AS3_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] = &[
("toExponential", to_exponential),
@ -389,7 +397,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("toString", to_string),
("valueOf", value_of),
];
write.define_as3_builtin_instance_methods(mc, AS3_INSTANCE_METHODS);
write.define_builtin_instance_methods(
mc,
activation.avm2().as3_namespace,
AS3_INSTANCE_METHODS,
);
class
}

View File

@ -8,9 +8,8 @@ use crate::avm2::traits::Trait;
use crate::avm2::value::Value;
use crate::avm2::Error;
use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::avm2::QName;
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
/// Implements `Object`'s instance initializer.
pub fn instance_init<'gc>(
@ -50,8 +49,8 @@ pub fn class_init<'gc>(
let this_class = this.as_class_object().unwrap();
let object_proto = this_class.prototype();
object_proto.set_property_local(
&Multiname::public("hasOwnProperty"),
object_proto.set_string_property_local(
"hasOwnProperty",
FunctionObject::from_method(
activation,
Method::from_builtin(has_own_property, "hasOwnProperty", gc_context),
@ -62,8 +61,8 @@ pub fn class_init<'gc>(
.into(),
activation,
)?;
object_proto.set_property_local(
&Multiname::public("propertyIsEnumerable"),
object_proto.set_string_property_local(
"propertyIsEnumerable",
FunctionObject::from_method(
activation,
Method::from_builtin(property_is_enumerable, "propertyIsEnumerable", gc_context),
@ -74,8 +73,8 @@ pub fn class_init<'gc>(
.into(),
activation,
)?;
object_proto.set_property_local(
&Multiname::public("setPropertyIsEnumerable"),
object_proto.set_string_property_local(
"setPropertyIsEnumerable",
FunctionObject::from_method(
activation,
Method::from_builtin(
@ -90,8 +89,8 @@ pub fn class_init<'gc>(
.into(),
activation,
)?;
object_proto.set_property_local(
&Multiname::public("isPrototypeOf"),
object_proto.set_string_property_local(
"isPrototypeOf",
FunctionObject::from_method(
activation,
Method::from_builtin(is_prototype_of, "isPrototypeOf", gc_context),
@ -102,8 +101,8 @@ pub fn class_init<'gc>(
.into(),
activation,
)?;
object_proto.set_property_local(
&Multiname::public("toString"),
object_proto.set_string_property_local(
"toString",
FunctionObject::from_method(
activation,
Method::from_builtin(to_string, "toString", gc_context),
@ -114,8 +113,8 @@ pub fn class_init<'gc>(
.into(),
activation,
)?;
object_proto.set_property_local(
&Multiname::public("toLocaleString"),
object_proto.set_string_property_local(
"toLocaleString",
FunctionObject::from_method(
activation,
Method::from_builtin(to_locale_string, "toLocaleString", gc_context),
@ -126,8 +125,8 @@ pub fn class_init<'gc>(
.into(),
activation,
)?;
object_proto.set_property_local(
&Multiname::public("valueOf"),
object_proto.set_string_property_local(
"valueOf",
FunctionObject::from_method(
activation,
Method::from_builtin(value_of, "valueOf", gc_context),
@ -211,7 +210,7 @@ pub fn has_own_property<'gc>(
args.get(0).ok_or_else(|| "No name specified".into());
let name = name?.coerce_to_string(activation)?;
let multiname = Multiname::public(name);
let multiname = Multiname::new(activation.avm2().public_namespace, name);
Ok(this.has_own_property(&multiname).into())
}
@ -274,9 +273,10 @@ pub fn set_property_is_enumerable<'gc>(
}
/// Construct `Object`'s class.
pub fn create_class<'gc>(gc_context: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let gc_context = activation.context.gc_context;
let object_class = Class::new(
QName::new(Namespace::public(), "Object"),
QName::new(activation.avm2().public_namespace, "Object"),
None,
Method::from_builtin(instance_init, "<Object instance initializer>", gc_context),
Method::from_builtin(class_init, "<Object class initializer>", gc_context),
@ -290,18 +290,22 @@ pub fn create_class<'gc>(gc_context: MutationContext<'gc, '_>) -> GcCell<'gc, Cl
));
write.define_class_trait(Trait::from_const(
QName::new(Namespace::public(), "length"),
Multiname::public("int"),
QName::new(activation.avm2().public_namespace, "length"),
Multiname::new(activation.avm2().public_namespace, "int"),
None,
));
// Fixed traits (in AS3 namespace)
const PUBLIC_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] = &[
const AS3_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] = &[
("hasOwnProperty", has_own_property),
("isPrototypeOf", is_prototype_of),
("propertyIsEnumerable", property_is_enumerable),
];
write.define_as3_builtin_instance_methods(gc_context, PUBLIC_INSTANCE_METHODS);
write.define_builtin_instance_methods(
gc_context,
activation.avm2().as3_namespace,
AS3_INSTANCE_METHODS,
);
object_class
}

View File

@ -9,7 +9,7 @@ use crate::avm2::Error;
use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::avm2::QName;
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
/// Implements `QName`'s instance initializer.
pub fn instance_init<'gc>(
@ -25,8 +25,11 @@ pub fn instance_init<'gc>(
let namespace = match ns_arg {
Value::Object(o) if o.as_namespace().is_some() => *o.as_namespace().unwrap(),
Value::Undefined | Value::Null => Namespace::Any,
v => Namespace::Namespace(v.coerce_to_string(activation)?),
Value::Undefined | Value::Null => Namespace::any(activation.context.gc_context),
v => Namespace::package(
v.coerce_to_string(activation)?,
activation.context.gc_context,
),
};
(namespace, local_arg)
@ -36,7 +39,7 @@ pub fn instance_init<'gc>(
Value::Object(o) if o.as_qname_object().is_some() => {
o.as_qname_object().unwrap().qname().unwrap().namespace()
}
_ => Namespace::Namespace("".into()),
_ => activation.avm2().public_namespace,
};
(namespace, qname_arg)
@ -68,10 +71,10 @@ pub fn class_init<'gc>(
let this = this.unwrap();
let scope = activation.create_scopechain();
let this_class = this.as_class_object().unwrap();
let mut qname_proto = this_class.prototype();
let qname_proto = this_class.prototype();
qname_proto.set_property(
&Multiname::public("toString"),
qname_proto.set_string_property_local(
"toString",
FunctionObject::from_method(
activation,
Method::from_builtin(to_string, "toString", activation.context.gc_context),
@ -83,8 +86,8 @@ pub fn class_init<'gc>(
activation,
)?;
qname_proto.set_property(
&Multiname::public("valueOf"),
qname_proto.set_string_property_local(
"valueOf",
FunctionObject::from_method(
activation,
Method::from_builtin(value_of, "valueOf", activation.context.gc_context),
@ -134,7 +137,7 @@ pub fn uri<'gc>(
if let Some(this) = this.and_then(|t| t.as_qname_object()) {
if let Some(qname) = this.qname() {
return Ok(match qname.namespace() {
Namespace::Any => Value::Null,
ns if ns.is_any() => Value::Null,
ns => ns.as_uri().into(),
});
}
@ -172,10 +175,11 @@ pub fn value_of<'gc>(
}
/// Construct `QName`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::public(), "QName"),
Some(Multiname::public("Object")),
QName::new(activation.avm2().public_namespace, "QName"),
Some(Multiname::new(activation.avm2().public_namespace, "Object")),
Method::from_builtin(instance_init, "<QName instance initializer>", mc),
Method::from_builtin(class_init, "<QName class initializer>", mc),
mc,
@ -193,11 +197,19 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("localName", Some(local_name), None),
("uri", Some(uri), None),
];
write.define_public_builtin_instance_properties(mc, PUBLIC_INSTANCE_PROPERTIES);
write.define_builtin_instance_properties(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_PROPERTIES,
);
const AS3_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] =
&[("toString", to_string), ("valueOf", value_of)];
write.define_as3_builtin_instance_methods(mc, AS3_INSTANCE_METHODS);
write.define_builtin_instance_methods(
mc,
activation.avm2().as3_namespace,
AS3_INSTANCE_METHODS,
);
class
}

View File

@ -7,11 +7,10 @@ use crate::avm2::regexp::RegExpFlags;
use crate::avm2::value::Value;
use crate::avm2::Error;
use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::avm2::QName;
use crate::avm2::{activation::Activation, array::ArrayStorage};
use crate::string::{AvmString, WString};
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
/// Implements `RegExp`'s instance initializer.
pub fn instance_init<'gc>(
@ -233,13 +232,9 @@ pub fn exec<'gc>(
let object = ArrayObject::from_storage(activation, storage)?;
object.set_property_local(
&Multiname::public("index"),
Value::Number(index as f64),
activation,
)?;
object.set_string_property_local("index", Value::Number(index as f64), activation)?;
object.set_property_local(&Multiname::public("input"), text.into(), activation)?;
object.set_string_property_local("input", text.into(), activation)?;
return Ok(object.into());
}
@ -268,16 +263,25 @@ pub fn test<'gc>(
}
/// Construct `RegExp`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::public(), "RegExp"),
Some(Multiname::public("Object")),
QName::new(activation.avm2().public_namespace, "RegExp"),
Some(Multiname::new(activation.avm2().public_namespace, "Object")),
Method::from_builtin_and_params(
instance_init,
"<RegExp instance initializer>",
vec![
ParamConfig::optional("re", Multiname::public("String"), ""),
ParamConfig::optional("flags", Multiname::public("String"), ""),
ParamConfig::optional(
"re",
Multiname::new(activation.avm2().public_namespace, "String"),
"",
),
ParamConfig::optional(
"flags",
Multiname::new(activation.avm2().public_namespace, "String"),
"",
),
],
false,
mc,
@ -307,10 +311,18 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("lastIndex", Some(last_index), Some(set_last_index)),
("source", Some(source), None),
];
write.define_public_builtin_instance_properties(mc, PUBLIC_INSTANCE_PROPERTIES);
write.define_builtin_instance_properties(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_PROPERTIES,
);
const AS3_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] = &[("exec", exec), ("test", test)];
write.define_as3_builtin_instance_methods(mc, AS3_INSTANCE_METHODS);
write.define_builtin_instance_methods(
mc,
activation.avm2().as3_namespace,
AS3_INSTANCE_METHODS,
);
class
}

View File

@ -8,11 +8,10 @@ use crate::avm2::regexp::RegExpFlags;
use crate::avm2::value::Value;
use crate::avm2::Error;
use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::avm2::QName;
use crate::avm2::{ArrayObject, ArrayStorage};
use crate::string::{AvmString, WString};
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
use std::iter;
/// Implements `String`'s instance initializer.
@ -611,10 +610,11 @@ fn to_upper_case<'gc>(
}
/// Construct `String`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::public(), "String"),
Some(Multiname::public("Object")),
QName::new(activation.avm2().public_namespace, "String"),
Some(Multiname::new(activation.avm2().public_namespace, "Object")),
Method::from_builtin(instance_init, "<String instance initializer>", mc),
Method::from_builtin(class_init, "<String class initializer>", mc),
mc,
@ -629,7 +629,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
Option<NativeMethodImpl>,
Option<NativeMethodImpl>,
)] = &[("length", Some(length), None)];
write.define_public_builtin_instance_properties(mc, PUBLIC_INSTANCE_PROPERTIES);
write.define_builtin_instance_properties(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_PROPERTIES,
);
const AS3_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] = &[
("charAt", char_at),
@ -650,12 +654,20 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("toLowerCase", to_lower_case),
("toUpperCase", to_upper_case),
];
write.define_as3_builtin_instance_methods(mc, AS3_INSTANCE_METHODS);
write.define_builtin_instance_methods(
mc,
activation.avm2().as3_namespace,
AS3_INSTANCE_METHODS,
);
const AS3_CLASS_METHODS: &[(&str, NativeMethodImpl)] = &[("fromCharCode", from_char_code)];
const PUBLIC_CLASS_METHODS: &[(&str, NativeMethodImpl)] = &[("fromCharCode", from_char_code)];
write.define_as3_builtin_class_methods(mc, AS3_CLASS_METHODS);
write.define_public_builtin_class_methods(mc, PUBLIC_CLASS_METHODS);
write.define_builtin_class_methods(mc, activation.avm2().as3_namespace, AS3_CLASS_METHODS);
write.define_builtin_class_methods(
mc,
activation.avm2().public_namespace,
PUBLIC_CLASS_METHODS,
);
class
}

View File

@ -7,10 +7,9 @@ use crate::avm2::method::{Method, NativeMethodImpl, ParamConfig};
use crate::avm2::object::{primitive_allocator, FunctionObject, Object, TObject};
use crate::avm2::value::Value;
use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::avm2::QName;
use crate::avm2::{AvmString, Error};
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
/// Implements `uint`'s instance initializer.
fn instance_init<'gc>(
@ -59,8 +58,8 @@ fn class_init<'gc>(
let this_class = this.as_class_object().unwrap();
let uint_proto = this_class.prototype();
uint_proto.set_property_local(
&Multiname::public("toExponential"),
uint_proto.set_string_property_local(
"toExponential",
FunctionObject::from_method(
activation,
Method::from_builtin(to_exponential, "toExponential", gc_context),
@ -71,8 +70,8 @@ fn class_init<'gc>(
.into(),
activation,
)?;
uint_proto.set_property_local(
&Multiname::public("toFixed"),
uint_proto.set_string_property_local(
"toFixed",
FunctionObject::from_method(
activation,
Method::from_builtin(to_fixed, "toFixed", gc_context),
@ -83,8 +82,8 @@ fn class_init<'gc>(
.into(),
activation,
)?;
uint_proto.set_property_local(
&Multiname::public("toPrecision"),
uint_proto.set_string_property_local(
"toPrecision",
FunctionObject::from_method(
activation,
Method::from_builtin(to_precision, "toPrecision", gc_context),
@ -95,8 +94,8 @@ fn class_init<'gc>(
.into(),
activation,
)?;
uint_proto.set_property_local(
&Multiname::public("toString"),
uint_proto.set_string_property_local(
"toString",
FunctionObject::from_method(
activation,
Method::from_builtin(to_string, "toString", gc_context),
@ -107,8 +106,8 @@ fn class_init<'gc>(
.into(),
activation,
)?;
uint_proto.set_property_local(
&Multiname::public("valueOf"),
uint_proto.set_string_property_local(
"valueOf",
FunctionObject::from_method(
activation,
Method::from_builtin(value_of, "valueOf", gc_context),
@ -264,10 +263,11 @@ fn value_of<'gc>(
}
/// Construct `uint`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::public(), "uint"),
Some(Multiname::public("Object")),
QName::new(activation.avm2().public_namespace, "uint"),
Some(Multiname::new(activation.avm2().public_namespace, "Object")),
Method::from_builtin(instance_init, "<uint instance initializer>", mc),
Method::from_builtin(class_init, "<uint class initializer>", mc),
mc,
@ -279,13 +279,20 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
write.set_native_instance_init(Method::from_builtin_and_params(
native_instance_init,
"<uint native instance initializer>",
vec![ParamConfig::of_type("num", Multiname::public("Object"))],
vec![ParamConfig::of_type(
"num",
Multiname::new(activation.avm2().public_namespace, "Object"),
)],
false,
mc,
));
const CLASS_CONSTANTS: &[(&str, u32)] = &[("MAX_VALUE", u32::MAX), ("MIN_VALUE", u32::MIN)];
write.define_public_constant_uint_class_traits(CLASS_CONSTANTS);
write.define_constant_uint_class_traits(
activation.avm2().public_namespace,
CLASS_CONSTANTS,
activation,
);
const AS3_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] = &[
("toExponential", to_exponential),
@ -294,7 +301,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("toString", to_string),
("valueOf", value_of),
];
write.define_as3_builtin_instance_methods(mc, AS3_INSTANCE_METHODS);
write.define_builtin_instance_methods(
mc,
activation.avm2().as3_namespace,
AS3_INSTANCE_METHODS,
);
class
}

View File

@ -6,17 +6,15 @@ use crate::avm2::globals::array::{
compare_numeric, compare_string_case_insensitive, compare_string_case_sensitive, ArrayIter,
SortOptions,
};
use crate::avm2::globals::NS_VECTOR;
use crate::avm2::method::{Method, NativeMethodImpl};
use crate::avm2::object::{vector_allocator, FunctionObject, Object, TObject, VectorObject};
use crate::avm2::value::Value;
use crate::avm2::vector::VectorStorage;
use crate::avm2::Error;
use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::avm2::QName;
use crate::string::AvmString;
use gc_arena::{GcCell, MutationContext};
use gc_arena::GcCell;
use std::cmp::{max, min, Ordering};
/// Implements `Vector`'s instance constructor.
@ -71,7 +69,7 @@ fn class_call<'gc>(
}
let length = arg
.get_property(&Multiname::public("length"), activation)?
.get_public_property("length", activation)?
.coerce_to_i32(activation)?;
let mut new_storage = VectorStorage::new(0, false, value_type, activation);
@ -98,17 +96,22 @@ pub fn class_init<'gc>(
let mut globals = activation.global_scope().unwrap();
let mut domain = activation.domain();
let vector_internal_namespace = activation.avm2().vector_internal_namespace;
//We have to grab Object's defining script instead of our own, because
//at this point Vector hasn't actually been defined yet. It doesn't
//matter because we only have one script for our globals.
let (_, script) = domain
.get_defining_script(&Multiname::public("Object"))?
.get_defining_script(&Multiname::new(
activation.avm2().public_namespace,
"Object",
))?
.unwrap();
let class_class = activation.avm2().classes().class;
let int_class = activation.avm2().classes().int;
let int_vector_class = this.apply(activation, &[int_class.into()])?;
let int_vector_name = QName::new(Namespace::internal(NS_VECTOR), "Vector$int");
let int_vector_name = QName::new(vector_internal_namespace, "Vector$int");
int_vector_class
.inner_class_definition()
.write(activation.context.gc_context)
@ -124,7 +127,7 @@ pub fn class_init<'gc>(
let uint_class = activation.avm2().classes().uint;
let uint_vector_class = this.apply(activation, &[uint_class.into()])?;
let uint_vector_name = QName::new(Namespace::internal(NS_VECTOR), "Vector$uint");
let uint_vector_name = QName::new(vector_internal_namespace, "Vector$uint");
uint_vector_class
.inner_class_definition()
.write(activation.context.gc_context)
@ -140,7 +143,7 @@ pub fn class_init<'gc>(
let number_class = activation.avm2().classes().number;
let number_vector_class = this.apply(activation, &[number_class.into()])?;
let number_vector_name = QName::new(Namespace::internal(NS_VECTOR), "Vector$double");
let number_vector_name = QName::new(vector_internal_namespace, "Vector$double");
number_vector_class
.inner_class_definition()
.write(activation.context.gc_context)
@ -155,7 +158,7 @@ pub fn class_init<'gc>(
domain.export_definition(number_vector_name, script, activation.context.gc_context)?;
let object_vector_class = this.apply(activation, &[Value::Null])?;
let object_vector_name = QName::new(Namespace::internal(NS_VECTOR), "Vector$object");
let object_vector_name = QName::new(vector_internal_namespace, "Vector$object");
object_vector_class
.inner_class_definition()
.write(activation.context.gc_context)
@ -180,8 +183,8 @@ pub fn specialized_class_init<'gc>(
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(this) = this {
let mut proto = this
.get_property(&Multiname::public("prototype"), activation)?
let proto = this
.get_public_property("prototype", activation)?
.as_object()
.ok_or_else(|| {
format!(
@ -213,8 +216,8 @@ pub fn specialized_class_init<'gc>(
("splice", splice),
];
for (pubname, func) in PUBLIC_PROTOTYPE_METHODS {
proto.set_property(
&Multiname::public(*pubname),
proto.set_string_property_local(
*pubname,
FunctionObject::from_function(
activation,
Method::from_builtin(*func, pubname, activation.context.gc_context),
@ -437,7 +440,7 @@ pub fn to_locale_string<'gc>(
) -> Result<Value<'gc>, Error<'gc>> {
join_inner(activation, this, &[",".into()], |v, act| {
if let Ok(o) = v.coerce_to_object(act) {
o.call_property(&Multiname::public("toLocaleString"), &[], act)
o.call_public_property("toLocaleString", &[], act)
} else {
Ok(v)
}
@ -592,7 +595,7 @@ pub fn index_of<'gc>(
let from_index = if from_index < 0 {
let length = this
.get_property(&Multiname::public("length"), activation)?
.get_public_property("length", activation)?
.coerce_to_i32(activation)?;
max(length + from_index, 0) as u32
} else {
@ -629,7 +632,7 @@ pub fn last_index_of<'gc>(
let from_index = if from_index < 0 {
let length = this
.get_property(&Multiname::public("length"), activation)?
.get_public_property("length", activation)?
.coerce_to_i32(activation)?;
max(length + from_index, 0) as u32
} else {
@ -1006,10 +1009,11 @@ pub fn splice<'gc>(
}
/// Construct `Vector`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::package(NS_VECTOR), "Vector"),
Some(Multiname::public("Object")),
QName::new(activation.avm2().vector_public_namespace, "Vector"),
Some(Multiname::new(activation.avm2().public_namespace, "Object")),
Method::from_builtin(instance_init, "<Vector instance initializer>", mc),
Method::from_builtin(class_init, "<Vector class initializer>", mc),
mc,
@ -1038,7 +1042,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("length", Some(length), Some(set_length)),
("fixed", Some(fixed), Some(set_fixed)),
];
write.define_public_builtin_instance_properties(mc, PUBLIC_INSTANCE_PROPERTIES);
write.define_builtin_instance_properties(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_PROPERTIES,
);
const AS3_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] = &[
("concat", concat),
@ -1063,7 +1071,11 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("sort", sort),
("splice", splice),
];
write.define_as3_builtin_instance_methods(mc, AS3_INSTANCE_METHODS);
write.define_builtin_instance_methods(
mc,
activation.avm2().as3_namespace,
AS3_INSTANCE_METHODS,
);
class
}

View File

@ -173,7 +173,7 @@ impl<'gc> BytecodeMethod<'gc> {
abc_method: abc_method.0,
abc_method_body: None,
signature,
return_type: Multiname::any(),
return_type: Multiname::any(activation.context.gc_context),
is_function,
})
}

View File

@ -126,15 +126,13 @@ impl<'gc> Multiname<'gc> {
let ns_set = ns_set?;
if ns_set.len() == 1 {
Ok(NamespaceSet::single(Namespace::from_abc_namespace(
translation_unit,
ns_set[0],
mc,
)?))
Ok(NamespaceSet::single(
translation_unit.pool_namespace(ns_set[0], mc)?,
))
} else {
let mut result = Vec::with_capacity(ns_set.len());
for ns in ns_set {
result.push(Namespace::from_abc_namespace(translation_unit, *ns, mc)?)
result.push(translation_unit.pool_namespace(*ns, mc)?)
}
Ok(NamespaceSet::multiple(result, mc))
}
@ -151,11 +149,7 @@ impl<'gc> Multiname<'gc> {
Ok(match abc_multiname {
AbcMultiname::QName { namespace, name } | AbcMultiname::QNameA { namespace, name } => {
Self {
ns: NamespaceSet::single(Namespace::from_abc_namespace(
translation_unit,
*namespace,
mc,
)?),
ns: NamespaceSet::single(translation_unit.pool_namespace(*namespace, mc)?),
name: translation_unit.pool_string_option(name.0, mc)?,
params: Vec::new(),
flags: Default::default(),
@ -290,9 +284,9 @@ impl<'gc> Multiname<'gc> {
}
/// Indicates the any type (any name in any namespace).
pub fn any() -> Self {
pub fn any(mc: MutationContext<'gc, '_>) -> Self {
Self {
ns: NamespaceSet::single(Namespace::Any),
ns: NamespaceSet::single(Namespace::any(mc)),
name: None,
params: Vec::new(),
flags: Default::default(),
@ -308,15 +302,6 @@ impl<'gc> Multiname<'gc> {
}
}
pub fn public(name: impl Into<AvmString<'gc>>) -> Self {
Self {
ns: NamespaceSet::single(Namespace::public()),
name: Some(name.into()),
params: Vec::new(),
flags: Default::default(),
}
}
pub fn namespace_set(&self) -> &[Namespace<'gc>] {
match &self.ns {
NamespaceSet::Single(ns) => std::slice::from_ref(ns),
@ -339,8 +324,8 @@ impl<'gc> Multiname<'gc> {
pub fn is_any(&self) -> bool {
self.name.is_none()
&& match self.ns {
NamespaceSet::Single(ns) => ns == Namespace::Any,
NamespaceSet::Multiple(ns) => ns.contains(&Namespace::Any),
NamespaceSet::Single(ns) => ns.is_any(),
NamespaceSet::Multiple(ns) => ns.iter().any(|ns| ns.is_any()),
}
}
@ -349,7 +334,7 @@ impl<'gc> Multiname<'gc> {
let ns_match = self
.namespace_set()
.iter()
.any(|ns| *ns == Namespace::Any || *ns == name.namespace());
.any(|ns| ns.is_any() || *ns == name.namespace());
let name_match = self.name.map(|n| n == name.local_name()).unwrap_or(true);
ns_match && name_match
@ -363,7 +348,7 @@ impl<'gc> Multiname<'gc> {
pub fn to_qualified_name(&self, mc: MutationContext<'gc, '_>) -> AvmString<'gc> {
let mut uri = WString::new();
let ns = match self.ns.get(0).filter(|_| self.ns.len() == 1) {
Some(Namespace::Any) => "*".into(),
Some(ns) if ns.is_any() => "*".into(),
Some(ns) => ns.as_uri(),
None => "".into(),
};
@ -398,7 +383,7 @@ impl<'gc> Multiname<'gc> {
pub fn to_error_qualified_name(&self, mc: MutationContext<'gc, '_>) -> AvmString<'gc> {
let mut uri = WString::new();
let ns = match self.ns.get(0).filter(|_| self.ns.len() == 1) {
Some(Namespace::Any) => "*".into(),
Some(ns) if ns.is_any() => "*".into(),
Some(ns) => ns.as_uri(),
None => "".into(),
};

View File

@ -1,15 +1,26 @@
use crate::avm2::script::TranslationUnit;
use crate::avm2::Error;
use crate::string::AvmString;
use gc_arena::{Collect, MutationContext};
use gc_arena::{Collect, Gc, MutationContext};
use std::fmt::Debug;
use swf::avm2::types::{Index, Namespace as AbcNamespace};
#[derive(Clone, Copy, Collect, Debug)]
#[collect(no_drop)]
pub struct Namespace<'gc>(pub Gc<'gc, NamespaceData<'gc>>);
impl<'gc> PartialEq for Namespace<'gc> {
fn eq(&self, other: &Self) -> bool {
*self.0 == *other.0
}
}
impl<'gc> Eq for Namespace<'gc> {}
/// Represents the name of a namespace.
#[allow(clippy::enum_variant_names)]
#[derive(Clone, Copy, Collect, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(Clone, Collect, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[collect(no_drop)]
pub enum Namespace<'gc> {
pub enum NamespaceData<'gc> {
// note: this is the default "public namespace", corresponding to both
// ABC Namespace and PackageNamespace
Namespace(AvmString<'gc>),
@ -24,13 +35,15 @@ pub enum Namespace<'gc> {
impl<'gc> Namespace<'gc> {
/// Read a namespace declaration from the ABC constant pool and copy it to
/// a namespace value.
/// NOTE: you should use the TranslationUnit.pool_namespace instead of calling this.
/// otherwise you run a risk of creating a duplicate of private ns singleton.
pub fn from_abc_namespace(
translation_unit: TranslationUnit<'gc>,
namespace_index: Index<AbcNamespace>,
mc: MutationContext<'gc, '_>,
) -> Result<Self, Error<'gc>> {
if namespace_index.0 == 0 {
return Ok(Self::Any);
return Ok(Self::any(mc));
}
let actual_index = namespace_index.0 as usize - 1;
@ -41,73 +54,84 @@ impl<'gc> Namespace<'gc> {
.get(actual_index)
.ok_or_else(|| format!("Unknown namespace constant {}", namespace_index.0).into());
Ok(match abc_namespace? {
let ns = match abc_namespace? {
AbcNamespace::Namespace(idx) => {
Self::Namespace(translation_unit.pool_string(idx.0, mc)?)
NamespaceData::Namespace(translation_unit.pool_string(idx.0, mc)?)
}
AbcNamespace::Package(idx) => {
NamespaceData::Namespace(translation_unit.pool_string(idx.0, mc)?)
}
AbcNamespace::Package(idx) => Self::Namespace(translation_unit.pool_string(idx.0, mc)?),
AbcNamespace::PackageInternal(idx) => {
Self::PackageInternal(translation_unit.pool_string(idx.0, mc)?)
NamespaceData::PackageInternal(translation_unit.pool_string(idx.0, mc)?)
}
AbcNamespace::Protected(idx) => {
Self::Protected(translation_unit.pool_string(idx.0, mc)?)
NamespaceData::Protected(translation_unit.pool_string(idx.0, mc)?)
}
AbcNamespace::Explicit(idx) => {
NamespaceData::Explicit(translation_unit.pool_string(idx.0, mc)?)
}
AbcNamespace::Explicit(idx) => Self::Explicit(translation_unit.pool_string(idx.0, mc)?),
AbcNamespace::StaticProtected(idx) => {
Self::StaticProtected(translation_unit.pool_string(idx.0, mc)?)
NamespaceData::StaticProtected(translation_unit.pool_string(idx.0, mc)?)
}
AbcNamespace::Private(idx) => Self::Private(translation_unit.pool_string(idx.0, mc)?),
})
AbcNamespace::Private(idx) => {
NamespaceData::Private(translation_unit.pool_string(idx.0, mc)?)
}
};
Ok(Self(Gc::allocate(mc, ns)))
}
pub fn public() -> Self {
Self::Namespace("".into())
pub fn any(mc: MutationContext<'gc, '_>) -> Self {
Self(Gc::allocate(mc, NamespaceData::Any))
}
pub fn as3_namespace() -> Self {
Self::Namespace("http://adobe.com/AS3/2006/builtin".into())
pub fn package(package_name: impl Into<AvmString<'gc>>, mc: MutationContext<'gc, '_>) -> Self {
Self(Gc::allocate(
mc,
NamespaceData::Namespace(package_name.into()),
))
}
pub fn package(package_name: impl Into<AvmString<'gc>>) -> Self {
Self::Namespace(package_name.into())
pub fn internal(package_name: impl Into<AvmString<'gc>>, mc: MutationContext<'gc, '_>) -> Self {
Self(Gc::allocate(
mc,
NamespaceData::PackageInternal(package_name.into()),
))
}
pub fn internal(package_name: impl Into<AvmString<'gc>>) -> Self {
Self::PackageInternal(package_name.into())
}
pub fn private(name: impl Into<AvmString<'gc>>) -> Self {
Self::Private(name.into())
// note: since private namespaces are compared by identity,
// if you try using it to create temporary namespaces it will likely not work.
pub fn private(name: impl Into<AvmString<'gc>>, mc: MutationContext<'gc, '_>) -> Self {
Self(Gc::allocate(mc, NamespaceData::Private(name.into())))
}
pub fn is_public(&self) -> bool {
matches!(self, Self::Namespace(name) if name.is_empty())
matches!(*self.0, NamespaceData::Namespace(name) if name.is_empty())
}
pub fn is_any(&self) -> bool {
matches!(self, Self::Any)
matches!(*self.0, NamespaceData::Any)
}
pub fn is_private(&self) -> bool {
matches!(self, Self::Private(_))
matches!(*self.0, NamespaceData::Private(_))
}
pub fn is_namespace(&self) -> bool {
matches!(self, Self::Namespace(_))
matches!(*self.0, NamespaceData::Namespace(_))
}
/// Get the string value of this namespace, ignoring its type.
///
/// TODO: Is this *actually* the namespace URI?
pub fn as_uri(&self) -> AvmString<'gc> {
match self {
Self::Namespace(s) => *s,
Self::PackageInternal(s) => *s,
Self::Protected(s) => *s,
Self::Explicit(s) => *s,
Self::StaticProtected(s) => *s,
Self::Private(s) => *s,
Self::Any => "".into(),
match &*self.0 {
NamespaceData::Namespace(s) => *s,
NamespaceData::PackageInternal(s) => *s,
NamespaceData::Protected(s) => *s,
NamespaceData::Explicit(s) => *s,
NamespaceData::StaticProtected(s) => *s,
NamespaceData::Private(s) => *s,
NamespaceData::Any => "".into(),
}
}
}

View File

@ -193,6 +193,18 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
}
}
/// Same as get_property, but constructs a public Multiname for you.
fn get_public_property(
self,
name: impl Into<AvmString<'gc>>,
activation: &mut Activation<'_, 'gc>,
) -> Result<Value<'gc>, Error<'gc>> {
self.get_property(
&Multiname::new(activation.avm2().public_namespace, name),
activation,
)
}
/// Set a local property of the object. The Multiname should always be public.
///
/// This skips class field lookups and looks at:
@ -208,6 +220,20 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
base.set_property_local(name, value, activation)
}
/// Same as get_property_local, but constructs a public Multiname for you.
/// TODO: this feels upside down, as in: we shouldn't need multinames/namespaces
/// by the time we reach dynamic properties.
/// But for now, this function is a smaller change to the core than a full refactor.
fn set_string_property_local(
self,
name: impl Into<AvmString<'gc>>,
value: Value<'gc>,
activation: &mut Activation<'_, 'gc>,
) -> Result<(), Error<'gc>> {
let name = Multiname::new(activation.avm2().public_namespace, name);
self.set_property_local(&name, value, activation)
}
/// Set a property by Multiname lookup.
///
/// This method should not be overridden.
@ -256,6 +282,20 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
}
}
/// Same as set_property, but constructs a public Multiname for you.
fn set_public_property(
&mut self,
name: impl Into<AvmString<'gc>>,
value: Value<'gc>,
activation: &mut Activation<'_, 'gc>,
) -> Result<(), Error<'gc>> {
self.set_property(
&Multiname::new(activation.avm2().public_namespace, name),
value,
activation,
)
}
/// Init a local property of the object. The Multiname should always be public.
///
/// This skips class field lookups and looks at:
@ -419,6 +459,20 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
}
}
/// Same as call_property, but constructs a public Multiname for you.
fn call_public_property(
self,
name: impl Into<AvmString<'gc>>,
arguments: &[Value<'gc>],
activation: &mut Activation<'_, 'gc>,
) -> Result<Value<'gc>, Error<'gc>> {
self.call_property(
&Multiname::new(activation.avm2().public_namespace, name),
arguments,
activation,
)
}
/// Retrieve a slot by its index.
fn get_slot(self, id: u32) -> Result<Value<'gc>, Error<'gc>> {
let base = self.base();
@ -559,6 +613,16 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
}
}
/// Same as delete_property, but constructs a public Multiname for you.
fn delete_public_property(
&self,
activation: &mut Activation<'_, 'gc>,
name: impl Into<AvmString<'gc>>,
) -> Result<bool, Error<'gc>> {
let name = Multiname::new(activation.avm2().public_namespace, name);
self.delete_property(activation, &name)
}
/// Retrieve the `__proto__` of a given object.
///
/// The proto is another object used to resolve methods across a class of
@ -630,7 +694,8 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
let name = self
.get_enumerant_name(index, activation)?
.coerce_to_string(activation)?;
self.get_property(&Multiname::public(name), activation)
// todo: this probably doesn't need non-public accesses
self.get_public_property(name, activation)
}
/// Determine if a property is currently enumerable.
@ -840,7 +905,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
class: Object<'gc>,
) -> Result<bool, Error<'gc>> {
let type_proto = class
.get_property(&Multiname::public("prototype"), activation)?
.get_public_property("prototype", activation)?
.as_object();
if let Some(type_proto) = type_proto {

View File

@ -284,11 +284,7 @@ impl<'gc> ClassObject<'gc> {
class_proto: Object<'gc>,
) -> Result<(), Error<'gc>> {
self.0.write(activation.context.gc_context).prototype = Some(class_proto);
class_proto.set_property_local(
&Multiname::public("constructor"),
self.into(),
activation,
)?;
class_proto.set_string_property_local("constructor", self.into(), activation)?;
class_proto.set_local_property_is_enumerable(
activation.context.gc_context,
"constructor".into(),
@ -353,7 +349,10 @@ impl<'gc> ClassObject<'gc> {
for interface_trait in iface_read.instance_traits() {
if !interface_trait.name().namespace().is_public() {
let public_name = QName::dynamic_name(interface_trait.name().local_name());
let public_name = QName::new(
activation.context.avm2.public_namespace,
interface_trait.name().local_name(),
);
self.instance_vtable().copy_property_for_interface(
activation.context.gc_context,
public_name,

View File

@ -4,7 +4,7 @@ use crate::avm2::activation::Activation;
use crate::avm2::object::script_object::ScriptObjectData;
use crate::avm2::object::{ClassObject, Object, ObjectPtr, TObject};
use crate::avm2::value::Value;
use crate::avm2::{Error, Multiname};
use crate::avm2::Error;
use crate::string::AvmString;
use core::fmt;
use fnv::FnvHashMap;
@ -153,10 +153,7 @@ impl<'gc> TObject<'gc> for DictionaryObject<'gc> {
if !name_value.is_primitive() {
Ok(self.get_property_by_object(name_value.as_object().unwrap()))
} else {
self.get_property(
&Multiname::public(name_value.coerce_to_string(activation)?),
activation,
)
self.get_public_property(name_value.coerce_to_string(activation)?, activation)
}
}

View File

@ -8,7 +8,6 @@ use crate::avm2::object::{ClassObject, Object, ObjectPtr, TObject};
use crate::avm2::string::AvmString;
use crate::avm2::value::Value;
use crate::avm2::Error;
use crate::avm2::Multiname;
use crate::string::WString;
use core::fmt;
use gc_arena::{Collect, GcCell, MutationContext};
@ -62,10 +61,10 @@ impl<'gc> ErrorObject<'gc> {
activation: &mut Activation<'_, 'gc>,
) -> Result<AvmString<'gc>, Error<'gc>> {
let name = self
.get_property(&Multiname::public("name"), activation)?
.get_public_property("name", activation)?
.coerce_to_string(activation)?;
let message = self
.get_property(&Multiname::public("message"), activation)?
.get_public_property("message", activation)?
.coerce_to_string(activation)?;
if message.is_empty() {
return Ok(name);

View File

@ -21,7 +21,7 @@ pub fn namespace_allocator<'gc>(
activation.context.gc_context,
NamespaceObjectData {
base,
namespace: Namespace::public(),
namespace: activation.context.avm2.public_namespace,
},
))
.into())

View File

@ -1,12 +1,10 @@
//! Object representation for `Proxy`.
use crate::avm2::activation::Activation;
use crate::avm2::globals::NS_FLASH_PROXY;
use crate::avm2::object::script_object::ScriptObjectData;
use crate::avm2::object::{ClassObject, Object, ObjectPtr, QNameObject, TObject};
use crate::avm2::value::Value;
use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::avm2::QName;
use crate::avm2::{AvmString, Error};
use core::fmt;
@ -79,7 +77,7 @@ impl<'gc> TObject<'gc> for ProxyObject<'gc> {
QNameObject::from_qname(activation, QName::new(*namespace, local_name))?;
return self.call_property(
&Multiname::new(Namespace::Namespace(NS_FLASH_PROXY.into()), "getProperty"),
&Multiname::new(activation.avm2().proxy_namespace, "getProperty"),
&[qname.into()],
activation,
);
@ -115,7 +113,7 @@ impl<'gc> TObject<'gc> for ProxyObject<'gc> {
QNameObject::from_qname(activation, QName::new(*namespace, local_name))?;
self.call_property(
&Multiname::new(Namespace::Namespace(NS_FLASH_PROXY.into()), "setProperty"),
&Multiname::new(activation.avm2().proxy_namespace, "setProperty"),
&[qname.into(), value],
activation,
)?;
@ -160,10 +158,7 @@ impl<'gc> TObject<'gc> for ProxyObject<'gc> {
args.extend_from_slice(arguments);
return self.call_property(
&Multiname::new(
Namespace::Namespace(NS_FLASH_PROXY.into()),
"callProperty",
),
&Multiname::new(activation.avm2().proxy_namespace, "callProperty"),
&args[..],
activation,
);
@ -195,10 +190,7 @@ impl<'gc> TObject<'gc> for ProxyObject<'gc> {
return Ok(self
.call_property(
&Multiname::new(
Namespace::Namespace(NS_FLASH_PROXY.into()),
"deleteProperty",
),
&Multiname::new(activation.avm2().proxy_namespace, "deleteProperty"),
&[qname.into()],
activation,
)?
@ -221,7 +213,7 @@ impl<'gc> TObject<'gc> for ProxyObject<'gc> {
) -> Result<bool, Error<'gc>> {
Ok(self
.call_property(
&Multiname::new(Namespace::Namespace(NS_FLASH_PROXY.into()), "hasProperty"),
&Multiname::new(activation.avm2().proxy_namespace, "hasProperty"),
// this should probably pass the multiname as-is? See above
&[name.local_name().unwrap().into()],
activation,
@ -236,7 +228,7 @@ impl<'gc> TObject<'gc> for ProxyObject<'gc> {
) -> Result<Option<u32>, Error<'gc>> {
Ok(Some(
self.call_property(
&Multiname::new(Namespace::Namespace(NS_FLASH_PROXY.into()), "nextNameIndex"),
&Multiname::new(activation.avm2().proxy_namespace, "nextNameIndex"),
&[last_index.into()],
activation,
)?
@ -250,7 +242,7 @@ impl<'gc> TObject<'gc> for ProxyObject<'gc> {
activation: &mut Activation<'_, 'gc>,
) -> Result<Value<'gc>, Error<'gc>> {
self.call_property(
&Multiname::new(Namespace::Namespace(NS_FLASH_PROXY.into()), "nextName"),
&Multiname::new(activation.avm2().proxy_namespace, "nextName"),
&[index.into()],
activation,
)
@ -262,7 +254,7 @@ impl<'gc> TObject<'gc> for ProxyObject<'gc> {
activation: &mut Activation<'_, 'gc>,
) -> Result<Value<'gc>, Error<'gc>> {
self.call_property(
&Multiname::new(Namespace::Namespace(NS_FLASH_PROXY.into()), "nextValue"),
&Multiname::new(activation.avm2().proxy_namespace, "nextValue"),
&[index.into()],
activation,
)

View File

@ -1,6 +1,7 @@
use crate::avm2::script::TranslationUnit;
use crate::avm2::Activation;
use crate::avm2::Error;
use crate::avm2::Namespace;
use crate::avm2::{Namespace, NamespaceData};
use crate::either::Either;
use crate::string::{AvmString, WStr, WString};
use gc_arena::{Collect, MutationContext};
@ -16,7 +17,7 @@ use swf::avm2::types::{Index, Multiname as AbcMultiname};
/// `QName`. All other forms of names and multinames are either versions of
/// `QName` with unspecified parameters, or multiple names to be checked in
/// order.
#[derive(Clone, Copy, Collect, Hash)]
#[derive(Clone, Copy, Collect)]
#[collect(no_drop)]
pub struct QName<'gc> {
ns: Namespace<'gc>,
@ -40,13 +41,6 @@ impl<'gc> QName<'gc> {
}
}
pub fn dynamic_name(local_part: impl Into<AvmString<'gc>>) -> Self {
Self {
ns: Namespace::public(),
name: local_part.into(),
}
}
/// Pull a `QName` from the multiname pool.
///
/// This function returns an Err if the multiname does not exist or is not
@ -70,7 +64,7 @@ impl<'gc> QName<'gc> {
Ok(match abc_multiname? {
AbcMultiname::QName { namespace, name } => Self {
ns: Namespace::from_abc_namespace(translation_unit, *namespace, mc)?,
ns: translation_unit.pool_namespace(*namespace, mc)?,
name: translation_unit.pool_string(name.0, mc)?,
},
_ => return Err("Attempted to pull QName from non-QName multiname".into()),
@ -83,19 +77,20 @@ impl<'gc> QName<'gc> {
/// NAMESPACE::LOCAL_NAME
/// NAMESPACE.LOCAL_NAME (Where the LAST dot is used to split the namespace & local_name)
/// LOCAL_NAME (Use the public namespace)
pub fn from_qualified_name(name: AvmString<'gc>, mc: MutationContext<'gc, '_>) -> Self {
pub fn from_qualified_name(name: AvmString<'gc>, activation: &mut Activation<'_, 'gc>) -> Self {
let mc = activation.context.gc_context;
let parts = name
.rsplit_once(WStr::from_units(b"::"))
.or_else(|| name.rsplit_once(WStr::from_units(b".")));
if let Some((package_name, local_name)) = parts {
Self {
ns: Namespace::Namespace(AvmString::new(mc, package_name)),
ns: Namespace::package(AvmString::new(mc, package_name), mc),
name: AvmString::new(mc, local_name),
}
} else {
Self {
ns: Namespace::public(),
ns: activation.avm2().public_namespace,
name,
}
}
@ -155,14 +150,14 @@ impl<'gc> QName<'gc> {
/// Get the string value of this QName, including the namespace URI.
pub fn as_uri(&self, mc: MutationContext<'gc, '_>) -> AvmString<'gc> {
let ns = match &self.ns {
Namespace::Namespace(s) => s,
Namespace::PackageInternal(s) => s,
Namespace::Protected(s) => s,
Namespace::Explicit(s) => s,
Namespace::StaticProtected(s) => s,
Namespace::Private(s) => s,
Namespace::Any => WStr::from_units(b"*"),
let ns = match &*self.ns.0 {
NamespaceData::Namespace(s) => s,
NamespaceData::PackageInternal(s) => s,
NamespaceData::Protected(s) => s,
NamespaceData::Explicit(s) => s,
NamespaceData::StaticProtected(s) => s,
NamespaceData::Private(s) => s,
NamespaceData::Any => WStr::from_units(b"*"),
};
if ns.is_empty() {

View File

@ -10,6 +10,7 @@ use crate::avm2::scope::ScopeChain;
use crate::avm2::traits::Trait;
use crate::avm2::value::Value;
use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::avm2::{Avm2, Error};
use crate::context::UpdateContext;
use crate::string::AvmString;
@ -18,7 +19,8 @@ use std::cell::Ref;
use std::mem::drop;
use std::rc::Rc;
use swf::avm2::types::{
AbcFile, Index, Method as AbcMethod, Multiname as AbcMultiname, Script as AbcScript,
AbcFile, Index, Method as AbcMethod, Multiname as AbcMultiname, Namespace as AbcNamespace,
Script as AbcScript,
};
#[derive(Copy, Clone, Collect)]
@ -60,6 +62,9 @@ pub struct TranslationUnitData<'gc> {
/// They're lazy loaded and offset by 1, with the 0th element being always None.
strings: Vec<Option<AvmString<'gc>>>,
/// All namespaces loaded from the ABC's scripts list.
namespaces: Vec<Option<Namespace<'gc>>>,
/// All multinames loaded from the ABC's multiname list
/// Note that some of these may have a runtime (lazy) component.
/// Make sure to check for that before using them.
@ -91,6 +96,7 @@ impl<'gc> TranslationUnit<'gc> {
let methods = vec![None; abc.methods.len()];
let scripts = vec![None; abc.scripts.len()];
let strings = vec![None; abc.constant_pool.strings.len() + 1];
let namespaces = vec![None; abc.constant_pool.namespaces.len() + 1];
let multinames = vec![None; abc.constant_pool.multinames.len() + 1];
let private_trait_scripts = PropertyMap::new();
@ -103,6 +109,7 @@ impl<'gc> TranslationUnit<'gc> {
methods,
scripts,
strings,
namespaces,
multinames,
private_trait_scripts,
},
@ -278,6 +285,28 @@ impl<'gc> TranslationUnit<'gc> {
.unwrap_or_default())
}
/// Retrieve a static, or non-runtime, multiname from the current constant
/// pool.
///
/// This version of the function treats index 0 as an error condition.
pub fn pool_namespace(
self,
ns_index: Index<AbcNamespace>,
mc: MutationContext<'gc, '_>,
) -> Result<Namespace<'gc>, Error<'gc>> {
let read = self.0.read();
if let Some(Some(namespace)) = read.namespaces.get(ns_index.0 as usize) {
return Ok(*namespace);
}
drop(read);
let namespace = Namespace::from_abc_namespace(self, ns_index, mc)?;
self.0.write(mc).namespaces[ns_index.0 as usize] = Some(namespace);
Ok(namespace)
}
/// Retrieve a multiname from the current constant pool.
/// The name can have a lazy component, do not pass it anywhere.
pub fn pool_maybe_uninitialized_multiname(
@ -326,7 +355,7 @@ impl<'gc> TranslationUnit<'gc> {
mc: MutationContext<'gc, '_>,
) -> Result<Gc<'gc, Multiname<'gc>>, Error<'gc>> {
if multiname_index.0 == 0 {
Ok(Gc::allocate(mc, Multiname::any()))
Ok(Gc::allocate(mc, Multiname::any(mc)))
} else {
self.pool_multiname_static(multiname_index, mc)
}

View File

@ -2,7 +2,6 @@
use crate::avm2::activation::Activation;
use crate::avm2::error;
use crate::avm2::globals::NS_VECTOR;
use crate::avm2::object::{ClassObject, NamespaceObject, Object, PrimitiveObject, TObject};
use crate::avm2::script::TranslationUnit;
use crate::avm2::Error;
@ -532,7 +531,7 @@ pub fn abc_default_value<'gc>(
| AbcDefaultValue::StaticProtected(ns)
| AbcDefaultValue::Private(ns) => Ok(NamespaceObject::from_namespace(
activation,
Namespace::from_abc_namespace(translation_unit, *ns, activation.context.gc_context)?,
translation_unit.pool_namespace(*ns, activation.context.gc_context)?,
)?
.into()),
}
@ -636,20 +635,16 @@ impl<'gc> Value<'gc> {
let mut prim = *self;
let object = *o;
if let Value::Object(_) =
object.get_property(&Multiname::public("toString"), activation)?
{
prim = object.call_property(&Multiname::public("toString"), &[], activation)?;
if let Value::Object(_) = object.get_public_property("toString", activation)? {
prim = object.call_public_property("toString", &[], activation)?;
}
if prim.is_primitive() {
return Ok(prim);
}
if let Value::Object(_) =
object.get_property(&Multiname::public("valueOf"), activation)?
{
prim = object.call_property(&Multiname::public("valueOf"), &[], activation)?;
if let Value::Object(_) = object.get_public_property("valueOf", activation)? {
prim = object.call_public_property("valueOf", &[], activation)?;
}
if prim.is_primitive() {
@ -662,20 +657,16 @@ impl<'gc> Value<'gc> {
let mut prim = *self;
let object = *o;
if let Value::Object(_) =
object.get_property(&Multiname::public("valueOf"), activation)?
{
prim = object.call_property(&Multiname::public("valueOf"), &[], activation)?;
if let Value::Object(_) = object.get_public_property("valueOf", activation)? {
prim = object.call_public_property("valueOf", &[], activation)?;
}
if prim.is_primitive() {
return Ok(prim);
}
if let Value::Object(_) =
object.get_property(&Multiname::public("toString"), activation)?
{
prim = object.call_property(&Multiname::public("toString"), &[], activation)?;
if let Value::Object(_) = object.get_public_property("toString", activation)? {
prim = object.call_public_property("toString", &[], activation)?;
}
if prim.is_primitive() {
@ -969,14 +960,16 @@ impl<'gc> Value<'gc> {
if let Some(vector) = object.as_vector_storage() {
let name = class.inner_class_definition().read().name();
if name == QName::new(Namespace::package(NS_VECTOR), "Vector")
|| (name == QName::new(Namespace::internal(NS_VECTOR), "Vector$int")
let vector_public_namespace = activation.avm2().vector_public_namespace;
let vector_internal_namespace = activation.avm2().vector_internal_namespace;
if name == QName::new(vector_public_namespace, "Vector")
|| (name == QName::new(vector_internal_namespace, "Vector$int")
&& vector.value_type() == activation.avm2().classes().int)
|| (name == QName::new(Namespace::internal(NS_VECTOR), "Vector$uint")
|| (name == QName::new(vector_internal_namespace, "Vector$uint")
&& vector.value_type() == activation.avm2().classes().uint)
|| (name == QName::new(Namespace::internal(NS_VECTOR), "Vector$number")
|| (name == QName::new(vector_internal_namespace, "Vector$number")
&& vector.value_type() == activation.avm2().classes().number)
|| (name == QName::new(Namespace::internal(NS_VECTOR), "Vector$object")
|| (name == QName::new(vector_internal_namespace, "Vector$object")
&& vector.value_type() == activation.avm2().classes().object)
{
return Ok(*self);

View File

@ -1319,8 +1319,9 @@ pub trait TDisplayObject<'gc>:
if self.has_explicit_name() {
if let Some(Avm2Value::Object(mut p)) = self.parent().map(|p| p.object2()) {
if let Avm2Value::Object(c) = self.object2() {
let name = Avm2Multiname::public(self.name());
let mut activation = Avm2Activation::from_nothing(context.reborrow());
let name =
Avm2Multiname::new(activation.avm2().public_namespace, self.name());
if let Err(e) = p.init_property(&name, c.into(), &mut activation) {
tracing::error!(
"Got error when setting AVM2 child named \"{}\": {}",
@ -1895,23 +1896,23 @@ impl SoundTransform {
) -> Result<Self, Avm2Error<'gc>> {
Ok(SoundTransform {
left_to_left: (as3_st
.get_property(&Avm2Multiname::public("leftToLeft"), activation)?
.get_public_property("leftToLeft", activation)?
.coerce_to_number(activation)?
* 100.0) as i32,
left_to_right: (as3_st
.get_property(&Avm2Multiname::public("leftToRight"), activation)?
.get_public_property("leftToRight", activation)?
.coerce_to_number(activation)?
* 100.0) as i32,
right_to_left: (as3_st
.get_property(&Avm2Multiname::public("rightToLeft"), activation)?
.get_public_property("rightToLeft", activation)?
.coerce_to_number(activation)?
* 100.0) as i32,
right_to_right: (as3_st
.get_property(&Avm2Multiname::public("rightToRight"), activation)?
.get_public_property("rightToRight", activation)?
.coerce_to_number(activation)?
* 100.0) as i32,
volume: (as3_st
.get_property(&Avm2Multiname::public("volume"), activation)?
.get_public_property("volume", activation)?
.coerce_to_number(activation)?
* 100.0) as i32,
})
@ -1927,31 +1928,27 @@ impl SoundTransform {
.soundtransform
.construct(activation, &[])?;
as3_st.set_property(
&Avm2Multiname::public("leftToLeft"),
as3_st.set_public_property(
"leftToLeft",
(self.left_to_left as f64 / 100.0).into(),
activation,
)?;
as3_st.set_property(
&Avm2Multiname::public("leftToRight"),
as3_st.set_public_property(
"leftToRight",
(self.left_to_right as f64 / 100.0).into(),
activation,
)?;
as3_st.set_property(
&Avm2Multiname::public("rightToLeft"),
as3_st.set_public_property(
"rightToLeft",
(self.right_to_left as f64 / 100.0).into(),
activation,
)?;
as3_st.set_property(
&Avm2Multiname::public("rightToRight"),
as3_st.set_public_property(
"rightToRight",
(self.right_to_right as f64 / 100.0).into(),
activation,
)?;
as3_st.set_property(
&Avm2Multiname::public("volume"),
(self.volume as f64 / 100.0).into(),
activation,
)?;
as3_st.set_public_property("volume", (self.volume as f64 / 100.0).into(), activation)?;
Ok(as3_st)
}

View File

@ -737,7 +737,7 @@ impl<'gc> MovieClip<'gc> {
let class_name = reader.read_str()?.to_str_lossy(reader.encoding());
let class_name = AvmString::new_utf8(activation.context.gc_context, class_name);
let name = Avm2QName::from_qualified_name(class_name, activation.context.gc_context);
let name = Avm2QName::from_qualified_name(class_name, &mut activation);
let library = activation
.context
.library

View File

@ -10,8 +10,8 @@ use crate::avm2::object::EventObject as Avm2EventObject;
use crate::avm2::object::LoaderStream;
use crate::avm2::object::TObject as _;
use crate::avm2::{
Activation as Avm2Activation, Avm2, Domain as Avm2Domain, Multiname as Avm2Multiname,
Object as Avm2Object, Value as Avm2Value,
Activation as Avm2Activation, Avm2, Domain as Avm2Domain, Object as Avm2Object,
Value as Avm2Value,
};
use crate::backend::navigator::{OwnedFuture, Request};
use crate::context::{ActionQueue, ActionType, UpdateContext};
@ -632,7 +632,7 @@ impl<'gc> Loader<'gc> {
if let Some(MovieLoaderEventHandler::Avm2LoaderInfo(loader_info)) = event_handler {
let mut activation = Avm2Activation::from_nothing(context.reborrow());
let mut loader = loader_info
.get_property(&Avm2Multiname::public("loader"), &mut activation)
.get_public_property("loader", &mut activation)
.map_err(|e| Error::Avm2Error(e.to_string()))?
.as_object()
.unwrap()
@ -1035,7 +1035,7 @@ impl<'gc> Loader<'gc> {
};
target
.set_property(&Avm2Multiname::public("data"), data_object, activation)
.set_public_property("data", data_object, activation)
.unwrap();
}
@ -1386,11 +1386,8 @@ impl<'gc> Loader<'gc> {
let mut activation = Avm2Activation::from_nothing(uc.reborrow());
let domain = context
.and_then(|o| {
o.get_property(
&Avm2Multiname::public("applicationDomain"),
&mut activation,
)
.ok()
o.get_public_property("applicationDomain", &mut activation)
.ok()
})
.and_then(|v| v.coerce_to_object(&mut activation).ok())
.and_then(|o| o.as_application_domain())