avm2: Handle TODOs, throw errors where applicable

This commit is contained in:
Adrian Wielgosik 2021-12-04 22:05:23 +01:00 committed by Adrian Wielgosik
parent 24247dff0b
commit 1d8c556944
5 changed files with 13 additions and 17 deletions

View File

@ -148,9 +148,10 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
if let Some(bound_method) = vtable.make_bound_method(activation, self.into(), disp_id) if let Some(bound_method) = vtable.make_bound_method(activation, self.into(), disp_id)
{ {
self.install_bound_method(activation.context.gc_context, disp_id, bound_method); self.install_bound_method(activation.context.gc_context, disp_id, bound_method);
return Ok(bound_method.into()); Ok(bound_method.into())
} else {
Err("Method not found".into())
} }
todo!("unreachable?")
} }
Some(Property::Virtual{get: Some(get), ..}) => { Some(Property::Virtual{get: Some(get), ..}) => {
self.call_method(get, &[], activation) self.call_method(get, &[], activation)
@ -191,7 +192,6 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
activation: &mut Activation<'_, 'gc, '_>, activation: &mut Activation<'_, 'gc, '_>,
) -> Result<(), Error> { ) -> Result<(), Error> {
match self.vtable().and_then(|vtable| vtable.get_trait(multiname)) { match self.vtable().and_then(|vtable| vtable.get_trait(multiname)) {
// also TODO: check for read-only (`const`)
Some(Property::Slot{slot_id}) => self.base_mut(activation.context.gc_context).set_slot(slot_id, value, activation.context.gc_context), Some(Property::Slot{slot_id}) => self.base_mut(activation.context.gc_context).set_slot(slot_id, value, activation.context.gc_context),
Some(Property::ConstSlot{..}) => { Some(Property::ConstSlot{..}) => {
Err("Illegal write to read-only property".into()) Err("Illegal write to read-only property".into())
@ -235,7 +235,6 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
value: Value<'gc>, value: Value<'gc>,
activation: &mut Activation<'_, 'gc, '_>, activation: &mut Activation<'_, 'gc, '_>,
) -> Result<(), Error> { ) -> Result<(), Error> {
// TODO: currently identical to set_property
match self.vtable().and_then(|vtable| vtable.get_trait(multiname)) { match self.vtable().and_then(|vtable| vtable.get_trait(multiname)) {
Some(Property::Slot{slot_id}) | Some(Property::ConstSlot{slot_id}) Some(Property::Slot{slot_id}) | Some(Property::ConstSlot{slot_id})
=> self.base_mut(activation.context.gc_context).set_slot(slot_id, value, activation.context.gc_context), => self.base_mut(activation.context.gc_context).set_slot(slot_id, value, activation.context.gc_context),
@ -290,22 +289,23 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
{ {
if !method.needs_arguments_object() { if !method.needs_arguments_object() {
let scope = superclass.unwrap().instance_scope(); let scope = superclass.unwrap().instance_scope();
return Executable::from_method(method, scope, None, superclass).exec( Executable::from_method(method, scope, None, superclass).exec(
Some(self.into()), Some(self.into()),
arguments, arguments,
activation, activation,
superclass.unwrap().into(), //Deliberately invalid. superclass.unwrap().into(), //Deliberately invalid.
); )
} else { } else {
if let Some(bound_method) = self.base().get_bound_method(disp_id) { if let Some(bound_method) = self.base().get_bound_method(disp_id) {
return bound_method.call(Some(self.into()), arguments, activation); return bound_method.call(Some(self.into()), arguments, activation);
} }
let bound_method = vtable.make_bound_method(activation, self.into(), disp_id).unwrap(); let bound_method = vtable.make_bound_method(activation, self.into(), disp_id).unwrap();
self.install_bound_method(activation.context.gc_context, disp_id, bound_method); self.install_bound_method(activation.context.gc_context, disp_id, bound_method);
return bound_method.call(Some(self.into()), arguments, activation); bound_method.call(Some(self.into()), arguments, activation)
} }
} else {
Err("Method not found".into())
} }
todo!("unreachable?")
}, },
Some(Property::Virtual{get: Some(get), ..}) => { Some(Property::Virtual{get: Some(get), ..}) => {
let obj = self.call_method(get, &[], activation)? let obj = self.call_method(get, &[], activation)?
@ -313,7 +313,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
obj.call(Some(self.into()), arguments, activation) obj.call(Some(self.into()), arguments, activation)
} }
Some(Property::Virtual{get: None, ..}) => { Some(Property::Virtual{get: None, ..}) => {
todo!("throw error") Err("Illegal read of write-only property".into())
} }
None => { None => {
self.call_property_local(multiname, arguments, activation) self.call_property_local(multiname, arguments, activation)

View File

@ -134,7 +134,6 @@ impl<'gc> TObject<'gc> for FunctionObject<'gc> {
activation: &mut Activation<'_, 'gc, '_>, activation: &mut Activation<'_, 'gc, '_>,
arguments: &[Value<'gc>], arguments: &[Value<'gc>],
) -> Result<Object<'gc>, Error> { ) -> Result<Object<'gc>, Error> {
// todo: handle errors?
let prototype = self.prototype().unwrap(); let prototype = self.prototype().unwrap();
let instance = prototype.derive(activation)?; let instance = prototype.derive(activation)?;

View File

@ -223,7 +223,6 @@ impl<'gc> TObject<'gc> for ProxyObject<'gc> {
Ok(self Ok(self
.call_property( .call_property(
&QName::new(Namespace::Namespace(NS_FLASH_PROXY.into()), "hasProperty").into(), &QName::new(Namespace::Namespace(NS_FLASH_PROXY.into()), "hasProperty").into(),
// TODO: handle unwrap?
// this should probably pass the multiname as-is? See above // this should probably pass the multiname as-is? See above
&[name.local_name().unwrap().into()], &[name.local_name().unwrap().into()],
activation, activation,

View File

@ -143,11 +143,11 @@ impl<'gc> ScriptObjectData<'gc> {
activation: &mut Activation<'_, 'gc, '_>, activation: &mut Activation<'_, 'gc, '_>,
) -> Result<Value<'gc>, Error> { ) -> Result<Value<'gc>, Error> {
if !multiname.contains_public_namespace() { if !multiname.contains_public_namespace() {
todo!("throw error") return Err("Non-public property not found on Object".into());
} }
let local_name = match multiname.local_name() { let local_name = match multiname.local_name() {
None => todo!("throw error"), None => return Err("Unnamed property not found on Object".into()),
Some(name) => name, Some(name) => name,
}; };
@ -189,11 +189,11 @@ impl<'gc> ScriptObjectData<'gc> {
} }
if !multiname.contains_public_namespace() { if !multiname.contains_public_namespace() {
todo!("throw error") return Err("Non-public property not found on Object".into());
} }
let local_name = match multiname.local_name() { let local_name = match multiname.local_name() {
None => todo!("throw error"), None => return Err("Unnamed property not found on Object".into()),
Some(name) => name, Some(name) => name,
}; };

View File

@ -99,8 +99,6 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
) -> Result<Value<'gc>, Error> { ) -> Result<Value<'gc>, Error> {
let read = self.0.read(); let read = self.0.read();
// TODO: why is this this way?
//if name.namespace().is_package("") {
if name.contains_public_namespace() { if name.contains_public_namespace() {
if let Some(name) = name.local_name() { if let Some(name) = name.local_name() {
if let Ok(index) = name.parse::<usize>() { if let Ok(index) = name.parse::<usize>() {