PatrickBay.ca

This time, it's personal.

Problem

When the ActionScript VM gets it wrong, sometimes it gets it really wrong. Makes you wanna drink.

Take the following runtime error:

TypeError: Error #1034: Type Coercion failed: cannot convert ca.patrickbay.events::CustomEvent@9262359 to ca.patrickbay.MyClass.
 at flash.events::EventDispatcher/dispatchEventFunction()
 at flash.events::EventDispatcher/dispatchEvent()
 at ca.patrickbay::MyClass/onTimerEnd()[C:\Users\patrick\Desktop\project\ca\patrickbay\MyClass.as:375]
 at flash.events::EventDispatcher/dispatchEventFunction()
 at flash.events::EventDispatcher/dispatchEvent()
 at flash.utils::Timer/tick()

Okay, obviously MyClass has a problem on line 375. Seems it should be using a CustomEvent type but it’s using a MyClass type instead. Clearly this is an easy fix. Here’s around line 375 of MyClass:

 var event:CustomEvent = new CustomEvent(CustomEvent.NOTIFY); 
 this.dispatchEvent(event);

Hmm, looks okay. I check both this class and CustomEvent to make sure they’re both actually the same thing … only one file of each, and renaming causes the compiler to complain, so they’re okay. Custom event does have a NOTIFY property. All good there.

The class paths are all okay and there are definitely no other conflicts. MyClass is extending EventDispatcher and being properly instantiated, so no issues there.

And here’s the weird part — I use this dispatch call liberally throughout MyClass, often verbatim, and it appears to work everywhere else except in this one enclosing function:

public function onTimerEnd(eventObj:TimerEvent):void {
   trace ("This appears in the trace log. eventObj is "+eventObj);
   var event:CustomEvent = new CustomEvent(CustomEvent.NOTIFY);
   this.dispatchEvent(event);
   trace ("This doesn't appear!");
}

The output log shows that, indeed, this function is invoked and that eventObj is an actual TimerEvent. Except that once I try to dispatch this one event, from this one function, the event dispatcher throws a runtime error. And did I mention that it’s only this one function?

Okay, so at least I can catch that sucker:

public function onTimerEnd(eventObj:TimerEvent):void {
   trace ("This appears in the trace log, part 2. eventObj is "+eventObj);
   try {
      var event:CustomEvent = new CustomEvent(CustomEvent.NOTIFY);
      this.dispatchEvent(event);
   } catch (err:*) {
      trace ("Here's what I caught: "+err);
   }
   trace ("This doesn't appear!");
}

I clear all the compiler caches, wipe the SWFs, make sure everything is fresh. I even update the trace log, as you may note.

And the error isn’t caught.

The “This appears…” line shows up but no “Here’s what I caught…”. Instead I get the same runtime error.

So it seems that I’ve encountered a non-catchable, fatal application error being thrown by the event dispatcher. I’ve gone over both classes – MyClass and the document class listening to it – about 15 times now, even going so far as to just accept any type of anything on the listener:

public function onCustomEvent(... args):void {
   trace ("Why won't I get called?!");
}

Again, wipey wipey. Re-compile and … the same runtime error.

The Flash VM is telling me that on line 375 of MyClass, I am providing a CustomEvent, which I head-shakingly re-verify, and that that event can’t be converted into a MyClass type.

But why … why is the event dispatcher trying to do this?

My listener’s wide open, it’ll take ANYTHING, and the event dispatcher is still trying to do something weird. Seriously … what does it have against me?

So I comment out that event dispatch, in that one function, and sure enough the application works again, albeit without this very necessary event dispatch. So that’s not a solution.

Solution

Ahem.

Well, I felt kinda dumb after figuring out this one. But, in my defense, the runtime error message was not at all clear.

In fact, the error originated in an entirely different class that I had imported at some point and that also happened to be listening to that CustomEvent from MyClass.

In this entirely different class, the listener was declared like so:

private function onTimerEventNotification(eventObj:MyClass):void {
   trace ("Timer has completed");
}

Late night, drink, code … I tell ya.

Anyway, as soon this was corrected, everything ran as expected.

The takeaway here is that if you’re seeing an error like this from EventDispatcher, it’s probably not giving you the whole story. A project-wide search may save you from the torment I’ve described.

Remember my anguish, drink to my memory.

August 19th, 2014

Posted In: Development / Coding

Tags: , , , ,

One Comment

Leave a Reply

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