Skip navigation.

exploreopera

| Help

Sign up | Help

Prototype findOrStore considered harmful

, , ,

Prototype 1.5.0 completely breaks CNN on certain mobile versions of Opera. All the text disappears.

We've dug up the source and it appears to be code from the common prototype.js that causes problems, CNN's prototype.js is here:


Element.extend.cache = {
  findOrStore: function(value) {
    return this[value] = this[value] || function() {
      return value.apply(null, [this].concat($A(arguments)));
    }
  }
};


Problem arises when the "value" argument is a function object. Then this[value] = this[value] requires decompilation, in order to create a string for the property name.

This is a bad idea because

  • Decompilation support is an optional feature. We disable it on many limited platforms for performance
  • Decompiling a function is in any case not a reliable way to create a unique hash key since functions can have exactly the same source code but live in different scopes or different closures, so this code as-is will create obscure bugs that are very hard to track down.


I hope the excellent Prototype devs can find a better approach. Unfortunately this code is still there in the latest version.

(Due to impatient family members I can't bug it in their tracker right now, post a link to the bug in comments if you do.)

DOMStorage and securityInteresting DOMContentLoaded question

Comments

avatar
What would be a good solution to this problem? They can't use a function as the map key unless they implement a map class themselves. There is no way I know of to get an address, ID, hash, etc for an object. Should JavaScript be extended to solve this problem?

I guess I'd use something like this:
function getID(obj) {
if( obj === null ) return 0;
if( obj === undefined ) return 1;
if( ! obj.__id__ )
obj.__id__ = randNumGreaterThan1();
return obj.__id__;
}
And call it when I wanted a map key.
this[getID(value)] = this[value] || function() {...}

By HeroreV, # 7. July 2007, 17:16:16

avatar
Yes, something like that is probably what I would do too.

Regarding your question "should JavaScript be extended..": quoting a somewhat related discussion on whether to add some form of unique object ID to ECMAScript 4 (quote is heavily snipped):
> What jumps out at me is the potential for developers to assume that a
> hashcode is the same as a unique ID (especially if some
> implementations enforce uniqueness while others don't), thus leading
> to subtle bugs. For that reason, I'd like to weigh in with the
> opinion that requiring uniqueness for hashcodes would be really
> nice. (Alternatively a separate mechanism for generating unique
> object IDs would be nice.)
<X>

If an implementation is going to guarantee uniqueness then it probably
needs to maintain a global table of all live objects whose hash codes
have been obtained, to avoid generating duplicate codes when the
global hash code counter wraps around (intrinsic::hashcode returns a
uint).
<X>
IMO we'd be better off following Java here and just spell out (more)
clearly that you can't use the hash code as an object ID.

Posted to ES4-discuss by Lars Thomas Hansen (sorry, listmembers-only archive but AFAIK anyone can join the list.)

By hallvors, # 7. July 2007, 22:30:14

avatar

By hallvors, # 7. July 2007, 22:50:56

avatar
And it has been fixed already :-D

By hallvors, # 8. July 2007, 12:35:26

avatar
How do we detect if decompilation is disabled? What does Function.prototype.toString() return instead? Does it error?

By deanedwards, # 14. July 2007, 08:34:35

avatar
hallvors explained this in bug report:

Originally posted by hallvors:

Decompilation support is an optional feature of ECMAScript. Opera disables it on limited platforms (mobiles, devices) for performance. When the output of Function.prototype.toString() is "[ecmascript code]" this is the case.

By d.i.z., # 14. July 2007, 11:03:37

avatar
Dean, good question - because I don't think we've been completely consistent in the past. It never throws an error but I seem to remember that some versions have returned the mixed case string "[ECMAScript code]" and some the all-lower case form..

By hallvors, # 20. July 2007, 14:39:38

Write a comment

You must be logged in to write a comment. if you're not a registered member, please sign up.