Bug 1166950 - Make generator methods constructors. r=efaust
authorTom Schuster <evilpies@gmail.com>
Mon, 25 May 2015 19:31:46 +0200
changeset 245497 0adc0764b127
parent 245496 80585eecc103
child 245498 f3bf2b462632
push id28806
push userphilringnalda@gmail.com
push dateTue, 26 May 2015 02:10:16 +0000
treeherdermozilla-central@4362d9251296 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersefaust
bugs1166950
milestone41.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1166950 - Make generator methods constructors. r=efaust
js/src/frontend/Parser.cpp
js/src/frontend/Parser.h
js/src/jsfun.h
js/src/tests/ecma_6/Class/methDefnGen.js
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -1205,34 +1205,39 @@ struct BindData
         this->op = op;
         this->isConst = op == JSOP_DEFCONST;
         this->binder = Parser<ParseHandler>::bindVarOrGlobalConst;
     }
 };
 
 template <typename ParseHandler>
 JSFunction*
-Parser<ParseHandler>::newFunction(HandleAtom atom, FunctionSyntaxKind kind, HandleObject proto)
+Parser<ParseHandler>::newFunction(HandleAtom atom, FunctionSyntaxKind kind,
+                                  GeneratorKind generatorKind, HandleObject proto)
 {
     MOZ_ASSERT_IF(kind == Statement, atom != nullptr);
 
     RootedFunction fun(context);
 
     gc::AllocKind allocKind = gc::AllocKind::FUNCTION;
     JSFunction::Flags flags;
     switch (kind) {
       case Expression:
         flags = JSFunction::INTERPRETED_LAMBDA;
         break;
       case Arrow:
         flags = JSFunction::INTERPRETED_LAMBDA_ARROW;
         allocKind = gc::AllocKind::FUNCTION_EXTENDED;
         break;
       case Method:
-        flags = JSFunction::INTERPRETED_METHOD;
+        MOZ_ASSERT(generatorKind == NotGenerator || generatorKind == StarGenerator);
+        if (generatorKind == NotGenerator)
+            flags = JSFunction::INTERPRETED_METHOD;
+        else
+            flags = JSFunction::INTERPRETED_METHOD_GENERATOR;
         allocKind = gc::AllocKind::FUNCTION_EXTENDED;
         break;
       case ClassConstructor:
         flags = JSFunction::INTERPRETED_CLASS_CONSTRUCTOR;
         allocKind = gc::AllocKind::FUNCTION_EXTENDED;
         break;
       case Getter:
         flags = JSFunction::INTERPRETED_GETTER;
@@ -2188,17 +2193,17 @@ Parser<ParseHandler>::functionDef(InHand
         // If we are off the main thread, the generator meta-objects have
         // already been created by js::StartOffThreadParseScript, so cx will not
         // be necessary.
         JSContext* cx = context->maybeJSContext();
         proto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, context->global());
         if (!proto)
             return null();
     }
-    RootedFunction fun(context, newFunction(funName, kind, proto));
+    RootedFunction fun(context, newFunction(funName, kind, generatorKind, proto));
     if (!fun)
         return null();
 
     // Speculatively parse using the directives of the parent parsing context.
     // If a directive is encountered (e.g., "use strict") that changes how the
     // function should have been parsed, we backup and reparse with the new set
     // of directives.
     Directives directives(pc);
@@ -7335,17 +7340,17 @@ Parser<ParseHandler>::generatorComprehen
     RootedObject proto(context);
     if (comprehensionKind == StarGenerator) {
         JSContext* cx = context->maybeJSContext();
         proto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, context->global());
         if (!proto)
             return null();
     }
 
-    RootedFunction fun(context, newFunction(/* atom = */ nullptr, Expression, proto));
+    RootedFunction fun(context, newFunction(/* atom = */ nullptr, Expression, comprehensionKind, proto));
     if (!fun)
         return null();
 
     // Create box for fun->object early to root it.
     Directives directives(/* strict = */ outerpc->sc->strict());
     FunctionBox* genFunbox = newFunctionBox(genfn, fun, outerpc, directives, comprehensionKind);
     if (!genFunbox)
         return null();
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -440,17 +440,18 @@ class Parser : private JS::AutoGCRooter,
     ObjectBox* newObjectBox(JSObject* obj);
     FunctionBox* newFunctionBox(Node fn, JSFunction* fun, ParseContext<ParseHandler>* pc,
                                 Directives directives, GeneratorKind generatorKind);
 
     /*
      * Create a new function object given a name (which is optional if this is
      * a function expression).
      */
-    JSFunction* newFunction(HandleAtom atom, FunctionSyntaxKind kind, HandleObject proto);
+    JSFunction* newFunction(HandleAtom atom, FunctionSyntaxKind kind, GeneratorKind generatorKind,
+                            HandleObject proto);
 
     void trace(JSTracer* trc);
 
     bool hadAbortedSyntaxParse() {
         return abortedSyntaxParse;
     }
     void clearAbortedSyntaxParse() {
         abortedSyntaxParse = false;
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -69,16 +69,17 @@ class JSFunction : public js::NativeObje
         SETTER_KIND = Setter << FUNCTION_KIND_SHIFT,
 
         /* Derived Flags values for convenience: */
         NATIVE_FUN = 0,
         NATIVE_CTOR = NATIVE_FUN | CONSTRUCTOR,
         ASMJS_CTOR = ASMJS_KIND | NATIVE_CTOR,
         ASMJS_LAMBDA_CTOR = ASMJS_KIND | NATIVE_CTOR | LAMBDA,
         INTERPRETED_METHOD = INTERPRETED | METHOD_KIND,
+        INTERPRETED_METHOD_GENERATOR = INTERPRETED | METHOD_KIND | CONSTRUCTOR,
         INTERPRETED_CLASS_CONSTRUCTOR = INTERPRETED | CLASSCONSTRUCTOR_KIND | CONSTRUCTOR,
         INTERPRETED_GETTER = INTERPRETED | GETTER_KIND,
         INTERPRETED_SETTER = INTERPRETED | SETTER_KIND,
         INTERPRETED_LAMBDA = INTERPRETED | LAMBDA | CONSTRUCTOR,
         INTERPRETED_LAMBDA_ARROW = INTERPRETED | LAMBDA | ARROW_KIND,
         INTERPRETED_NORMAL = INTERPRETED | CONSTRUCTOR,
 
         STABLE_ACROSS_CLONES = IS_FUN_PROTO | CONSTRUCTOR | EXPR_BODY | HAS_GUESSED_ATOM |
--- a/js/src/tests/ecma_6/Class/methDefnGen.js
+++ b/js/src/tests/ecma_6/Class/methDefnGen.js
@@ -67,9 +67,18 @@ assertEq(next.value.hello, 2);
 assertEq(next.value.world, 3);
 
 // Strict mode
 a = {*b(c){"use strict";yield c;}};
 assertEq(a.b(1).next().value, 1);
 a = {*["b"](c){"use strict";return c;}};
 assertEq(a.b(1).next().value, 1);
 
+// Constructing
+a = {*g() { yield 1; }}
+it = new a.g;
+next = it.next();
+assertEq(next.done, false);
+assertEq(next.value, 1);
+next = it.next();
+assertEq(next.done, true);
+
 reportCompare(0, 0, "ok");