The fascinating Flash. One moment it works, the other things go odd, and then you have no idea how did it even escalate to that.
One of those moments was encountered by me when reimplementing flash.net.URLVariables class yesterday for OpenFL-bitfive, and this is a bit of a blog post about that.
To say a thing first, my original intentions did not actually include rewriting the class.
If you may know, I have a small repository with different single-file programs that test one or other aspect of Flash API implementation in OpenFL. There aren't streamlined tests, but rather something that you can stare at and compare (or debug) with.
So there, I've decided to make a test for flash.net.URLVariables class. It looks like a really simple one, and even less it seems that one can make a mistake in it's implementation, but I wanted to make sure, since pulling of HTTP GET parameters from application URL is normally done with this.
Perhaps, the "changing" decision here was that I decided to reuse the same URLVariables object (rather than creating a new one on each input). Documentation states that decode method is mostly used internally, but you are alright to use it also. So nothing could go wrong, right? But things did.
So, consider that we make a new URLVariables instance, called uv:
var uv = new URLVariables();
We do not provide any string to be decoded, so it's fields are essentially a { }.
Then, we decode a string with it, for example...
uv.decode("a=1&b=2");
It's value is now around { a: "1", b: "2"}. So far so good.
Now, let's decode another string,
uv.decode("b=1&c=2");
The trick question! What is uv equal to now?
Seemingly logical answer (and one implemented in all OpenFL variants) is { b: "1", c: "2" }.
But is that what really happens? No.
Perhaps it replaces the values then, making it into { a: "1", b: "1", c: "2" }? Also no.
What it does, is... stacking the values. So, in fact, the uv is now...
{ a: "1", b: ["2", "1"], c: "2" }
b becomes an array instead of single value. The toString output of uv is also fairly interesting - instead of any kind of array serialization, it will output arrays as sets of duplicate values:
"b=2&b=1&c=2&a=1"
Which actually... kind of makes sense. This way you get the same result after loading the data back into URLVariables.
Another thing worth mentioning is that URLVariables is fairly... error-proof. Anything is valid as long as is has equals sign between delimiters. So,
new URLVariables("a = 1"); // { "a ": " 1" } new URLVariables("a=&b=1"); // { a: "", b: "1" } new URLVariables("a=1&a=2"); // { a: ["1", "2"] } new URLVariables("=1"); // { "": "1" } // ? new URLVariables("="); // { "": "" } // ?? new URLVariables("=&=&="); // { "": ["", "", ""] } // ??? new URLVariables(""); // Error #2101: The String passed to URLVariables.decode() must be a URL-encoded query string containing name/value pairs. new URLVariables("&"); // ditto above new URLVariables("a=1&&b=2"); // ditto ditto above
(apparently, error 2101 is the only thing that can go wrong with URLVariables)
That said, after poking a while at existing behaviour, I went and made a Flash-equivalent version for OpenFL-bitfive. You can also take a look at source or a test file: