2

Let's say I had an array of Javascript file names:

["funScriptStuff.js", "jQuery.js", "dojo.js", "scriptyScript.js"]

how could I execute them independently of each other?

For example, let's suppose one script did some evil stuff like

var undefined = true;
var window = "Windows 98";

and another script had code that relied on these global variables being unsabotaged

if (a !== undefined) {
  window.open(url);
}

if the first script ran first, it would ruin everything in the second one. Without changing anything in these script files, how can I run them independently of each other to prevent them from messing each other up?

EDIT: I am not asking what Javascript patterns to use to prevent namespace collisions, like wrapping my code in a big closure and so forth. I know about those. I'm trying to create an environment where you can run arbitrary scripts that I have no control over without them stepping on each other's toes.

Peter Olson
  • 139,199
  • 49
  • 202
  • 242
  • how about iterating on the array and doing a document.write() for each js file? that may work i guess. – aishwarya Dec 06 '11 at 23:58
  • I think you'll have to run them in separate documents on different domains. No other way to prevent them from messing with each other with 100% certainty – Pekka Dec 06 '11 at 23:59
  • But they're not messing each other up, they're messing up the global object. All scripts that are executed inside the same browser window share the same global object. – Šime Vidas Dec 07 '11 at 00:06
  • Could you maybe make a copy of the global state and reset it after each script runs? – Peter Olson Dec 07 '11 at 00:08
  • @Šime yeah, but that's what I mean essentially: You can't reliably prevent another script inside your document's context from breaking something (in the global space) for another script. And there is no good way to fix such a breakage without reloading the document... (If there is one I don't know about, I'd be very interested in hearing about it) – Pekka Dec 07 '11 at 00:12
  • 1
    @PeterOlson how about not loading any javascript files that do something stupid. – Raynos Dec 07 '11 at 00:24
  • I suspect this is a pendantic question. If not, why are you even running such malicious code? There's your solution: Only run code you trust. – Thomas Eding Dec 07 '11 at 00:56

4 Answers4

3

As far as I know, you can't reliably roll back pollution of global variables within the same document.

I think you'll have to run them in separate documents (= <iframe>s) on different domains. No other way to prevent them from messing with each other with 100% certainty.

(The "different domains" thing is to prevent really malicious code from polluting the other scripts (as iframes on the same domain have access to each other, so a malicious script could be looking for other iframes to compromise.)

Pekka
  • 442,112
  • 142
  • 972
  • 1,088
  • Let's suppose that somehow (I'm not sure how) I had a program that saved the initial global state and after each script ran, reset it to what it was before. Would that not accomplish the goal correctly? – Peter Olson Dec 07 '11 at 00:14
  • @Peter I'm not sure whether there is a way to do that that works reliably and without major problems in all browsers. There doesn't seem to be anything along those lines there at the moment, but maybe someone manages to come up with a suggestion... – Pekka Dec 07 '11 at 00:17
  • 2
    ` – Raynos Dec 07 '11 at 00:23
  • @Raynos hey, that is coool! (HTML5 only though, so I'm assuming it won't work in IE <=8) – Pekka Dec 07 '11 at 00:32
  • @Pekka wont work in legacy platforms. It might be possible to emulate using [caja](http://code.google.com/p/google-caja/) – Raynos Dec 07 '11 at 00:50
2

Please define you target environment. Within browser and having only filenames the only thing you can do is to download each script with XHR, treat it as string data, and eval it (yes, solution is as clumsy as it sounds). To prevent rogue script messing with your Global scope you need to use with statement:

var safeGlobal = {};
safeGlobal.isHoneyPot = true;   // whatever scripts might expect in Global scope
with ( safeGlobal ) {
  eval( scriptText );
}
delete safeGlobal;  // purge whatever pollution script leaves in Global scope

The other approach within browser is to use multiple windows or iframes, but this does not make the namespace flat, thus you will have to reference functions via window/iframe variables.

OnTheFly
  • 2,059
  • 5
  • 26
  • 61
  • 2
    +1 just because you managed to fit two "evil" features of Javascript into one concise hacky solution. – Peter Olson Dec 07 '11 at 00:22
  • 1
    Hey, this sounds interesting! Is it possible to break out of a `with` from inside? @Raynos yeah, but in this case, if it does the job....? – Pekka Dec 07 '11 at 00:24
  • Related: [Are there legitimate uses for JavaScript's "with" statement?](http://stackoverflow.com/q/61552) – Pekka Dec 07 '11 at 00:25
  • 1
    @Pekka no it does not :\ It murderous all optimization. I wouldn't pay the performance penalty, ever. Nor does it protect global scope at all http://jsfiddle.net/C9uLm/ – Raynos Dec 07 '11 at 00:28
  • 1
    @Raynos, dont be so dogmatic :-) What do you think what browser do when script source completes loading? :-) – OnTheFly Dec 07 '11 at 00:32
  • @Pekka, unfortunately, no, it only adds some degree of control over rogue script from out there. – OnTheFly Dec 07 '11 at 00:35
0

I often use this pattern.

(function(myNamespace, $, undefined) {

    //Public Method
    myNamespace.foo = function() {
        // ..
    };

    //Private Method
    function bar() {
        // ..
    }
}(window.myNamespace = window.myNamespace || {}, jQuery));

Because the third argument isn't provided, it is certain to be undefined.
If you use jQuery, it makes sure $ isn't set to something else (unless, of course, jQuery was set to something else).

Community
  • 1
  • 1
kapex
  • 28,903
  • 6
  • 107
  • 121
0

.js files are just blocks of javascript that are included in the page. It's not difficult to document.write a script tag into the page based on whatever criteria you have. So, you can have a script that checks for some condition and then adds whatever external script you want, based on that condition.

However, in terms of their "independence" you have a bit of a problem (which is usually Javascript's critics primary one) which is that everything you toss into the page is global and visible to everything else. This is actually quite useful at times, but it does mean that you have to encapsulate your objects very carefully to keep them from bleeding all over one another.

So, if all these scripts are your own, you can control this by making sure that each set of tools is part of some larger object that is very unique. As for using frameworks like jQuery, you just have to be careful not to encroach on their objects. They took this into consideration, however, so, as long as you know what to look for, you should be ok.

Yevgeny Simkin
  • 27,946
  • 39
  • 137
  • 236