Digital Edition

SYS-CON.TV
Eval JavaScript in a Global Context
For more standards-respecting browsers, the way to do this should be to use the call function

Even though it's considered bad practice, it's often handy to eval code in JavaScript.  And in my case, it was simply necessary, since the JSF specification requires eval of scripts. And it's also necessary to execute those evaluated scripts in the global scope. It's not as easy as it first looks.

For our first naive implementation, we'd simply used eval(src) in our first pass at the implementation.

This is utterly wrong, and to understand why, you'll need to understand scopes. JavaScript has what you can think of as two different scopes - function scope, where you're executing something in the context of a function, and global scope, where you're executing something in a global context - for instance, if I say var j = 1; within a function's scope, then the variable j is set to 1 within that function. If I say the same expression, var j = 1 within the global scope, then j is set to 1 everywhere in the program - in every function, provided that that function doesn't define a j variable in its local scope. In browsers, the global context is window - this is the default object that everything gets hung off of if you don't specify any other object.

So, when we said eval(src), we were executing the src scripts within the local scope of the function where eval was called - that meant that I would be getting different results when variables were declared and set than would be expected - in fact, for some cases, it just seemed like the scripts weren't being executed at all.

So, what to do? Well, as is usual for the browser JavaScript, there's Internet Explorer, then there's everyone else. As is usual, IE, the crazy cousin Larry of the browser world, has a convenient, well intentioned, and utterly nonstandard way to do this: window.execScript(src) It works great - and the other ways I'll detail here break rather infamously, so use this non-standard function on IE.

For more standards-respecting browsers, the way to do this should be to use the call function, which is a standard function attached to every Function object. So, eval.call(window, src) should work. But to understand why, it's important to know about context, in addition to scope. Every function call has it's own context: this is the object that's represented by the special value this. When we use the call function, the first parameter is the context object we'll use for this. This is handy for all kinds of purposes, but for us, it's just nice to use to set the context to the window object - which, you'll recall, is the global.

Sadly, eval.call(window,src) breaks on Chrome - it complains about contexts not matching. Odd - and I was unable to Google up why this might be so. But a couple lucky guesses later, and I discovered that window.eval.call(window,src) works on all non-IE browsers. Now, when I say "var j = 1", the window[j] is the variable that's set... So, that's good. Why do we have to add the extra window. on Chrome? Not sure - I could guess, but it's too likely to be wrong.

At this point, I thought we'd licked the problem. No such luck. Sure, global variables are getting set, but it turns out that if you say: alert(this) - then you would correctly receive the global object back on Chrome and Safari, but not Firefox - there, you'd get back the object that was the enclosing object before the call function got called. Very odd, and likely a bug in their implementation.

With a little help from Werner Punz, we figured out that they best way to get around this issue is to wrap the calling function in an anonymous globally scoped function. Like the Chrome bug, I can guess why this might work, but it would only be a guess. Better not to clutter up the internets with more guesses - I'll just stick to what I know works.

Here's the code that I now use to do a global eval:

Read the original blog entry...

About Jim Driscoll
Jim Driscoll has worked at Sun Microsystems for 12 years, working on such projects as the first version of Servlets (in the Java Web Server), and the initial implementation of Java 2, Enterprise Edition. He is currently a Senior Engineer working on the implementation of Java Server Faces, helping to integrate technologies such as AJAX and Comet into the new release.



ADS BY GOOGLE
Subscribe to the World's Most Powerful Newsletters

ADS BY GOOGLE

Bill Schmarzo, Tech Chair of "Big Data | Analytics" of upcoming CloudEXPO | DXWorldEXPO New York (No...
DXWorldEXPO | CloudEXPO are the world's most influential, independent events where Cloud Computing w...
DXWorldEXPO LLC announced today that Telecom Reseller has been named "Media Sponsor" of CloudEXPO | ...
In his keynote at 19th Cloud Expo, Sheng Liang, co-founder and CEO of Rancher Labs, discussed the te...
Enterprises are striving to become digital businesses for differentiated innovation and customer-cen...
The best way to leverage your Cloud Expo presence as a sponsor and exhibitor is to plan your news an...
To Really Work for Enterprises, MultiCloud Adoption Requires Far Better and Inclusive Cloud Monitori...
A valuable conference experience generates new contacts, sales leads, potential strategic partners a...
Containers and Kubernetes allow for code portability across on-premise VMs, bare metal, or multiple ...
Everyone wants the rainbow - reduced IT costs, scalability, continuity, flexibility, manageability, ...
SYS-CON Events announced today that Silicon India has been named “Media Sponsor” of SYS-CON's 21st I...
We are seeing a major migration of enterprises applications to the cloud. As cloud and business use ...
SYS-CON Events announced today that CrowdReviews.com has been named “Media Sponsor” of SYS-CON's 22n...
Founded in 2000, Chetu Inc. is a global provider of customized software development solutions and IT...
DXWorldEXPO LLC announced today that "IoT Now" was named media sponsor of CloudEXPO | DXWorldEXPO 20...
Andi Mann, Chief Technology Advocate at Splunk, is an accomplished digital business executive with e...
Most DevOps journeys involve several phases of maturity. Research shows that the inflection point wh...
DXWorldEXPO LLC announced today that ICOHOLDER named "Media Sponsor" of Miami Blockchain Event by Fi...
Today, we have more data to manage than ever. We also have better algorithms that help us access our...
DXWordEXPO New York 2018, colocated with CloudEXPO New York 2018 will be held November 11-13, 2018, ...