ExternalInterface#call in a deadly loop (__flash__toXML)
I am currently building a rails app with a small flash widget to capture and encode webcam frames into a couple of jpeg frames. When the flash app has completed all tasks I want to show a modal html thank you window with some links.
To accomplish the communication from flash to JS I need some kind of bridge. ExternalInterface is the solution to go. Call your JS method like this.
ExternalInterface.call("method",args..)
easy, isn't it ?
My concrete call looks like this:
ExternalInterface.call("window.App.flash.openThankYouDialog")
In Google Chrome I see a lag between pressing my flash button and the opening of the modal window. In Firefox it completely HANGS asking to stop a long running script.
With a small profiling session I see eeeeeeendlessss stack of flashtoXML calls which looks like this.
__flash__toXML
__flash__toXML
__flash__toXML
__flash__toXML
__flash__toXML
__flash__toXML
__flash__toXML
__flash__toXML
__flash__toXML
__flash__toXML
__flash__toXML
__flash__toXML
So what the heck is going on ? I know that function is dynamically created by flash to prepare the flash call for a evil eval. But there are no arguments I pass and it is not the first time I used a namespaced path to a function. So what is wrong now? I tested and debugged and tested and debugged and than I had my moment!!
The problem is somehow related to coffescript. YES coffescript. Look at my JS implementation of openThankYouDialog
class SomeApp.Views.FlashApplication extends Backbone.View
openThankYouDialog:->
@trigger('showThankYou')
_getFlashAppp:->
$(@el).get(0)
This Backbone View is some kind of mediator for my flash application. Backbone's 'el' points directly to the flash object/embed tag.
When called by flash openThankYouDialog returns a reference to the current view. This is because coffescript creates a implicit return and trigger returns the current object, therefore the current Backbone View.
And what is flash doing? It tries to parse the whole 'SomeApp.Views.FlashApplication' with flashtoXML. At some point flashtoXML will try to parse the flash object/embed tag itself. And I think here starts the journey again. I guess a reference to flashtoXML is found there and flashtoXML calls flashtoXML and kills my script.
Solution:
class SomeApp.Views.FlashApplication extends Backbone.View
openThankYouDialog:->
@trigger('showThankYou')
return
Yes, a simple empty return. Thanks coffescript! (psst I still love you!)
Written by George
Related protips
3 Responses
Just leaving a message to tell you that you saved my day!
This recursive call was driving me crazy and I don't think I would have found the problem without your blog post.
THANKS A LOT!!!
WOoooo! Thanks a ton, this was super helpful! We got to the IE profiler and found 3 million calls to String.replace, and 600k to flashtoXML, and did a O______O, then found this, then fixed it!
Many many thanks ! We've considerably reduced the calls to flash. If you come in France, I'll pay you a beer. Thanks again !