Last call: Function

Lars Hansen lhansen at adobe.com
Thu Mar 20 19:35:50 PDT 2008


> -----Original Message-----
> From: Mark S. Miller [mailto:erights at google.com] 
> Sent: 20. mars 2008 17:51
> To: Lars Hansen
> Cc: es4-discuss at mozilla.org
> Subject: Re: Last call: Function
> 
> 2008/3/20 Lars Hansen <lhansen at adobe.com>:
> > Last call for comments on the Function spec.
> 
> 
> * There's a conflict between defining call, apply, and bind 
> as static methods on the Function constructor vs defining 
> them as instance methods on functions (or as members of 
> Function.prototype). The problem is that the Function 
> constructor is itself a function. When we see
> 
>     Function.call(...)
> 
> is this invoking the static "call" method of the function 
> constructor, or is it invoking the instance "call" method 
> common to all functions?

That depends.  There are three things called 'call' here: 
the intrinsic method on Function instances; the property
(in the empty namespace) on the Function prototype object; and
the property (in the empty namespace) on the Function object. 
The latter shadows the prototype property if accessed via the
Function object.  So if I say Function.call I either get the
intrinsic one if the intrinsic namespace is open, or the
static one otherwise.  There is IMO not really any room for
ambiguity because the intrinsic namespace is not open by
default, and if it is opened then it takes precedence by 
normal rules.  The two functions have different signatures,
but that's OK.

I agree this may not be the best design.  At the same time
it does not seem to be actually wrong.  On the third hand,
the reference implementation does not behave as I thought
it ought to, so my reasoning could be faulty.  I will log
the question as a ticket to be investigated.

> * At the last ES-wide face-to-face, I thought we'd all agreed 
> that the value of the thisObj argument to call/apply/bind, no 
> matter what this value is, would be the value that gets bound 
> to "this" in the called function.

I think you have found a spec bug.  The code in the spec assumes a
single global object and is correct for that, but it's not the
right way.  If thisObj is null then it should be passed as null,
and the language implementation will substitute the callee's global
object for that value, it should not be done in apply as it is now.
Thanks.

> If I understand this proposed spec, f.call(null, ...) would
> invoke f with its "this" bound to the global object.

f's global object, yes.

> That behavior makes 
> JavaScript harder to secure, since this implicit access to 
> the global object enable privilege escalation attacks.

Access to the global object is unfortunately pervasive in the
language, and we're not making any effort to crack down on that.

> Such implicit access to the global object also prevents garbage 
> collection opportunities: In a frame in which the global object
> were otherwise inaccessible, it would still need to be retained by 
> any function that might be called so as to manufacture access 
> to the global object.

The global object is in principle part of every function's scope
chain, and in a multi-global environment (like a browser) it's
hard to get away from that.  Consider that even code generated for
an object initializer expression needs access to the global object
to find the 'Object' constructor (in ES3 anyway), and similarly
the expression x.y may need to convert x to a String object
if it is a primitive string (in ES3 for any y, and in ES4 for at
least some y).  It may not need the global object for that,
but it needs access to a primitive global-like environment that
has a lot of things connected to it.

Given enough information it's probably possible to optimize the global
object away.  I don't know about any implementations that do that
(but I haven't looked at the guts of e.g. IE and Safari).

Thanks for the very useful comments.

--lars



More information about the Es4-discuss mailing list