Implement slot traits.

This commit is contained in:
David Wendt 2020-02-20 22:04:31 -05:00
parent 200c10b4a2
commit af70024f62
2 changed files with 36 additions and 2 deletions

View File

@ -8,7 +8,7 @@ use crate::avm2::property::Attribute;
use crate::avm2::return_value::ReturnValue;
use crate::avm2::scope::Scope;
use crate::avm2::script_object::ScriptObject;
use crate::avm2::value::Value;
use crate::avm2::value::{abc_default_value, Value};
use crate::avm2::{Avm2, Error};
use crate::context::UpdateContext;
use enumset::EnumSet;
@ -173,6 +173,14 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
);
match &trait_entry.kind {
AbcTraitKind::Slot { slot_id, value, .. } => {
let value = if let Some(value) = value {
abc_default_value(&abc, value)?
} else {
Value::Undefined
};
self.install_slot(context.gc_context, trait_name, *slot_id, value);
}
AbcTraitKind::Method { method, .. } => {
let method = Avm2MethodEntry::from_method_index(abc, method.clone()).unwrap();
let function =

View File

@ -5,7 +5,7 @@ use crate::avm2::object::Object;
use crate::avm2::Error;
use gc_arena::Collect;
use std::f64::NAN;
use swf::avm2::types::{AbcFile, Index};
use swf::avm2::types::{AbcFile, DefaultValue as AbcDefaultValue, Index};
/// An AVM2 value.
///
@ -210,6 +210,32 @@ pub fn abc_string_option(file: &AbcFile, index: Index<String>) -> Result<Option<
.ok_or_else(|| format!("Unknown string constant {}", index.0).into())
}
/// Retrieve a default value as an AVM2 `Value`.
pub fn abc_default_value<'gc>(
file: &AbcFile,
default: &AbcDefaultValue,
) -> Result<Value<'gc>, Error> {
match default {
AbcDefaultValue::Int(i) => abc_int(file, *i).map(|v| v.into()),
AbcDefaultValue::Uint(u) => abc_uint(file, *u).map(|v| v.into()),
AbcDefaultValue::Double(d) => abc_double(file, *d).map(|v| v.into()),
AbcDefaultValue::String(s) => abc_string(file, s.clone()).map(|v| v.into()),
AbcDefaultValue::True => Ok(true.into()),
AbcDefaultValue::False => Ok(false.into()),
AbcDefaultValue::Null => Ok(Value::Null),
AbcDefaultValue::Undefined => Ok(Value::Undefined),
AbcDefaultValue::Namespace(ns)
| AbcDefaultValue::Package(ns)
| AbcDefaultValue::PackageInternal(ns)
| AbcDefaultValue::Protected(ns)
| AbcDefaultValue::Explicit(ns)
| AbcDefaultValue::StaticProtected(ns)
| AbcDefaultValue::Private(ns) => {
Namespace::from_abc_namespace(file, ns.clone()).map(|v| v.into())
}
}
}
impl<'gc> Value<'gc> {
pub fn as_object(&self) -> Result<Object<'gc>, Error> {
if let Value::Object(object) = self {