Why does ExternalInterface breaks when I pass parameter with JSON like string?
Asked Answered
C

2

14

I have a very odd problem with Flash 10 and ExternalInterface. I am currently using a homemade bridge to use RTMFP with Javascript and whenever I try to pass data that contains JSON, I get a wierd Javascript error that comes from Flash :

missing ) after argument list
try { __flash__toXML(Flash.Utilities.A..."")) ; } catch (e) { "<undefined/>"; }

It's impossible to get more information since this come from Flash and it's not bound to any Javascript file.

To reproduce this problem you can use this script :

package 
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.external.ExternalInterface;

    public class Main extends Sprite 
    {

        public function Main():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }

        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            var test:String;

            test = "\"\\\"\"";

            ExternalInterface.call("console.log", test);
        }

    }

}

What can I do to avoid this problem and is it a known problem ?

Claresta answered 1/3, 2011 at 0:57 Comment(7)
@kjy112 No, I'm assuming that ExternalInterface.call would take care of properly escaping the data that I am passing to it.Claresta
@holyvier maccherone.com/larry/projects/…Everson
@kjy112 Well the JSON encoding is done outside of Flash. What I am using is just a bridge.Claresta
or serialize it and deserialize on the JS side: snipplr.com/view/6494/…Gardiner
This is not a legal construct: __flash__toXML(Flash.Utilities.A..."")) ; Is there more code you masked with the ... or is this what the code actually says?Troy
@weltraympirat That's all I get from the Firebug console. I believe there is more code, it's just that Firebug display it that way. And this code is from Flash since it's not bound to any line of actual code, so I can't see more of it.Claresta
@HoLyVieR: You will have to debug the flash code, then. If your bridge is homemade, you should have access, right?Troy
C
22

This is apparently a known issue and it doesn't seems like Adobe is going to fix it anytime soon.

I found a detailled explaination of this problem and basicly the issue seems to be that Flash doesn't handle the \ and the & properly which can lead to javascript error or data corruption during the transfer from Flash to javascript.

What Flash attempts to do when you transfer data from Flash to JS is to execute the following thing :

try {
    __flash__toXML(yourJavascriptFunction("[DATA]")) ;
} catch (e) { "<undefined/>"; }

The problem is that it puts your data raw and it doesn't escape the backslash at all. If your string contains only \ and you want to call console.log on it, it will try to do the following thing :

try {
    __flash__toXML(console.log("\")) ;
} catch (e) { "<undefined/>"; }

As you can see this is invalid javascript. It will throws an error in your Javascript console and it will never call console.log.

The solution is to either ducktape Flash behavior or do some nasty hack to get around it.

To ducktape Flash buggyness you can escape the blackslash before you transfer them. This solution will work for now, but when Flash will fix it (most probably not in a near future, if you consider that this bug is known for more than 4 years), it will break your application.

The other possibility is to url encode the character that Flash doesn't handle well (\, ", &) and to decode them on the other side.

Flash :

data = data.split("%").join("%25")
           .split("\\").join("%5c")
           .split("\"").join("%22")
           .split("&").join("%26");

Javascript :

data = data.replace(/%22/g, "\"")
           .replace(/%5c/g, "\\")
           .replace(/%26/g, "&")
           .replace(/%25/g, "%");

It's ugly, but it works.

Claresta answered 3/3, 2011 at 0:30 Comment(1)
The "ugly" hack didn't work, but the escape below did. Still the explanation is extensive enough to bring something positive.Unction
E
6

Admittedly this wouldn't work directly for output to the console in Firebug, but for most other applications (i.e. sending a potentially 'invalid' string to Javascript), escape and unescape should work just fine:

AS3:

var testString:String = "\"\\\"\"";
ExternalInterface.call("showString", escape(testString));

And then in Javascript:

function showString(msg) {
    console.log(unescape(msg));
    document.getElementById('messagebox').innerHTML = unescape(msg);
}

<div id="messagebox"></div>
Em answered 18/11, 2011 at 17:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.