ES3 10.1.3 says:
"For each FunctionDeclaration in the code, in source text order,
create a property of the variable object whose name is the Identifier
in the FunctionDeclaration, whose value is the result returned by
creating a Function object as described in section 13, and whose
attributes are determined by the type of code. If the variable object
already has a property with this name, replace its value and
attributes. Semantically, this step must follow the creation of
FormalParameterList properties."
But in eval code this is a botch, since it requires
function foo(a, s) {
var x = a * a;
eval(s);
return x;
}
alert(foo(2, "function x() { return 'ha ha!'; }"));
to alert the function x's toString results.
Still, the spec is clear enough, and Firefox 3 (not 2 or earlier),
Safari, and Opera all agree (I can't test IE atm).
ES3.1 changes the rules to use CreateMutableBinding when entering the
eval execution context only if x is not already bound, and in any case
then to call SetMutableBinding (10.2.1.2.3 in the feb09 draft).
SetMutableBinding calls [[ThrowingPut]]. Strict mode adds value in its
own way but let's assume it's not used in the following.
The change in spec between 3 and 3.1 does not affect the outcome for
the example above, but changing the attributes of x before the eval
call, or giving it a setter somehow (the native implementation might
use some kind of internal setter, depending on how it handles eval and
function activations), would make a big difference: the old spec says
to blow away any pre-existing x including its attributes, getter, and
setter.
The new 3.1 language would respect the attributes and call the setter.
And 3.1 Object.defineProperty, etc., lets users define setters on
objects they can reference.
Since the activation object is censored, the issue becomes function
foo in global code, not var or function x in function code. Code on
the web today can count on a function declaration being processed from
global code (and possibly from eval from global code, depending on the
implementation) so that any pre-existing writable binding of the same
name is destroyed. This gives some integrity that otherwise can't be
recovered.
With ES3.1, programmers will have to use
Object.getOwnPropertyDescriptor(this, 'foo') and check first to avoid
spoofing and luring attacks via setters. If an unwanted foo pre-
exists, the code can work around the name conflict or try to delete
that foo.
A pre-existing non-writable (const) property is not a threat (except
of the trivial DOS kind), and indeed Firefox throws an error given
const foo = 42; (in its own script tag or earlier in the same one as
function foo shown above) and then function foo(){...}. Silent failure
to update foo would be inferior, but better than recreating foo and
violating the integrity of const.
The problem is setters (and getters) on the global object combined
with the change to function binding, from re-creation to conditional
creation followed by assignment. I can't prove this is going to burn
programmers in the future, but I suspect it will. Anway, it is a big
enough change from ES3 and implementation behavior -- for global code
at least -- that I wanted to bring it up for discussion here.
/be
_______________________________________________
Es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss