Wrapping function calls in ActionScript 2

Also known as:

  • debugging function calls
  • displaying the name of a called function
  • tracing function calls director like

Today I finally got to try something I had been wanting to try for a long time: wrapping function calls in a nice way.

I had been playing around with function pointers etc, which was ok in itself, but I was forced to create the messy pointer bit each time over again. So I implemented a FunctionWrapper class.

Say we have a class Test, with a method testMethod.

Now we want to execute some code before calling testMethod and after calling testMethod. “Well write another function to do so”, you might say. Of course that is one option, but assume we are looking for another way to do so (I’ll discuss some scenario’s in a minute).

Using function pointers you can let the Test.testMethod reference point to your own method and from your own method execute the original method, pre and postpending it with some functionality. I think this is a bit like the AOP mechanism, but I’m not too sure.

The FunctionWrapper class takes care of all this reference shuffling for you:

FunctionWrapper.wrap (
	TestClass,
	"testMethod",
	_preFunction,
	null,	//no additional args to pre
	_postFunction,
	null  //no additional args to post
);

Now I won’t explain a lot more about that on this page, since I’ve got an example for download here: FunctionWrapper (506), which contains all required classes and documentation. Note that the example requires some support classes which aren’t ‘really’ needed, but I don’t like to write anything twice and I hate searching for null pointer errors, so I use a lot of utility functions and a lot of assertions.

So I’ll skip to the uses.

I see one major use: debugging.
And then debugging without modifying your existing code!

Imagine these scenario’s:

  • you are refactoring your code, and want to get a signal when some old code is being executed.
  • you want to print whether a function is executed, with what arguments and inspect the return value, but you don’t want to or can’t change the source code
  • you want to see a nested function trace without using the debugger
  • you have all these debug statements, but it might be harming performance so you want to take them out

Note that for these scenario’s, the FunctionWrapper isn’t enough, but it’s a start. For example using my upcoming reflection package you can traverse all functions in a class and have them wrapped with a debug mechanism automatically. At this time you still have to specify each functionname manually.

A small example of what it looks like, imagine I have the following class:

class TestClass {

	/**
	* Just a simple test method, which returns a value as well so we can test the post process mechanism.
	*
	* @return a string
	*/
	public function testMethod() : String {
		trace ("This is printed by testMethod");
		testMethod2();

		return "I am testMethod's returnvalue";
	}

	/**
	* Just a simple test method without a return value
	*/
	public function testMethod2() : Void {
		trace ("This is printed by testMethod 2");
	}
}

Now we execute the following code:

var lTestClass:TestClass = new TestClass ();
lTestClass.testMethod(1,2,3);

it will print:

This is printed by testMethod
This is printed by testMethod 2

Now assume for a moment that those werent trace statements but silent operations, you would see:

Yes exactly nothing….

Now we wrap our function calls, as mentioned before, at this time this has to be done manually, or you have to create a simple prototype/class iterator looking for functions on a class, but for the sake of simplicity, we’ll do it manually:

FunctionWrapper.traceWrap (TestClass, "testMethod");
FunctionWrapper.traceWrap (TestClass, "testMethod2");

Note that this is done WITHOUT altering the TestClass, so the TestClass stays the same.
If we re-execute our example again (lTestClass.testMethod(1,2,3);), you will see the following:

=> Entering testMethod with arguments 1,2,3
This is printed by testMethod
  => Entering testMethod2
This is printed by testMethod 2
  <= Exiting testMethod2 with no return value.
<= Exiting testMethod with return value:I am testMethod's returnvalue

You can see testMethod is called first, and with which arguments. You can see it then calls testMethod2, which is nested one level deeper and that testMethod2 exits again with no return value. In turn testMethod returns with its original return value.

So we get to see the method flow including parameters and return types without ever touching the original functions themselves.

There is more but you’ll have to check for yourself by downloading the example and all required code here: FunctionWrapper (506).

image_pdfimage_print
0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *