Function.prototype.bind

David-Sarah Hopwood david.hopwood at industrial-designers.co.uk
Tue Sep 9 21:47:37 PDT 2008


Mark S. Miller wrote:
> On Tue, Sep 9, 2008 at 9:21 AM, Mark S. Miller <erights at google.com> wrote:
>> I still need to spec Function.prototype.bind in our funny spec language.
>>    Anyone care to contribute a draft?
> 
> The simplest way to specify this would be in terms of the rest of the
> ES3.1 spec, i.e., a "self-hosting" spec. Perhaps like the following:
> 
>   Function.prototype.bind = function(self, var_args) {
>     var thisFunc = this;
>     var leftArgs = Array.slice(arguments, 1);
>     return function(var_args) {
>       var args = leftArgs.concat(Array.slice(arguments, 0));
>       return thisFunc.apply(self, args);
>     };
>   };
> 
> Post ES3.1, we hope to turn in general to the specification style that
> had been used for the ES4 spec -- SML + self-hosting. However, even
> the ES3 spec does make some use of self-hosting language such as "as
> if by the expression 'new Object()'", which the ES3.1 draft keeps, but
> clarifies to refer to the original binding of 'Object'. Could we use
> the same trick for Function.prototype.bind by saying something like
> "the original bindings of Array.slice, Array.prototype.concat, and
> Function.prototype.apply? Post ES3.1, to enable self-hosting specs,
> we'll need to solve this problem anyway. Any ideas how we should do
> that then?

As an alternative to saying "the original bindings of..." in the spec,
we could provide a way to actually get the original bindings in ECMAScript
code. This is independently useful, e.g. for secure subset run-times.
For instance:

  Function.prototype.bind = function(self, var_args) {
    var thisFunc = this;
    var leftArgs = original.Array.slice(arguments, 1);
    return function(var_args) {
      var args = leftArgs.concat(original.Array.slice(arguments, 0));
      return original.Function.apply(thisFunc, self, args);
    }
  }

where 'original' is a non-Writable property of the global object that
refers to a sealed object, which in turn refers to sealed copies of
the primordial constructors.

(If there were a "run in this scope with no other bindings" primitive,
the 'original' object could then be used with that primitive to run
code in an environment that provides no authority.)

I have also assumed the existence of a "static" Function.apply which
takes the function to be applied as an explicit first argument. This
is necessary because otherwise there is no way to bind 'this' correctly
given that thisFunc.apply may have been overridden (or at least, I
don't know of any way to do it).

-- 
David-Sarah Hopwood



More information about the Es-discuss mailing list