Posts Tagged ‘eval’

John Resig’s degrading script tags

Thursday, November 13th, 2008

I just re-discovered this interesting Javascript trick from John Resig’s blog (link here). Under usual circumstances, I would frown when I see eval in Javascript code, the one construct I tried to avoid like a plague. But I don’t resist interesting usage of eval. This is one of them. Basically, the trick allows you to have a script tag with an embedded Javascript, like this:

<script src="some_js_file.js">
  // Do something with the loaded file.
  callSomething(); ...
</script>

Interesting huh? To make this work, the loaded script file itself will end with the a two-liner that basically find the script element and evaluates the innerHTML of the element:

var scripts =
    document.getElementsByTagName("script");
eval(scripts[scripts.length - 1].innerHTML);

Ingenious. As an added bonus, the content of the script element will not be executed if the Javascript fails to download (since, obviously, the last two lines that we just added won’t be executed).

Also interesting is how this hack utilizes the synchronous property of Javascript loading. In most browsers except the most recent ones (most of them still in beta/nightly), whenever a script tag is encountered, the rendering stops until the script is downloaded and executed. That means by the time the script is loaded, it knows for sure that the script tag it is in is the last one on the DOM since nothing else has been rendered. Thus, you can access the element by using the above method (see scripts[scripts.length - 1] part of the code).

I’m a little bit behind with how newer browsers download its Javascript. I suspect that the method above may not work. I guess it’ll depend on the heuristics the browsers use to make Javascript download not blocking. I heard that Firefox will actually assume that the script does not do anything to the DOM and continues rendering, in which case the above technique may not work. (I’m sure I’m missing something, probably there are some heuristics that FF used that I’m not aware of.)

Well, still, it is an ingenuous way of utilizing eval.