Fix the error messages for `findpropstrict` and `getlex` to be more informative.

This commit is contained in:
David Wendt 2020-02-22 19:02:53 -05:00
parent 843de29460
commit 38b1524a49
2 changed files with 31 additions and 26 deletions

View File

@ -730,11 +730,12 @@ impl<'gc> Avm2<'gc> {
index: Index<AbcMultiname>, index: Index<AbcMultiname>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let multiname = self.pool_multiname(index)?; let multiname = self.pool_multiname(index)?;
let result = if let Some(scope) = self.current_stack_frame().unwrap().read().scope() { let result = self
scope.read().find(&multiname, self, context)? .current_stack_frame()
} else { .unwrap()
None .read()
}; .scope()
.and_then(|scope| scope.read().find(&multiname, self, context));
self.push(result.map(|o| o.into()).unwrap_or(Value::Undefined)); self.push(result.map(|o| o.into()).unwrap_or(Value::Undefined));
@ -747,12 +748,12 @@ impl<'gc> Avm2<'gc> {
index: Index<AbcMultiname>, index: Index<AbcMultiname>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let multiname = self.pool_multiname(index)?; let multiname = self.pool_multiname(index)?;
let found: Result<Object<'gc>, Error> = let found: Result<Object<'gc>, Error> = self
if let Some(scope) = self.current_stack_frame().unwrap().read().scope() { .current_stack_frame()
scope.read().find(&multiname, self, context)? .unwrap()
} else { .read()
None .scope()
} .and_then(|scope| scope.read().find(&multiname, self, context))
.ok_or_else(|| format!("Property does not exist: {:?}", multiname.local_name()).into()); .ok_or_else(|| format!("Property does not exist: {:?}", multiname.local_name()).into());
let result: Value<'gc> = found?.into(); let result: Value<'gc> = found?.into();
@ -767,13 +768,14 @@ impl<'gc> Avm2<'gc> {
index: Index<AbcMultiname>, index: Index<AbcMultiname>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let multiname = self.pool_multiname_static(index)?; let multiname = self.pool_multiname_static(index)?;
let found: Result<ReturnValue<'gc>, Error> = let found: Result<Result<ReturnValue<'gc>, Error>, Error> = self
if let Some(scope) = self.current_stack_frame().unwrap().read().scope() { .current_stack_frame()
Ok(scope.read().resolve(&multiname, self, context)?) .unwrap()
} else { .read()
Err("No objects exist on scope".into()) .scope()
}; .and_then(|scope| scope.read().resolve(&multiname, self, context))
let result: Value<'gc> = found?.resolve(self, context)?; .ok_or_else(|| format!("Property does not exist: {:?}", multiname.local_name()).into());
let result: Value<'gc> = found??.resolve(self, context)?;
self.push(result); self.push(result);

View File

@ -3,7 +3,6 @@
use crate::avm2::names::Multiname; use crate::avm2::names::Multiname;
use crate::avm2::object::{Object, TObject}; use crate::avm2::object::{Object, TObject};
use crate::avm2::return_value::ReturnValue; use crate::avm2::return_value::ReturnValue;
use crate::avm2::value::Value;
use crate::avm2::{Avm2, Error}; use crate::avm2::{Avm2, Error};
use crate::context::UpdateContext; use crate::context::UpdateContext;
use gc_arena::{Collect, GcCell, MutationContext}; use gc_arena::{Collect, GcCell, MutationContext};
@ -96,15 +95,17 @@ impl<'gc> Scope<'gc> {
} }
/// Find an object that contains a given property in the scope stack. /// Find an object that contains a given property in the scope stack.
///
/// This function yields `None` if no such scope exists.
pub fn find( pub fn find(
&self, &self,
name: &Multiname, name: &Multiname,
avm: &mut Avm2<'gc>, avm: &mut Avm2<'gc>,
context: &mut UpdateContext<'_, 'gc, '_>, context: &mut UpdateContext<'_, 'gc, '_>,
) -> Result<Option<Object<'gc>>, Error> { ) -> Option<Object<'gc>> {
if let Some(qname) = self.locals().resolve_multiname(name) { if let Some(qname) = self.locals().resolve_multiname(name) {
if self.locals().has_property(&qname) { if self.locals().has_property(&qname) {
return Ok(Some(*self.locals())); return Some(*self.locals());
} }
} }
@ -112,20 +113,22 @@ impl<'gc> Scope<'gc> {
return scope.find(name, avm, context); return scope.find(name, avm, context);
} }
//TODO: This should actually be an error. None
Ok(None)
} }
/// Resolve a particular value in the scope chain. /// Resolve a particular value in the scope chain.
///
/// This function yields `None` if no such scope exists to provide the
/// property's value.
pub fn resolve( pub fn resolve(
&self, &self,
name: &Multiname, name: &Multiname,
avm: &mut Avm2<'gc>, avm: &mut Avm2<'gc>,
context: &mut UpdateContext<'_, 'gc, '_>, context: &mut UpdateContext<'_, 'gc, '_>,
) -> Result<ReturnValue<'gc>, Error> { ) -> Option<Result<ReturnValue<'gc>, Error>> {
if let Some(qname) = self.locals().resolve_multiname(name) { if let Some(qname) = self.locals().resolve_multiname(name) {
if self.locals().has_property(&qname) { if self.locals().has_property(&qname) {
return self.locals().get_property(&qname, avm, context); return Some(self.locals().get_property(&qname, avm, context));
} }
} }
@ -134,6 +137,6 @@ impl<'gc> Scope<'gc> {
} }
//TODO: Should undefined variables halt execution? //TODO: Should undefined variables halt execution?
Ok(Value::Undefined.into()) None
} }
} }