Today’s JavaScript WTF
MooTools cohort Jim Wilson sends me this wonderful little nugget of entertainment today. Microsoft’s SharePoint app has in it’s web app code this lovely little bit of JavaScript:
function DeferCall() {
if (arguments.length == 0) {
return null;
}
var args = arguments;
var fn = null;
if (browseris.ie5up || browseris.nav6up) {
eval("if (typeof(" + args[0] + ")=='function') { fn=" + args[0] + "; }");
}
if (fn == null) { return null; }
if (args.length == 1) {
return fn();
} else if (args.length == 2) {
return fn(args[1]);
} else if (args.length == 3) {
return fn(args[1], args[2]);
} else if (args.length == 4) {
return fn(args[1], args[2], args[3]);
} else if (args.length == 5) {
return fn(args[1], args[2], args[3], args[4]);
} else if (args.length == 6) {
return fn(args[1], args[2], args[3], args[4], args[5]);
} else if (args.length == 7) {
return fn(args[1], args[2], args[3], args[4], args[5], args[6]);
} else if (args.length == 8) {
return fn(args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
} else if (args.length == 9) {
return fn(args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);
} else if (args.length == 10) {
return fn(args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);
} else {
var L_TooManyDefers_Text = "Too many arguments passed to DeferCall"
alert(L_TooManyDefers_Text);
}
return null;
}
As Jim put it, “and we wonder why windows has 40 million lines of code.”
Update: This article got featured on Reddit and I have another post about my actual thoughts on this chunk of code above: The Reddit crowd weighs in on the JavaScript WTF
No TweetBacks yet. (Be the first to Tweet this post)
Follow @clientcide on twitter to get notified of new posts.
To follow me personally on twitter, follow @anutron.
November 17th, 2008 at 12:11 pm
Seriously.. what are they thinking!? This is some ridiculous code.
November 18th, 2008 at 5:36 am
Can’t help but to feel there’s going to be one *very* embarrassed Microsoft employee out there…
November 19th, 2008 at 2:00 am
[...] JavaScript below was pointed out by Aaron Newton, and it comes from SharePoint. Jim Wilson said about it: “and we wonder why windows has 40 million [...]
November 19th, 2008 at 3:02 am
Hahah, that’s really todays laugh :)
I’ve been there, peeking deep inside the Sharepoint js, and what you can find there is truly hillarious stuff. My favourite was how the code assumed quirksmode behaviour, so you started getting js errors with a proper doctype. Luckily, js methods are overridable.
November 19th, 2008 at 3:06 am
Why did he stop at 10 ?
November 19th, 2008 at 10:59 am
Yes, that does look stupid… Until you start thinking and realize this was probably done to be compatible with IE5, which doesn’t have apply. Amazing how the very first assumption about MS devs is that they must be idiots. Never that they have to deal with constraints that you might have no idea about.
November 19th, 2008 at 11:03 am
Even if that’s the case, they obviously have the ability to detect the difference between ie5 and other browsers (as they do so in the script above). If they wanted to add support to ie5 they could do this hacky work for ie5, but use apply for everything else.
November 19th, 2008 at 1:10 pm
True.
November 20th, 2008 at 7:02 pm
Really nice one !
November 21st, 2008 at 6:52 am
Why would they bother detecting ie5 or not for the hack? They have to write it one way or another and it works fine in all the newer browsers. Writing detection and then the elegant code for newer browsers would just be writing more code than they need to.
November 21st, 2008 at 9:49 am
var i=0;var exec_statement = "fn(";
for(i=0;i<args.length-1;i++) {
exec_statement += "args["+i+"],";
}
if (i<args.length) {
exec_statement+="args["+i+"]);";
} else {
exec_statement+=");";
}
return eval(exec_statement);
Bertrand Le Roy: this took me ten seconds to come up with and I’ve never written a line of javascript in my life. You’re telling me this wouldn’t work in IE5? I find that hard to believe.
November 21st, 2008 at 11:36 am
I guess you can replace it with the following, and this isn’t limited to 10 arguments:
function DeferCall() {if (arguments.length == 0) {
return null;
}
var args = arguments;
// ... some stuff ...
var fn = args.shift();
fn.apply(args);
}
November 21st, 2008 at 11:46 am
Jesper, using .apply would be the best way to accomplish it, but Bertrand’s point is that you can’t use .apply for older versions of IE, and cutting support for it isn’t something MSFT is willing to do. My point was to use .apply for everything else and only use the hack for ie5.
November 22nd, 2008 at 12:31 am
[...] point out that the code in question (on a Function.apply method for IE5) that I understand why Microsoft would write such a hack, as IE5 doesn’t have a suitable [...]
November 22nd, 2008 at 3:32 pm
emailtoid is on the right track. You can simplify that code just a bit. Here’s a complete replacement for the original function:
function DeferCall( fn ) {
if( typeof fn != 'function' )
return null;
var args = [];
for( var i = 1, n = arguments.length; i < n; ++i )
args[i-1] = 'arguments[' + i + ']';
return eval( 'fn(' + args.join(',') + ')' );
}
November 22nd, 2008 at 5:57 pm
It figures that I missed something in the original code. It accepts a string as the first argument, which can be either a function definition or the name of a function. Here’s a version that allows that:
function DeferCall( fn ) {if( typeof fn == 'string' )
eval( 'fn = ' + fn );
if( typeof fn != 'function' )
return null;
var args = [];
for( var i = 1, n = arguments.length; i < n; ++i )
args[i-1] = 'arguments[' + i + ']';
return eval( 'fn(' + args.join(',') + ')' );
}
and some tests:
function myfn( a, b ) { return a + b; }
alert( DeferCall() );
alert( DeferCall( function() { return 'none'; } ) );
alert( DeferCall( 'function( a ) { return a; }', 'A' ) );
alert( DeferCall( myfn, 'A', 'B' ) );
alert( DeferCall( function( a, b, c ) { return a + b + c; }, 'A', 'B', 'C' ) );