avm2: Fix 'hasDefinition' and 'getDefinition' for ApplicationDomain

These methods were incorrectly treating the argument as a local name,
instead of a qualified name. Additionally, 'getDefinition' now throws
an AVM error.
This commit is contained in:
Aaron Hill 2022-10-05 12:29:21 -05:00
parent a9dedf759a
commit 4b2907ead5
6 changed files with 46 additions and 8 deletions

View File

@ -66,16 +66,25 @@ pub fn get_definition<'gc>(
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(appdomain) = this.and_then(|this| this.as_application_domain()) {
let local_name = args
let name = args
.get(0)
.cloned()
.unwrap_or_else(|| "".into())
.coerce_to_string(activation)?;
let name = Multiname::public(local_name);
let (qname, mut defined_script) = appdomain
.get_defining_script(&name)?
.ok_or_else(|| format!("No definition called {} exists", local_name))?;
let name = QName::from_qualified_name(name, activation.context.gc_context);
let (qname, mut defined_script) = match appdomain.get_defining_script(&name.into())? {
Some(data) => data,
None => {
return Err(Error::AvmError(crate::avm2::error::reference_error(
activation,
&format!(
"Error #1065: Variable {} is not defined.",
name.local_name()
),
1065,
)?))
}
};
let globals = defined_script.globals(&mut activation.context)?;
let definition = globals.get_property(&qname.into(), activation)?;
@ -92,12 +101,13 @@ pub fn has_definition<'gc>(
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(appdomain) = this.and_then(|this| this.as_application_domain()) {
let local_name = args
let name = args
.get(0)
.cloned()
.unwrap_or_else(|| "".into())
.coerce_to_string(activation)?;
let qname = QName::new(Namespace::public(), local_name);
let qname = QName::from_qualified_name(name, activation.context.gc_context);
return Ok(appdomain.has_definition(qname).into());
}

View File

@ -155,6 +155,7 @@ swf_tests! {
(as2_super_and_this_v8, "avm1/as2_super_and_this_v8", 1),
(as2_super_via_manual_prototype, "avm1/as2_super_via_manual_prototype", 1),
(as3_add, "avm2/add", 1),
(as3_application_domain, "avm2/application_domain", 1),
(as3_array_access, "avm2/array_access", 1),
(as3_array_concat, "avm2/array_concat", 1),
(as3_array_constr, "avm2/array_constr", 1),

View File

@ -0,0 +1,23 @@
package {
import flash.system.ApplicationDomain;
public class Test {
public function Test() {
try {
ApplicationDomain.currentDomain.getDefinition("some.package.MissingClass")
} catch (e:Error) {
trace("Caught error: " + e);
}
try {
ApplicationDomain.currentDomain.getDefinition("OtherMissingClass")
} catch (e:Error) {
trace("Caught error: " + e);
}
trace("Has definition: " + ApplicationDomain.currentDomain.hasDefinition("flash.display.MovieClip"));
var cls = ApplicationDomain.currentDomain.getDefinition("flash.display.MovieClip");
trace("Got class: " + cls);
}
}
}

View File

@ -0,0 +1,4 @@
Caught error: ReferenceError: Error #1065: Variable MissingClass is not defined.
Caught error: ReferenceError: Error #1065: Variable OtherMissingClass is not defined.
Has definition: true
Got class: [class MovieClip]

Binary file not shown.

Binary file not shown.