avm2: Put some more Multinames behind a Gc
This commit is contained in:
parent
5512bc5742
commit
4a43ec0548
|
@ -16,7 +16,7 @@ use crate::PlayerRuntime;
|
|||
|
||||
use fnv::FnvHashMap;
|
||||
use gc_arena::lock::GcRefLock;
|
||||
use gc_arena::{Collect, Mutation};
|
||||
use gc_arena::{Collect, Gc, Mutation};
|
||||
use std::sync::Arc;
|
||||
use swf::avm2::read::Reader;
|
||||
use swf::DoAbc2Flag;
|
||||
|
@ -79,7 +79,7 @@ pub use crate::avm2::domain::{Domain, DomainPtr};
|
|||
pub use crate::avm2::error::Error;
|
||||
pub use crate::avm2::flv::FlvValueAvm2Ext;
|
||||
pub use crate::avm2::globals::flash::ui::context_menu::make_context_menu_state;
|
||||
pub use crate::avm2::multiname::Multiname;
|
||||
pub use crate::avm2::multiname::{CommonMultinames, Multiname};
|
||||
pub use crate::avm2::namespace::Namespace;
|
||||
pub use crate::avm2::object::{
|
||||
ArrayObject, BitmapDataObject, ClassObject, EventObject, Object, SoundChannelObject,
|
||||
|
@ -153,6 +153,8 @@ pub struct Avm2<'gc> {
|
|||
pub flash_text_engine_internal: Namespace<'gc>,
|
||||
pub flash_net_internal: Namespace<'gc>,
|
||||
|
||||
pub multinames: Gc<'gc, CommonMultinames<'gc>>,
|
||||
|
||||
#[collect(require_static)]
|
||||
native_method_table: &'static [Option<(&'static str, NativeMethodImpl)>],
|
||||
|
||||
|
@ -207,27 +209,33 @@ impl<'gc> Avm2<'gc> {
|
|||
player_version: u8,
|
||||
player_runtime: PlayerRuntime,
|
||||
) -> Self {
|
||||
let playerglobals_domain = Domain::uninitialized_domain(context.gc_context, None);
|
||||
let stage_domain =
|
||||
Domain::uninitialized_domain(context.gc_context, Some(playerglobals_domain));
|
||||
let mc = context.gc_context;
|
||||
|
||||
let playerglobals_domain = Domain::uninitialized_domain(mc, None);
|
||||
let stage_domain = Domain::uninitialized_domain(mc, Some(playerglobals_domain));
|
||||
|
||||
let public_namespaces = (0..=(ApiVersion::VM_INTERNAL as usize))
|
||||
.map(|val| Namespace::package("", ApiVersion::from_usize(val).unwrap(), context))
|
||||
.collect();
|
||||
|
||||
let public_namespace_base_version =
|
||||
Namespace::package("", ApiVersion::AllVersions, context);
|
||||
|
||||
let multinames = CommonMultinames::new(context, public_namespace_base_version);
|
||||
|
||||
Self {
|
||||
player_version,
|
||||
player_runtime,
|
||||
stack: Vec::new(),
|
||||
scope_stack: Vec::new(),
|
||||
call_stack: GcRefLock::new(context.gc_context, CallStack::new().into()),
|
||||
call_stack: GcRefLock::new(mc, CallStack::new().into()),
|
||||
playerglobals_domain,
|
||||
stage_domain,
|
||||
system_classes: None,
|
||||
system_class_defs: None,
|
||||
toplevel_global_object: None,
|
||||
|
||||
public_namespace_base_version: Namespace::package("", ApiVersion::AllVersions, context),
|
||||
public_namespace_base_version,
|
||||
public_namespaces,
|
||||
public_namespace_vm_internal: Namespace::package("", ApiVersion::VM_INTERNAL, context),
|
||||
internal_namespace: Namespace::internal("", context),
|
||||
|
@ -255,6 +263,8 @@ impl<'gc> Avm2<'gc> {
|
|||
flash_text_engine_internal: Namespace::internal("flash.text.engine", context),
|
||||
flash_net_internal: Namespace::internal("flash.net", context),
|
||||
|
||||
multinames: Gc::new(mc, multinames),
|
||||
|
||||
native_method_table: Default::default(),
|
||||
native_instance_allocator_table: Default::default(),
|
||||
native_super_initializer_table: Default::default(),
|
||||
|
|
|
@ -16,7 +16,7 @@ use crate::context::UpdateContext;
|
|||
use crate::string::WString;
|
||||
use bitflags::bitflags;
|
||||
use fnv::FnvHashMap;
|
||||
use gc_arena::{Collect, GcCell, Mutation};
|
||||
use gc_arena::{Collect, Gc, GcCell, Mutation};
|
||||
|
||||
use std::cell::Ref;
|
||||
use std::collections::HashSet;
|
||||
|
@ -524,7 +524,7 @@ impl<'gc> Class<'gc> {
|
|||
// A 'callable' class doesn't have a signature - let the
|
||||
// method do any needed coercions
|
||||
vec![],
|
||||
Multiname::any(),
|
||||
Gc::new(activation.gc(), Multiname::any()),
|
||||
true,
|
||||
activation.context.gc_context,
|
||||
);
|
||||
|
@ -1031,7 +1031,7 @@ impl<'gc> Class<'gc> {
|
|||
activation.context.gc_context,
|
||||
Trait::from_const(
|
||||
name,
|
||||
Multiname::new(activation.avm2().public_namespace_base_version, "Function"),
|
||||
activation.avm2().multinames.function,
|
||||
Some(value),
|
||||
),
|
||||
);
|
||||
|
@ -1049,7 +1049,7 @@ impl<'gc> Class<'gc> {
|
|||
activation.context.gc_context,
|
||||
Trait::from_const(
|
||||
QName::new(namespace, name),
|
||||
Multiname::new(activation.avm2().public_namespace_base_version, "Number"),
|
||||
activation.avm2().multinames.number,
|
||||
Some(value.into()),
|
||||
),
|
||||
);
|
||||
|
@ -1068,7 +1068,7 @@ impl<'gc> Class<'gc> {
|
|||
activation.context.gc_context,
|
||||
Trait::from_const(
|
||||
QName::new(namespace, name),
|
||||
Multiname::new(activation.avm2().public_namespace_base_version, "uint"),
|
||||
activation.avm2().multinames.uint,
|
||||
Some(value.into()),
|
||||
),
|
||||
);
|
||||
|
@ -1087,7 +1087,7 @@ impl<'gc> Class<'gc> {
|
|||
activation.context.gc_context,
|
||||
Trait::from_const(
|
||||
QName::new(namespace, name),
|
||||
Multiname::new(activation.avm2().public_namespace_base_version, "int"),
|
||||
activation.avm2().multinames.int,
|
||||
Some(value.into()),
|
||||
),
|
||||
);
|
||||
|
@ -1121,7 +1121,7 @@ impl<'gc> Class<'gc> {
|
|||
&'static str,
|
||||
NativeMethodImpl,
|
||||
Vec<ParamConfig<'gc>>,
|
||||
Multiname<'gc>,
|
||||
Gc<'gc, Multiname<'gc>>,
|
||||
)>,
|
||||
) {
|
||||
for (name, value, params, return_type) in items {
|
||||
|
@ -1198,7 +1198,7 @@ impl<'gc> Class<'gc> {
|
|||
activation.context.gc_context,
|
||||
Trait::from_const(
|
||||
QName::new(namespace, name),
|
||||
Multiname::new(activation.avm2().public_namespace_base_version, "int"),
|
||||
activation.avm2().multinames.int,
|
||||
Some(value.into()),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -2,7 +2,6 @@ use crate::avm2::activation::Activation;
|
|||
use crate::avm2::api_version::ApiVersion;
|
||||
use crate::avm2::class::Class;
|
||||
use crate::avm2::domain::Domain;
|
||||
use crate::avm2::multiname::Multiname;
|
||||
use crate::avm2::object::{ClassObject, ScriptObject, TObject};
|
||||
use crate::avm2::scope::{Scope, ScopeChain};
|
||||
use crate::avm2::script::Script;
|
||||
|
@ -613,7 +612,7 @@ pub fn load_player_globals<'gc>(
|
|||
// right now.
|
||||
global_traits.push(Trait::from_const(
|
||||
qname,
|
||||
Multiname::new(public_ns, "Function"),
|
||||
activation.avm2().multinames.function,
|
||||
Some(Value::Null),
|
||||
));
|
||||
}
|
||||
|
|
|
@ -183,6 +183,8 @@ fn describe_internal_body<'gc>(
|
|||
class_def: Class<'gc>,
|
||||
flags: DescribeTypeFlags,
|
||||
) -> Result<Object<'gc>, Error<'gc>> {
|
||||
let mc = activation.gc();
|
||||
|
||||
let traits = activation
|
||||
.avm2()
|
||||
.classes()
|
||||
|
@ -225,30 +227,18 @@ fn describe_internal_body<'gc>(
|
|||
traits.set_public_property("methods", Value::Null, activation)?;
|
||||
}
|
||||
|
||||
let mut bases_array = bases
|
||||
.as_array_storage_mut(activation.context.gc_context)
|
||||
.unwrap();
|
||||
let mut interfaces_array = interfaces
|
||||
.as_array_storage_mut(activation.context.gc_context)
|
||||
.unwrap();
|
||||
let mut variables_array = variables
|
||||
.as_array_storage_mut(activation.context.gc_context)
|
||||
.unwrap();
|
||||
let mut accessors_array = accessors
|
||||
.as_array_storage_mut(activation.context.gc_context)
|
||||
.unwrap();
|
||||
let mut methods_array = methods
|
||||
.as_array_storage_mut(activation.context.gc_context)
|
||||
.unwrap();
|
||||
let mut bases_array = bases.as_array_storage_mut(mc).unwrap();
|
||||
let mut interfaces_array = interfaces.as_array_storage_mut(mc).unwrap();
|
||||
let mut variables_array = variables.as_array_storage_mut(mc).unwrap();
|
||||
let mut accessors_array = accessors.as_array_storage_mut(mc).unwrap();
|
||||
let mut methods_array = methods.as_array_storage_mut(mc).unwrap();
|
||||
|
||||
let superclass = class_def.super_class();
|
||||
|
||||
if flags.contains(DescribeTypeFlags::INCLUDE_BASES) {
|
||||
let mut current_super_class = superclass;
|
||||
while let Some(super_class) = current_super_class {
|
||||
let super_name = super_class
|
||||
.name()
|
||||
.to_qualified_name(activation.context.gc_context);
|
||||
let super_name = super_class.name().to_qualified_name(mc);
|
||||
bases_array.push(super_name.into());
|
||||
current_super_class = super_class.super_class();
|
||||
}
|
||||
|
@ -259,9 +249,7 @@ fn describe_internal_body<'gc>(
|
|||
|
||||
if flags.contains(DescribeTypeFlags::INCLUDE_INTERFACES) {
|
||||
for interface in &*class_def.all_interfaces() {
|
||||
let interface_name = interface
|
||||
.name()
|
||||
.to_qualified_name(activation.context.gc_context);
|
||||
let interface_name = interface.name().to_qualified_name(mc);
|
||||
interfaces_array.push(interface_name.into());
|
||||
}
|
||||
}
|
||||
|
@ -314,9 +302,7 @@ fn describe_internal_body<'gc>(
|
|||
if !flags.contains(DescribeTypeFlags::INCLUDE_VARIABLES) {
|
||||
continue;
|
||||
}
|
||||
let prop_class_name = vtable
|
||||
.slot_class_name(*slot_id)?
|
||||
.to_qualified_name_or_star(activation.context.gc_context);
|
||||
let prop_class_name = vtable.slot_class_name(mc, *slot_id)?;
|
||||
|
||||
let access = match prop {
|
||||
Property::ConstSlot { .. } => "readonly",
|
||||
|
@ -370,10 +356,7 @@ fn describe_internal_body<'gc>(
|
|||
continue;
|
||||
}
|
||||
|
||||
let return_type_name = method
|
||||
.method
|
||||
.return_type()
|
||||
.to_qualified_name_or_star(activation.context.gc_context);
|
||||
let return_type_name = method.method.return_type().to_qualified_name_or_star(mc);
|
||||
let declared_by = method.class;
|
||||
|
||||
if flags.contains(DescribeTypeFlags::HIDE_OBJECT)
|
||||
|
@ -382,9 +365,7 @@ fn describe_internal_body<'gc>(
|
|||
continue;
|
||||
}
|
||||
|
||||
let declared_by_name = declared_by
|
||||
.dollar_removed_name(activation.context.gc_context)
|
||||
.to_qualified_name(activation.context.gc_context);
|
||||
let declared_by_name = declared_by.dollar_removed_name(mc).to_qualified_name(mc);
|
||||
|
||||
let trait_metadata = vtable.get_metadata_for_disp(disp_id);
|
||||
|
||||
|
@ -475,11 +456,8 @@ fn describe_internal_body<'gc>(
|
|||
Some(ns.as_uri())
|
||||
};
|
||||
|
||||
let accessor_type =
|
||||
method_type.to_qualified_name_or_star(activation.context.gc_context);
|
||||
let declared_by = defining_class
|
||||
.dollar_removed_name(activation.context.gc_context)
|
||||
.to_qualified_name(activation.context.gc_context);
|
||||
let accessor_type = method_type.to_qualified_name_or_star(mc);
|
||||
let declared_by = defining_class.dollar_removed_name(mc).to_qualified_name(mc);
|
||||
|
||||
let accessor_obj = activation
|
||||
.avm2()
|
||||
|
|
|
@ -9,6 +9,8 @@ use crate::avm2::object::{primitive_allocator, FunctionObject, Object, TObject};
|
|||
use crate::avm2::value::Value;
|
||||
use crate::avm2::{AvmString, Error, Multiname, QName};
|
||||
|
||||
use gc_arena::Gc;
|
||||
|
||||
/// Implements `int`'s instance initializer.
|
||||
fn instance_init<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
|
@ -227,10 +229,10 @@ pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> Class<'gc> {
|
|||
"<int instance initializer>",
|
||||
vec![ParamConfig {
|
||||
param_name: AvmString::new_utf8(activation.context.gc_context, "value"),
|
||||
param_type_name: Multiname::any(),
|
||||
param_type_name: Gc::new(mc, Multiname::any()),
|
||||
default_value: Some(Value::Integer(0)),
|
||||
}],
|
||||
Multiname::any(),
|
||||
Gc::new(mc, Multiname::any()),
|
||||
true,
|
||||
mc,
|
||||
),
|
||||
|
|
|
@ -10,6 +10,8 @@ use crate::avm2::Error;
|
|||
use crate::avm2::Multiname;
|
||||
use crate::avm2::QName;
|
||||
|
||||
use gc_arena::Gc;
|
||||
|
||||
/// Implements `Object`'s instance initializer.
|
||||
pub fn instance_init<'gc>(
|
||||
_activation: &mut Activation<'_, 'gc>,
|
||||
|
@ -279,30 +281,30 @@ pub fn create_i_class<'gc>(activation: &mut Activation<'_, 'gc>) -> Class<'gc> {
|
|||
has_own_property,
|
||||
vec![ParamConfig::optional(
|
||||
"name",
|
||||
Multiname::any(),
|
||||
Gc::new(gc_context, Multiname::any()),
|
||||
Value::Undefined,
|
||||
)],
|
||||
Multiname::new(activation.avm2().public_namespace_base_version, "Boolean"),
|
||||
activation.avm2().multinames.boolean,
|
||||
),
|
||||
(
|
||||
"isPrototypeOf",
|
||||
is_prototype_of,
|
||||
vec![ParamConfig::optional(
|
||||
"theClass",
|
||||
Multiname::any(),
|
||||
Gc::new(gc_context, Multiname::any()),
|
||||
Value::Undefined,
|
||||
)],
|
||||
Multiname::new(activation.avm2().public_namespace_base_version, "Boolean"),
|
||||
activation.avm2().multinames.boolean,
|
||||
),
|
||||
(
|
||||
"propertyIsEnumerable",
|
||||
property_is_enumerable,
|
||||
vec![ParamConfig::optional(
|
||||
"name",
|
||||
Multiname::any(),
|
||||
Gc::new(gc_context, Multiname::any()),
|
||||
Value::Undefined,
|
||||
)],
|
||||
Multiname::new(activation.avm2().public_namespace_base_version, "Boolean"),
|
||||
activation.avm2().multinames.boolean,
|
||||
),
|
||||
];
|
||||
object_i_class.define_builtin_instance_methods_with_sig(
|
||||
|
@ -337,7 +339,7 @@ pub fn create_c_class<'gc>(
|
|||
gc_context,
|
||||
Trait::from_const(
|
||||
QName::new(activation.avm2().public_namespace_base_version, "length"),
|
||||
Multiname::new(activation.avm2().public_namespace_base_version, "int"),
|
||||
activation.avm2().multinames.int,
|
||||
Some(1.into()),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -9,6 +9,8 @@ use crate::avm2::object::{primitive_allocator, FunctionObject, Object, TObject};
|
|||
use crate::avm2::value::Value;
|
||||
use crate::avm2::{AvmString, Error, Multiname, QName};
|
||||
|
||||
use gc_arena::Gc;
|
||||
|
||||
/// Implements `uint`'s instance initializer.
|
||||
fn instance_init<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
|
@ -228,10 +230,10 @@ pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> Class<'gc> {
|
|||
"<uint instance initializer>",
|
||||
vec![ParamConfig {
|
||||
param_name: AvmString::new_utf8(activation.context.gc_context, "value"),
|
||||
param_type_name: Multiname::any(),
|
||||
param_type_name: Gc::new(mc, Multiname::any()),
|
||||
default_value: Some(Value::Integer(0)),
|
||||
}],
|
||||
Multiname::any(),
|
||||
Gc::new(mc, Multiname::any()),
|
||||
true,
|
||||
mc,
|
||||
),
|
||||
|
|
|
@ -15,7 +15,6 @@ use gc_arena::lock::Lock;
|
|||
use gc_arena::{Collect, Gc, GcCell, Mutation};
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use swf::avm2::types::{
|
||||
|
@ -61,7 +60,7 @@ pub struct ParamConfig<'gc> {
|
|||
pub param_name: AvmString<'gc>,
|
||||
|
||||
/// The name of the type of the parameter.
|
||||
pub param_type_name: Multiname<'gc>,
|
||||
pub param_type_name: Gc<'gc, Multiname<'gc>>,
|
||||
|
||||
/// The default value for this parameter.
|
||||
pub default_value: Option<Value<'gc>>,
|
||||
|
@ -80,10 +79,7 @@ impl<'gc> ParamConfig<'gc> {
|
|||
} else {
|
||||
AvmString::from("<Unnamed Parameter>")
|
||||
};
|
||||
let param_type_name = txunit
|
||||
.pool_multiname_static_any(config.kind, activation.context)?
|
||||
.deref()
|
||||
.clone();
|
||||
let param_type_name = txunit.pool_multiname_static_any(config.kind, activation.context)?;
|
||||
|
||||
let default_value = if let Some(dv) = &config.default_value {
|
||||
Some(abc_default_value(txunit, dv, activation)?)
|
||||
|
@ -98,7 +94,10 @@ impl<'gc> ParamConfig<'gc> {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn of_type(name: impl Into<AvmString<'gc>>, param_type_name: Multiname<'gc>) -> Self {
|
||||
pub fn of_type(
|
||||
name: impl Into<AvmString<'gc>>,
|
||||
param_type_name: Gc<'gc, Multiname<'gc>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
param_name: name.into(),
|
||||
param_type_name,
|
||||
|
@ -108,7 +107,7 @@ impl<'gc> ParamConfig<'gc> {
|
|||
|
||||
pub fn optional(
|
||||
name: impl Into<AvmString<'gc>>,
|
||||
param_type_name: Multiname<'gc>,
|
||||
param_type_name: Gc<'gc, Multiname<'gc>>,
|
||||
default_value: impl Into<Value<'gc>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
|
@ -142,7 +141,7 @@ pub struct BytecodeMethod<'gc> {
|
|||
pub signature: Vec<ParamConfig<'gc>>,
|
||||
|
||||
/// The return type of this method.
|
||||
pub return_type: Multiname<'gc>,
|
||||
pub return_type: Gc<'gc, Multiname<'gc>>,
|
||||
|
||||
/// The associated activation class. Initialized lazily, and only
|
||||
/// if the method requires it.
|
||||
|
@ -163,9 +162,11 @@ impl<'gc> BytecodeMethod<'gc> {
|
|||
is_function: bool,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
) -> Result<Self, Error<'gc>> {
|
||||
let mc = activation.gc();
|
||||
|
||||
let abc = txunit.abc();
|
||||
let mut signature = Vec::new();
|
||||
let mut return_type = Multiname::any();
|
||||
let mut return_type = Gc::new(mc, Multiname::any());
|
||||
let mut abc_method_body = None;
|
||||
|
||||
if abc.methods.get(abc_method.0 as usize).is_some() {
|
||||
|
@ -174,10 +175,8 @@ impl<'gc> BytecodeMethod<'gc> {
|
|||
signature.push(ParamConfig::from_abc_param(param, txunit, activation)?);
|
||||
}
|
||||
|
||||
return_type = txunit
|
||||
.pool_multiname_static_any(method.return_type, activation.context)?
|
||||
.deref()
|
||||
.clone();
|
||||
return_type =
|
||||
txunit.pool_multiname_static_any(method.return_type, activation.context)?;
|
||||
|
||||
if let Some(body) = method.body {
|
||||
abc_method_body = Some(body.0);
|
||||
|
@ -189,7 +188,7 @@ impl<'gc> BytecodeMethod<'gc> {
|
|||
abc: txunit.abc(),
|
||||
abc_method: abc_method.0,
|
||||
abc_method_body,
|
||||
verified_info: GcCell::new(activation.context.gc_context, None),
|
||||
verified_info: GcCell::new(mc, None),
|
||||
signature,
|
||||
return_type,
|
||||
is_function,
|
||||
|
@ -337,7 +336,7 @@ pub struct NativeMethod<'gc> {
|
|||
pub resolved_signature: GcCell<'gc, Option<Vec<ResolvedParamConfig<'gc>>>>,
|
||||
|
||||
/// The return type of this method.
|
||||
pub return_type: Multiname<'gc>,
|
||||
pub return_type: Gc<'gc, Multiname<'gc>>,
|
||||
|
||||
/// Whether or not this method accepts parameters beyond those
|
||||
/// mentioned in the parameter list.
|
||||
|
@ -391,7 +390,7 @@ impl<'gc> Method<'gc> {
|
|||
method: NativeMethodImpl,
|
||||
name: &'static str,
|
||||
signature: Vec<ParamConfig<'gc>>,
|
||||
return_type: Multiname<'gc>,
|
||||
return_type: Gc<'gc, Multiname<'gc>>,
|
||||
is_variadic: bool,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Self {
|
||||
|
@ -418,7 +417,7 @@ impl<'gc> Method<'gc> {
|
|||
signature: Vec::new(),
|
||||
resolved_signature: GcCell::new(mc, None),
|
||||
// FIXME - take in the real return type. This is needed for 'describeType'
|
||||
return_type: Multiname::any(),
|
||||
return_type: Gc::new(mc, Multiname::any()),
|
||||
is_variadic: true,
|
||||
},
|
||||
))
|
||||
|
@ -436,10 +435,10 @@ impl<'gc> Method<'gc> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn return_type(&self) -> Multiname<'gc> {
|
||||
pub fn return_type(&self) -> Gc<'gc, Multiname<'gc>> {
|
||||
match self {
|
||||
Method::Native(nm) => nm.return_type.clone(),
|
||||
Method::Bytecode(bm) => bm.return_type.clone(),
|
||||
Method::Native(nm) => nm.return_type,
|
||||
Method::Bytecode(bm) => bm.return_type,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::avm2::Error;
|
|||
use crate::avm2::Namespace;
|
||||
use crate::avm2::QName;
|
||||
use crate::avm2::{Object, Value};
|
||||
use crate::context::UpdateContext;
|
||||
use crate::context::{GcContext, UpdateContext};
|
||||
use crate::string::{AvmString, WStr, WString};
|
||||
use bitflags::bitflags;
|
||||
use gc_arena::Gc;
|
||||
|
@ -519,3 +519,40 @@ impl<'gc> From<QName<'gc>> for Multiname<'gc> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub struct CommonMultinames<'gc> {
|
||||
pub boolean: Gc<'gc, Multiname<'gc>>,
|
||||
pub function: Gc<'gc, Multiname<'gc>>,
|
||||
pub int: Gc<'gc, Multiname<'gc>>,
|
||||
pub number: Gc<'gc, Multiname<'gc>>,
|
||||
pub uint: Gc<'gc, Multiname<'gc>>,
|
||||
}
|
||||
|
||||
impl<'gc> CommonMultinames<'gc> {
|
||||
pub fn new(
|
||||
context: &mut GcContext<'_, 'gc>,
|
||||
public_namespace_base_version: Namespace<'gc>,
|
||||
) -> Self {
|
||||
let mut create_pub_multiname = |local_name: &'static [u8]| -> Gc<'gc, Multiname<'gc>> {
|
||||
Gc::new(
|
||||
context.gc_context,
|
||||
Multiname::new(
|
||||
public_namespace_base_version,
|
||||
context
|
||||
.interner
|
||||
.intern_static(context.gc_context, WStr::from_units(local_name)),
|
||||
),
|
||||
)
|
||||
};
|
||||
|
||||
Self {
|
||||
boolean: create_pub_multiname(b"Boolean"),
|
||||
function: create_pub_multiname(b"Function"),
|
||||
int: create_pub_multiname(b"int"),
|
||||
number: create_pub_multiname(b"Number"),
|
||||
uint: create_pub_multiname(b"uint"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,20 +30,22 @@ pub fn function_allocator<'gc>(
|
|||
) -> Result<Object<'gc>, Error<'gc>> {
|
||||
let base = ScriptObjectData::new(class);
|
||||
|
||||
let mc = activation.gc();
|
||||
|
||||
let dummy = Gc::new(
|
||||
activation.context.gc_context,
|
||||
mc,
|
||||
NativeMethod {
|
||||
method: |_, _, _| Ok(Value::Undefined),
|
||||
name: "<Empty Function>",
|
||||
signature: vec![],
|
||||
resolved_signature: GcCell::new(activation.context.gc_context, None),
|
||||
return_type: Multiname::any(),
|
||||
resolved_signature: GcCell::new(mc, None),
|
||||
return_type: Gc::new(mc, Multiname::any()),
|
||||
is_variadic: true,
|
||||
},
|
||||
);
|
||||
|
||||
Ok(FunctionObject(Gc::new(
|
||||
activation.context.gc_context,
|
||||
mc,
|
||||
FunctionObjectData {
|
||||
base,
|
||||
exec: RefLock::new(BoundMethod::from_method(
|
||||
|
|
|
@ -5,6 +5,7 @@ use crate::avm2::Error;
|
|||
use crate::avm2::Multiname;
|
||||
use crate::avm2::TranslationUnit;
|
||||
use crate::avm2::Value;
|
||||
use crate::string::AvmString;
|
||||
use gc_arena::{Collect, Gc, Mutation};
|
||||
|
||||
use super::class::Class;
|
||||
|
@ -39,13 +40,13 @@ pub enum PropertyClass<'gc> {
|
|||
/// from the `Object` class
|
||||
Any,
|
||||
Class(Class<'gc>),
|
||||
Name(Gc<'gc, (Multiname<'gc>, Option<TranslationUnit<'gc>>)>),
|
||||
Name(Gc<'gc, (Gc<'gc, Multiname<'gc>>, Option<TranslationUnit<'gc>>)>),
|
||||
}
|
||||
|
||||
impl<'gc> PropertyClass<'gc> {
|
||||
pub fn name(
|
||||
mc: &Mutation<'gc>,
|
||||
name: Multiname<'gc>,
|
||||
name: Gc<'gc, Multiname<'gc>>,
|
||||
unit: Option<TranslationUnit<'gc>>,
|
||||
) -> Self {
|
||||
PropertyClass::Name(Gc::new(mc, (name, unit)))
|
||||
|
@ -127,11 +128,11 @@ impl<'gc> PropertyClass<'gc> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_name(&self) -> Multiname<'gc> {
|
||||
pub fn get_name(&self, mc: &Mutation<'gc>) -> AvmString<'gc> {
|
||||
match self {
|
||||
PropertyClass::Class(class) => class.name().into(),
|
||||
PropertyClass::Name(gc) => gc.0.clone(),
|
||||
PropertyClass::Any => Multiname::any(),
|
||||
PropertyClass::Class(class) => class.name().to_qualified_name(mc),
|
||||
PropertyClass::Name(gc) => gc.0.to_qualified_name_or_star(mc),
|
||||
PropertyClass::Any => AvmString::new_utf8(mc, "*"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,8 +10,7 @@ use crate::avm2::Error;
|
|||
use crate::avm2::Multiname;
|
||||
use crate::avm2::QName;
|
||||
use bitflags::bitflags;
|
||||
use gc_arena::Collect;
|
||||
use std::ops::Deref;
|
||||
use gc_arena::{Collect, Gc};
|
||||
use swf::avm2::types::{
|
||||
DefaultValue as AbcDefaultValue, Trait as AbcTrait, TraitKind as AbcTraitKind,
|
||||
};
|
||||
|
@ -75,7 +74,7 @@ pub enum TraitKind<'gc> {
|
|||
/// to.
|
||||
Slot {
|
||||
slot_id: u32,
|
||||
type_name: Multiname<'gc>,
|
||||
type_name: Gc<'gc, Multiname<'gc>>,
|
||||
default_value: Value<'gc>,
|
||||
unit: Option<TranslationUnit<'gc>>,
|
||||
},
|
||||
|
@ -100,7 +99,7 @@ pub enum TraitKind<'gc> {
|
|||
/// be overridden.
|
||||
Const {
|
||||
slot_id: u32,
|
||||
type_name: Multiname<'gc>,
|
||||
type_name: Gc<'gc, Multiname<'gc>>,
|
||||
default_value: Value<'gc>,
|
||||
unit: Option<TranslationUnit<'gc>>,
|
||||
},
|
||||
|
@ -157,7 +156,7 @@ impl<'gc> Trait<'gc> {
|
|||
|
||||
pub fn from_slot(
|
||||
name: QName<'gc>,
|
||||
type_name: Multiname<'gc>,
|
||||
type_name: Gc<'gc, Multiname<'gc>>,
|
||||
default_value: Option<Value<'gc>>,
|
||||
) -> Self {
|
||||
Trait {
|
||||
|
@ -175,7 +174,7 @@ impl<'gc> Trait<'gc> {
|
|||
|
||||
pub fn from_const(
|
||||
name: QName<'gc>,
|
||||
type_name: Multiname<'gc>,
|
||||
type_name: Gc<'gc, Multiname<'gc>>,
|
||||
default_value: Option<Value<'gc>>,
|
||||
) -> Self {
|
||||
Trait {
|
||||
|
@ -205,10 +204,7 @@ impl<'gc> Trait<'gc> {
|
|||
type_name,
|
||||
value,
|
||||
} => {
|
||||
let type_name = unit
|
||||
.pool_multiname_static_any(*type_name, activation.context)?
|
||||
.deref()
|
||||
.clone();
|
||||
let type_name = unit.pool_multiname_static_any(*type_name, activation.context)?;
|
||||
let default_value = slot_default_value(unit, value, &type_name, activation)?;
|
||||
Trait {
|
||||
name,
|
||||
|
@ -272,10 +268,7 @@ impl<'gc> Trait<'gc> {
|
|||
type_name,
|
||||
value,
|
||||
} => {
|
||||
let type_name = unit
|
||||
.pool_multiname_static_any(*type_name, activation.context)?
|
||||
.deref()
|
||||
.clone();
|
||||
let type_name = unit.pool_multiname_static_any(*type_name, activation.context)?;
|
||||
let default_value = slot_default_value(unit, value, &type_name, activation)?;
|
||||
Trait {
|
||||
name,
|
||||
|
|
|
@ -112,13 +112,17 @@ impl<'gc> VTable<'gc> {
|
|||
self.0.read().disp_metadata_table.get(disp_id).cloned()
|
||||
}
|
||||
|
||||
pub fn slot_class_name(&self, slot_id: u32) -> Result<Multiname<'gc>, Error<'gc>> {
|
||||
pub fn slot_class_name(
|
||||
&self,
|
||||
mc: &Mutation<'gc>,
|
||||
slot_id: u32,
|
||||
) -> Result<AvmString<'gc>, Error<'gc>> {
|
||||
self.0
|
||||
.read()
|
||||
.slot_classes
|
||||
.get(slot_id as usize)
|
||||
.ok_or_else(|| "Invalid slot ID".into())
|
||||
.map(|c| c.get_name())
|
||||
.map(|c| c.get_name(mc))
|
||||
}
|
||||
|
||||
pub fn get_trait(self, name: &Multiname<'gc>) -> Option<Property> {
|
||||
|
|
Loading…
Reference in New Issue