Generator methods incorrectly restricted from use as constructors

RESOLVED FIXED in Firefox 41

Status

()

defect
RESOLVED FIXED
4 years ago
4 years ago

People

(Reporter: jugglinmike, Assigned: evilpie)

Tracking

(Blocks 1 bug)

unspecified
mozilla41
Points:
---
Dependency tree / graph

Firefox Tracking Flags

(firefox41 fixed)

Details

Attachments

(3 attachments)

Reporter

Description

4 years ago
Input:

    var g = { *g() {} }.g; new g();

Expected: an object is created whose [[Prototype]] internal slot is the
generator function defined in the object initializer.

Actual: TypeError

Demo:

    $ js -e "var g = { *g() {} }.g; new g();"
    -e:1:27 TypeError: g is not a constructor

"Normal" functions declared within object initializers using the
MethodDefinition syntax do not defined a [[Construct]] internal method and
cannot be used as constructors. The same is not true for generator functions:

> 14.4.13 Runtime Semantics: PropertyDefinitionEvaluation
> 
> GeneratorMethod : * PropertyName ( StrictFormalParameters ) { GeneratorBody }
> 
> [...]
> 5. Let closure be GeneratorFunctionCreate(Method, StrictFormalParameters,
>    GeneratorBody, scope, strict).
> 6. Perform MakeMethod(closure, object).
> 7. Let prototype be ObjectCreate(%GeneratorPrototype%).
> 8. Perform MakeConstructor(closure, true, prototype).
> [...]

> 9.2.6 GeneratorFunctionCreate (kind, ParameterList, Body, Scope, Strict)
> 
> 1. Let functionPrototype be the intrinsic object %Generator%.
> 2. Let F be FunctionAllocate(functionPrototype, Strict, "generator").
> 3. Return FunctionInitialize(F, kind, ParameterList, Body, Scope).

> 9.2.3 FunctionAllocate (functionPrototype, strict [,functionKind] )
> 
> [...]
> 3. If functionKind is not present, let functionKind be "normal".
> 4. If functionKind is "non-constructor", then
>    a. Let functionKind be "normal".
>    b. Let needsConstruct be false.
> 5. Else let needsConstruct be true.
> [...]
> 9. If needsConstruct is true, then
>    a. Set F’s [[Construct]] internal method to the definition specified in
>       9.2.2.
>    b. If functionKind is "generator", set the [[ConstructorKind]] internal
>       slot of F to "derived".
>    c. Else, set the [[ConstructorKind]] internal slot of F to "base".
>    d. NOTE Generator functions are tagged as "derived" constructors to
>       prevent [[Construct]] from preallocating a generator instance.
>       Generator instance objects are allocated when EvaluateBody is applied
>       to the GeneratorBody of a generator function.

Sources:

- https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generator-function-definitions-runtime-semantics-propertydefinitionevaluation
- https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorfunctioncreate
- https://people.mozilla.org/~jorendorff/es6-draft.html#sec-functionallocate

Updated

4 years ago
Blocks: es6
See Also: → 1059908

Comment 1

4 years ago
And Method Definitions except for GeneratorMethod should not have a prototype property:

js> ({m(){}}).m.hasOwnProperty("prototype")
true // should be false

js> ({*g(){}}).g.hasOwnProperty("prototype")
true // √

js> (class {constructor(){} static m(){}}).m.hasOwnProperty("prototype")
true // should be false

js> (class {constructor(){} static *g(){}}).g.hasOwnProperty("prototype")
true // √

js> (new (class {constructor(){} m(){}})).m.hasOwnProperty("prototype")
true // should be false

js> (new (class {constructor(){} *g(){}})).g.hasOwnProperty("prototype")
true // √

js> Object.getOwnPropertyDescriptor({set m(_){}}, "m").set.hasOwnProperty("prototype")
true // should be false

js> Object.getOwnPropertyDescriptor({get m(){}}, "m").get.hasOwnProperty("prototype")
true // should be false
See Also: → 1069402
Assignee

Updated

4 years ago
Assignee: nobody → evilpies
Assignee

Comment 3

4 years ago
Attachment #8609835 - Flags: review?(efaustbmo)
Comment on attachment 8609834 [details] [diff] [review]
Introduce a new FunctionKind for class-constructors

Review of attachment 8609834 [details] [diff] [review]:
-----------------------------------------------------------------

Looks fine.

::: js/src/jsfun.h
@@ +165,5 @@
>  
>      // Arrow functions store their lexical |this| in the first extended slot.
>      bool isArrow()                  const { return kind() == Arrow; }
>      // Every class-constructor is also a method.
> +    bool isMethod()                 const { return kind() == Method || kind() == ClassConstructor; }

nit: || isClassConstructor()
Attachment #8609834 - Flags: review?(efaustbmo) → review+
Comment on attachment 8609835 [details] [diff] [review]
Make generator methods constructors

Review of attachment 8609835 [details] [diff] [review]:
-----------------------------------------------------------------

Yup
Attachment #8609835 - Flags: review?(efaustbmo) → review+
Comment on attachment 8609836 [details] [diff] [review]
Only give constructor functions a prototype

Review of attachment 8609836 [details] [diff] [review]:
-----------------------------------------------------------------

Thanks for taking this, too.
Attachment #8609836 - Flags: review?(efaustbmo) → review+
You need to log in before you can comment on or make changes to this bug.