First draft of the spec for the Function class.  Please comment.

--lars
Title: The class "Function"

The class Function



NAME:                       "The class 'Function'"
FILE:                       spec/library/Function.html
CATEGORY:                   Pre-defined classes
SOURCES:                    REFERENCES [1], [2], [3], [5]
SPEC AUTHOR:                Lars
DRAFT STATUS:               DRAFT 1 - 2008-03-10
REVIEWED AGAINST ES3:       YES
REVIEWED AGAINST ERRATA:    YES
REVIEWED AGAINST BASE DOC:  YES
REVIEWED AGAINST PROPOSALS: YES
REVIEWED AGAINST CODE:      YES
REVIEWED AGAINST TICKETS:   YES
IMPLEMENTATION STATUS:      ES4RI
TEST CASE STATUS:           ?


OPEN ISSUES

  * ES3 restrictions on argArray having to be an Array or an arguments
    object in Function.prototype.apply have been removed here.


NOTES

  * The annotation '/*: function*/' below looks like that because the
    reference implementation does not yet accept plain 'function' as a
    type annotation to mean 'anything callable' (ticket #153).

  * The use of 'Private' instead of 'private' is a workaround for a
    bug in the reference implementation (#368).


REFERENCES

[1] ECMAScript 3rd Edition specification section 15.3
[2] http://wiki.ecmascript.org/doku.php?id=proposals:static_generics
[2] http://bugs.ecmascript.org/ticket/172
[4] http://bugs.ecmascript.org/ticket/173
[5] http://bugs.ecmascript.org/ticket/174


The class Function is a dynamic, non-final, direct subclass of Object (see class Object).

All objects defined by function definitions or expressions in ECMAScript are instances of the class Function.

Not all objects that can be called as functions are instances of subclasses of the Function class, however. Any object that has a meta::invoke method can be called as a function.

NOTE   Host functions may also not be instances of Function or its subclasses, but must to some extent behave as if they are (see Host objects). However, host functions need not provide meta::invoke methods to be callable. The type function, defined elsewhere, matches invokable host functions even if they do not have a meta::invoke method.

Synopsis

The class Function provides the following interface:

dynamic class Function extends Object
{
    public function Function(...args) …
    static meta function invoke(...args) …

    static public function apply(fn /*: function*/, thisArg: Object=null, argArray: Object=null) …
    static public function bind(method /*: function*/, thisObj: Object=null, ...args) …
    static public function call(fn /*: function*/, thisObj: Object=null, ...args) …

    static public const length = 1

    meta final function invoke( … ) …

    override intrinsic function toString() : string …

    intrinsic function apply(thisArg: Object=null, argArray: Object=null) …
    intrinsic function bind(thisObj: Object=null, ...args) …
    intrinsic function call(thisObj: Object=null, ...args) …

    public const length = …
    public var   prototype = …
}

The Function prototype object provides these direct properties:

    meta::invoke: function () …
    length:       0
    toString:     function () …
    apply:        function(thisArg, argArray) …
    bind:         function(thisArg, ...args) …
    call:         function(thisArg, ...args) …

Methods on the Function class object

new Function (p1, p2, … , pn, body)

Description

When the Function constructor is called with some arguments as part of a new _expression_, it creates a new Function instance whose parameter list is given by the concatenation of the pi arguments separated by "," and whose executable code is given by the body argument.

There may be no pi arguments, and body is optional too, defaulting to the empty string.

If the first character of the comma-separated concatenation of the pi is a left parenthesis then the list of parameters must be parseable as a FormalParameterListopt enclosed in parentheses and optionally followed by a colon and a return type.

Otherwise, the list of parameters must be parsable as a FormalParameterListopt.

If the list of parameters is not parseable as outlined in the previous two paragraphs, or if the body is not parsable as a FunctionBody, then a SyntaxError exception is thrown (see the grammar in section ECMAScript grammar).

Regardless of the form of the parameter list, it may include type annotations, default parameter values, and rest arguments.

Returns

The Function constructor returns a new Function instance.

Implementation

public function Function(...args)
    helper::createFunction(args);

helper function createFunction(args) {
    let parameters = "";
    let body = "";
    if (args.length > 0) {
        body = args[args.length-1];
        args.length = args.length-1;
        parameters = args.join(",");
    }
    body = string(body);
    magic::initializeFunction(this, __ES4__::global, parameters, body);
}

The magic function initializeFunction initializes the function object this from the list of parameters and the body, as specified in section translation:FunctionExpression. The global object is passed in as the scope parameter.

A prototype object is automatically created for every function, to provide for the possibility that the function will be used as a constructor.

NOTE   It is permissible but not necessary to have one argument for each formal parameter to be specified. For example, all three of the following expressions produce the same result:

new Function("a", "b", "c", "return a+b+c")

new Function("a, b, c", "return a+b+c")

new Function("a,b", "c", "return a+b+c")

Function (p1, p2, … , pn, body)

Description

When the Function class object is called as a function it creates and initialises a new Function object. Thus the function call Function(…) is equivalent to the object creation _expression_ new Function(…) with the same arguments.

Returns

The Function class object called as a function returns a new Function instance.

Implementation

meta static function invoke(...args)
    new Function(...args);

FIXME   Ticket #357: That particular definition makes use of the prefix "spread" operator, which has not yet been formally accepted into the language.

apply ( fn, thisArg=…, argArray=… )

Description

The static apply method takes arguments fn, thisArg, and argArray and invokes fn in the standard manner, passing thisArg as the value for this and the members of argArray as the individual argument values.

Returns

The apply method returns the value returned by fn.

Implementation

static public function apply(fn /*: function*/, thisArg: Object=null, argArray: Object=null) {
    if (thisArg === null)
        thisArg = global;
    if (argArray === null)
        argArray = [];
    return magic::apply(fn, thisArg, argArray);
}

NOTE   The magic apply function performs the actual invocation (see magic::apply). This code will eventually change to use the prefix "spread" operator.

bind ( fn, thisArg=…, ...args )

Description

The static bind method takes arguments fn, thisArg, and optionally some args.

Returns

The bind method returns a Function object that accepts some arguments moreargs and which calls fn with thisArg as the this object and the values of args and moreargs as actual arguments.

Implementation

static public function bind(method /*: function*/, thisObj: Object=null, ...args)
    helper::bind(method, thisObj, args);

static helper function bind(method, thisObj, args)
    function (...moreargs)
        method.apply(thisObj, args.concat(moreargs));

call ( fn, thisArg=…, ...args )

Description

The static call method takes arguments fn and thisArg and optionally some args and invokes fn in the standard manner, passing thisArg as the value for this and the members of args as the individual argument values.

Returns

The call method returns the value returned by fn.

Implementation

static public function call(fn /*: function*/, thisObj: Object=null, ...args)
    Function.apply(fn, thisObj, args);

Methods on Function instances

meta::invoke ( … )

Description

The meta method invoke is specialized to the individual Function object. When called, it evaluates the executable code for the function.

The meta method invoke is typically called by the ECMAScript implementation as part of the function invocation and object construction protocols. When a function or method is invoked, the invoke method of the function or method object provides the code to run. When a function is used to construct a new object, the invoke method provides the code for the constructor function.

The signature of the meta method invoke is determined when the Function instance is created, and is determined by the text that defines the function being created.

NOTE   The meta method invoke is final; therefore subclasses can add properties and methods but can't override the function calling behavior.

FIXME   (Ticket #173.) While it is necessary that the invoke method is completely magic in Function instances, it's not clear it needs to be magic for instances of subclasses of Function, because these can be treated like other objects that have invoke methods (and which already work just fine in the reference implementation). Therefore it should not be final.

Returns

The meta method invoke returns the value produces by the first return statement that is evaluated during the evaluation of the executable code for the function represented by this Function object.

Implementation

The implementation of the meta function invoke is implementation-dependent.

intrinsic::toString ( )

Description

The intrinsic toString method converts the executable code of the function to a string representation. This representation has the syntax of a FunctionDeclaration or FunctionExpression. Note in particular that the use and placement of white space, line terminators, and semicolons within the representation string is implementation-dependent.

COMPATIBILITY NOTE   ES3 required the syntax to be that of a FunctionDeclaration only, but that made it impossible to produce a string representation for functions created from unnamed function expressions.

Returns

The intrinsic toString method returns a string.

Implementation

override intrinsic function toString() : string
    Private::toString();

The private function toString is implementation-dependent.

intrinsic::apply ( thisObj=…, args=… )

Description

The intrinsic apply method calls the static apply method with the value of this as the first argument.

Returns

The intrinsic apply method returns the result of the static apply method.

Implementation

intrinsic function apply(thisArg: Object=null, argArray: Object=null)
    Function.apply(this, thisArg, argArray);

intrinsic::bind ( thisObj=…, ...args)

Description

The intrinsic bind method calls the static bind method with the value of this as the first argument.

Returns

The intrinsic bind method returns the result of the static bind method.

Implementation

intrinsic function bind(thisObj: Object=null, ...args)
    Function.helper::bind(this, thisObj, args);

intrinsic::call ( thisObj=…, ...args)

Description

The intrinsic call method calls the static apply method with the value of this as the first argument.

Returns

The intrinsic call method returns the result of the static call method.

Implementation

intrinsic function call(thisObj: Object=null, ...args)
    Function.apply(this, thisObj, args);

Value properties of Function instances

length

The value of the constant length property is the number of non-rest arguments accepted by the function.

The value of the length property is an integer that indicates the "typical" number of arguments expected by the function. However, the language permits the function to be invoked with some other number of arguments. The behaviour of a function when invoked on a number of arguments other than the number specified by its length property depends on the function.

prototype

The initial value of the prototype property is a fresh Object instance.

The value of the prototype property is used to initialise the internal [[Prototype]] property of a newly created object before the Function instance is invoked as a constructor for that newly created object.

Invoking the Function prototype object

When the Function prototype object is invoked it accepts any arguments and returns undefined:

prototype meta function invoke(...args)
    undefined;

Methods on the Function prototype object

The methods on the Function prototype object perform simple type adjustments and then perform the same actions as their intrinsic counterparts:

prototype function toString(this:Function)
    this.Private::toString();

prototype function apply(/*this: function, */ thisArg=undefined, argArray=undefined)
    Function.apply(this,
                   thisArg === undefined ? null : thisArg,
                   argArray === undefined ? null : argArray);

prototype function bind(/*this: function, */ thisObj=undefined, ...args)
    Function.helper::bind(this,
                          thisObj === undefined ? null : thisObj,
                          args);

prototype function call(/*this: function, */ thisObj=undefined, ...args)
    Function.apply(this,
                   thisObj === undefined ? null : thisObj,
                   args);

Value properties on the Function prototype object

length

The initial value of the length prototype property is 0.

Implementation

prototype var length : uint = 0;

COMPATIBILITY NOTE   The "length" property of the prototype is not obviously required by the 3rd Edition of this Standard, but MSIE, Firefox, Opera, and Safari all provide it.

_______________________________________________
Es4-discuss mailing list
Es4-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es4-discuss

Reply via email to