I came across a funny bug the other day when checking in some code for our big project. I had my changes all double-checked and was ready for an svn update. So I pulled down the latest revision and did one more sanity check. Surprise! Nothing worked any more. What had happened?
Sure enough, further poking revealed prototype.js as the source of the exception. I was creating an Ajax.Request to chat with a little JSON producer and it wasn’t even getting to socket opening. Instead, it provided me with this fairly cryptic exception:
[Exception... "Component returned failure code: 0x80070057 (NS_ERROR_ILLEGAL_VALUE) [nsIXMLHttpRequest.setRequestHeader]" nsresult: "0x80070057 (NS_ERROR_ILLEGAL_VALUE)" location: "JS frame :: http://192.168.0.81/Exhibit/templates/prototype.js :: anonymous :: line 1284" data: no]
What? I mean, XMLHttpRequest.setRequestHeader() is obviously getting a bad value, but what in the world could it be? So I plunged into prototype.js itself and did more looking. It didn’t take long to find the problem section:
for (var name in headers)
What was the bad value? It was a function I had added to Object.prototype, which implements class-like inheritance. It was getting picked up in the hash-style loop, which didn’t exist in the earlier version of prototype.js we were using, and passed along to setRequestHeader like it was any old primitive member variable. Removing the function from Object.prototype, making it a global function, and rewriting all the inheritance calls fixed the problem.
I won’t get into the argument about whether it’s kosher to modify Object.prototype. I’m not a style or standards zealot. I understand the reasons why it’s dangerous to modify Object.prototype. I also understand the power it gives a developer. The only thing anyone should take away from the discussion is that managing compatibility expectations is a constant process. One should always be on their toes.