GeneratorFunctionPrototype should probably be a function

# Andy Wingo (12 years ago)

Section 15.19.3.3 of the July 15 draft says:

Properties of the GeneratorFunction Prototype Object

The GeneratorFunction prototype object is an ordinary object. It is not a function object and does not have a [[Code]] internal data property or any other of the internal data properties listed in Table 13. In addition to being the value of the prototype property of the %GeneratorFunction% intrinsic and is itself the %Generator% instrinsic.

See people.mozilla.org/~jorendorff/es6-draft.html#sec-15.19.3 for the gnarlies. To be explicit, we are talking about this object:

var GeneratorFunctionPrototype = function*(){}.__proto__;

I think this object should be a function and not a normal object.

  1. The spec doesn't specify any other objects for which "x instanceof Function" that aren't functions.

  2. Function.prototype.toString is the binding for ".toString()" on this object, but it is only applicable to function receivers.

Sending here as I seem to have forgotten my bugzilla password, and the mail is taking too long to get here. Sorry 'bout that.

# André Bargull (12 years ago)

1. The spec doesn't specify any other objects for which "x instanceof Function" that aren't functions.

Isn't that just because no other object inherits from the Function object in the specification? For example on the user level you can write class MyFunction extends Function {}, where MyFunction.prototype instanceof Function yields true, but typeof MyFunction.prototype is still "object". IIRC Allen even spec'ed GeneratorFunction similar to if it was written in the class syntax.

2. Function.prototype.toString is the binding for ".toString()" on this object, but it is only applicable to function receivers.

The same restriction also applies to Number, String, Boolean, RegExp and Date (or rather to the corresponding prototype objects). So this is not a unique behaviour w.r.t. the GeneratorFunction prototype object.

# Allen Wirfs-Brock (12 years ago)

On Aug 13, 2013, at 9:41 AM, André Bargull wrote:

1. The spec doesn't specify any other objects for which "x instanceof Function" that aren't functions.

Isn't that just because no other object inherits from the Function object in the specification? For example on the user level you can write class MyFunction extends Function {}, where MyFunction.prototype instanceof Function yields true, but typeof MyFunction.prototype is still "object". IIRC Allen even spec'ed GeneratorFunction similar to if it was written in the class syntax.

More generally, we've previously discussed and decided to break from the ES<6 convention that built-in prototype objects act as if they were instances of their associated constructors. That generally won't be the case for prototypes defined using a class declarations. We even decided to relax that requirement for the existing built-in, except where it would create backwards compat issues (Function.prototype and Array.prototype appear to be situations where there are such issues.)

instanceof is essentially broken when applied to most non-built-in prototype objects because they usually just aren't defined to proper operate as instances of the associated constructor.

2. Function.prototype.toString is the binding for ".toString()" on this object, but it is only applicable to function receivers.

The same restriction also applies to Number, String, Boolean, RegExp and Date (or rather to the corresponding prototype objects). So this is not a unique behaviour w.r.t. the GeneratorFunction prototype object.

same basic issue, many own or inherited prototype methods won't work on prototype objects.

# Andy Wingo (12 years ago)

Thanks Allen and André for replying; I admit that I haven't payed much attention to the new classy parts of ES6.

On Tue 13 Aug 2013 19:44, Allen Wirfs-Brock <allen at wirfs-brock.com> writes:

instanceof is essentially broken when applied to most non-built-in prototype objects because they usually just aren't defined to proper operate as instances of the associated constructor.

Why is there a "constructor" link, then, from GeneratorObjectPrototype to GeneratorFunctionPrototype, if the latter isn't a constructor? Or is it, somehow?

BTW, I find that the lack of clear names in the spec makes thinking and communication difficult. If you can, I would call them "GeneratorFunction", "GeneratorFunctionPrototype", and "GeneratorObjectPrototype", in LTR order in the section 15.19.3 diagram. They don't have to be bound on the global object, but having well-known names in the spec makes it easier to talk about them.

# Allen Wirfs-Brock (12 years ago)

On Aug 14, 2013, at 3:51 AM, Andy Wingo wrote:

Why is there a "constructor" link, then, from GeneratorObjectPrototype to GeneratorFunctionPrototype, if the latter isn't a constructor? Or is it, somehow?

(I'm going to use the names from the figure in 15.19.3 and suggest that you reference that diagram while reading the following and remember that in UML the names of associations (properties) are at the opposite end of an association line)

So, why? It's because (Generator) (aka (GeneratorFunction).prototype and (Generator).prototype.constructor) serves two distinct roles. It is the prototype object associated with the constructor named (GeneratorFunction) and it is an abstract super constructor (ie abstract superclass object). In the latter role it has an associated prototype object (Generator).prototype, aka (GeneratorFunction).prototype.prototype.

This arrangement allows the following to work:

function * g(){};
let gObj = new g(); //or just g()
console.log(g instanceof (GeneratorFunction));  //true
console.log(g instanceof Function);  //true
console.log(g instanceof Object); //true
console.log(gObj instanceof g);  //true
console.log(gObj instanceof (Generator)); //true
console.log(gObj instanceof Object); //true
console.log(gObj instanceof Function);  //false

The existence of a 'constructor' property on (Generator).prototype is a direct reflection of the class pattern and {Generator)'s role as an abstract class. In general, a 'constructor' property on a class's prototype (even when abstract) is needed so that a subclass constructor can make a super call to the super class constructor. However, this scenario isn't applicable to generator functions and generator objects, but we've still followed that general pattern.

There is one intentional anomaly in the application of the class pattern to generator objects. The prototype associated with an individual generator function does not have a 'constructor' own property that references back to the generator function. For example, using the definitions in the above example, the following expression evaluates to false:

gObj.constructor === g // false because g.prototype does not have a 'constructor' own property

The reason for that was that we didn't want access to a generator instance to implicitly provide the capability to access the associated generator function and hence the capability to create additional generator instances.

If we also did not have a 'constructor' property on (Generator).prototype then gObj.constructor would evaluate to Object. It seems more reasonable for it to evaluate to (Generator) and that is what the existence of (Generator).prototype.constructor enables.

BTW, I find that the lack of clear names in the spec makes thinking and communication difficult. If you can, I would call them "GeneratorFunction", "GeneratorFunctionPrototype", and "GeneratorObjectPrototype", in LTR order in the section 15.19.3 diagram. They don't have to be bound on the global object, but having well-known names in the spec makes it easier to talk about them.

The naming in the spec is the naming that was developed and agreed to at the Nov. 27, 2012 TC-39 meeting dl.dropboxusercontent.com/u/3531958/tc39/generator-diagram-1.jpg

The main rationale for these names goes something like:

Normally a constructor for instances of an abstraction is given the name of the abstraction and we don't formally append "Object" to such names. Instead we use the abstract name as an adjective to "object" or "instance". So, "generator objects" are instances of the "generator" abstraction and hence the name of the (abstract) constructor/class should be Generator. So what do you call the abstraction over the special kind of functions that are the subclasses of Generator? We decided on GeneratorFunction. Individual generator functions such as g above are GeneratorFunction instances, just like regular constructor functions are instances of Function.