Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this a Chrome bug or is my use of "use strict" and eval invalid?

This code works alerts "ok" in all browsers except Chrome:

eval("var outer = 0; function test() {'use strict'; outer = 1; } test(); alert('ok');");

(Try it on jsfiddle).

All I'm doing is referencing an outer variable from a 'use strict' function, all in eval context. Chrome says

Uncaught ReferenceError: outer is not defined 

Note: I originally faced it when using devtool: 'eval' in Webpack.

like image 646
Dan Abramov Avatar asked Aug 21 '14 11:08

Dan Abramov


People also ask

Is eval harmful?

eval() is a dangerous function, which executes the code it's passed with the privileges of the caller. If you run eval() with a string that could be affected by a malicious party, you may end up running malicious code on the user's machine with the permissions of your webpage / extension.

How do I get rid of use strict?

No, you can't disable strict mode per function. Notice how we can define function outside of strict code and then pass it into the function that's strict. You can do something similar in your example — have an object with "sloppy" functions, then pass that object to that strict immediately invoked function.

What does use strict mean?

In this tutorial, you will learn about the JavaScript 'use strict' syntax with the help of examples. In JavaScript, 'use strict'; states that the code should be executed in 'strict mode'. This makes it easier to write good and secure JS code.

Is it safe to use eval in JavaScript?

Do NOT use eval() Executing JavaScript from a string is an BIG security risk. With eval(), malicious code can run inside your application without permission. With eval(), third-party code can see the scope of your application, which can lead to possible attacks.


2 Answers

To simplify the problem : http://jsfiddle.net/rokkkjcs/6/

eval("var outer=0;");
function test() {'use strict'; outer = 1; } 
test(); 
alert('ok');

And the explanation is :

Non-strict code can use the ‘eval’ function to add new variables to the surrounding scope. Prior to native JSON support in browsers, ‘eval’ was commonly (and unsafely) used to construct objects from strings. The constructed objects then became a part of the surrounding scope. In strict mode, ‘eval’ cannot introduce new variables. When executed in strict mode, the following piece of code will not introduce the ‘bar’ variable into the surrounding scope. Note: if a function containing ‘eval’ is executed in strict mode, then the code inside the ‘eval’ function is also executed in strict mode.

More info : http://cjihrig.com/blog/javascripts-strict-mode-and-why-you-should-use-it/

like image 127
ovi Avatar answered Sep 28 '22 19:09

ovi


Actually eval creates variables or modifies variables in scope where it is defined, no matter if you use val or not. Or in other words, by default it doesn't have it's own scope.

So when you do this

eval("var outer = 0;");
console.log(outer); //0

you create variable in outer scope. Surprisingly, this works the same way in chrome too - and it doesn't matter if window.onload is used or not.

To make eval has it's own scope you must do the following:

eval("'use strict'; var outer = 0;"); 
console.log(outer); //Uncaught ReferenceError: outer is not defined 

Now there is a separate scope for eval. With 'use strict' in eval your code will work in chrome and won't allow to override variables outside eval.

eval("'use strict'; var outer = 0; function test() {'use strict'; outer = 1; } test(); alert('ok');");

So this part answers how can you avoid error.

The second part that I am very intersted in but couldn't find an answer by myself.

The question is following, why your code throws an error in chrome while this works in chrome(which means the global variable is created):

window.onload = function() {
   eval("var outer = 0; function test(){console.log(outer); } test();");
}

And also why it happens only with window.onload.

like image 29
Elena Avatar answered Sep 28 '22 18:09

Elena