From: Garrett Smith on
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
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
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
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
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