Today’s JavaScript WTF

Monday, November 17th, 2008 @ 11:14 am | filed under: Examples

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)

16 Responses to “Today’s JavaScript WTF”

  1. Garrick Says:

    Seriously.. what are they thinking!? This is some ridiculous code.

  2. craiga Says:

    Can’t help but to feel there’s going to be one *very* embarrassed Microsoft employee out there…

  3. Ajaxian » When generated JavaScript goes wild; JavaScript WTF in SharePoint Says:

    [...] 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 [...]

  4. Emil Stenström Says:

    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.

  5. Laurent Raufaste Says:

    Why did he stop at 10 ?

  6. Bertrand Le Roy Says:

    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.

  7. Aaron N. Says:

    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.

  8. Bertrand Le Roy Says:

    True.

  9. emailtoid.net/i/09f9a6b7/ Says:

    Really nice one !

  10. me.yahoo.com/cody.rioux Says:

    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.

  11. emailtoid.net/i/b172417b/ Says:

    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.

  12. Jesper Says:

    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);
    }

  13. Aaron N. Says:

    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.

  14. The Reddit crowd weighs in on the JavaScript WTF » Clientcide (Formerly CNET’s Clientside) Says:

    [...] 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 [...]

  15. Geary Says:

    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(',') + ')' );
    }

  16. Geary Says:

    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' ) );