Skip to Content Skip to Search Go to Top Navigation Go to Side Menu
Search on Site

Prototype String.toQueryParams() weirdness

Tuesday, April 15, 2008

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. if (value != undefined) value = decodeURIComponent(value);
  3.  
  4. to
  5.  
  6. var key = decodeURIComponent(escape(pair.shift()));
  7. 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. 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: 98% [?]

7 Responses to “Prototype String.toQueryParams() weirdness”


  1. Daniel Says:

    I have the same problem and i was making my brain ache too!! DAMN!

  2. Daniel Says:

    no it didnt worked :(

  3. alex Says:

    Daniel - what didn’t work?

  4. Martin Says:

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

  5. alex Says:

    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. AP Says:

    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. AP Says:

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

Leave a Reply


In order to submit a comment, you need to mention your name and your email address (which won't be published).

Comment Form