Aching Brain Just another WordPress weblog

15Apr/087

Prototype String.toQueryParams() weirdness

I just came across this while using Prototype:

  1. "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:

  1. var key = decodeURIComponent(pair.shift());
  2. ...
  3. if (value != undefined) value = decodeURIComponent(value);
  4.  
  5. to
  6.  
  7. var key = decodeURIComponent(escape(pair.shift()));
  8. ...
  9. 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:

  1. var key = unescape(decodeURIComponent(escape(pair.shift())));
  2. ...
  3. 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:

  1. 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% [?]

Comments (7) Trackbacks (0)
  1. I have the same problem and i was making my brain ache too!! DAMN!

  2. no it didnt worked :(

  3. Daniel – what didn’t work?

  4. why do you still bother using Prototype? it’s a real PITA from the code, implementation and to the documentation itself!

  5. 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?

  6. 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’

  7. Nevermind the above comment we found the backend was doing the conversion.


Leave a comment


No trackbacks yet.

Pages

Categories

Blogroll

Archive

Meta