tags:

views:

690

answers:

3

I am developing a dynamic mocking framework for Flex/AS3 and am having trouble with private/support types (ie. those declared outside the package {} in a class file).

In my ABC "file", I am declaring the instance with the PROTECTED_NAMESPACE class flag and with a PRIVATE_NS multiname. I have also experimented with giving it the same namespace as the class it is subclassing (eg. PRIVATE_NS("ContainerClass.as$123")).

No matter what I do, I always get the following error after loadBytes:

VerifyError: Error #1014: Class ContainerClass.as$123::PrivateClass could not be found.

I have experimented with loading the generated bytecode into the same ApplicationDomain as the private class (I use a child domain by default). I even tried registering a class alias before the load (though that was a bit of a stretch).

Am I forgetting anything or is it simply a restriction of the AVM?

Please note that I am fully aware that this is illegal in ActionScript 3.0, I am looking for whether this is actually possible in the AVM.

Edit: For those interested in the work so far, the project is asmock and is on sourceforge.

+1  A: 

I'm no expert with ABC files but I just don't think this is possible in the AVM2. I did several tests a while ago with the AS3 Eval lib and they all failed.

Related to dynamic mocking, I have filed an issue in Adobe bugbase, asking for a dynamic proxy mechanism: http://bugs.adobe.com/jira/browse/ASC-3136

Christophe Herreman
I have actually developed a dynamic proxy framework and it works well (with package classes/interfaces). The only major outstanding feature of the framework is mocking 'private' classes (declared outside the package).
Richard Szalay
Wow, then I must really check that out! I'm assuming you did not do this with the standard AS3 capabilities?
Christophe Herreman
Actually, I'm just using Loader.loadBytes(). Generating a dynamic SWF/ABC at runtime was the tricky part ;)
Richard Szalay
Awesome! I can imagine you had a hard time with the bytecode. I looked at it a while ago, but got so scared, I ran away ;-)
Christophe Herreman
Alot of determination helped.
Richard Szalay
+1  A: 

I'm not sure what you mean by PRIVATE_NS("ContainerClass.as$123"), My reading of avm2overview.pdf 4.4.1 is that private namespaces are not permitted to have a name, hence that the "<class name>$<number>" namespace in debug output is generated for your convenience. I would assume that would mean you would have to hack your abc into the same abc tag in the source swf to access the namespace constant index (and that sounds too much like hard work to me!)

I haven't actually managed to generate a loading swf, though, so take this with a grain of salt.

Simon Buchan
4.4.1 designates that SYSTEM namespaces are empty (ie. String, int, etc), but private namespaces (ie. those with a multiname kind of PrivateNs/0x5) still have names) still have values. <file>.as$<number> is automatically allocated as the (private) multiname to nested classes.
Richard Szalay
Also, the framework that I'm working does generate a loading swf and supports generation of all types of classes (including Vector.<T>). It's only the "nested" classes that are causing me grief. If you are interested in the work so far, the source is available at http://asmock.sourceforge.net
Richard Szalay
"User-defined namespaces have kind CONSTANT_Namespace orCONSTANT_ExplicitNamespace and a non-empty name. System namespaces have empty names and one of the other kinds" is the text I'm thinking of here. This implies CONSTANT_PrivateNs is a system NS, and has no stored name.
Simon Buchan
And I'm thinking you might have to parse in the abc tag from the swf, merge in your generated code and splice it back into the swf (in memory). Of course, you won't be able to do this within the swf you are mocking :(.
Simon Buchan
I guess it will have to wait for when I refactor my reflection lib to parse the abc tag. I wonder if the type assignment will work if it's declared in multiple application domains.
Richard Szalay
I might not have been clear: from my understanding, PrivateNs's are private because they are not referenceable outside the tag. You would have to parse the incoming swf, and modify the abc tag to include your mock class *before* loading: meaning only one App Domain.
Simon Buchan
Ah, I see what you mean. Unfortunately that's not feasible as the swf in question would have already been loaded (it's a runtime dynamic mocking framework). Thanks for the clarification!
Richard Szalay
A: 

Having gone back to look at this problem in ernest, I can definitively answer this question: private classes can only be referenced from the LoaderContext

I have been able to add support for private interfaces by reproducing the interface in the loaded ABC 'file', but it cannot be coerced/cast back to the original private interface.

This is still useful for my requirements, as a private interface can be used to combine multiple interfaces.

Richard Szalay