Last Updated: February 25, 2016
·
2.71K
· georgiee

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!)

3 Responses
Add your response

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!!!

over 1 year ago ·

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!

over 1 year ago ·

Many many thanks ! We've considerably reduced the calls to flash. If you come in France, I'll pay you a beer. Thanks again !

over 1 year ago ·