After a lot of time of searching what is the best way to synchronously load javascript from javascript I finally found a way to do it that works in almost any browser. The hardest part of it all is not loading and eval’ing the script, but allowing the script to set new variables in the global scope.
if (window.execScript) { window.execScript(contents); } else { with (window) { window.eval(contents); } }
This is what I’m finally using on my open source modular javascript project. To test it out I also found this website very useful. What I did was to create a test page that loaded a script, declared some global variables in different ways:
var someVariable = true; someVariableWithoutVar = true; eval("var someVariableWithEval = true"); eval("someVariableWithEvalWithoutVar = true");
Then loaded the website through browsershots and the results came in a few minutes. The tests passed on a lot of browsers including all versions I could test of Firefox, Opera, MSIE, Safari, with some minor exceptions: Safari 3.2.1 on Windows XP and OS X 10.5, Opera 7.54 on Windows XP, Konqueror 4.2 on Ubuntu 9.04.
The case with Safari 3.2.1 is that it cannot set global variables declared with var inside a eval’ed script. There’s a newer 3.2.3 version that I would like to test on to see if there is any difference. As for Opera, it’s an old version that nobody is probably using anymore. But for Konqueror I really don’t know the source of the error.
Take the test yourself. If you would like to see how the tests were done take a look at the sources here.
Update: The test suite now passes in almost every browser with the exception of some older versions of opera :).
Hi César,
I’m curious what difference it makes to enclose window.eval() in the with statement since you access window.eval explicitly?
Thanks,
-Andrew
Hi Andrew,
There are several ways that other sites mention to have this working correctly, for example:
For a script to run correctly in eval the way it would run if loaded through an script tag these things have to be set:
IIRC: This means that if in the eval’d code there’s a variable assignment then it is assigned to the Activation Object. If “this” is used is assigned to the Variable Object. The Global Object that is always “window”.
I haven’t checked this extensively, but different browsers set this objects to different values. Using only window.eval(contents) just forces the Variable Object to be set to window but not the Activation Object that might not be what we expect. Hence the use of “with(window)” is needed to set the Activation Object explicitly and is the only cross-browser solution I have tested personally. When eval’ing, there’s also a different Execution Context than when we include code with an script tag. But that is not possible to change using javascript and might, in some cases, present a problem to eval’d scripts.
There is more information in this site: http://bclary.com/2004/11/07/#a-10