Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dojo 1.8 - create global variable in require

I noticed that some of the legacy scripts that I'm working on for a project weren't working anymore after my team upgraded to Dojo 1.8. Specifically, the global variable that they created wasn't being created any more.

I dug around and found out that the Dojo 1.8 team is very much opposed to global variables. So opposed, in fact, that they make it physically impossible for the user to create a global variable in a required script using the following code at the end of their require:

req.eval =
        function(text, hint){
            return eval_(text + "\r\n////@ sourceURL=" + hint);
        };
var eval_ = new Function('return eval(arguments[0]);');

That's wonderful and all, but the old code I'm working with can't be changed, so I've been trying to figure out how to get around this and execute the eval in the local context instead.

Fortunately, dojo.eval is still there from older versions of Dojo, and that does what I want it to. So I just need to get access to req.eval and change the function to do return dojo.eval(...) or even just eval(...) in certain instances.

The problem is, I haven't been able to figure out how to get access to req. Here's what happens:

I include dojo.js in script tags at the top of my HTML file. It loads in its own script file.

dojo.require is accessible from my own files. It's defined with define in the script file:

'dojo/_base/loader':function(){
define(["./kernel", "../has", "require", "module", "./json", "./lang", "./array"], function(dojo, has, require, thisModule, json, lang, array) {

I'm not sure if that's important or not. Anyway, inside the scope of dojo.require, I can see something called injectModule, while in my own file I can't. injectModule is a local variable so you can't see it with this. It is defined in an anonymous function at the start of the file, i.e.

(function(){ ... injectModule = function(){} ... })();

Inside the injectModule function, there's the following line:

req.getText(url, legacyMode!=sync, xhrCallback);

which goes to req.eval. So injectModule can see req.

I'm not sure what to do. None of my nefarious JavaScript tricks have helped me even begin to navigate this gridlock of scopes. A good start would be figuring out how to see injectModule from my outer script file that calls dojo.require. I wasn't able to do it with 'bind', though, because it's a local variable defined in an anonymous function. Is this even going to be possible?

To make things a little easier, here's a summary:

File 1:

<script src="dojo.js"></script>
dojo.require(File 3);
console.log(globalVar);

File 2:

(function(){req.eval = unhelpful function})();
define(["require"], function(module){
    dojo.require = function(x){req.eval(x)}
});

File 3:

globalVar = ...;

I can modify files 1 and 3, but file 3 will always need a global variable. I can't modify file 2. The goal is to change req.eval in file 2 to be a better function.

Declaring the global variable earlier doesn't work because the scope change means file 3 still won't be able to see it.

Reflection and string replacement doesn't work because the scope is wrong and the JS is minified on the server-side.

Overwriting the methods from file 1 doesn't work because I can't see through the scope.

Using the JavaScript bind function has been fruitless as well.

like image 810
Andrew Latham Avatar asked Oct 30 '12 17:10

Andrew Latham


2 Answers

For this, dojo has created dojo.global. It will point to the window in which dojo has been loaded (nice for framed layouts).

So declare your global variables like so:

require([ "dojo/_base/kernel", ... ] , function(kernel) {
    kernel.global.globalVariable = 1;
    console.log('set')
})

dojo.addOnLoad(function() {console.log('get', globalVariable);});
like image 142
mschr Avatar answered Oct 22 '22 09:10

mschr


Global scope can be accessed through the global window object, so window.foo = 'bar' is the same as creating a global variable foo. More details about this here: https://stackoverflow.com/a/4862268/168382

like image 40
slikts Avatar answered Oct 22 '22 10:10

slikts