Prototype String.toQueryParams() weirdness
I just came across this while using Prototype:
-
"section=blo%g&id=45".toQueryParams();
To save you the trouble of running it yourself, I'll tell you what happens - the unescaped percent symbol causes a URI malformed error to be thrown.
Very odd. The Prototype documentation for toQueryParams says:
Parses a URI-like query string and returns an object composed of parameter/value pairs.
Since it's a URI-like query string and not an actual query string (by which I mean one that's been through the browser address bar and as such subject to whatever text munging the browser does), my example above should be a legal use case.
After a little digging around in prototype.js, it seems that the problem is caused by the JavaScript function decodeURIComponent() not enjoying being given a string that contains an unescaped percent symbol. Usually percent symbols are used in conjunction with a number to represent a non-alphanumeric character in a URL - %20 for space, etc, but in the above it's a literal percent symbol.
My first attempt to fix it changed lines 98 and 100 of string.js in the Prototype source to use the built in escape function:
-
var key = decodeURIComponent(pair.shift());
-
...
-
if (value != undefined) value = decodeURIComponent(value);
-
-
to
-
-
var key = decodeURIComponent(escape(pair.shift()));
-
...
-
if (value != undefined) value = decodeURIComponent(escape(value));
This worked for my use case but caused Prototype to fail a different unit test. Changing them to the following worked out okay:
-
var key = unescape(decodeURIComponent(escape(pair.shift())));
-
...
-
if (value != undefined) value = unescape(decodeURIComponent(escape(value)));
Granted the unescape(...(escape(...)) is a little clumsy, but it seems to get the job done.
Adding the following unit test to string.html allows to test for the above:
-
this.assertHashEqual({'key1': 'va%lue1'}, 'key1=va%lue1'.toQueryParams(), 'rogue percent symbol test');
I've created some test pages which demonstrate the problem.
There is also a patch file available. Apply it to /src/string.js in your Prototype source tree.
Update
I've also filed a bug.
Popularity: 100% [?]
April 17th, 2008 - 03:46
I have the same problem and i was making my brain ache too!! DAMN!
April 17th, 2008 - 04:11
no it didnt worked
April 17th, 2008 - 09:52
Daniel – what didn’t work?
April 18th, 2008 - 06:43
why do you still bother using Prototype? it’s a real PITA from the code, implementation and to the documentation itself!
April 18th, 2008 - 07:38
Mainly because of work. When the project began, Prototype best fitted our needs and we’re too far along to consider re-implementing. Not until version 2 at any rate.
Granted at one point the documentation (or lack thereof) was shockingly bad, but nowadays we are spoilt.
I’m not sure why you have a problem with the implementation as it’s a library like any other – code to the API and forget about it. When it doesn’t work as expected, file a bug.
As for the code, again I’m not sure what you mean. Could the problem you have be that it doesn’t look like Java?
June 25th, 2008 - 17:35
I applied the patch and it seemed to be working, but if you throw it an ASCII Hex code/value, like %50, it fails. Or not fail, but it converts it to its keyboard character equivalent, %50 = ‘P’
June 26th, 2008 - 18:09
Nevermind the above comment we found the backend was doing the conversion.