avm2: Fix QName::from_qualified_name for Vector.<some_ns::Type>

We weren't handling names like
`__AS3__.vec::Vector.<rs.ruffle.CustomClass>`
This commit is contained in:
Aaron Hill 2023-03-07 14:06:49 -06:00
parent 613d4e3160
commit 2c1936db18
5 changed files with 56 additions and 5 deletions

View File

@ -192,7 +192,8 @@ impl<'gc> Domain<'gc> {
// to a lookup of `Vector,` a lookup of `SomeType`, and `vector_class.apply(some_type_class)`
let mut type_name = None;
if (name.namespace() == activation.avm2().vector_public_namespace
|| name.namespace() == activation.avm2().vector_internal_namespace)
|| name.namespace() == activation.avm2().vector_internal_namespace
|| name.namespace() == activation.avm2().public_namespace)
&& (name.local_name().starts_with(b"Vector.<".as_slice())
&& name.local_name().ends_with(b">".as_slice()))
{
@ -201,7 +202,7 @@ impl<'gc> Domain<'gc> {
activation.context.gc_context,
&local_name["Vector.<".len()..(local_name.len() - 1)],
));
name = QName::new(name.namespace(), "Vector");
name = QName::new(activation.avm2().vector_public_namespace, "Vector");
}
let res = self.get_defined_value(activation, name);

View File

@ -79,9 +79,28 @@ impl<'gc> QName<'gc> {
/// LOCAL_NAME (Use the public namespace)
pub fn from_qualified_name(name: AvmString<'gc>, activation: &mut Activation<'_, 'gc>) -> Self {
let mc = activation.context.gc_context;
let parts = name
.rsplit_once(WStr::from_units(b"::"))
.or_else(|| name.rsplit_once(WStr::from_units(b".")));
// If we have a type like 'some::namespace::Vector.<other::namespace::MyType>',
// we want to look at 'some::namespace::Vector' when splitting out the namespace
let before_type_param = if let Some(type_param_start) = name.find(WStr::from_units(b".<")) {
&name[..type_param_start]
} else {
&name
};
// We unfortunately can't use 'rsplit' here, because we would need to split
// the entire string, but only before the first '.<'
//
// Get the last '::' or '.', only considering the string before '.<' (if any).
// This will ignore any namespaces that are part of a type parameter (e.g 'Vector.<other::namespace::MyType>').
// The type parameter will stay combined with the type name (so we'll have 'Vector.<other::namespace::MyType>')
// in some namespace, depending on whether or not anything comes before 'Vector')
let parts = if let Some(last_separator) = before_type_param.rfind(WStr::from_units(b"::")) {
Some((&name[..last_separator], &name[(last_separator + 2)..]))
} else if let Some(last_separator) = before_type_param.rfind(b".".as_slice()) {
Some((&name[..last_separator], &name[(last_separator + 1)..]))
} else {
None
};
if let Some((package_name, local_name)) = parts {
Self {

View File

@ -3,6 +3,8 @@
import flash.utils.getQualifiedClassName;
import flash.system.ApplicationDomain;
public class Test {
public function Test() {
var vec;
@ -43,6 +45,27 @@
trace("Vector.<Test>: " + getDefinitionByName(name));
trace("ApplicationDomain.hasDefinition Vector.<Test>: " + ApplicationDomain.currentDomain.hasDefinition(name));
trace("ApplicationDomain.getDefinition Vector.<Test>: " + ApplicationDomain.currentDomain.getDefinition(name));
import rs.ruffle.CustomClass;
trace("Vector.<rs.ruffle.CustomClass>: " + getDefinitionByName("Vector.<rs.ruffle.CustomClass>"));
trace("__AS3__.vec::Vector.<rs.ruffle.CustomClass>: " + getDefinitionByName("__AS3__.vec::Vector.<rs.ruffle.CustomClass>"));
vec = new Vector.<CustomClass>([]);
name = getQualifiedClassName(vec);
trace("Vector.<CustomClass> name: " + name);
trace("Vector.<CustomClass>: " + getDefinitionByName(name));
trace("ApplicationDomain.hasDefinition Vector.<CustomClass>: " + ApplicationDomain.currentDomain.hasDefinition(name));
trace("ApplicationDomain.getDefinition Vector.<CustomClass>: " + ApplicationDomain.currentDomain.getDefinition(name));
trace("Vector.<Number> without namespace" + getDefinitionByName("Vector.<Number>"));
try {
trace("Vector without namespace: " + getDefinitionByName("Vector"));
} catch (e) {
trace("Caught error: " + e);
}
}
}
}

View File

@ -19,3 +19,11 @@ Vector.<Test> name: __AS3__.vec::Vector.<Test>
Vector.<Test>: [class Vector.<Test>]
ApplicationDomain.hasDefinition Vector.<Test>: true
ApplicationDomain.getDefinition Vector.<Test>: [class Vector.<Test>]
Vector.<rs.ruffle.CustomClass>: [class Vector.<rs.ruffle::CustomClass>]
__AS3__.vec::Vector.<rs.ruffle.CustomClass>: [class Vector.<rs.ruffle::CustomClass>]
Vector.<CustomClass> name: __AS3__.vec::Vector.<rs.ruffle::CustomClass>
Vector.<CustomClass>: [class Vector.<rs.ruffle::CustomClass>]
ApplicationDomain.hasDefinition Vector.<CustomClass>: true
ApplicationDomain.getDefinition Vector.<CustomClass>: [class Vector.<rs.ruffle::CustomClass>]
Vector.<Number> without namespace[class Vector.<Number>]
Caught error: ReferenceError: Error #1065: Variable Vector is not defined.