Skip navigation.

exploreopera

| Help

Sign up | Help

Posts tagged with "coding"

jQuery relies on function decompile, won't work on Opera mobile

, , ,

A colleague just noticed that the otherwise excellent jQuery JS library has an "isFunction" method that relies on decompiling functions to figure out if they really, really are functions. This is not a good idea because decompiling functions is an optional feature of the ES-262 spec. It is slow and requires too many resources for certain low-end platforms, so it is not supported by any of the Opera Mobile versions.

Here's the code, complete with a frustrated comment from John Resig himself:
// This may seem like some crazy code, but trust me when I say that this
// is the only cross-browser way to do this. --John
isFunction: function( fn ) {
return !!fn && typeof fn != "string" && !fn.nodeName && 
fn.constructor != Array && /function/i.test( fn + "" );
}


John, I feel your pain and that code clearly took quite some effort and testing across various browsers passing in various types of objects - IE collections allowing ()-reference, anyone? It wouldn't surprise me if Opera is one of the culprits that caused you problems here since we try to support some of IE's weirdness and hence "typeof" sometimes returns 'function' when you'd expect it not to.

So I'm sorry to break it to you, but /function/i.test( fn + "" ) won't do what you think on Opera's mobile versions, causing really-hard-to-track-down bugs.

May I suggest adding the below workaround somewhere?
if( (function(){}).toString().match(/\^[ecmascript/i) ) Function.prototype.toString = function(){return 'function'};


Should be all you need..

RSnake wants your briefest self-replicating snippet

, ,

I'm wary of adding too many RSS feeds to the Opera installation I use for work. One of the few bloggs in there is RSnake's ha.ckers.org, and some of my readers might be interested in his diminutive worm replication contest. I've even submitted an entry which I think is quite good though it might be dodging too many (so far unwritten) rules to be a contestant :lol:

If you feel like submitting - go for it, dissecting the entries, writing new ones and following the discussion is a nice way to learn more about JavaScript :smile:

function(p,a,c,k,e,r) de-mystify trick

,

If you ever came across code that starts
eval(function(p,a,c,k,e,r)

here's a small demonstration of how to turn that code into something sensible..

A word of warning: I'm experimenting with Wink for creating Flash screencast-type demonstrations. That means you agree to receive a 1.5 M .swf file of screenshots and text by clicking through to the post.

I haven't quite mastered Wink, some unintentional mouse movement might occur but anything in the spirit of experimentation.. Feel free to tell me in comments whether you like more of those Flash-based visual demonstrations or prefer the old-fashioned screenshot approach.

Read more...

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 security

, , , ...

The DOMStorage feature of the WHATWG WebApps spec is criticised for the security implications. 0x000000 has excellent points (particularly in comments) and I'll think out loud about how UAs like Firefox and Opera will need to address them. I'm not terribly good at spec writing and not implementing this stuff myself so only personal opinion and thoughts to be found here..

Quoting 0x000000:
Starting in Firefox 2 but mainly in Firefox 3, the browser is fully capable of restoring this sessiondata after a crash. This is interesting because we could on purposely crash a window and inject sessiondata to make it an persistent denial of service


Yes, that's a real threat. Opera already addresses a similar issue in the dialog you get on resuming after a crash, where you can choose to start without open windows. An even better implementation might be to detect what window or session caused a crash, and attempt to restore all others - I assume it would require quite some engineering like a separate monitoring process or something. In any case, users will need a "start without restoring sessions" option to avoid persistent session storage enabling persistent crashers.

this storage engine allows me to store what ever I want, whenever I want, and it allows huge data -if I have access to that page- which is useful when there is some XSS hole on that page


Um, if there is an XSS hole on the page you've got the data anyway, is this really more dangerous than just submitting it to a server you control?

It can be used to store worms and activate them across webpages instead of calling remote scripts


Still requires some XSS vulnerability on the page you want to run the worm on. If white-list restriction is implemented it requires both attacker and target to be white-listed.

it can used to store heapspray shellcode to actively stay under the radar of anti virus programs


The bad code needs to travel over the wire at least once to get to the local storage, so that's not entirely true but still an interesting point. I guess it's a matter of timing. If you can get a piece of malware into the local storage of a sufficient number of UAs before security software is updated to detect this threat, you could then activate the attach with some fairly innocent-looking JS that might be much harder to filter out. Should UA vendors collaborate with Antivirus companies on enabling local storage scanning? I'm not sure here, guess malware detection evasion side effects of local storage need more thinking..

it can store a great deal of information later to used on sub domains to read them out again and use them, like defeating single sign on schemes


I'm not sure what he means by "defeating single sign on schemes" here.

it can also be used to profile users and de-annonymize them by storing data vectors in their browser


Yes, it can if you find an XSS hole on a site I give personal information to (or if a web developer by mistake stores given information in a too public part of the local storage).

Now, security concerns are addressed by the specification. Perhaps it's too easy to overlook, but note how the spec explicitly states that
user agents may prevent domains from storing data in and reading data from the top-level domain entries in the globalStorage object

and I guess UAs will in practice require per-domain white-listing of domains that are allowed to use global storage, or make it available only in "application-like" contexts such as widgets. I can't imagine any UAs implementing this part of the spec without additional security restrictions, that would indeed be crazy. On the other hand, per-domain whitelisting will address most of his potential exploits as long as the white-listed sites themselves are safe.

Nevertheless, the spec gives greater powers to web developers. It will enable them to do interesting things more easily, but as we know with greater powers comes greater responsibility - including responsibility for coding responsibly and preventing XSS. The greater capabilities we give JavaScript, the greater the damage a single XSS exploit can cause.

(Opera doesn't support DOMStorage yet but we probably will at some point, apparently Firefox 3 will support it according to 0x000000's post.)

can you improve ebDCKillCheckMousedown?

, ,

Busy with my regular passtime eBay JavaScript browsing (I think I spend more time on their site reading their .js files than looking at auction listings) I came across this:

var ebAllowClick=true;function ebDCKillCheckMousedown()
{if(ebAllowClick)
{ebAllowClick=false;setTimeout("ebAllowClick=true;",1250);}}
document.onclick=ebDCKillCheckMousedown;


Now, there is nothing technically wrong with that but I'm not terribly impressed with the quality of this snippet. Actually I find it hard to believe that a site with the scale and resources of eBay doesn't do review their scripts more carefully for efficiency.. but rather than me launching into one of my familiar rants I'll just pass the buck this time: so, if you were to teach the author a thing or two about efficient JavaScripting, what would you say?

Edit: proofreading the posted post I noticed yet another bug, not just performance improvements stuff..

A problem with John Resig's addEvent

, , , ...

A while ago, Peter-Paul Koch and some other JavaScript-interested bloggers held a competition for improving the "addEvent" function. The winner was John Resig's flexible JavaScript events function.

It creates a new property of the object you add an event listener to as follows:
obj['e'+type+fn] = fn;

The main purpose of that is to make the "this" keyword work inside event listeners. It is a clever hack, though looks a bit ugly - to ensure that the object property has a unique name, it concatenates "type" and "fn", meaning the browser has to decompile the function and use its entire source as part of the property name. Decompiling a function object is slow, the property name becomes nothing short of ugly. Perhaps a few lines of code to make a prettier unique property name would be worth it?

Besides the ugliness, here comes the real problem: the code assumes that all implementations can decompile functions. Opera can on desktop, but to save footprint this feature is disabled on mobile phones. Function.prototype.toString simply returns "[ECMAScript code]". Hence, each call to Resig's addEvent will overwrite the previous function object for that type, and the last function added will be called as many times as addEvent itself has been called. I'm afraid the clever hack has turned rather destructive - bad enough to break cross-platform compatibility for any app.

As written, the function makes the assumption that all browsers which have attachEvent support has IE's bugs. The simple fix would be to follow this rule: use object detection and try the standards-compliant path first. First looking for the standards-compliant (thus probably the best defined) function might be a good general rule of thumb for compatibility. Cross-browser support for a method that is implemented by trying to figure out what another browser is doing is likely worse than support for a method specified in detail by the W3C, so by choosing the W3C stuff if it exists should get you better compatibility.

how to say hello world with JavaScript

, ,

..if you're Google

My apologies, this isn't funny. This post won't even try to be funny. Promise.

Just a trick question for my skilled readers: where is the code that runs when you click on the button on this page?