Why I can't access global variable from javascript function in jasmine - javascript

I'm using Jasmine standalone https://github.com/jasmine/jasmine/releases
I have declared a global variable global_song in SpecRunner.html (I can access it from chrome console so it's truly global) which includes script where I am trying to concatenate global_song to "should be able to play Song " :
it("should be able to play Song " + global_song, function() {
player.play(song);
expect(player.currentlyPlayingSong).toEqual(global_song);
//demonstrates use of custom matcher
expect(player).toBePlaying(song);
});
Why it cannot access global_song variable ?
Update : expect(player.currentlyPlayingSong).toEqual(global_song) works whereas it("should be able to play Song " + global_song doesn't work.

Where have you defined global_song? If you did that in the beforeEach() function this behaviour would make sense as the code in the describe block (which attempts to define your it() function) gets executed before the beforeEach() as described in this other SO answer.

Well i suppose your global_song created after executing of
player.play(song);
That's way it's not available in test as first parameter of it and available after executing player.play in expect(player.currentlyPlayingSong).toEqual(global_song) assertion.
Try to add simple assignment to global_song separatelly from player.play to verify that it's available before player.play executed:
window.global_song = 'value'
Just take a look on that sample to illustrate the main possible candidate of problem:
function foo(){
window['bar'] = 'bar';
}
console.log(window.bar); // Undefined
foo(); // now window contain bar variable.
console.log(window.bar); // 'bar'

Related

JavaScript: One can't view a non-global variable in the Browser Tool Console?

Might be a silly question but it still got me a bit stuck, not being 100% sure of the answers.
So I have an index.html file which calls a function in an example.js-file (just adding it for clarification):
function sinusGraph() {
var plotstart = 0,
plotrange = 20,
stepsize = 0.5; // not in use right now
var yValues, xValues;
function sinusValues(startinput, stopinput)
{
return d3.range(startinput, stopinput+1).map(function(i)
{
return Math.sin(i);
})
};
function xAxisValues(startinput, stopinput)
{
return d3.range(startinput, stopinput+1).map(function(i)
{
return i;
})
};
xValues = xAxisValues(plotstart, plotrange);
yValues = sinusValues(plotstart, plotrange); };
Writing, for example, "xValues" with the variables declared in the browser's returns "xValues is not defined(...)".
Removing "var xValues" letting it be a global variable does return the value.
My questions:
The browser's Tool Console can't see non-global variables within functions?
If that is the case, then is this a good tool to look for potential global variables that you have created by mistake?
Is there any way to view these variables in the browser's tool console, other than using console.log(myVariable) within the function where it is declared?
The browser's Tool Console can't see non-global variables within functions?
Yes.
Here is why it can't work: Local variables of a function only exist while the function is running. Code you type into the console will either be executed before or after the function is executed.
Even if you were able to access local variables after a function was executed:
which value would you expect to get when you type varname in the console? The inital value, the last value or all values?
what if multiple functions have a local variable with the same name?
what if the same function was already executed multiple times?
You can only inspect the current state of your application.
If that is the case, then is this a good tool to look for potential global variables that you have created by mistake?
No. You should use a linter such as ESLint that warns you if you forget e.g. a var declaration. Also enable strict mode: Assignments to undeclared variables will throw an error then.
Is there any way to view these variables in the browser's tool console, other than using console.log(myVariable) within the function where it is declared?
Set a break point in your code, either through the devtools or via debugger. Code execution will pause at the breakpoint and the console has access to everything that is accessible at the breakpoint.
The console has to run the code some scope (and it can't access a scope defined by a function that isn't running anyway).
Set a breakpoint inside the function, to pause execution there. When that breakpoint is triggered, the console's scope will be to that function.

How to call/use this module in other JS files/modules

I read some JS module design patterns recently. I came across this small code snippet as below.
(function(window) {
var Module = {
data: "I'm happy now!"
};
window.Module = Module;
})(window);
Still not quite understand this code well, my questions are:
How to use/call this module outside this particluar JS file? Need I
assign a variable to this module? e.g. var module1 = (...)(...);
Could anyone explain what the window parameter here stands for?
Is it a good practice to have two/three such kind of modules in the
same file?
The main reason to create an anonymous function in this case is to prevent global object pollution. It's not really a module pattern.
The problem arise when you declare a variable. Without the function scope, the variable will be added to the global object (window). If you were to declare the variables within a function. It would add the variable to the function scope without polluting the global object window.
What happen is that a javascript file could add a variable named foo and on a different file use that variable named foo too. Unless you really want to have a variable shared by two javascript files, it would probably create conflicts and bug that are difficult to fix.
For example: a.js
var foo = "one"
b.js
var foo = "two"
c.js
alert(foo)
In this case, the alert box might show either "one" or "two", depending of the order in the javascript files are included.
But having this a.js:
(function () {
var foo = "one"
})()
b.js
(function () {
var foo = "two"
})()
c.js
(function () {
alert(foo)
})()
This would create an error as you cannot alert a non declared variable.
One way to detect undefined variables, is to make sure to execute the javascript code in strict mode.
To do that, add the string "use strict" at the top of the file or function.
function () {
"use strict"
...
}
Undeclared variable will raise errors and it should be possible to fix the code that way.
Also, if you forget to declare a variable with the var keyword, it might end up adding the variable to the global scope even if the code is scoped into a function. The only way to prevent global scope pollution is to run the code in strict mode.
In the code snippet that you provided, the module with name Module is explicitly added to the window object. You can access the window object from any place in javascript unless the window name is ghosted by an other variable.
Now, back to the modules. If you want to define modules, it can be done in many ways. As an exemple, you could create an object on the window object called modules. In this object, you'll insert your modules.
module.js
window.modules = {}
foo.js
(function (window) {
var module = {}
...
window.modules.foo = module
})(window)
This variant isn't super good as you have to manually add the module to the modules object. You have to manually modify the window object, and that can be subject to errors.
modules.js
window.modules = {}
function define(name, constructor) {
var module = {exports: {}}
constructor(module)
window.modules[name] = module.exports
}
function require(name) {
return window.modules[name]
}
foo.js
define("foo", function (module) {
module.exports.one = function () {
return 1
}
module.exports.plus = function (a, b) {
return a + b
}
})
bar.js
define("bar", function (module) {
module.exports = function () {
var foo = require("foo")
return foo.plus(foo.one(), foo.one())
}
})
This is a module definition that looks a bit like module defined with http://requirejs.org/. It is quite basic as it doesn't take into account module dependencies so if bar is loaded and used before foo. Then the require method won't be able to return the module.
Also, if you want to store modules without having them visible into the global scope, you can only define the require and define method on the window object and hide modules into an anonymous scope like this:
(function (window) {
var modules = {}
function define(name, constructor) {
var module = {exports: {}}
constructor(module)
modules[name] = module.exports
}
function require(name) {
return modules[name]
}
window.define = define
window.require = require
})(window)
This way, define and require are the only function that can give you access to modules. Other modules won't be able to modify other modules without requiring them first. This can be useful when using third parties script that could conflict with your module system.
In fact this is not a module, but a Self-Invoking Ananymous function or an Immediate function which gets an object in parameter and assign a Module property to it:
The page window is a parameter passed to this function.
So an object named Module containing a data property is assigned to window.
JavaScript Self-Invoking Functions:
A self-invoking expression is invoked (started) automatically, without being called.
Function expressions will execute automatically if the expression is
followed by ().
You cannot self-invoke a function declaration.
You have to add parentheses around the function to indicate that it is
a function expression
So As you can see Immediate Functions can't be called as its name states it will be immediately executed and by its self, no other function or scope can execute it.
For better reference take a look at :
Javascript Self Invoking Functions.
Self-Invoking Functions section in JavaScript Function Definitions.
And concerning your last question about its benefits and good practices as shown on the given Article reference:
Where to use self-executing functions?
One obvious situation is when you want to auto-run a function like I
showed in above example but that is trivial. If you are in a situation
where you want to run a piece of code repeatedly like updating
something in the database based on user interaction or fetching
records from database every 10 seconds or you want to load new stories
via ajax similar to how facebook does on its homepage or some other
similar situation, one would normally go for setInterval function
something like this:
setInterval(doStuff, 10000);
Above, doStuff function will get called every 10 seconds. That is the
normal approach most developers seem to go with. However, there is a
huge problem with that.
The setInterval will call doStuff function exactly at specified time of 10 seconds again and again irrespective
of whether doStuff function actually finished doing what it is
supposed to do. That is bad and will certainly get you into unexpected
results.
That is one example of where setInterval is "bad" and should be
avoided.
This is exactly where self-executing functions come in handy. We can
do the same task with the help of self-executing function along with
setTimeout like this:
function foo(){
// your other code here
setTimeout(foo, 10000);
}();
This code will also repeat itself again and again with one difference.
setTimeout will never get triggered unless doStuff is finished. A much
better approach than using setInterval in this situation.
Calling it from another file:
And if this function is on another file it will be called automatically if this file is included.
Why do we use Self-Invoking Functions in JavaScript?
And if you ask yourself why do we use these functions, self-invoked function are used to manage Variable Scope.
Take a look at the answer here for further information.

Differences when using functions for casper.evaluate

I'm using PhantomJS v2.0 and CasperJS 1.1.0-beta3. I want to query a specific part inside the page DOM.
Here the code that did not work:
function myfunc()
{
return document.querySelector('span[style="color:#50aa50;"]').innerText;
}
var del=this.evaluate(myfunc());
this.echo("value: " + del);
And here the code that did work:
var del=this.evaluate(function()
{
return document.querySelector('span[style="color:#50aa50;"]').innerText;
});
this.echo("value: " + del);
It seems to be the same, but it works different, I don't understand.
And here a code that did also work:
function myfunc()
{
return document.querySelector('span[style="color:#50aa50;"]').innerText;
}
var del=this.evaluate(myfunc);
this.echo("value: " + del);
The difference here, I call the myfunc without the '()'.
Can anyone explain the reason?
The problem is this:
var text = this.evaluate(myfunc());
Functions in JavaScript are first class citizen. You can pass them into other functions. But that's not what you are doing here. You call the function and pass the result into evaluate, but the result is not a function.
Also casper.evaluate() is the page context, and only the page context has access to the document. When you call the function (with ()) essentially before executing casper.evaluate(), you erroneously try to access the document, when it is not possible.
The difference to casper.evaluate(function(){...}); is that the anonymous function is defined and passed into the evaluate() function.
There are cases where a function should be called instead of passed. For example when currying is done, but this is not applicable to casper.evaluate(), because it is sandboxed and the function that is finally run in casper.evaluate() cannot use variables from outside. It must be self contained. So the following code will also not work:
function myFunc2(a){
return function(){
// a is from outer scope so it will be inaccessible in `evaluate`
return a;
};
}
casper.echo(casper.evaluate(myFunc2("asd"))); // null
You should use
var text = this.evaluate(myfunc);
to pass a previously defined function to run in the page context.
It's also not a good idea to use reserved keywords like del as variable names.

JavaScript sandboxing: hide global variables from a given scope

I want to create an HTML+JS environment where user can enter and run arbitrary JavaScript code which will be executed in context of given jail object. I've set up a playground to illustrate what I have so far.
This one does a somewhat decent job:
Basic evaluation works:
Input: 2 + 2
Output: 4
this returns jail object
Input: this
Output: [object Object]
this.hello() runs expected method
Input: this.hello()
Output: hello world!
User can set up their own functions and execute them later:
Input: this.foo = function() { return 42; }
Output: function () { return 42; }
Input: this.foo()
Ouput: 42
Trying to access some object that I want to stay "hidden" from jail context fails:
Input: hidden
Output: ReferenceError: hidden is not defined
However, it completely fails to hide globally accessible properties, such as window or document for user:
Input: window
Current output: [object Window]
Desired output: ReferenceError: window is not defined
The best solution I've came up so far is to just fill up all the global variable I can think of with undefined or null right in the Jail object declaration, as illustrated in updated version. This way they seem to be lost forever inside the scope of jail and user won't be able to access them. My questions:
Am I right? Is this safe enough?
Is there any better way, i.e. to really undefine global stuff in certain scope instead of rewriting them with some placeholder values?
If it’s client-side and you can guarantee a modern browser, use web workers instead; they’re much safer, and you can also stop infinite loops from tying up the main thread, and implement timeouts by calling Worker#terminate.
Start up a new worker for each execution:
var worker = new Worker('path/to/evaluator.js');
Receive messages from the worker:
worker.onmessage = function (e) {
console.log(e.data);
};
Send over the code to execute:
worker.postMessage(someCode);
In the worker, listen:
onmessage = function (e) {
postMessage(eval(e.data));
};
And make sure to call terminate after receiving the message, too, because the worker can call postMessage itself. (You can prevent that, but there’s really no point.)
Web workers don’t have access to anything in the main execution context, they run on another thread, and they’re implemented by the browser, so they’re much safer than the typical delete-dangerous-things sandbox.
They do, however, have access to XMLHttpRequest; see Is It Possible to Sandbox JavaScript Running In the Browser? for other approaches if this is a problem.

How to execute different partsof the JS code in one scope

I have several script blocks depend on each other. I need to perform them in one scope.
My attempt:
var scopeWrapper = {};
with(scopeWrapper) {
(function() {
this.run = function(code) {
eval(code);
};
}).call(scopeWrapper);
}
scopeWrapper.run('function test() { alert("passed"); }');
scopeWrapper.run('test();');
I get 'test is not defined' error. It seems that the code is executed in different scopes.
Why is this happening?
Edit: Bergi pointed out my original answer was wrong, he is correct. Since eval runs in its own scope and the function constructor still runs in function scope according to the spec this is not possible with either.
While I have done this sort of thing myself several times with node.js using the vm module where you get much finer grain of control over where your code executes, it seems browsers require a different approach.
The only way you can share variables in such a way is to do so in the global scope of JavaScript execution (possibly, in an iframe). One way you could do this is script tag injection.
function run(code){
var sc = document.createElement("script");
sc.setAttribute("type","text/javascript");
sc.innerHTML = code;
document.body.appendChild(sc);
}
run("var x = 5");
run("document.write(x)");
(here is this code in action)
As for the scope wrapper, instead of injecting them in the same frame inject them in another iframe. That will scope their window object to that iframe and will allow you to share context.
I humbly apologize for my previous answer, I misread the spec. I hope this answer helps you.
I'm leaving my previous answer here because I still believe it provides some insight into how eval and the Function constructor work.
When running code in non-strict mode eval runs in the current context of your page
After your function declaration is done, the scope it was declared in dies, and with it the function.
Consider using the Function constructor and then .calling it
In your case that would be something like:
var scopeWrapper = {};
scopeWrapper.run = function(code){
var functionToRun = new Function(code);
functionToRun.call(scopeWrapper);
}
scopeWrapper.run('this.test = function() { alert("passed"); }');
scopeWrapper.run("this.test()")
Here is a reference directly from the spec:
If there is no calling context or if the eval code is not being evaluated by a direct call (15.1.2.1.1) to the eval function then,
Initialize the execution context as if it was a global execution context using the eval code as C as described in 10.4.1.1.
If this code is run in the node.js consider using the vm module. Also note that this approach is still not secure in the way it'll allow code you run to change your code.
test only exists in the scope of this.run and only at call time :
// global scope
(function(){
// local scope (equivalent of your "run" function scope)
eval('function f(){};');
console.log(f); // prints "function f(){}"
})();
console.log(f); // prints "ReferenceError: f is not defined"
Each call of run creates a new scope in which each code is evaluated separately.

Categories