Prev: html form in javascript variable
Next: Microsoft and attributes--will they ever figure them out?
From: Garrett Smith on 16 Nov 2009 14:23 Richard Cornford wrote: > Garrett Smith wrote: > <snip> >> IIRC jquery uses window["eval"] in the source code. looking... >> >> hat rack: >> | // Get the JavaScript object, if JSON is used. >> | if ( type == "json" ) >> | data = window["eval"]("(" + data + ")"); >> >> Not sure why they chose that approach over: >> data = eval("(" + data + ")"); >> >> That approach uses indirect eval. The calling context's scope is >> used, so is just as unsafe in that regard. Only difference is older >> implementations' thisArg is different. >> >> It indirect eval, for reasons I'm failing to comprehend. >> >> I believe I mentioned this very issue about a year or so ago on >> the jquery newsgroup. > > I have a recollection of discussions around the use of - eval - relating > the 'compressors' (YUI compressor, as I recall) that modify (shorten) > Identifier names. Much like the way such a compressor cannot act on code > within a - with - statement because there is no means of determining > whether an unqualified Identifier in that context is a name of a > property of the object added to the scope chain or a reference to a > variable/function/parameter from a containing scope, such compressors > cannot act on unqualified Identifiers in the lexically containing scopes > when - eval - is used, because it has no way of determining whether any > string that is - eval-ed will attempt to use them to refer to items from > those containing scopes. > > My impression was JQuery's authors were then going to do whatever was > necessary to fool the compressor in question into not noticing the - > eval - use (and making it unrecognisably indirect should achieve that). > Obviously the sane alternative, of using - new Function - to create a > minimal scope chain function that wrapped the (now not indirect) eval > call, did not occur to them. > I see. That could be avoided by either Function constructor or a separate, globally-accssible method: jQuery.evalString = function(s) { return eval(s); }; That function would not be compressed, but it would be so short that it wouldn't matter. The eval call, as used there, has potential to modify variables in the calling context's scope chain. Using new Function or a call to eval in global context and scope avoids that. ES5 would "fix" that: | 10.4.2: In Edition 5, indirect calls to the eval function use the | global environment as both the variable environment and lexical | environment for the eval code. In Edition 3, the variable and lexical | environments of the caller of an indirect eval was used as the | environments for the eval code. That would be a significant change, but one that would be of use to jQuery here. Indirect eval does not throw EvalError in ES5. | 15.1.2.1. Implementations are no longer permitted to restrict the use | of eval in ways that are not a direct call. In addition, any | invocation of eval that is not a direct call uses the global | environment as its variable environment rather than the caller�s | variable environment. The jQuery code escapes any problem with indirect eval throwing EvalError. -- Garrett comp.lang.javascript FAQ: http://jibbering.com/faq/
From: Stefan Weiss on 16 Nov 2009 15:08 On 16/11/09 20:23, Garrett Smith wrote: > Richard Cornford wrote: >> I have a recollection of discussions around the use of - eval - relating >> the 'compressors' (YUI compressor, as I recall) that modify (shorten) >> Identifier names. Much like the way such a compressor cannot act on code >> within a - with - statement because there is no means of determining >> whether an unqualified Identifier in that context is a name of a >> property of the object added to the scope chain or a reference to a >> variable/function/parameter from a containing scope, such compressors >> cannot act on unqualified Identifiers in the lexically containing scopes >> when - eval - is used, because it has no way of determining whether any >> string that is - eval-ed will attempt to use them to refer to items from >> those containing scopes. >> >> My impression was JQuery's authors were then going to do whatever was >> necessary to fool the compressor in question into not noticing the - >> eval - use (and making it unrecognisably indirect should achieve that). >> Obviously the sane alternative, of using - new Function - to create a >> minimal scope chain function that wrapped the (now not indirect) eval >> call, did not occur to them. >> > > I see. > > That could be avoided by either Function constructor or a separate, > globally-accssible method: > > jQuery.evalString = function(s) { > return eval(s); > }; > > That function would not be compressed, but it would be so short that it > wouldn't matter. > > The eval call, as used there, has potential to modify variables in the > calling context's scope chain. Using new Function or a call to eval > in global context and scope avoids that. Your evalString example cannot be used to create new global variables: function evalStr (code) { return eval(code); } evalStr("var foo = 42"); // --> foo was not declared globally Neither can |new Function|: function evalStr (code) { return (new Function(code))(); } evalStr("var foo = 42"); // --> foo was not declared globally window.eval, on the other hand, can do it: function evalStr (code) { return window.eval(code); } evalStr("var foo = 42"); // --> global foo is now 42 execScript() can be used for the same purpose in IE. Neither of these are well supported, of course; it may be better to just do without global 'var' statements in the evaluated strings. cheers, stefan
From: John G Harris on 16 Nov 2009 15:13 On Mon, 16 Nov 2009 at 11:52:33, in comp.lang.javascript, The Natural Philosopher wrote: <snip> >Babbages Difference engine, a computer made out of brass cogs, was >posited by an ENGINEER in 1786. Babbage proposed to make it in 1822 > >and finally gave up around 1860 Actually he thought of a better idea, and then the money ran out, mainly because of his talent for annoying everyone he had any dealings with. <snip> >It wasn't till around 1940 that the advent of valves made a functional >digital computer a possibility, and it took a dedicated engineer to >make it work. Yes, it was some advanced mathematics that hinted at the >idea of a general purpose programmable computer, but having hinted, >that's roughly where the clever bit stopped. Yes, Babbage was a mathematician, and because of what he published in the early 1800s the main principles of the programmable computer couldn't be patented in the 1940s. Babbage also invented new ways of designing and making mechanical contrivances. <snip> >And of course, it also had its usual paradox inherent in it, in that >Turing showed that you couldn't actually work out whether a given >algorithm would ever finish without actually trying it (gross >simplification). See Turings incomputability theorems. Turing proved that you can't have a single algorithm that will say for every program and their legal inputs whether it will terminate. That doesn't mean you can't prove it for an individual program. Often you can, but you may need a different way to prove it for different programs. Most "Hello World" programs provably terminate. <snip> >There are no prizes for elegance. The prizes go to the humble people >who turn out plain standard workmanlike code that everyone else can >understand and fix, and if that's too dull for you, the door is over >there ->, and if you like intellectual puzzles, do the crossword in >your lunch break' Elegance can also be very, very, very, clear. See the writings of Bertrand Russel and John von Neumann for example. John -- John Harris
From: Garrett Smith on 16 Nov 2009 15:38 Stefan Weiss wrote: > On 16/11/09 20:23, Garrett Smith wrote: >> Richard Cornford wrote: [...] >> jQuery.evalString = function(s) { >> return eval(s); >> }; >> >> That function would not be compressed, but it would be so short that it >> wouldn't matter. >> >> The eval call, as used there, has potential to modify variables in the >> calling context's scope chain. Using new Function or a call to eval >> in global context and scope avoids that. > > Your evalString example cannot be used to create new global variables: > No, obviously not; "How do I make a global variable from eval" was not a proposed problem nor was there any such solution discussed. If creating properties of the global object through a string is desired, then it can be done in the string, as: eval( 'window.x = "s"' ); -- Garrett comp.lang.javascript FAQ: http://jibbering.com/faq/
From: Asen Bozhilov on 16 Nov 2009 16:36
Garrett Smith wrote: >>> jQuery.evalString = function(s) { >>> return eval(s); >> }; But `this' still associated with execution context in which been executed `eval'. With [[Construct]] and [[Call]] method of object who refer `Function' you create `object' who internal [[scope]] refer Global Object independent of execution context in who's been called Function.[[Construct]] or Function.[[Call]]. After that if you call this `object' without providing `this' value from caller, `this' in created execution context will be referrer to Global Object. I like much more that approach with Function construct and call method. > If creating properties of the global object through a string is desired, > then it can be done in the string, as: > eval( 'window.x = "s"' ); What about this in Spider Monkey: function evalCode(code) { return eval.call(null, code); } evalCode('var a = 10;'); window.alert('a' in this); //true window.alert(a); //10 |