Victory!

1 view
Skip to first unread message

Maxim Porges

unread,
Apr 10, 2009, 12:14:30 PM4/10/09
to loom...@googlegroups.com
Hey guys,

Here it is, after just under three months of work - the long-awaited working DynamicProxyFactory. Please find the quick n' dirty test case and output from it below.

The original methodOne() implementation in BaseClass just traces "BaseClass::methodCallOne()" and returns the value 100, and you can see the output in the first non-proxied invocation. Next, the proxy handler is attached for methodCallOne() and invoked against the original instance, and you can see the before/after tracing advice working away.

Now that this is all working, I'm going to be writing some more thorough unit tests for DynamicProxyFactory and then refactoring it heavily. Once DynamicProxyFactory can create a proxy from any class, I'll get started on the SWFLoader. Regardless of where I get to today, I'll send out a copy of the project later so you guys can start messing with creating proxies against instances of BaseClass at the very least. Then you can let me know what else you need from the API and any other ideas that start cropping up.

Thanks,

- max


======== Test Class ===

public class DynamicProxyFactoryTest extends TestCase
{
   public function testCreateProxy() : void
   {
      var fixture : DynamicProxyFactory = new DynamicProxyFactory();
      var proxyFile : AbcFile = new AbcDeserializer(TestConstants.getBaseClassTemplate()).deserialize();

      // We enhance the loaded ABC file to save the work the compiler already did, and just add to/replace as necessary
      fixture.createProxy(proxyFile);

      var classLoader : AbcClassLoader = new AbcClassLoader();
      classLoader.addEventListener(
         Event.COMPLETE,
         function (event : Event) : void
         {
            var classRef : * = getDefinitionByName("loom.template::DynamicSubClass");
            trace(describeType(classRef));
                    
            // This would blow up if the types were not compatible
            var instance : BaseClass = new classRef(nullnull);
            assertTrue(instance is BaseClass); // redundant, yet satisfying :)
                    
            // Run original method invocation
            trace(">>> Original method invocation");
            trace(instance.methodCallOne("Hello Original Method Invocation!", -1));
                    
            // Set up a handler
            instance.loom_namespace::setHandler(
               "methodCallOne",
               function (invocation : MethodInvocation) : *
               {
                  trace("Before advice for: " + invocation);

                           

                  try
                  {
                     return invocation.proceed();
                  }
                  catch (e : Error)
                  {
                     trace("Throws advice for: " + e);
                  }
                  finally
                  {
                     trace("After advice for: " + invocation);
                  }
               }
            );
            trace(">>> AOP method invocation");
            trace(instance.methodCallOne("Hello Dynamic Method Invocation!", 1234));
         }
      );

      // Load in the proxied class definition
      classLoader.loadClassDefinitionsFromBytecode([
      TestConstants.getBaseClassTemplate(),
         new AbcSerializer().serializeAbcFile(proxyFile)
      ]);
   }
}


======== Output ===

<type name="loom.template::DynamicSubClass" base="Class" isDynamic="true" isFinal="true" isStatic="true">
  <extendsClass type="Class"/>
  <extendsClass type="Object"/>
  <accessor name="prototype" access="readonly" type="*" declaredBy="Class"/>
  <factory type="loom.template::DynamicSubClass">
    <extendsClass type="loom.template::BaseClass"/>
    <extendsClass type="Object"/>
    <constructor>
      <parameter index="1" type="String" optional="false"/>
      <parameter index="2" type="String" optional="false"/>
    </constructor>
    <method name="methodCallThree" declaredBy="loom.template::DynamicSubClass" returnType="String">
      <parameter index="1" type="String" optional="false"/>
      <parameter index="2" type="Number" optional="false"/>
    </method>
    <variable name="handlerMappings" type="flash.utils::Dictionary" uri="http://loom.ninjitsoft.com"/>
    <method name="setHandler" declaredBy="loom.template::DynamicSubClass" returnType="void" uri="http://loom.ninjitsoft.com">
      <parameter index="1" type="String" optional="false"/>
      <parameter index="2" type="Function" optional="false"/>
    </method>
    <method name="methodCallOne" declaredBy="loom.template::DynamicSubClass" returnType="int">
      <parameter index="1" type="String" optional="false"/>
      <parameter index="2" type="Number" optional="false"/>
    </method>
    <method name="methodCallTwo" declaredBy="loom.template::DynamicSubClass" returnType="void">
      <parameter index="1" type="String" optional="false"/>
      <parameter index="2" type="Number" optional="false"/>
      <parameter index="3" type="Object" optional="false"/>
    </method>
    <method name="proxyInvocation" declaredBy="loom.template::DynamicSubClass" returnType="*" uri="http://loom.ninjitsoft.com">
      <parameter index="1" type="loom.template::MethodInvocation" optional="false"/>
    </method>
  </factory>
</type>
BaseClass::constructor()
>>> Original method invocation
BaseClass::methodCallOne()
100
>>> AOP method invocation
Before advice for: methodCallOne(Hello Dynamic Method Invocation!, 1234)
BaseClass::methodCallOne()
After advice for: methodCallOne(Hello Dynamic Method Invocation!, 1234)
100


Roland Zwaga

unread,
Apr 10, 2009, 12:37:08 PM4/10/09
to loom-as3
Hey max,

thanks a lot for the invite, your work sounds quite amazing and I
can't wait to start
fiddling around with Loom. Absolutely amazing job!

cheers,

Roland

Maxim Porges

unread,
Apr 10, 2009, 12:53:57 PM4/10/09
to loom...@googlegroups.com
Thanks Roland! I can't wait to get it in to the hands of the people on
this list. The true test of this thing will be mass compatibility, so
I'll be asking you guys to test it heavily once the SWF loader is
finished.

- max

Chris Scott

unread,
Apr 10, 2009, 1:16:26 PM4/10/09
to loom...@googlegroups.com
I cannot wait to start working with this!! I do have a crap load on my list to get through, but I am super psyched to get back into Swiz's AOP framework.

-c

maxim.porges

unread,
Apr 11, 2009, 2:41:49 AM4/11/09
to loom-as3
Hey guys,

I just got done Mavenizing the Loom project, so I figured I would
throw the SWC up for you as promised. I have uploaded a file to the
group called "loom-test.zip" which contains the Loom super-alpha SWC
and some sample code for setting up a proxy, along with the ABC file
for BaseClass that you can slurp in.

I got a lot of cleanup done today but I still have a little more work
before you can proxy any object, so stick to BaseClass for now. I
should have Loom working with whatever class you want to throw at it
within a day or two.

Happy tinkering! I'm looking forward to your feedback.

- max

maxim.porges

unread,
Apr 12, 2009, 3:52:55 PM4/12/09
to loom-as3
Hey guys,

Just a quick note to let you know that I uploaded a fresh version of
the sample app with the generated asdocs.

- max
Reply all
Reply to author
Forward
0 new messages