6 ms·
It's probably judicious to avoid using eval in a lot of everyday application, but there's places where using it isn't particularly harmful. One example of this
by TheAceOfHearts 11y ago
It's probably judicious to avoid using eval in a lot of everyday application, but there's places where using it isn't particularly harmful. One example of this is when using Webpack, if you set the devtool option to use eval, it'll build and rebuild faster than the other options.
Another cool thing that you find is JavaScript is the "with" keyword. A lot of people don't even know it exists. I think Chrome's DevTools uses it along with eval. When you type something invalid, you can see stuff like:
with (typeof __commandLineAPI !== 'undefined' ? __commandLineAPI : { __proto__: null }) {
whatever
}
- orf 11y ago> A lot of people don't even know it exists Good, it's fantastically broken and shouldn't be used.
- Klathmon 11y agoThat's the kind of black-and-white thinking that he is talking about. It might be terrible to use in the vast majority of situations, but it works and it works great for those few situations that it's extremely useful for. Blacklisting something like that as a hard rule ends up doing much more harm than good in my opinion.
- LunaSea 11y agoThe issue is rather that even though the situation isn't black and white, a very large majority of web developers aren't security knowledgable enough to make the decision of if it is or isn't safe to use it in each specific case. This is why blanket black-listing (or white-listing in cases where it is possible) is a better option because, similar to Murphy's law, if something (like eval) can be misused it will be.
- Klathmon 11y agoBut that kind of hand-holding doesn't ever work. if someone wants to do something "bad" in a language, it's better to teach them why it's bad than to blacklist certain parts of it. I've seen developers tell me that eval is bad, but they found a way to do what they want by using `new Function()` (which takes a string of code and makes it into a function that can be executed...) Teach why these things are a good idea to avoid, teach why it's dangerous, teach scenarios where it's tempting but there is a better way, but don't disallow their use entirely. We wouldn't be developers if we just gave up the first time someone told us that we couldn't do it that way.
- LunaSea 11y agoI disagree. Security is a job on it's own and although you can teach some security know how in the grand scheme of things a web developer will never be at the same level of understanding than an actual penetration tester or security researcher. To enforce rules like this, the best practice I would say is to add JSLint or ESLint with a strict rule set on a pre-commit hook and then refuse any commits / merges that don't pass the static analysis of those tools.
- Klathmon 11y agoI agree that security stuff is best left to security researchers. However you need to draw the line somewhere. Allowing a while loop can be a security issue for some applications. I was more talking about issues like the `with` in JS or `goto` in other languages. Yeah, they are a really bad idea for the vast majority of situations, but every now and then they are incredibly useful or provide an insane speed improvement and they can be safely used. An eval example i've seen recently was about sending functions to web-workers. The only way to allow code to run in a web worker without a separate file is to convert a function to a string and eval the code in the web-worker side. So i could massively over complicate my build system, duplicate code in a bunch of places, and near-double the size of the downloaded code to get it working without eval, or i could setup a simple eval system and have it run a function passed in as a string. Yeah, you shouldn't be using eval to decide if the number entered was 5 or 6, but saying it's disallowed from the codebase entirely is silly. Even a policy like "any code that uses eval must be approved by X, Y, and Z before they will be allowed in the codebase" is much more sane.
- orf 11y agoIt's so broken strict mode disallows it's use. A very popular JS book (by a very knowledgeable author) simply says "with is so broken it won't be discussed at all". Maybe there are minor use cases where it's helpful, but for 99% of cases it's just plain bad. Why publicise it if it's not very useful, broken and will cause even experienced developers (not to mention new ones) debugging headaches?
- Klathmon 11y agoIMO sweeping dangerous features under the rug doesn't do anyone any good. Bring them out in the open, talk about why they are useful (or were in the past) and why they are dangerous, talk about what problem they were meant to solve at the time and what the better ways there are now to do it. I'm not going to mourn the loss of `with` if it gets removed from the language, but i'm not going to shove my head in the sand and pretend like it doesn't exist either.
- todd8 11y agoUsing the JavaScript "with" is discouraged. It introduces code that cannot be optimized, but more importantly it is code that is hard to reason about. The body of the with executes in a scope modified by an arbitrary object, determined at that point in the program's execution. To understand the semantics of a use of with, it is necessary to understand everywhere when and how the object that the with is acting on can change. See the tweet by Brendan Eich (inventor of JavaScript) on the with: https://twitter.com/BrendanEich/status/68001466471817216 https://twitter.com/BrendanEich/status/68001466471817216 From here on, this rest of this comment is probably of little interest, but for those curious about what I mean when I say "reason about" a program let me try to explain in more detail. Programming in an imperative language (i.e. not a functional programming language) involves a series of steps which make changes to the state of the program's data. We can't desk check interesting programs by working through all interesting steps by hand (or otherwise there is no point in having a computer do it); there are typically just too many steps and iterations. So how do programmers do it? One reasons about the state of a program by examining and understanding how it is affected by each statement. So, for example, in a while loop like: while x != y do x = f(x) end t = x the loop does something and even without understanding exactly what the side effects of f(x) are, we are able to reason about the properties of x once the program reaches the point where x is being assigned to t. We know that x equals y and so after the assignment statement we can assert that t, x and y are all equal. Now consider the same while loop with only a slight change: while x != y do x = f(x) end L: t = x Now the assignment of x to t has a label and can be the destination of a goto statement (I'm using an example from the bad old days when goto statements could take you anywhere in a program). What can be said about the relationship between t, x, and y after the assignment? It depends on anyplace in the code that can goto to label L. We can no longer reason about the code by examining it statically. We have to understand the global execution and when and where the goto can happen and what the value of x and y might be at each of these potential goto statements during the execution of the program. We've lost the ability to reason about the code in a systematic way by simply looking at it. We would have to consider every possible way the execution of the program could change x or y and then jump to L. Certain programming patterns make understanding programs difficult. Unbridled goto's were an early source of such problems. Now, most languages and programers restrict how they use goto to patterns that are safer because they don't make reasoning about the programs much more difficult. Dynamic scoping (around since the early days of LISP) makes reasoning about a program's state more difficult than lexical scoping; consequently, most programming languages now eschew dynamic scoping in favor of lexical scopes (that is scopes for variables determined by the structure of the source code rather than the dynamic call patterns during execution). The JavaScript "with" is deprecated because it can be applied to an object that is unknown until the program actually runs. The body of the with is executing in this dynamically determined scope so we can't really reason about what is going on while looking at the code.