Like many people, I've been using the FABridge a lot and loving the simplicity it provides. Also like many people I've run into the following JavaScript error thrown by the FABridge:
You are trying to call recursively into the Flash Player which is not allowed. In most cases the JavaScript setTimeout function, can be used as a workaround.
In a pinch, I've worked around this error using the suggested JS setTimeout() function or by retrieving data by other means. I've finally decided to see if there was a better way and found one.
For the impatient (like myself), the solution is to use the following FABridge static constants:
FABridge.EventsToCallLater
FABridge.MethodsToCallLater
Let's look at a test project:
Open the FABridge Test and you'll see a bunch of links. Click FireBugLite to open a console. Then click embedSwf() to embed the swf which will output to the console when the FABridge has initialized (see the JavaScript callback() method on the HTML page . You should then see the following in the console:
embedSwf franky.name: franky franky.children.length: 2 franky.children[0]: Object franky.children[0].name: john
The JS callback() method is a simple demonstration of getting data from the SWF through the FABridge. Now click on the requestRingo() link. That calls the following JS code:
getRoot().requestRingo();
That in turn calls the following ActionScipt code in FABridgetTest.as which dispatches a ringoRequested event:
public function requestRingo():void {
var e:NodeEvent = new NodeEvent("ringoRequested");
e.node = new Node("ringo", 14);
e.node.children.push(new Node("dingo", 2));
dispatchEvent(e); // dispatch right away
}
In the JavaScript, we've added an event listener for that event in the callback() method. The JS requestRingoHandler() method is called as a result:
function requestRingoHandler(event) {
console.log("ringo");
try {
var ringo = event.getNode();
console.log("ringo.name:", ringo.getName());
console.log("ringo.children[0].name:", ringo.getChildren()[0].getName());
} catch (e) {
console.log("error:", e.message);
}
}
So we've click on the requestRingo() link and will get the following output in the console:
ringo error: You are trying to call recursively into the Flash Player which is not allowed. In most cases the JavaScript setTimeout function, can be used as a workaround.
ringo ringo.name: ringo ringo.children[0].name: dingo
The setEventsToCallLater() method registered the fabridgetest::NodeEvent class with the FABridge as an event to dispatch after a delay. This registration is done using the FABridge.EventsToCallLater Object constant. In a normal application you'd hard code these registrations, e.g.
FABridge.EventsToCallLater["fabridgetest::NodeEvent"] = "true";
You can also register the general flash.events.::Event class to cover all cases, but there may be performance concerns so that will have to be tested before I use it in production code.
In addition to the EventsToCallLater constant, FABridge has the MethodsToCallLater constant which is the same thing but for specified methods for classes. The FABridge registers the following automatically:
MethodsToCallLater["mx.collections::ArrayCollection"]="refresh,removeItemAt";
Between EventsToCallLater and MethodsToCallLater you should be able to avoid many of the "You are trying to call recursively into the Flash Player..." errors.
Have you successfully uses these constants? Are there any pitfalls and/or performance issues?
Took me awhile to understand what you are talking about but I think i got it. It’s a work a round for the error message?. you are trying to make flah do something it doesn’t want to do???? sorry I’m not a progammer yet but when I grow up I want to become one :-)
Thanks for the article. Only thing related to my problem I could find.
I’m getting this nasty when using FABridge to create a NetStream for P2P using Stratus. It’s thrown whenever a NetStatusEvent is dispatched, regardless of whether I’ve registered a listener or not:
Error: Error #1023: Stack overflow occurred.
at flash.net::NetStreamInfo()
at flash.net::NetStream/get info()
at flash.external::ExternalInterface$/_objectToJS()
at flash.external::ExternalInterface$/_toJS()
at flash.external::ExternalInterface$/_objectToJS()
at flash.external::ExternalInterface$/_toJS()
repeating…
I could not figure out how to use FABridge.NameOfmyBridge.root().setEventsToCallLater(…). Traversing the root object showed there was no such function.
HGP
Sorry about the confusion. The setEventsToCallLater() method is one I wrote to dynamically add events for demo purposes.
In your case, try adding this line of code during initialization:
FABridge.EventsToCallLater["flash.events::NetStatusEvent"] = “true”;
Though if that stack overflow is thrown even without registering a listener, “EventsToCallLater” may not solve the issue. It’s difficult to say becaue it could be even be a bug in Stratus.
Let me know if you figure out what’s going on. I have yet to play around with Stratus.