Backed out changeset bfa3c469cb74 (bug 666399) for bustage on a CLOSED TREE.
authorRyan VanderMeulen <ryanvm@gmail.com>
Wed, 14 Aug 2013 16:50:21 -0400
changeset 155579 a869023cf9b6370d0200efb4098268851356faec
parent 155578 4c57db53faa4ad64ddea69c748e0846ac29ce835
child 155580 07fdbc86f5b1dff1edd1130f56506c45e86c9a59
push id2961
push userlsblakk@mozilla.com
push dateMon, 28 Oct 2013 21:59:28 +0000
treeherdermozilla-beta@73ef4f13486f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs666399
milestone26.0a1
backs outbfa3c469cb74338fef257b8ee6031cdb6888aa95
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
Backed out changeset bfa3c469cb74 (bug 666399) for bustage on a CLOSED TREE.
js/src/frontend/BytecodeCompiler.cpp
js/src/frontend/ParseNode.cpp
js/src/frontend/Parser.cpp
js/src/frontend/Parser.h
js/src/frontend/SharedContext.h
js/src/frontend/TokenStream.cpp
js/src/frontend/TokenStream.h
js/src/jit-test/tests/generators/es6-syntax.js
js/src/jit/AsmJS.cpp
js/src/js.msg
js/src/jsanalyze.cpp
js/src/jsatom.cpp
js/src/jsatom.h
js/src/jsfun.cpp
js/src/jsfun.h
js/src/jsiter.cpp
js/src/jsreflect.cpp
js/src/jsscript.cpp
js/src/jsscript.h
js/src/tests/ecma_6/Generators/shell.js
js/src/tests/ecma_6/Generators/syntax.js
js/src/vm/CommonPropertyNames.h
js/src/vm/Keywords.h
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -64,17 +64,17 @@ CheckArgumentsWithinEval(JSContext *cx, 
     // |arguments| within an eval.
     RootedScript script(cx, fun->nonLazyScript());
     if (script->argumentsHasVarBinding()) {
         if (!JSScript::argumentsOptimizationFailed(cx, script))
             return false;
     }
 
     // It's an error to use |arguments| in a legacy generator expression.
-    if (script->isGeneratorExp && script->isLegacyGenerator()) {
+    if (script->isGeneratorExp && script->isLegacyGenerator) {
         parser.report(ParseError, false, NULL, JSMSG_BAD_GENEXP_BODY, js_arguments_str);
         return false;
     }
 
     return true;
 }
 
 static bool
@@ -288,18 +288,17 @@ frontend::CompileScript(ExclusiveContext
         if (evalCaller && evalCaller->functionOrCallerFunction()) {
             /*
              * An eval script in a caller frame needs to have its enclosing
              * function captured in case it refers to an upvar, and someone
              * wishes to decompile it while it's running.
              */
             JSFunction *fun = evalCaller->functionOrCallerFunction();
             Directives directives(/* strict = */ fun->strict());
-            ObjectBox *funbox = parser.newFunctionBox(/* fn = */ NULL, fun, pc.addr(),
-                                                      directives, fun->generatorKind());
+            ObjectBox *funbox = parser.newFunctionBox(/* fn = */ NULL, fun, pc.addr(), directives);
             if (!funbox)
                 return NULL;
             bce.objectList.add(funbox);
         }
     }
 
     bool canHaveDirectives = true;
     for (;;) {
@@ -409,19 +408,17 @@ frontend::CompileLazyFunction(JSContext 
 #endif
 
     Parser<FullParseHandler> parser(cx, &cx->tempLifoAlloc(), options, chars, length,
                                     /* foldConstants = */ true, NULL, lazy);
 
     uint32_t staticLevel = lazy->staticLevel(cx);
 
     Rooted<JSFunction*> fun(cx, lazy->function());
-    JS_ASSERT(!lazy->isLegacyGenerator());
-    ParseNode *pn = parser.standaloneLazyFunction(fun, staticLevel, lazy->strict(),
-                                                  lazy->generatorKind());
+    ParseNode *pn = parser.standaloneLazyFunction(fun, staticLevel, lazy->strict());
     if (!pn)
         return false;
 
     if (!NameFunctions(cx, pn))
         return false;
 
     RootedObject enclosingScope(cx, lazy->enclosingScope());
     JS::RootedScriptSource sourceObject(cx, lazy->sourceObject());
@@ -515,17 +512,17 @@ frontend::CompileFunctionBody(JSContext 
     Directives directives(options.strictOption);
 
     TokenStream::Position start(parser.keepAtoms);
     parser.tokenStream.tell(&start);
 
     ParseNode *fn;
     while (true) {
         Directives newDirectives = directives;
-        fn = parser.standaloneFunctionBody(fun, formals, NotGenerator, directives, &newDirectives);
+        fn = parser.standaloneFunctionBody(fun, formals, directives, &newDirectives);
         if (fn)
             break;
 
         if (parser.hadAbortedSyntaxParse()) {
             // Hit some unrecoverable ambiguity during an inner syntax parse.
             // Syntax parsing has now been disabled in the parser, so retry
             // the parse.
             parser.clearAbortedSyntaxParse();
--- a/js/src/frontend/ParseNode.cpp
+++ b/js/src/frontend/ParseNode.cpp
@@ -379,19 +379,19 @@ Parser<FullParseHandler>::cloneParseTree
 
     switch (pn->getArity()) {
 #define NULLCHECK(e)    JS_BEGIN_MACRO if (!(e)) return NULL; JS_END_MACRO
 
       case PN_CODE:
         if (pn->getKind() == PNK_MODULE) {
             MOZ_ASSUME_UNREACHABLE("module nodes cannot be cloned");
         }
-        NULLCHECK(pn->pn_funbox = newFunctionBox(pn, opn->pn_funbox->function(), pc,
-                                                 Directives(/* strict = */ opn->pn_funbox->strict),
-                                                 opn->pn_funbox->generatorKind()));
+        NULLCHECK(pn->pn_funbox =
+                  newFunctionBox(pn, opn->pn_funbox->function(), pc,
+                                 Directives(/* strict = */ opn->pn_funbox->strict)));
         NULLCHECK(pn->pn_body = cloneParseTree(opn->pn_body));
         pn->pn_cookie = opn->pn_cookie;
         pn->pn_dflags = opn->pn_dflags;
         pn->pn_blockid = opn->pn_blockid;
         break;
 
       case PN_LIST:
         pn->makeEmpty();
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -51,16 +51,17 @@ using namespace js::gc;
 using mozilla::Maybe;
 
 namespace js {
 namespace frontend {
 
 typedef Rooted<StaticBlockObject*> RootedStaticBlockObject;
 typedef Handle<StaticBlockObject*> HandleStaticBlockObject;
 
+typedef MutableHandle<PropertyName*> MutableHandlePropertyName;
 
 /*
  * Insist that the next token be of type tt, or report errno and return null.
  * NB: this macro uses cx and ts from its lexical environment.
  */
 #define MUST_MATCH_TOKEN(tt, errno)                                                         \
     JS_BEGIN_MACRO                                                                          \
         if (tokenStream.getToken() != tt) {                                                 \
@@ -449,24 +450,23 @@ Parser<ParseHandler>::newObjectBox(JSObj
     traceListHead = objbox;
 
     return objbox;
 }
 
 template <typename ParseHandler>
 FunctionBox::FunctionBox(ExclusiveContext *cx, ObjectBox* traceListHead, JSFunction *fun,
                          ParseContext<ParseHandler> *outerpc, Directives directives,
-                         bool extraWarnings, GeneratorKind generatorKind)
+                         bool extraWarnings)
   : ObjectBox(fun, traceListHead),
     SharedContext(cx, directives, extraWarnings),
     bindings(),
     bufStart(0),
     bufEnd(0),
     ndefaults(0),
-    generatorKindBits_(GeneratorKindAsBits(generatorKind)),
     inWith(false),                  // initialized below
     inGenexpLambda(false),
     hasDestructuringArgs(false),
     useAsm(directives.asmJS()),
     insideUseAsm(outerpc && outerpc->useAsmOrInsideUseAsm()),
     usesArguments(false),
     usesApply(false),
     funCxFlags()
@@ -517,31 +517,30 @@ FunctionBox::FunctionBox(ExclusiveContex
         if (parent && parent->inWith)
             inWith = true;
     }
 }
 
 template <typename ParseHandler>
 FunctionBox *
 Parser<ParseHandler>::newFunctionBox(Node fn, JSFunction *fun, ParseContext<ParseHandler> *outerpc,
-                                     Directives inheritedDirectives, GeneratorKind generatorKind)
+                                     Directives inheritedDirectives)
 {
     JS_ASSERT(fun && !IsPoisonedPtr(fun));
 
     /*
      * We use JSContext.tempLifoAlloc to allocate parsed objects and place them
      * on a list in this Parser to ensure GC safety. Thus the tempLifoAlloc
      * arenas containing the entries must be alive until we are done with
      * scanning, parsing and code generation for the whole script or top-level
      * function.
      */
     FunctionBox *funbox =
         alloc.new_<FunctionBox>(context, traceListHead, fun, outerpc,
-                                inheritedDirectives, options().extraWarningsOption,
-                                generatorKind);
+                                inheritedDirectives, options().extraWarningsOption);
     if (!funbox) {
         js_ReportOutOfMemory(context);
         return NULL;
     }
 
     traceListHead = funbox;
     if (fn)
         handler.setFunctionBox(fn, funbox);
@@ -848,33 +847,31 @@ Parser<ParseHandler>::checkStrictBinding
     }
 
     return true;
 }
 
 template <>
 ParseNode *
 Parser<FullParseHandler>::standaloneFunctionBody(HandleFunction fun, const AutoNameVector &formals,
-                                                 GeneratorKind generatorKind,
                                                  Directives inheritedDirectives,
                                                  Directives *newDirectives)
 {
     Node fn = handler.newFunctionDefinition();
     if (!fn)
         return null();
 
     ParseNode *argsbody = ListNode::create(PNK_ARGSBODY, &handler);
     if (!argsbody)
         return null();
     argsbody->setOp(JSOP_NOP);
     argsbody->makeEmpty();
     fn->pn_body = argsbody;
 
-    FunctionBox *funbox = newFunctionBox(fn, fun, /* outerpc = */ NULL, inheritedDirectives,
-                                         generatorKind);
+    FunctionBox *funbox = newFunctionBox(fn, fun, /* outerpc = */ NULL, inheritedDirectives);
     if (!funbox)
         return null();
     handler.setFunctionBox(fn, funbox);
 
     ParseContext<FullParseHandler> funpc(this, pc, fn, funbox, newDirectives,
                                          /* staticLevel = */ 0, /* bodyid = */ 0);
     if (!funpc.init())
         return null();
@@ -1069,41 +1066,32 @@ Parser<ParseHandler>::functionBody(Funct
         if (!kid)
             return null();
 
         pn = handler.newReturnStatement(kid, handler.getPosition(kid));
         if (!pn)
             return null();
     }
 
-    switch (pc->generatorKind()) {
-      case NotGenerator:
-        JS_ASSERT(pc->lastYieldOffset == startYieldOffset);
-        break;
-
-      case LegacyGenerator:
-        // FIXME: Catch these errors eagerly, in yieldExpression().
-        JS_ASSERT(pc->lastYieldOffset != startYieldOffset);
+    if (pc->lastYieldOffset != startYieldOffset) {
+        JS_ASSERT(pc->isLegacyGenerator());
         if (kind == Arrow) {
             reportWithOffset(ParseError, false, pc->lastYieldOffset,
                              JSMSG_YIELD_IN_ARROW, js_yield_str);
             return null();
         }
         if (type == ExpressionBody) {
             reportBadReturn(pn, ParseError,
                             JSMSG_BAD_GENERATOR_RETURN,
                             JSMSG_BAD_ANON_GENERATOR_RETURN);
             return null();
         }
-        break;
-
-      case StarGenerator:
-        JS_ASSERT(kind != Arrow);
-        JS_ASSERT(type == StatementListBody);
-        break;
+        pc->sc->asFunctionBox()->setIsLegacyGenerator();
+    } else {
+        JS_ASSERT(!pc->isLegacyGenerator());
     }
 
     /* Check for falling off the end of a function that returns a value. */
     if (options().extraWarningsOption && pc->funHasReturnExpr && !checkFinalReturn(pn))
         return null();
 
     /* Define the 'arguments' binding if necessary. */
     if (!checkFunctionArguments())
@@ -1629,40 +1617,34 @@ Parser<ParseHandler>::functionArguments(
                     if (!list)
                         return false;
                     *listp = list;
                 }
                 break;
               }
 #endif /* JS_HAS_DESTRUCTURING */
 
-              case TOK_YIELD:
-                if (!checkYieldNameValidity(JSMSG_MISSING_FORMAL))
-                    return false;
-                goto TOK_NAME;
-
               case TOK_TRIPLEDOT:
               {
                 hasRest = true;
                 tt = tokenStream.getToken();
                 if (tt != TOK_NAME) {
                     if (tt != TOK_ERROR)
                         report(ParseError, false, null(), JSMSG_NO_REST_NAME);
                     return false;
                 }
-                goto TOK_NAME;
+                /* Fall through */
               }
 
-              TOK_NAME:
               case TOK_NAME:
               {
                 if (parenFreeArrow)
                     funbox->setStart(tokenStream);
 
-                RootedPropertyName name(context, tokenStream.currentName());
+                RootedPropertyName name(context, tokenStream.currentToken().name());
                 bool disallowDuplicateArgs = funbox->hasDestructuringArgs || hasDefaults;
                 if (!defineArg(funcpn, name, disallowDuplicateArgs, &duplicatedArg))
                     return false;
 
                 if (tokenStream.matchToken(TOK_ASSIGN)) {
                     // A default argument without parentheses would look like:
                     // a = expr => body, but both operators are right-associative, so
                     // that would have been parsed as a = (expr => body) instead.
@@ -1703,45 +1685,28 @@ Parser<ParseHandler>::functionArguments(
             report(ParseError, false, null(), JSMSG_PAREN_AFTER_FORMAL);
             return false;
         }
     }
 
     return true;
 }
 
-template <typename ParseHandler>
-bool
-Parser<ParseHandler>::checkFunctionName(HandlePropertyName funName)
-{
-    if (pc->isStarGenerator() && funName == context->names().yield) {
-        // The name of a named function expression is specified to be bound in
-        // the outer context as if via "let".  In an ES6 generator, "yield" is
-        // not a valid name for a let-bound variable.
-        report(ParseError, false, null(), JSMSG_RESERVED_ID, "yield");
-        return false;
-    }
-    return true;
-}
-
 template <>
 bool
 Parser<FullParseHandler>::checkFunctionDefinition(HandlePropertyName funName,
                                                   ParseNode **pn_, FunctionSyntaxKind kind,
                                                   bool *pbodyProcessed)
 {
     ParseNode *&pn = *pn_;
     *pbodyProcessed = false;
 
     /* Function statements add a binding to the enclosing scope. */
     bool bodyLevel = pc->atBodyLevel();
 
-    if (!checkFunctionName(funName))
-        return false;
-
     if (kind == Statement) {
         /*
          * Handle redeclaration and optimize cases where we can statically bind the
          * function (thereby avoiding JSOP_DEFFUN and dynamic name lookup).
          */
         if (Definition *dn = pc->decls().lookupFirst(funName)) {
             JS_ASSERT(!dn->isUsed());
             JS_ASSERT(dn->isDefn());
@@ -1845,19 +1810,17 @@ Parser<FullParseHandler>::checkFunctionD
     }
 
     // When a lazily-parsed function is called, we only fully parse (and emit)
     // that function, not any of its nested children. The initial syntax-only
     // parse recorded the free variables of nested functions and their extents,
     // so we can skip over them after accounting for their free variables.
     if (LazyScript *lazyOuter = handler.lazyOuterFunction()) {
         JSFunction *fun = handler.nextLazyInnerFunction();
-        JS_ASSERT(!fun->isLegacyGenerator());
-        FunctionBox *funbox = newFunctionBox(pn, fun, pc, Directives(/* strict = */ false),
-                                             fun->generatorKind());
+        FunctionBox *funbox = newFunctionBox(pn, fun, pc, Directives(/* strict = */ false));
         if (!funbox)
             return false;
 
         if (!addFreeVariablesFromLazyFunction(fun, pc))
             return false;
 
         // The position passed to tokenStream.advance() is relative to
         // userbuf.base() while LazyScript::{begin,end} offsets are relative to
@@ -1923,19 +1886,16 @@ Parser<SyntaxParseHandler>::checkFunctio
                                                     Node *pn, FunctionSyntaxKind kind,
                                                     bool *pbodyProcessed)
 {
     *pbodyProcessed = false;
 
     /* Function statements add a binding to the enclosing scope. */
     bool bodyLevel = pc->atBodyLevel();
 
-    if (!checkFunctionName(funName))
-        return false;
-
     if (kind == Statement) {
         /*
          * Handle redeclaration and optimize cases where we can statically bind the
          * function (thereby avoiding JSOP_DEFFUN and dynamic name lookup).
          */
         if (DefinitionNode dn = pc->decls().lookupFirst(funName)) {
             if (dn == Definition::CONST) {
                 JSAutoByteString name;
@@ -1964,18 +1924,17 @@ Parser<SyntaxParseHandler>::checkFunctio
     }
 
     return true;
 }
 
 template <typename ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::functionDef(HandlePropertyName funName, const TokenStream::Position &start,
-                                  FunctionType type, FunctionSyntaxKind kind,
-                                  GeneratorKind generatorKind)
+                                  FunctionType type, FunctionSyntaxKind kind)
 {
     JS_ASSERT_IF(kind == Statement, funName);
 
     /* Make a TOK_FUNCTION node. */
     Node pn = handler.newFunctionDefinition();
     if (!pn)
         return null();
 
@@ -1993,17 +1952,17 @@ Parser<ParseHandler>::functionDef(Handle
     // 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);
     Directives newDirectives = directives;
 
     while (true) {
-        if (functionArgsAndBody(pn, fun, type, kind, generatorKind, directives, &newDirectives))
+        if (functionArgsAndBody(pn, fun, type, kind, directives, &newDirectives))
             break;
         if (tokenStream.hadError() || directives == newDirectives)
             return null();
 
         // Assignment must be monotonic to prevent reparsing iloops
         JS_ASSERT_IF(directives.strict(), newDirectives.strict());
         JS_ASSERT_IF(directives.asmJS(), newDirectives.asmJS());
         directives = newDirectives;
@@ -2097,37 +2056,35 @@ Parser<SyntaxParseHandler>::finishFuncti
     JS_ASSERT(i == numFreeVariables);
 
     HeapPtrFunction *innerFunctions = lazy->innerFunctions();
     for (size_t i = 0; i < numInnerFunctions; i++)
         innerFunctions[i].init(pc->innerFunctions[i]);
 
     if (pc->sc->strict)
         lazy->setStrict();
-    lazy->setGeneratorKind(funbox->generatorKind());
     if (funbox->usesArguments && funbox->usesApply)
         lazy->setUsesArgumentsAndApply();
     PropagateTransitiveParseFlags(funbox, lazy);
 
     fun->initLazyScript(lazy);
     return true;
 }
 
 template <>
 bool
 Parser<FullParseHandler>::functionArgsAndBody(ParseNode *pn, HandleFunction fun,
                                               FunctionType type, FunctionSyntaxKind kind,
-                                              GeneratorKind generatorKind,
                                               Directives inheritedDirectives,
                                               Directives *newDirectives)
 {
     ParseContext<FullParseHandler> *outerpc = pc;
 
     // Create box for fun->object early to protect against last-ditch GC.
-    FunctionBox *funbox = newFunctionBox(pn, fun, pc, inheritedDirectives, generatorKind);
+    FunctionBox *funbox = newFunctionBox(pn, fun, pc, inheritedDirectives);
     if (!funbox)
         return false;
 
     // Try a syntax parse for this inner function.
     do {
         Parser<SyntaxParseHandler> *parser = handler.syntaxParser;
         if (!parser)
             break;
@@ -2193,24 +2150,23 @@ Parser<FullParseHandler>::functionArgsAn
     PropagateTransitiveParseFlags(funbox, outerpc->sc);
     return true;
 }
 
 template <>
 bool
 Parser<SyntaxParseHandler>::functionArgsAndBody(Node pn, HandleFunction fun,
                                                 FunctionType type, FunctionSyntaxKind kind,
-                                                GeneratorKind generatorKind,
                                                 Directives inheritedDirectives,
                                                 Directives *newDirectives)
 {
     ParseContext<SyntaxParseHandler> *outerpc = pc;
 
     // Create box for fun->object early to protect against last-ditch GC.
-    FunctionBox *funbox = newFunctionBox(pn, fun, pc, inheritedDirectives, generatorKind);
+    FunctionBox *funbox = newFunctionBox(pn, fun, pc, inheritedDirectives);
     if (!funbox)
         return false;
 
     // Initialize early for possible flags mutation via destructuringExpr.
     ParseContext<SyntaxParseHandler> funpc(this, pc, handler.null(), funbox, newDirectives,
                                            outerpc->staticLevel + 1, outerpc->blockidGen);
     if (!funpc.init())
         return false;
@@ -2226,25 +2182,24 @@ Parser<SyntaxParseHandler>::functionArgs
     // not need any further parsing or processing of the inner function.
     JS_ASSERT(fun->lazyScript());
     return outerpc->innerFunctions.append(fun);
 }
 
 template <>
 ParseNode *
 Parser<FullParseHandler>::standaloneLazyFunction(HandleFunction fun, unsigned staticLevel,
-                                                 bool strict, GeneratorKind generatorKind)
+                                                 bool strict)
 {
     Node pn = handler.newFunctionDefinition();
     if (!pn)
         return null();
 
     Directives directives(/* strict = */ strict);
-    FunctionBox *funbox = newFunctionBox(pn, fun, /* outerpc = */ NULL, directives,
-                                         generatorKind);
+    FunctionBox *funbox = newFunctionBox(pn, fun, /* outerpc = */ NULL, directives);
     if (!funbox)
         return null();
 
     Directives newDirectives = directives;
     ParseContext<FullParseHandler> funpc(this, /* parent = */ NULL, pn, funbox,
                                          &newDirectives, staticLevel, /* bodyid = */ 0);
     if (!funpc.init())
         return null();
@@ -2308,20 +2263,16 @@ Parser<ParseHandler>::functionArgsAndBod
     if (kind == Arrow && !tokenStream.matchToken(TOK_ARROW)) {
         report(ParseError, false, null(), JSMSG_BAD_ARROW_ARGS);
         return false;
     }
 
     // Parse the function body.
     FunctionBodyType bodyType = StatementListBody;
     if (tokenStream.getToken(TokenStream::Operand) != TOK_LC) {
-        if (funbox->isStarGenerator()) {
-            report(ParseError, false, null(), JSMSG_CURLY_BEFORE_BODY);
-            return false;
-        }
         tokenStream.ungetToken();
         bodyType = ExpressionBody;
         fun->setIsExprClosure();
     }
 
     Node body = functionBody(kind, bodyType);
     if (!body)
         return false;
@@ -2349,17 +2300,17 @@ Parser<ParseHandler>::functionArgsAndBod
 
     return finishFunctionDefinition(pn, funbox, prelude, body);
 }
 
 template <>
 ParseNode *
 Parser<FullParseHandler>::moduleDecl()
 {
-    JS_ASSERT(tokenStream.currentName() == context->names().module);
+    JS_ASSERT(tokenStream.currentToken().name() == context->names().module);
     if (!((pc->sc->isGlobalSharedContext() || pc->sc->isModuleBox()) && pc->atBodyLevel()))
     {
         report(ParseError, false, NULL, JSMSG_MODULE_STATEMENT);
         return NULL;
     }
 
     ParseNode *pn = CodeNode::create(PNK_MODULE, &handler);
     if (!pn)
@@ -2392,92 +2343,54 @@ template <>
 SyntaxParseHandler::Node
 Parser<SyntaxParseHandler>::moduleDecl()
 {
     JS_ALWAYS_FALSE(abortIfSyntaxParser());
     return SyntaxParseHandler::NodeFailure;
 }
 
 template <typename ParseHandler>
-bool
-Parser<ParseHandler>::checkYieldNameValidity(unsigned errorNumber)
-{
-    // In star generators and in JS >= 1.7, yield is a keyword.
-    if (pc->isStarGenerator() || versionNumber() >= JSVERSION_1_7) {
-        report(ParseError, false, null(), errorNumber);
-        return false;
-    }
-    // Otherwise in strict mode, yield is a future reserved word.
-    if (pc->sc->strict) {
-        report(ParseError, false, null(), JSMSG_RESERVED_ID, "yield");
-        return false;
-    }
-    return true;
-}
-
-template <typename ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::functionStmt()
 {
-    JS_ASSERT(tokenStream.isCurrentTokenType(TOK_FUNCTION));
+    JS_ASSERT(tokenStream.currentToken().type == TOK_FUNCTION);
 
     TokenStream::Position start(keepAtoms);
     tokenStream.tell(&start);
 
     RootedPropertyName name(context);
-    GeneratorKind generatorKind = NotGenerator;
-    TokenKind tt = tokenStream.getToken(TokenStream::KeywordIsName);
-
-    if (tt == TOK_MUL) {
-        tokenStream.tell(&start);
-        tt = tokenStream.getToken(TokenStream::KeywordIsName);
-        generatorKind = StarGenerator;
-    }
-
-    if (tt == TOK_NAME) {
-        name = tokenStream.currentName();
+    if (tokenStream.getToken(TokenStream::KeywordIsName) == TOK_NAME) {
+        name = tokenStream.currentToken().name();
     } else {
         /* Unnamed function expressions are forbidden in statement context. */
         report(ParseError, false, null(), JSMSG_UNNAMED_FUNCTION_STMT);
         return null();
     }
 
     /* We forbid function statements in strict mode code. */
     if (!pc->atBodyLevel() && pc->sc->needStrictChecks() &&
         !report(ParseStrictError, pc->sc->strict, null(), JSMSG_STRICT_FUNCTION_STATEMENT))
         return null();
 
-    return functionDef(name, start, Normal, Statement, generatorKind);
+    return functionDef(name, start, Normal, Statement);
 }
 
 template <typename ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::functionExpr()
 {
-    JS_ASSERT(tokenStream.isCurrentTokenType(TOK_FUNCTION));
-
+    RootedPropertyName name(context);
+    JS_ASSERT(tokenStream.currentToken().type == TOK_FUNCTION);
     TokenStream::Position start(keepAtoms);
     tokenStream.tell(&start);
-
-    RootedPropertyName name(context);
-    GeneratorKind generatorKind = NotGenerator;
-    TokenKind tt = tokenStream.getToken(TokenStream::KeywordIsName);
-
-    if (tt == TOK_MUL) {
-        tokenStream.tell(&start);
-        tt = tokenStream.getToken(TokenStream::KeywordIsName);
-        generatorKind = StarGenerator;
-    }
-
-    if (tt == TOK_NAME)
-        name = tokenStream.currentName();
+    if (tokenStream.getToken(TokenStream::KeywordIsName) == TOK_NAME)
+        name = tokenStream.currentToken().name();
     else
         tokenStream.ungetToken();
-
-    return functionDef(name, start, Normal, Expression, generatorKind);
+    return functionDef(name, start, Normal, Expression);
 }
 
 /*
  * Return true if this node, known to be an unparenthesized string literal,
  * could be the string of a directive in a Directive Prologue. Directive
  * strings never contain escape sequences or line continuations.
  * isEscapeFreeStringLiteral, below, checks whether the node itself could be
  * a directive.
@@ -2601,17 +2514,17 @@ Parser<ParseHandler>::maybeParseDirectiv
                     if (tokenStream.sawOctalEscape()) {
                         report(ParseError, false, null(), JSMSG_DEPRECATED_OCTAL);
                         return false;
                     }
                     pc->sc->strict = true;
                 }
             }
         } else if (directive == context->names().useAsm) {
-            if (pc->sc->isFunctionBox() && !pc->isGenerator())
+            if (pc->sc->isFunctionBox())
                 return asmJS(list);
             return report(ParseWarning, false, pn, JSMSG_USE_ASM_DIRECTIVE_FAIL);
         }
     }
     return true;
 }
 
 /*
@@ -2683,31 +2596,25 @@ Parser<ParseHandler>::condition()
     if (handler.isOperationWithoutParens(pn, PNK_ASSIGN) &&
         !report(ParseExtraWarning, false, null(), JSMSG_EQUAL_AS_ASSIGN))
     {
         return null();
     }
     return pn;
 }
 
-template <typename ParseHandler>
-bool
-Parser<ParseHandler>::matchLabel(MutableHandle<PropertyName*> label)
+static bool
+MatchLabel(TokenStream &ts, MutableHandlePropertyName label)
 {
-    TokenKind tt = tokenStream.peekTokenSameLine(TokenStream::Operand);
+    TokenKind tt = ts.peekTokenSameLine(TokenStream::Operand);
     if (tt == TOK_ERROR)
         return false;
     if (tt == TOK_NAME) {
-        tokenStream.consumeKnownToken(TOK_NAME);
-        label.set(tokenStream.currentName());
-    } else if (tt == TOK_YIELD) {
-        tokenStream.consumeKnownToken(TOK_YIELD);
-        if (!checkYieldNameValidity())
-            return false;
-        label.set(tokenStream.currentName());
+        (void) ts.getToken();
+        label.set(ts.currentToken().name());
     } else {
         label.set(NULL);
     }
     return true;
 }
 
 template <typename ParseHandler>
 bool
@@ -3323,17 +3230,17 @@ Parser<SyntaxParseHandler>::pushLetScope
  * Parse a let block statement or let expression (determined by 'letContext').
  * In both cases, bindings are not hoisted to the top of the enclosing block
  * and thus must be carefully injected between variables() and the let body.
  */
 template <typename ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::letBlock(LetContext letContext)
 {
-    JS_ASSERT(tokenStream.isCurrentTokenType(TOK_LET));
+    JS_ASSERT(tokenStream.currentToken().type == TOK_LET);
 
     RootedStaticBlockObject blockObj(context, StaticBlockObject::create(context));
     if (!blockObj)
         return null();
 
     uint32_t begin = pos().begin;
 
     MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_LET);
@@ -3413,17 +3320,17 @@ PushBlocklikeStatement(StmtInfoPC *stmt,
     PushStatementPC(pc, stmt, type);
     return GenerateBlockId(pc, stmt->blockid);
 }
 
 template <typename ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::blockStatement()
 {
-    JS_ASSERT(tokenStream.isCurrentTokenType(TOK_LC));
+    JS_ASSERT(tokenStream.currentToken().type == TOK_LC);
 
     StmtInfoPC stmtInfo(context);
     if (!PushBlocklikeStatement(&stmtInfo, STMT_BLOCK, pc))
         return null();
 
     Node list = statements();
     if (!list)
         return null();
@@ -3455,16 +3362,17 @@ Parser<ParseHandler>::newBindingNode(Pro
                 pc->lexdeps->remove(p);
                 handler.setPosition(pn, pos());
                 return pn;
             }
         }
     }
 
     /* Make a new node for this declarator name (or destructuring pattern). */
+    JS_ASSERT(tokenStream.currentToken().type == TOK_NAME);
     return newName(name);
 }
 
 /*
  * The 'blockObj' parameter is non-null when parsing the 'vars' in a let
  * expression, block statement, non-top-level let declaration in statement
  * context, and the let-initializer of a for-statement.
  */
@@ -3543,27 +3451,22 @@ Parser<ParseHandler>::variables(ParseNod
             if (!pn2)
                 return null();
             handler.addList(pn, pn2);
             continue;
         }
 #endif /* JS_HAS_DESTRUCTURING */
 
         if (tt != TOK_NAME) {
-            if (tt == TOK_YIELD) {
-                if (!checkYieldNameValidity(JSMSG_NO_VARIABLE_NAME))
-                    return null();
-            } else {
-                if (tt != TOK_ERROR)
-                    report(ParseError, false, null(), JSMSG_NO_VARIABLE_NAME);
-                return null();
-            }
+            if (tt != TOK_ERROR)
+                report(ParseError, false, null(), JSMSG_NO_VARIABLE_NAME);
+            return null();
         }
 
-        RootedPropertyName name(context, tokenStream.currentName());
+        RootedPropertyName name(context, tokenStream.currentToken().name());
         pn2 = newBindingNode(name, kind == PNK_VAR || kind == PNK_CONST, varContext);
         if (!pn2)
             return null();
         if (data.op == JSOP_DEFCONST)
             handler.setFlag(pn2, PND_CONST);
         data.pn = pn2;
         if (!data.binder(&data, name, this))
             return null();
@@ -4210,24 +4113,19 @@ Parser<SyntaxParseHandler>::forStatement
      * the types of 'for' statements likely to be seen in web content.
      */
     JS_ASSERT(tokenStream.isCurrentTokenType(TOK_FOR));
 
     StmtInfoPC forStmt(context);
     PushStatementPC(pc, &forStmt, STMT_FOR_LOOP);
 
     /* Don't parse 'for each' loops. */
-    if (allowsForEachIn()) {
-        TokenKind tt = tokenStream.peekToken();
-        // Not all "yield" tokens are names, but the ones that aren't names are
-        // invalid in this context anyway.
-        if (tt == TOK_NAME || tt == TOK_YIELD) {
-            JS_ALWAYS_FALSE(abortIfSyntaxParser());
-            return null();
-        }
+    if (allowsForEachIn() && tokenStream.peekToken() == TOK_NAME) {
+        JS_ALWAYS_FALSE(abortIfSyntaxParser());
+        return null();
     }
 
     MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_AFTER_FOR);
 
     /* True if we have 'for (var ...)'. */
     bool isForDecl = false;
     bool simpleForDecl = true;
 
@@ -4419,17 +4317,17 @@ Parser<ParseHandler>::switchStatement()
 template <typename ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::continueStatement()
 {
     JS_ASSERT(tokenStream.isCurrentTokenType(TOK_CONTINUE));
     uint32_t begin = pos().begin;
 
     RootedPropertyName label(context);
-    if (!matchLabel(&label))
+    if (!MatchLabel(tokenStream, &label))
         return null();
 
     StmtInfoPC *stmt = pc->topStmt;
     if (label) {
         for (StmtInfoPC *stmt2 = NULL; ; stmt = stmt->down) {
             if (!stmt) {
                 report(ParseError, false, null(), JSMSG_LABEL_NOT_FOUND);
                 return null();
@@ -4466,17 +4364,17 @@ Parser<ParseHandler>::continueStatement(
 template <typename ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::breakStatement()
 {
     JS_ASSERT(tokenStream.isCurrentTokenType(TOK_BREAK));
     uint32_t begin = pos().begin;
 
     RootedPropertyName label(context);
-    if (!matchLabel(&label))
+    if (!MatchLabel(tokenStream, &label))
         return null();
     StmtInfoPC *stmt = pc->topStmt;
     if (label) {
         for (; ; stmt = stmt->down) {
             if (!stmt) {
                 report(ParseError, false, null(), JSMSG_LABEL_NOT_FOUND);
                 return null();
             }
@@ -4497,164 +4395,118 @@ Parser<ParseHandler>::breakStatement()
     if (!MatchOrInsertSemicolon(tokenStream))
         return null();
 
     return handler.newBreakStatement(label, TokenPos(begin, pos().end));
 }
 
 template <typename ParseHandler>
 typename ParseHandler::Node
-Parser<ParseHandler>::returnStatement()
+Parser<ParseHandler>::returnStatementOrYieldExpression()
 {
-    JS_ASSERT(tokenStream.isCurrentTokenType(TOK_RETURN));
+    JS_ASSERT(tokenStream.isCurrentTokenType(TOK_RETURN) ||
+              tokenStream.isCurrentTokenType(TOK_YIELD));
+    bool isYield = tokenStream.isCurrentTokenType(TOK_YIELD);
     uint32_t begin = pos().begin;
 
     if (!pc->sc->isFunctionBox()) {
-        report(ParseError, false, null(), JSMSG_BAD_RETURN_OR_YIELD, js_return_str);
+        report(ParseError, false, null(), JSMSG_BAD_RETURN_OR_YIELD,
+               isYield ? js_yield_str : js_return_str);
         return null();
     }
 
+    // Legacy generators are identified by the presence of "yield" in their
+    // bodies.  We only see "yield" as TOK_YIELD in JS 1.7+.
+    if (isYield) {
+        JS_ASSERT(tokenStream.versionNumber() >= JSVERSION_1_7);
+        if (!abortIfSyntaxParser())
+            return null();
+
+        if (pc->isLegacyGenerator()) {
+            // We are in a legacy generator: a function that has already seen a
+            // yield.
+            JS_ASSERT(pc->sc->isFunctionBox());
+            JS_ASSERT(pc->lastYieldOffset != ParseContext<ParseHandler>::NoYieldOffset);
+        } else {
+            // We are in a code that has not seen a yield, and in JS 1.8 so
+            // "yield" parsed as TOK_YIELD.  Try to transition to being a legacy
+            // generator.
+            JS_ASSERT(tokenStream.currentToken().type == TOK_YIELD);
+            JS_ASSERT(pc->lastYieldOffset == ParseContext<ParseHandler>::NoYieldOffset);
+
+            if (!pc->sc->isFunctionBox()) {
+                report(ParseError, false, null(), JSMSG_BAD_RETURN_OR_YIELD, js_yield_str);
+                return null();
+            }
+
+            pc->generatorParseMode = ParseContext<ParseHandler>::LegacyGenerator;
+        }
+
+        pc->lastYieldOffset = begin;
+    }
+
     // Parse an optional operand.
     //
-    // This is ugly, but we don't want to require a semicolon.
+    // Checking whether yield has an operand is especially wonky since
+    // there is not a mandatory semicolon.
+    //
+    // ES6 does not permit yield without an operand. We will have to sunset
+    // this extension in order to conform to the ES6 syntax, which treats
+    // "yield \n expr;" as a single ExpressionStatement.
     Node exprNode;
-    switch (tokenStream.peekTokenSameLine(TokenStream::Operand)) {
-      case TOK_ERROR:
+    TokenKind next = tokenStream.peekTokenSameLine(TokenStream::Operand);
+    if (next == TOK_ERROR)
         return null();
-      case TOK_EOF:
-      case TOK_EOL:
-      case TOK_SEMI:
-      case TOK_RC:
+    if (next == TOK_EOF || next == TOK_EOL || next == TOK_SEMI || next == TOK_RC ||
+        (isYield && (next == TOK_RB || next == TOK_RP || next == TOK_COLON || next == TOK_COMMA)))
+    {
+        if (isYield) {
+            if (!reportWithOffset(ParseWarning, false, pos().begin, JSMSG_YIELD_WITHOUT_OPERAND))
+                return null();
+        }
+
         exprNode = null();
-        pc->funHasReturnVoid = true;
-        break;
-      default: {
-        exprNode = expr();
+        if (!isYield)
+            pc->funHasReturnVoid = true;
+    } else {
+        exprNode = isYield ? assignExpr() : expr();
         if (!exprNode)
             return null();
-        pc->funHasReturnExpr = true;
-      }
+        if (!isYield)
+            pc->funHasReturnExpr = true;
     }
 
-    if (!MatchOrInsertSemicolon(tokenStream))
-        return null();
-
-    Node pn = handler.newReturnStatement(exprNode, TokenPos(begin, pos().end));
+    if (!isYield) {
+        if (!MatchOrInsertSemicolon(tokenStream))
+            return null();
+    }
+
+    Node pn = isYield
+              ? handler.newUnary(PNK_YIELD, JSOP_YIELD, begin, exprNode)
+              : handler.newReturnStatement(exprNode, TokenPos(begin, pos().end));
     if (!pn)
         return null();
 
+    if (pc->funHasReturnExpr && pc->isLegacyGenerator()) {
+        /* As in Python (see PEP-255), disallow return v; in generators. */
+        reportBadReturn(pn, ParseError, JSMSG_BAD_GENERATOR_RETURN,
+                        JSMSG_BAD_ANON_GENERATOR_RETURN);
+        return null();
+    }
+
     if (options().extraWarningsOption && pc->funHasReturnExpr && pc->funHasReturnVoid &&
         !reportBadReturn(pn, ParseExtraWarning,
                          JSMSG_NO_RETURN_VALUE, JSMSG_ANON_NO_RETURN_VALUE))
     {
         return null();
     }
 
-    if (pc->isLegacyGenerator() && exprNode) {
-        /* Disallow "return v;" in legacy generators. */
-        reportBadReturn(pn, ParseError, JSMSG_BAD_GENERATOR_RETURN,
-                        JSMSG_BAD_ANON_GENERATOR_RETURN);
-        return null();
-    }
-
     return pn;
 }
 
-template <typename ParseHandler>
-typename ParseHandler::Node
-Parser<ParseHandler>::yieldExpression()
-{
-    JS_ASSERT(tokenStream.isCurrentTokenType(TOK_YIELD));
-    uint32_t begin = pos().begin;
-
-    switch (pc->generatorKind()) {
-      case StarGenerator:
-      {
-        JS_ASSERT(pc->sc->isFunctionBox());
-
-        pc->lastYieldOffset = begin;
-
-        bool isDelegatingYield = tokenStream.matchToken(TOK_MUL);
-
-        // ES6 generators require a value.
-        Node exprNode = assignExpr();
-        if (!exprNode)
-            return null();
-
-        // FIXME: Plumb isDelegatingYield appropriately.
-        (void) isDelegatingYield;
-        return handler.newUnary(PNK_YIELD, JSOP_YIELD, begin, exprNode);
-      }
-
-      case NotGenerator:
-        // We are in code that has not seen a yield, but we are in JS 1.7 or
-        // later.  Try to transition to being a legacy generator.
-        JS_ASSERT(tokenStream.versionNumber() >= JSVERSION_1_7);
-        JS_ASSERT(pc->lastYieldOffset == ParseContext<ParseHandler>::NoYieldOffset);
-
-        if (!abortIfSyntaxParser())
-            return null();
-
-        if (!pc->sc->isFunctionBox()) {
-            report(ParseError, false, null(), JSMSG_BAD_RETURN_OR_YIELD, js_yield_str);
-            return null();
-        }
-
-        pc->sc->asFunctionBox()->setGeneratorKind(LegacyGenerator);
-
-        if (pc->funHasReturnExpr) {
-            /* As in Python (see PEP-255), disallow return v; in generators. */
-            reportBadReturn(null(), ParseError, JSMSG_BAD_GENERATOR_RETURN,
-                            JSMSG_BAD_ANON_GENERATOR_RETURN);
-            return null();
-        }
-        // Fall through.
-
-      case LegacyGenerator:
-      {
-        // We are in a legacy generator: a function that has already seen a
-        // yield, or in a legacy generator comprehension.
-        JS_ASSERT(pc->sc->isFunctionBox());
-
-        pc->lastYieldOffset = begin;
-
-        // Legacy generators do not require a value.
-        Node exprNode;
-        switch (tokenStream.peekTokenSameLine(TokenStream::Operand)) {
-          case TOK_ERROR:
-            return null();
-          case TOK_EOF:
-          case TOK_EOL:
-          case TOK_SEMI:
-          case TOK_RC:
-          case TOK_RB:
-          case TOK_RP:
-          case TOK_COLON:
-          case TOK_COMMA:
-            // No value.
-            exprNode = null();
-            // ES6 does not permit yield without an operand.  We should
-            // encourage users of yield expressions of this kind to pass an
-            // operand, to bring users closer to standard syntax.
-            if (!reportWithOffset(ParseWarning, false, pos().begin, JSMSG_YIELD_WITHOUT_OPERAND))
-                return null();
-            break;
-          default:
-            exprNode = assignExpr();
-            if (!exprNode)
-                return null();
-        }
-
-        return handler.newUnary(PNK_YIELD, JSOP_YIELD, begin, exprNode);
-      }
-    }
-
-    MOZ_ASSUME_UNREACHABLE("yieldExpr");
-}
-
 template <>
 ParseNode *
 Parser<FullParseHandler>::withStatement()
 {
     // test262/ch12/12.10/12.10-0-1.js fails if we try to parse with-statements
     // in syntax-parse mode. See bug 892583.
     if (handler.syntaxParser) {
         handler.disableSyntaxParser();
@@ -4714,17 +4566,17 @@ Parser<SyntaxParseHandler>::withStatemen
     return null();
 }
 
 template <typename ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::labeledStatement()
 {
     uint32_t begin = pos().begin;
-    RootedPropertyName label(context, tokenStream.currentName());
+    RootedPropertyName label(context, tokenStream.currentToken().name());
     for (StmtInfoPC *stmt = pc->topStmt; stmt; stmt = stmt->down) {
         if (stmt->type == STMT_LABEL && stmt->label == label) {
             report(ParseError, false, null(), JSMSG_DUPLICATE_LABEL);
             return null();
         }
     }
 
     tokenStream.consumeKnownToken(TOK_COLON);
@@ -4855,23 +4707,19 @@ Parser<ParseHandler>::tryStatement()
               case TOK_LB:
               case TOK_LC:
                 catchName = destructuringExpr(&data, tt);
                 if (!catchName)
                     return null();
                 break;
 #endif
 
-              case TOK_YIELD:
-                if (!checkYieldNameValidity(JSMSG_CATCH_IDENTIFIER))
-                    return null();
-                // Fall through.
               case TOK_NAME:
               {
-                RootedPropertyName label(context, tokenStream.currentName());
+                RootedPropertyName label(context, tokenStream.currentToken().name());
                 catchName = newBindingNode(label, false);
                 if (!catchName)
                     return null();
                 data.pn = catchName;
                 if (!data.binder(&data, label, this))
                     return null();
                 break;
               }
@@ -4997,17 +4845,17 @@ Parser<ParseHandler>::statement(bool can
         return forStatement();
       case TOK_SWITCH:
         return switchStatement();
       case TOK_CONTINUE:
         return continueStatement();
       case TOK_BREAK:
         return breakStatement();
       case TOK_RETURN:
-        return returnStatement();
+        return returnStatementOrYieldExpression();
       case TOK_WITH:
         return withStatement();
       case TOK_THROW:
         return throwStatement();
       case TOK_TRY:
         return tryStatement();
       case TOK_FUNCTION:
         return functionStmt();
@@ -5028,28 +4876,20 @@ Parser<ParseHandler>::statement(bool can
 
       case TOK_STRING:
         if (!canHaveDirectives && tokenStream.currentToken().atom() == context->names().useAsm) {
             if (!report(ParseWarning, false, null(), JSMSG_USE_ASM_DIRECTIVE_FAIL))
                 return null();
         }
         return expressionStatement();
 
-      case TOK_YIELD:
-        if (tokenStream.peekToken() == TOK_COLON) {
-            if (!checkYieldNameValidity())
-                return null();
-            return labeledStatement();
-        }
-        return expressionStatement();
-
       case TOK_NAME:
         if (tokenStream.peekToken() == TOK_COLON)
             return labeledStatement();
-        if (tokenStream.currentName() == context->names().module
+        if (tokenStream.currentToken().name() == context->names().module
             && tokenStream.peekTokenSameLine() == TOK_STRING)
         {
             return moduleDecl();
         }
         return expressionStatement();
 
       default:
         return expressionStatement();
@@ -5352,18 +5192,18 @@ Parser<ParseHandler>::assignExpr()
         return identifierName();
 
     if (tt == TOK_NUMBER && tokenStream.nextTokenEndsExpr())
         return newNumber(tokenStream.currentToken());
 
     if (tt == TOK_STRING && tokenStream.nextTokenEndsExpr())
         return stringLiteral();
 
-    if (tt == TOK_YIELD && (versionNumber() >= JSVERSION_1_7 || pc->isGenerator()))
-        return yieldExpression();
+    if (tt == TOK_YIELD)
+        return returnStatementOrYieldExpression();
 
     tokenStream.ungetToken();
 
     // Save the tokenizer state in case we find an arrow function and have to
     // rewind.
     TokenStream::Position start(keepAtoms);
     tokenStream.tell(&start);
 
@@ -5391,17 +5231,17 @@ Parser<ParseHandler>::assignExpr()
         tokenStream.seek(start);
         if (!abortIfSyntaxParser())
             return null();
 
         if (tokenStream.getToken() == TOK_ERROR)
             return null();
         tokenStream.ungetToken();
 
-        return functionDef(NullPtr(), start, Normal, Arrow, NotGenerator);
+        return functionDef(NullPtr(), start, Normal, Arrow);
       }
 
       default:
         JS_ASSERT(!tokenStream.isCurrentTokenAssignment());
         tokenStream.ungetToken();
         return lhs;
     }
 
@@ -5812,17 +5652,17 @@ Parser<FullParseHandler>::comprehensionT
     }
 
     unsigned adjust;
     ParseNode *pn, *pn2, *pn3, **pnp;
     StmtInfoPC stmtInfo(context);
     BindData<FullParseHandler> data(context);
     TokenKind tt;
 
-    JS_ASSERT(tokenStream.isCurrentTokenType(TOK_FOR));
+    JS_ASSERT(tokenStream.currentToken().type == TOK_FOR);
 
     if (kind == PNK_SEMI) {
         /*
          * Generator expression desugars to an immediately applied lambda that
          * yields the next value from a for-in loop (possibly nested, and with
          * optional if guard). Make pn be the TOK_LC body node.
          */
         pn = pushLexicalScope(&stmtInfo);
@@ -5897,17 +5737,17 @@ Parser<FullParseHandler>::comprehensionT
             pn3 = primaryExpr(tt);
             pc->inDeclDestructuring = false;
             if (!pn3)
                 return null();
             break;
 #endif
 
           case TOK_NAME:
-            name = tokenStream.currentName();
+            name = tokenStream.currentToken().name();
 
             /*
              * Create a name node with pn_op JSOP_NAME.  We can't set pn_op to
              * JSOP_GETLOCAL here, because we don't yet know the block's depth
              * in the operand stack frame.  The code generator computes that,
              * and it tries to bind all names to slots, so we must let it do
              * the deed.
              */
@@ -6105,18 +5945,17 @@ Parser<FullParseHandler>::generatorExpr(
         ParseContext<FullParseHandler> *outerpc = pc;
 
         RootedFunction fun(context, newFunction(outerpc, /* atom = */ NullPtr(), Expression));
         if (!fun)
             return null();
 
         /* Create box for fun->object early to protect against last-ditch GC. */
         Directives directives(/* strict = */ outerpc->sc->strict);
-        FunctionBox *genFunbox = newFunctionBox(genfn, fun, outerpc, directives,
-                                                LegacyGenerator);
+        FunctionBox *genFunbox = newFunctionBox(genfn, fun, outerpc, directives);
         if (!genFunbox)
             return null();
 
         ParseContext<FullParseHandler> genpc(this, outerpc, genfn, genFunbox,
                                              /* newDirectives = */ NULL, outerpc->staticLevel + 1,
                                              outerpc->blockidGen);
         if (!genpc.init())
             return null();
@@ -6126,17 +5965,17 @@ Parser<FullParseHandler>::generatorExpr(
          * come from the kid. So we propagate these flags into genfn. For code
          * simplicity we also do not detect if the flags were only set in the
          * kid and could be removed from pc->sc.
          */
         genFunbox->anyCxFlags = outerpc->sc->anyCxFlags;
         if (outerpc->sc->isFunctionBox())
             genFunbox->funCxFlags = outerpc->sc->asFunctionBox()->funCxFlags;
 
-        JS_ASSERT(genFunbox->isLegacyGenerator());
+        genFunbox->setIsLegacyGenerator();
         genFunbox->inGenexpLambda = true;
         genfn->pn_blockid = genpc.bodyid;
 
         ParseNode *body = comprehensionTail(pn, outerpc->blockid(), true, outerpc);
         if (!body)
             return null();
         JS_ASSERT(!genfn->pn_body);
         genfn->pn_body = body;
@@ -6267,17 +6106,17 @@ Parser<ParseHandler>::memberExpr(TokenKi
 
     while ((tt = tokenStream.getToken()) > TOK_EOF) {
         Node nextMember;
         if (tt == TOK_DOT) {
             tt = tokenStream.getToken(TokenStream::KeywordIsName);
             if (tt == TOK_ERROR)
                 return null();
             if (tt == TOK_NAME) {
-                PropertyName *field = tokenStream.currentName();
+                PropertyName *field = tokenStream.currentToken().name();
                 nextMember = handler.newPropertyAccess(lhs, field, pos().end);
                 if (!nextMember)
                     return null();
             } else {
                 report(ParseError, false, null(), JSMSG_NAME_AFTER_DOT);
                 return null();
             }
         } else if (tt == TOK_LB) {
@@ -6342,17 +6181,19 @@ Parser<ParseHandler>::newName(PropertyNa
 {
     return handler.newName(name, pc->blockid(), pos());
 }
 
 template <typename ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::identifierName()
 {
-    RootedPropertyName name(context, tokenStream.currentName());
+    JS_ASSERT(tokenStream.isCurrentTokenType(TOK_NAME));
+
+    RootedPropertyName name(context, tokenStream.currentToken().name());
     Node pn = newName(name);
     if (!pn)
         return null();
 
     if (!pc->inDeclDestructuring && !noteNameUse(name, pn))
         return null();
 
     return pn;
@@ -6556,31 +6397,31 @@ Parser<ParseHandler>::primaryExpr(TokenK
                 tmp = DoubleValue(tokenStream.currentToken().number());
                 atom = ToAtom<CanGC>(context, HandleValue::fromMarkedLocation(&tmp));
                 if (!atom)
                     return null();
                 pn3 = newNumber(tokenStream.currentToken());
                 break;
               case TOK_NAME:
                 {
-                    atom = tokenStream.currentName();
+                    atom = tokenStream.currentToken().name();
                     if (atom == context->names().get) {
                         op = JSOP_INITPROP_GETTER;
                     } else if (atom == context->names().set) {
                         op = JSOP_INITPROP_SETTER;
                     } else {
                         pn3 = handler.newIdentifier(atom, pos());
                         if (!pn3)
                             return null();
                         break;
                     }
 
                     tt = tokenStream.getToken(TokenStream::KeywordIsName);
                     if (tt == TOK_NAME) {
-                        atom = tokenStream.currentName();
+                        atom = tokenStream.currentToken().name();
                         pn3 = newName(atom->asPropertyName());
                         if (!pn3)
                             return null();
                     } else if (tt == TOK_STRING) {
                         atom = tokenStream.currentToken().atom();
 
                         uint32_t index;
                         if (atom->isIndex(&index)) {
@@ -6617,17 +6458,17 @@ Parser<ParseHandler>::primaryExpr(TokenK
 
                     handler.setListFlag(pn, PNX_NONCONST);
 
                     /* NB: Getter function in { get x(){} } is unnamed. */
                     Rooted<PropertyName*> funName(context, NULL);
                     TokenStream::Position start(keepAtoms);
                     tokenStream.tell(&start);
                     pn2 = functionDef(funName, start, op == JSOP_INITPROP_GETTER ? Getter : Setter,
-                                      Expression, NotGenerator);
+                                      Expression);
                     if (!pn2)
                         return null();
                     pn2 = handler.newBinary(PNK_COLON, pn3, pn2, op);
                     goto skip;
                 }
               case TOK_STRING: {
                 atom = tokenStream.currentToken().atom();
                 uint32_t index;
@@ -6773,20 +6614,16 @@ Parser<ParseHandler>::primaryExpr(TokenK
         if (!genexp)
             MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_IN_PAREN);
         return pn;
       }
 
       case TOK_STRING:
         return stringLiteral();
 
-      case TOK_YIELD:
-        if (!checkYieldNameValidity())
-            return null();
-        // Fall through.
       case TOK_NAME:
         return identifierName();
 
       case TOK_REGEXP:
         return newRegExp();
 
       case TOK_NUMBER:
         return newNumber(tokenStream.currentToken());
@@ -6838,17 +6675,17 @@ Parser<ParseHandler>::primaryExpr(TokenK
         return null();
     }
 }
 
 template <typename ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::parenExpr(bool *genexp)
 {
-    JS_ASSERT(tokenStream.isCurrentTokenType(TOK_LP));
+    JS_ASSERT(tokenStream.currentToken().type == TOK_LP);
     uint32_t begin = pos().begin;
 
     if (genexp)
         *genexp = false;
 
     uint32_t startYieldOffset = pc->lastYieldOffset;
 
     /*
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -99,30 +99,28 @@ struct ParseContext : public GenericPars
     StmtInfoPC      *topStmt;       /* top of statement info stack */
     StmtInfoPC      *topScopeStmt;  /* top lexical scope statement */
     Rooted<StaticBlockObject *> blockChain;
                                     /* compile time block scope chain */
     Node            maybeFunction;  /* sc->isFunctionBox, the pn where pn->pn_funbox == sc */
 
     const unsigned  staticLevel;    /* static compilation unit nesting level */
 
+    // Functions start off being parsed as NotGenerator.
+    // NotGenerator transitions to LegacyGenerator on parsing "yield" in JS 1.7.
+    enum GeneratorParseMode { NotGenerator, LegacyGenerator };
+    GeneratorParseMode generatorParseMode;
+
     // lastYieldOffset stores the offset of the last yield that was parsed.
     // NoYieldOffset is its initial value.
     static const uint32_t NoYieldOffset = UINT32_MAX;
     uint32_t         lastYieldOffset;
 
-    // Most functions start off being parsed as non-generators.
-    // Non-generators transition to LegacyGenerator on parsing "yield" in JS 1.7.
-    // An ES6 generator is marked as a "star generator" before its body is parsed.
-    GeneratorKind generatorKind() const {
-        return sc->isFunctionBox() ? sc->asFunctionBox()->generatorKind() : NotGenerator;
-    }
-    bool isGenerator() const { return generatorKind() != NotGenerator; }
-    bool isLegacyGenerator() const { return generatorKind() == LegacyGenerator; }
-    bool isStarGenerator() const { return generatorKind() == StarGenerator; }
+    bool isGenerator() const { return generatorParseMode != NotGenerator; }
+    bool isLegacyGenerator() const { return generatorParseMode == LegacyGenerator; }
 
     Node            blockNode;      /* parse node for a block with let declarations
                                        (block with its own lexical scope)  */
   private:
     AtomDecls<ParseHandler> decls_; /* function, const, and var declarations */
     DeclVector      args_;          /* argument definitions */
     DeclVector      vars_;          /* var/const definitions */
 
@@ -246,16 +244,17 @@ struct ParseContext : public GenericPars
       : GenericParseContext(parent, sc),
         bodyid(0),           // initialized in init()
         blockidGen(bodyid),  // used to set |bodyid| and subsequently incremented in init()
         topStmt(NULL),
         topScopeStmt(NULL),
         blockChain(prs->context),
         maybeFunction(maybeFunction),
         staticLevel(staticLevel),
+        generatorParseMode(NotGenerator),
         lastYieldOffset(NoYieldOffset),
         blockNode(ParseHandler::null()),
         decls_(prs->context, prs->alloc),
         args_(prs->context),
         vars_(prs->context),
         parserPC(&prs->pc),
         oldpc(prs->pc),
         lexdeps(prs->context),
@@ -395,17 +394,17 @@ class Parser : private AutoGCRooter, pub
 
     /*
      * Allocate a new parsed object or function container from
      * cx->tempLifoAlloc.
      */
     ObjectBox *newObjectBox(JSObject *obj);
     ModuleBox *newModuleBox(Module *module, ParseContext<ParseHandler> *pc);
     FunctionBox *newFunctionBox(Node fn, JSFunction *fun, ParseContext<ParseHandler> *pc,
-                                Directives directives, GeneratorKind generatorKind);
+                                Directives directives);
 
     /*
      * Create a new function object given parse context (pc) and a name (which
      * is optional if this is a function expression).
      */
     JSFunction *newFunction(GenericParseContext *pc, HandleAtom atom, FunctionSyntaxKind kind);
 
     void trace(JSTracer *trc);
@@ -428,26 +427,23 @@ class Parser : private AutoGCRooter, pub
     inline bool abortIfSyntaxParser();
 
   public:
 
     /* Public entry points for parsing. */
     Node statement(bool canHaveDirectives = false);
     bool maybeParseDirective(Node list, Node pn, bool *cont);
 
-    // Parse a function, given only its body. Used for the Function and
-    // Generator constructors.
+    // Parse a function, given only its body. Used for the Function constructor.
     Node standaloneFunctionBody(HandleFunction fun, const AutoNameVector &formals,
-                                GeneratorKind generatorKind,
                                 Directives inheritedDirectives, Directives *newDirectives);
 
     // Parse a function, given only its arguments and body. Used for lazily
     // parsed functions.
-    Node standaloneLazyFunction(HandleFunction fun, unsigned staticLevel, bool strict,
-                                GeneratorKind generatorKind);
+    Node standaloneLazyFunction(HandleFunction fun, unsigned staticLevel, bool strict);
 
     /*
      * Parse a function body.  Pass StatementListBody if the body is a list of
      * statements; pass ExpressionBody if the body is a single expression.
      */
     enum FunctionBodyType { StatementListBody, ExpressionBody };
     Node functionBody(FunctionSyntaxKind kind, FunctionBodyType type);
 
@@ -485,70 +481,65 @@ class Parser : private AutoGCRooter, pub
     Node blockStatement();
     Node ifStatement();
     Node doWhileStatement();
     Node whileStatement();
     Node forStatement();
     Node switchStatement();
     Node continueStatement();
     Node breakStatement();
-    Node returnStatement();
+    Node returnStatementOrYieldExpression();
     Node withStatement();
     Node labeledStatement();
     Node throwStatement();
     Node tryStatement();
     Node debuggerStatement();
 
 #if JS_HAS_BLOCK_SCOPE
     Node letStatement();
 #endif
     Node expressionStatement();
     Node variables(ParseNodeKind kind, bool *psimple = NULL,
                    StaticBlockObject *blockObj = NULL,
                    VarContext varContext = HoistVars);
     Node expr();
     Node assignExpr();
     Node assignExprWithoutYield(unsigned err);
-    Node yieldExpression();
     Node condExpr1();
     Node orExpr1();
     Node unaryExpr();
     Node memberExpr(TokenKind tt, bool allowCallSyntax);
     Node primaryExpr(TokenKind tt);
     Node parenExpr(bool *genexp = NULL);
 
     /*
      * Additional JS parsers.
      */
     bool functionArguments(FunctionSyntaxKind kind, Node *list, Node funcpn, bool &hasRest);
 
     Node functionDef(HandlePropertyName name, const TokenStream::Position &start,
-                     FunctionType type, FunctionSyntaxKind kind, GeneratorKind generatorKind);
+                     FunctionType type, FunctionSyntaxKind kind);
     bool functionArgsAndBody(Node pn, HandleFunction fun,
                              FunctionType type, FunctionSyntaxKind kind,
-                             GeneratorKind generatorKind,
                              Directives inheritedDirectives, Directives *newDirectives);
 
     Node unaryOpExpr(ParseNodeKind kind, JSOp op, uint32_t begin);
 
     Node condition();
     Node comprehensionTail(Node kid, unsigned blockid, bool isGenexp,
                            ParseContext<ParseHandler> *outerpc,
                            ParseNodeKind kind = PNK_SEMI, JSOp op = JSOP_NOP);
     bool arrayInitializerComprehensionTail(Node pn);
     Node generatorExpr(Node kid);
     bool argumentList(Node listNode);
     Node letBlock(LetContext letContext);
     Node destructuringExpr(BindData<ParseHandler> *data, TokenKind tt);
 
     Node identifierName();
 
-    bool matchLabel(MutableHandle<PropertyName*> label);
-    bool checkYieldNameValidity(unsigned errorNumber = JSMSG_SYNTAX_ERROR);
-
     bool allowsForEachIn() {
 #if !JS_HAS_FOR_EACH_IN
         return false;
 #else
         return versionNumber() >= JSVERSION_1_6;
 #endif
     }
 
@@ -559,17 +550,16 @@ class Parser : private AutoGCRooter, pub
         IncDecAssignment
     };
 
     bool checkAndMarkAsAssignmentLhs(Node pn, AssignmentFlavor flavor);
     bool matchInOrOf(bool *isForOfp);
 
     bool checkFunctionArguments();
     bool makeDefIntoUse(Definition *dn, Node pn, JSAtom *atom);
-    bool checkFunctionName(HandlePropertyName funName);
     bool checkFunctionDefinition(HandlePropertyName funName, Node *pn, FunctionSyntaxKind kind,
                                  bool *pbodyProcessed);
     bool finishFunctionDefinition(Node pn, FunctionBox *funbox, Node prelude, Node body);
     bool addFreeVariablesFromLazyFunction(JSFunction *fun, ParseContext<ParseHandler> *pc);
 
     bool isValidForStatementLHS(Node pn1, JSVersion version,
                                 bool forDecl, bool forEach, bool forOf);
     bool checkAndMarkAsIncOperand(Node kid, TokenKind tt, bool preorder);
--- a/js/src/frontend/SharedContext.h
+++ b/js/src/frontend/SharedContext.h
@@ -67,16 +67,20 @@ class AnyContextFlags
     { }
 };
 
 class FunctionContextFlags
 {
     // This class's data is all private and so only visible to these friends.
     friend class FunctionBox;
 
+    // We parsed a yield statement in the function, which can happen in JS1.7+
+    // mode.
+    bool isLegacyGenerator:1;
+
     // The function or a function that encloses it may define new local names
     // at runtime through means other than calling eval.
     bool mightAliasLocals:1;
 
     // This function does something that can extend the set of bindings in its
     // call objects --- it does a direct eval in non-strict code, or includes a
     // function statement (as opposed to a function definition).
     //
@@ -120,17 +124,18 @@ class FunctionContextFlags
     // dataflow analysis only looks at how JSOP_ARGUMENTS is used, so it will
     // be unsound in several cases. The frontend filters out such cases by
     // setting this flag which eagerly sets script->needsArgsObj to true.
     //
     bool definitelyNeedsArgsObj:1;
 
   public:
     FunctionContextFlags()
-     :  mightAliasLocals(false),
+     :  isLegacyGenerator(false),
+        mightAliasLocals(false),
         hasExtensibleScope(false),
         needsDeclEnvObject(false),
         argumentsHasLocalBinding(false),
         definitelyNeedsArgsObj(false)
     { }
 };
 
 class GlobalSharedContext;
@@ -254,57 +259,46 @@ class FunctionBox : public ObjectBox, pu
 {
   public:
     Bindings        bindings;               /* bindings for this function */
     uint32_t        bufStart;
     uint32_t        bufEnd;
     uint32_t        startLine;
     uint32_t        startColumn;
     uint16_t        ndefaults;
-
-    uint8_t         generatorKindBits_;     /* The GeneratorKind of this function. */
     bool            inWith:1;               /* some enclosing scope is a with-statement */
     bool            inGenexpLambda:1;       /* lambda from generator expression */
     bool            hasDestructuringArgs:1; /* arguments list contains destructuring expression */
     bool            useAsm:1;               /* function contains "use asm" directive */
     bool            insideUseAsm:1;         /* nested function of function of "use asm" directive */
 
     // Fields for use in heuristics.
     bool            usesArguments:1;  /* contains a free use of 'arguments' */
     bool            usesApply:1;      /* contains an f.apply() call */
 
     FunctionContextFlags funCxFlags;
 
     template <typename ParseHandler>
     FunctionBox(ExclusiveContext *cx, ObjectBox* traceListHead, JSFunction *fun,
                 ParseContext<ParseHandler> *pc, Directives directives,
-                bool extraWarnings, GeneratorKind generatorKind);
+                bool extraWarnings);
 
     ObjectBox *toObjectBox() { return this; }
     JSFunction *function() const { return &object->as<JSFunction>(); }
 
-    GeneratorKind generatorKind() const { return GeneratorKindFromBits(generatorKindBits_); }
-    bool isGenerator() const { return generatorKind() != NotGenerator; }
-    bool isLegacyGenerator() const { return generatorKind() == LegacyGenerator; }
-    bool isStarGenerator() const { return generatorKind() == StarGenerator; }
-
-    void setGeneratorKind(GeneratorKind kind) {
-        // A generator kind can be set at initialization, or when "yield" is
-        // first seen.  In both cases the transition can only happen from
-        // NotGenerator.
-        JS_ASSERT(!isGenerator());
-        generatorKindBits_ = GeneratorKindAsBits(kind);
-    }
-
+    // In the future, isGenerator will also return true for ES6 generators.
+    bool isGenerator()              const { return isLegacyGenerator(); }
+    bool isLegacyGenerator()        const { return funCxFlags.isLegacyGenerator; }
     bool mightAliasLocals()         const { return funCxFlags.mightAliasLocals; }
     bool hasExtensibleScope()       const { return funCxFlags.hasExtensibleScope; }
     bool needsDeclEnvObject()       const { return funCxFlags.needsDeclEnvObject; }
     bool argumentsHasLocalBinding() const { return funCxFlags.argumentsHasLocalBinding; }
     bool definitelyNeedsArgsObj()   const { return funCxFlags.definitelyNeedsArgsObj; }
 
+    void setIsLegacyGenerator()            { funCxFlags.isLegacyGenerator        = true; }
     void setMightAliasLocals()             { funCxFlags.mightAliasLocals         = true; }
     void setHasExtensibleScope()           { funCxFlags.hasExtensibleScope       = true; }
     void setNeedsDeclEnvObject()           { funCxFlags.needsDeclEnvObject       = true; }
     void setArgumentsHasLocalBinding()     { funCxFlags.argumentsHasLocalBinding = true; }
     void setDefinitelyNeedsArgsObj()       { JS_ASSERT(funCxFlags.argumentsHasLocalBinding);
                                              funCxFlags.definitelyNeedsArgsObj   = true; }
 
     // Return whether this function has either specified "use asm" or is
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -927,20 +927,20 @@ TokenStream::checkForKeyword(const jscha
             // Working keyword.
             if (ttp) {
                 *ttp = kw->tokentype;
                 return true;
             }
             return reportError(JSMSG_RESERVED_ID, kw->chars);
         }
 
-        // The keyword is not in this version. Treat it as an identifier, unless
-        // it is let which we treat as TOK_STRICT_RESERVED by falling through to
-        // the code below (ES5 forbids it in strict mode).
-        if (kw->tokentype != TOK_LET)
+        // The keyword is not in this version. Treat it as an identifier,
+        // unless it is let or yield which we treat as TOK_STRICT_RESERVED by
+        // falling through to the code below (ES5 forbids them in strict mode).
+        if (kw->tokentype != TOK_LET && kw->tokentype != TOK_YIELD)
             return true;
     }
 
     // Strict reserved word.
     return reportStrictModeError(JSMSG_RESERVED_ID, kw->chars);
 }
 
 enum FirstCharKind {
--- a/js/src/frontend/TokenStream.h
+++ b/js/src/frontend/TokenStream.h
@@ -402,23 +402,16 @@ class MOZ_STACK_CLASS TokenStream
     const CharBuffer &getTokenbuf() const { return tokenbuf; }
     const char *getFilename() const { return filename; }
     unsigned getLineno() const { return lineno; }
     unsigned getColumn() const { return userbuf.addressOfNextRawChar() - linebase - 1; }
     JSPrincipals *getOriginPrincipals() const { return originPrincipals; }
     JSVersion versionNumber() const { return VersionNumber(options().version); }
     JSVersion versionWithFlags() const { return options().version; }
 
-    PropertyName *currentName() const {
-        if (isCurrentTokenType(TOK_YIELD))
-            return cx->names().yield;
-        JS_ASSERT(isCurrentTokenType(TOK_NAME));
-        return currentToken().name();
-    }
-
     bool isCurrentTokenAssignment() const {
         return TokenKindIsAssignment(currentToken().type);
     }
 
     // Flag methods.
     bool isEOF() const { return flags.isEOF; }
     bool sawOctalEscape() const { return flags.sawOctalEscape; }
     bool hadError() const { return flags.hadError; }
deleted file mode 100644
--- a/js/src/jit-test/tests/generators/es6-syntax.js
+++ /dev/null
@@ -1,38 +0,0 @@
-// Test interactions between ES6 generators and not-yet-standard
-// features.
-
-function assertSyntaxError(str) {
-    var msg;
-    var evil = eval;
-    try {
-        // Non-direct eval.
-        evil(str);
-    } catch (exc) {
-        if (exc instanceof SyntaxError)
-            return;
-        msg = "Assertion failed: expected SyntaxError, got " + exc;
-    }
-    if (msg === undefined)
-        msg = "Assertion failed: expected SyntaxError, but no exception thrown";
-    throw new Error(msg + " - " + str);
-}
-
-// Destructuring binding.
-assertSyntaxError("function* f(x = yield) {}");
-assertSyntaxError("function* f(x = yield 17) {}");
-assertSyntaxError("function* f([yield]) {}");
-assertSyntaxError("function* f({ yield }) {}");
-assertSyntaxError("function* f(...yield) {}");
-
-// For each.
-assertSyntaxError("for yield");
-assertSyntaxError("for yield (;;) {}");
-assertSyntaxError("for yield (x of y) {}");
-assertSyntaxError("for yield (var i in o) {}");
-
-// Expression bodies.
-assertSyntaxError("function* f() yield 7");
-
-// Asm.js.
-load(libdir + "asm.js");
-assertAsmDirectiveFail("function* f() { 'use asm'; function g() { return 0; } return g; })()")
--- a/js/src/jit/AsmJS.cpp
+++ b/js/src/jit/AsmJS.cpp
@@ -4620,17 +4620,17 @@ ParseFunction(ModuleCompiler &m, ParseNo
                                            m.cx()->global(), name, JSFunction::FinalizeKind,
                                            TenuredObject));
     if (!fun)
         return false;
 
     AsmJSParseContext *outerpc = m.parser().pc;
 
     Directives directives(outerpc);
-    FunctionBox *funbox = m.parser().newFunctionBox(fn, fun, outerpc, directives, NotGenerator);
+    FunctionBox *funbox = m.parser().newFunctionBox(fn, fun, outerpc, directives);
     if (!funbox)
         return false;
 
     Directives newDirectives = directives;
     AsmJSParseContext funpc(&m.parser(), outerpc, fn, funbox, &newDirectives,
                             outerpc->staticLevel + 1, outerpc->blockidGen);
     if (!funpc.init())
         return false;
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -404,9 +404,8 @@ MSG_DEF(JSMSG_DEPRECATED_SOURCE_MAP,  35
 MSG_DEF(JSMSG_BAD_DESTRUCT_ASSIGN,    351, 1, JSEXN_SYNTAXERR, "can't assign to {0} using destructuring assignment")
 MSG_DEF(JSMSG_BINARYDATA_ARRAYTYPE_BAD_ARGS, 352, 0, JSEXN_ERR, "Invalid arguments")
 MSG_DEF(JSMSG_BINARYDATA_BINARYARRAY_BAD_INDEX, 353, 0, JSEXN_RANGEERR, "invalid or out-of-range index")
 MSG_DEF(JSMSG_BINARYDATA_STRUCTTYPE_BAD_ARGS, 354, 0, JSEXN_RANGEERR, "invalid field descriptor")
 MSG_DEF(JSMSG_BINARYDATA_NOT_BINARYSTRUCT,   355, 1, JSEXN_TYPEERR, "{0} is not a BinaryStruct")
 MSG_DEF(JSMSG_BINARYDATA_SUBARRAY_INTEGER_ARG, 356, 1, JSEXN_ERR, "argument {0} must be an integer")
 MSG_DEF(JSMSG_BINARYDATA_STRUCTTYPE_EMPTY_DESCRIPTOR, 357, 0, JSEXN_ERR, "field descriptor cannot be empty")
 MSG_DEF(JSMSG_BINARYDATA_STRUCTTYPE_BAD_FIELD, 358, 1, JSEXN_ERR, "field {0} is not a valid BinaryData Type descriptor")
-MSG_DEF(JSMSG_ES6_UNIMPLEMENTED,      359, 0, JSEXN_ERR, "ES6 functionality not yet implemented")
--- a/js/src/jsanalyze.cpp
+++ b/js/src/jsanalyze.cpp
@@ -1824,17 +1824,17 @@ ScriptAnalysis::needsArgsObj(JSContext *
     JS_ASSERT(script_->argumentsHasVarBinding());
 
     /*
      * Always construct arguments objects when in debug mode and for generator
      * scripts (generators can be suspended when speculation fails).
      *
      * FIXME: Don't build arguments for ES6 generator expressions.
      */
-    if (cx->compartment()->debugMode() || script_->isGenerator())
+    if (cx->compartment()->debugMode() || script_->isGenerator)
         return true;
 
     /*
      * If the script has dynamic name accesses which could reach 'arguments',
      * the parser will already have checked to ensure there are no explicit
      * uses of 'arguments' in the function. If there are such uses, the script
      * will be marked as definitely needing an arguments object.
      *
--- a/js/src/jsatom.cpp
+++ b/js/src/jsatom.cpp
@@ -99,16 +99,17 @@ const char js_static_str[]          = "s
 const char js_super_str[]           = "super";
 const char js_switch_str[]          = "switch";
 const char js_this_str[]            = "this";
 const char js_try_str[]             = "try";
 const char js_typeof_str[]          = "typeof";
 const char js_void_str[]            = "void";
 const char js_while_str[]           = "while";
 const char js_with_str[]            = "with";
+const char js_yield_str[]           = "yield";
 
 /*
  * For a browser build from 2007-08-09 after the browser starts up there are
  * just 55 double atoms, but over 15000 string atoms. Not to penalize more
  * economical embeddings allocating too much memory initially we initialize
  * atomized strings with just 1K entries.
  */
 #define JS_STRING_HASH_COUNT   1024
--- a/js/src/jsatom.h
+++ b/js/src/jsatom.h
@@ -148,16 +148,17 @@ extern const char js_static_str[];
 extern const char js_super_str[];
 extern const char js_switch_str[];
 extern const char js_this_str[];
 extern const char js_try_str[];
 extern const char js_typeof_str[];
 extern const char js_void_str[];
 extern const char js_while_str[];
 extern const char js_with_str[];
+extern const char js_yield_str[];
 
 namespace js {
 
 extern const char * const TypeStrings[];
 
 /*
  * Initialize atom state. Return true on success, false on failure to allocate
  * memory. The caller must zero rt->atomState before calling this function and
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -521,17 +521,16 @@ FindBody(JSContext *cx, HandleFunction f
     AutoKeepAtoms keepAtoms(cx->perThreadData);
     TokenStream ts(cx, options, chars.get(), length, NULL);
     int nest = 0;
     bool onward = true;
     // Skip arguments list.
     do {
         switch (ts.getToken()) {
           case TOK_NAME:
-          case TOK_YIELD:
             if (nest == 0)
                 onward = false;
             break;
           case TOK_LP:
             nest++;
             break;
           case TOK_RP:
             if (--nest == 0)
@@ -1224,17 +1223,24 @@ static bool
 fun_isGenerator(JSContext *cx, unsigned argc, Value *vp)
 {
     JSFunction *fun;
     if (!IsFunctionObject(vp[1], &fun)) {
         JS_SET_RVAL(cx, vp, BooleanValue(false));
         return true;
     }
 
-    JS_SET_RVAL(cx, vp, BooleanValue(fun->isGenerator()));
+    bool result = false;
+    if (fun->hasScript()) {
+        JSScript *script = fun->nonLazyScript();
+        JS_ASSERT(script->length != 0);
+        result = script->isGenerator;
+    }
+
+    JS_SET_RVAL(cx, vp, BooleanValue(result));
     return true;
 }
 
 /* ES5 15.3.4.5. */
 static bool
 fun_bind(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
@@ -1445,36 +1451,31 @@ js::Function(JSContext *cx, unsigned arg
                  * Check that it's a name.  This also implicitly guards against
                  * TOK_ERROR, which was already reported.
                  */
                 if (hasRest) {
                     ts.reportError(JSMSG_PARAMETER_AFTER_REST);
                     return false;
                 }
 
-                if (tt == TOK_YIELD && ts.versionNumber() < JSVERSION_1_7)
-                    tt = TOK_NAME;
-
                 if (tt != TOK_NAME) {
                     if (tt == TOK_TRIPLEDOT) {
                         hasRest = true;
                         tt = ts.getToken();
-                        if (tt == TOK_YIELD && ts.versionNumber() < JSVERSION_1_7)
-                            tt = TOK_NAME;
                         if (tt != TOK_NAME) {
                             if (tt != TOK_ERROR)
                                 ts.reportError(JSMSG_NO_REST_NAME);
                             return false;
                         }
                     } else {
                         return OnBadFormal(cx, tt);
                     }
                 }
 
-                if (!formals.append(ts.currentName()))
+                if (!formals.append(ts.currentToken().name()))
                     return false;
 
                 /*
                  * Get the next token.  Stop on end of stream.  Otherwise
                  * insist on a comma, get another name, and iterate.
                  */
                 tt = ts.getToken();
                 if (tt == TOK_EOF)
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -277,28 +277,16 @@ class JSFunction : public JSObject
         return u.i.s.lazy_;
     }
 
     js::LazyScript *lazyScriptOrNull() const {
         JS_ASSERT(isInterpretedLazy());
         return u.i.s.lazy_;
     }
 
-    js::GeneratorKind generatorKind() const {
-        if (!isInterpreted())
-            return js::NotGenerator;
-        return hasScript() ? nonLazyScript()->generatorKind() : lazyScript()->generatorKind();
-    }
-
-    bool isGenerator() const { return generatorKind() != js::NotGenerator; }
-
-    bool isLegacyGenerator() const { return generatorKind() == js::LegacyGenerator; }
-
-    bool isStarGenerator() const { return generatorKind() == js::StarGenerator; }
-
     inline void setScript(JSScript *script_);
     inline void initScript(JSScript *script_);
     void initLazyScript(js::LazyScript *lazy) {
         JS_ASSERT(isInterpreted());
         flags &= ~INTERPRETED;
         flags |= INTERPRETED_LAZY;
         u.i.s.lazy_ = lazy;
     }
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -1470,23 +1470,16 @@ Class GeneratorObject::class_ = {
  * if they are non-null.
  */
 JSObject *
 js_NewGenerator(JSContext *cx, const FrameRegs &stackRegs)
 {
     JS_ASSERT(stackRegs.stackDepth() == 0);
     StackFrame *stackfp = stackRegs.fp();
 
-    JS_ASSERT(stackfp->script()->isGenerator());
-
-    if (stackfp->script()->isStarGenerator()) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_ES6_UNIMPLEMENTED);
-        return NULL;
-    }
-
     Rooted<GlobalObject*> global(cx, &stackfp->global());
     RootedObject obj(cx);
     {
         JSObject *proto = global->getOrCreateGeneratorPrototype(cx);
         if (!proto)
             return NULL;
         obj = NewObjectWithGivenProto(cx, &GeneratorObject::class_, proto, global);
     }
--- a/js/src/jsreflect.cpp
+++ b/js/src/jsreflect.cpp
@@ -2782,17 +2782,16 @@ ASTSerializer::module(ParseNode *pn, Mut
            builder.module(&pn->pn_pos, name, body, dst);
 }
 
 bool
 ASTSerializer::function(ParseNode *pn, ASTType type, MutableHandleValue dst)
 {
     RootedFunction func(cx, pn->pn_funbox->function());
 
-    // FIXME: Provide more information (legacy generator vs star generator).
     bool isGenerator = pn->pn_funbox->isGenerator();
 
     bool isExpression =
 #if JS_HAS_EXPR_CLOSURES
         func->isExprClosure();
 #else
         false;
 #endif
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -402,19 +402,19 @@ js::XDRScript(XDRState<mode> *xdr, Handl
         SavedCallerFun,
         Strict,
         ContainsDynamicNameAccess,
         FunHasExtensibleScope,
         FunNeedsDeclEnvObject,
         FunHasAnyAliasedFormal,
         ArgumentsHasVarBinding,
         NeedsArgsObj,
+        IsGenerator,
         IsGeneratorExp,
         IsLegacyGenerator,
-        IsStarGenerator,
         OwnSource,
         ExplicitUseStrict,
         SelfHosted
     };
 
     uint32_t length, lineno, nslots;
     uint32_t natoms, nsrcnotes, ntrynotes, nobjects, nregexps, nconsts, i;
     uint32_t prologLength, version;
@@ -491,22 +491,22 @@ js::XDRScript(XDRState<mode> *xdr, Handl
         if (script->funHasAnyAliasedFormal)
             scriptBits |= (1 << FunHasAnyAliasedFormal);
         if (script->argumentsHasVarBinding())
             scriptBits |= (1 << ArgumentsHasVarBinding);
         if (script->analyzedArgsUsage() && script->needsArgsObj())
             scriptBits |= (1 << NeedsArgsObj);
         if (!enclosingScript || enclosingScript->scriptSource() != script->scriptSource())
             scriptBits |= (1 << OwnSource);
+        if (script->isGenerator)
+            scriptBits |= (1 << IsGenerator);
         if (script->isGeneratorExp)
             scriptBits |= (1 << IsGeneratorExp);
-        if (script->isLegacyGenerator())
+        if (script->isLegacyGenerator)
             scriptBits |= (1 << IsLegacyGenerator);
-        if (script->isStarGenerator())
-            scriptBits |= (1 << IsStarGenerator);
 
         JS_ASSERT(!script->compileAndGo);
         JS_ASSERT(!script->hasSingletons);
     }
 
     if (!xdr->codeUint32(&prologLength))
         return false;
     if (!xdr->codeUint32(&version))
@@ -591,24 +591,22 @@ js::XDRScript(XDRState<mode> *xdr, Handl
         if (scriptBits & (1 << FunNeedsDeclEnvObject))
             script->funNeedsDeclEnvObject = true;
         if (scriptBits & (1 << FunHasAnyAliasedFormal))
             script->funHasAnyAliasedFormal = true;
         if (scriptBits & (1 << ArgumentsHasVarBinding))
             script->setArgumentsHasVarBinding();
         if (scriptBits & (1 << NeedsArgsObj))
             script->setNeedsArgsObj(true);
+        if (scriptBits & (1 << IsGenerator))
+            script->isGenerator = true;
         if (scriptBits & (1 << IsGeneratorExp))
             script->isGeneratorExp = true;
-
-        if (scriptBits & (1 << IsLegacyGenerator)) {
-            JS_ASSERT(!(scriptBits & (1 << IsStarGenerator)));
-            script->setGeneratorKind(LegacyGenerator);
-        } else if (scriptBits & (1 << IsStarGenerator))
-            script->setGeneratorKind(StarGenerator);
+        if (scriptBits & (1 << IsLegacyGenerator))
+            script->isLegacyGenerator = true;
     }
 
     JS_STATIC_ASSERT(sizeof(jsbytecode) == 1);
     JS_STATIC_ASSERT(sizeof(jssrcnote) == 1);
 
     if (scriptBits & (1 << OwnSource)) {
         if (!script->scriptSource()->performXDR<mode>(xdr))
             return false;
@@ -1959,18 +1957,19 @@ JSScript::fullyInitFromEmitter(Exclusive
         }
 
         script->ndefaults = funbox->ndefaults;
     }
 
     RootedFunction fun(cx, NULL);
     if (funbox) {
         JS_ASSERT(!bce->script->noScriptRval);
+        script->isGenerator = funbox->isGenerator();
         script->isGeneratorExp = funbox->inGenexpLambda;
-        script->setGeneratorKind(funbox->generatorKind());
+        script->isLegacyGenerator = funbox->isLegacyGenerator();
         script->setFunction(funbox->function());
     }
 
     for (unsigned i = 0, n = script->bindings.numArgs(); i < n; ++i) {
         if (script->formalIsAliased(i)) {
             script->funHasAnyAliasedFormal = true;
             break;
         }
@@ -2469,18 +2468,18 @@ js::CloneScript(JSContext *cx, HandleObj
     dst->strict = src->strict;
     dst->explicitUseStrict = src->explicitUseStrict;
     dst->bindingsAccessedDynamically = src->bindingsAccessedDynamically;
     dst->funHasExtensibleScope = src->funHasExtensibleScope;
     dst->funNeedsDeclEnvObject = src->funNeedsDeclEnvObject;
     dst->funHasAnyAliasedFormal = src->funHasAnyAliasedFormal;
     dst->hasSingletons = src->hasSingletons;
     dst->treatAsRunOnce = src->treatAsRunOnce;
+    dst->isGenerator = src->isGenerator;
     dst->isGeneratorExp = src->isGeneratorExp;
-    dst->setGeneratorKind(src->generatorKind());
 
     /* Copy over hints. */
     dst->shouldInline = src->shouldInline;
     dst->shouldCloneAtCallsite = src->shouldCloneAtCallsite;
     dst->isCallsiteClone = src->isCallsiteClone;
 
     if (nconsts != 0) {
         HeapValue *vector = Rebase<HeapValue>(dst, src, src->consts()->vector);
@@ -2911,17 +2910,17 @@ JSScript::argumentsOptimizationFailed(JS
      * everything has been fixed up, but there was an outstanding magic value
      * on the stack that has just now flowed into an apply. In this case, there
      * is nothing to do; GuardFunApplySpeculation will patch in the real
      * argsobj.
      */
     if (script->needsArgsObj())
         return true;
 
-    JS_ASSERT(!script->isGenerator());
+    JS_ASSERT(!script->isGenerator);
 
     script->needsArgsObj_ = true;
 
 #ifdef JS_ION
     /*
      * Since we can't invalidate baseline scripts, set a flag that's checked from
      * JIT code to indicate the arguments optimization failed and JSOP_ARGUMENTS
      * should create an arguments object next time.
@@ -3003,17 +3002,16 @@ LazyScript::LazyScript(JSFunction *fun, 
   : script_(NULL),
     function_(fun),
     enclosingScope_(NULL),
     sourceObject_(NULL),
     table_(table),
     version_(version),
     numFreeVariables_(numFreeVariables),
     numInnerFunctions_(numInnerFunctions),
-    generatorKindBits_(GeneratorKindAsBits(NotGenerator)),
     strict_(false),
     bindingsAccessedDynamically_(false),
     hasDebuggerStatement_(false),
     directlyInsideEval_(false),
     usesArgumentsAndApply_(false),
     hasBeenCloned_(false),
     begin_(begin),
     end_(end),
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -409,29 +409,16 @@ class ScriptSourceObject : public JSObje
     }
 
     void setSource(ScriptSource *source);
 
   private:
     static const uint32_t SOURCE_SLOT = 0;
 };
 
-enum GeneratorKind { NotGenerator, LegacyGenerator, StarGenerator };
-
-static inline unsigned
-GeneratorKindAsBits(GeneratorKind generatorKind) {
-    return static_cast<unsigned>(generatorKind);
-}
-
-static inline GeneratorKind
-GeneratorKindFromBits(unsigned val) {
-    JS_ASSERT(val <= StarGenerator);
-    return static_cast<GeneratorKind>(val);
-}
-
 } /* namespace js */
 
 class JSScript : public js::gc::Cell
 {
     static const uint32_t stepFlagMask = 0x80000000U;
     static const uint32_t stepCountMask = 0x7fffffffU;
 
   public:
@@ -546,19 +533,16 @@ class JSScript : public js::gc::Cell
 
     typedef uint8_t ArrayBitsT;
 
   private:
     // The bits in this field indicate the presence/non-presence of several
     // optional arrays in |data|.  See the comments above Create() for details.
     ArrayBitsT      hasArrayBits;
 
-    // The GeneratorKind of the script.
-    uint8_t         generatorKindBits_;
-
     // 1-bit fields.
 
   public:
     bool            noScriptRval:1; /* no need for result value of last
                                        expression statement */
     bool            savedCallerFun:1; /* can call getCallerFunction() */
     bool            strict:1; /* code is in strict mode */
     bool            explicitUseStrict:1; /* code has "use strict"; explicitly */
@@ -600,19 +584,24 @@ class JSScript : public js::gc::Cell
     bool            hadFrequentBailouts:1;
 #else
     bool            failedBoundsCheckPad:1;
     bool            failedShapeGuardPad:1;
     bool            hadFrequentBailoutsPad:1;
 #endif
     bool            invalidatedIdempotentCache:1; /* idempotent cache has triggered invalidation */
 
+    // All generators have isGenerator set to true.
+    bool            isGenerator:1;
     // If the generator was created implicitly via a generator expression,
     // isGeneratorExp will be true.
     bool            isGeneratorExp:1;
+    // Generators are either legacy-style (JS 1.7+ starless generators with
+    // StopIteration), or ES6-style (function* with boxed return values).
+    bool            isLegacyGenerator:1;
 
     bool            hasScriptCounts:1;/* script has an entry in
                                          JSCompartment::scriptCountsMap */
     bool            hasDebugScript:1; /* script has an entry in
                                          JSCompartment::debugScriptMap */
     bool            hasFreezeConstraints:1; /* freeze constraints for stack
                                              * type sets have been generated */
 
@@ -653,29 +642,16 @@ class JSScript : public js::gc::Cell
 
     void setVersion(JSVersion v) { version = v; }
 
     /* See ContextFlags::funArgumentsHasLocalBinding comment. */
     bool argumentsHasVarBinding() const { return argsHasVarBinding_; }
     jsbytecode *argumentsBytecode() const { JS_ASSERT(code[0] == JSOP_ARGUMENTS); return code; }
     void setArgumentsHasVarBinding();
 
-    js::GeneratorKind generatorKind() const {
-        return js::GeneratorKindFromBits(generatorKindBits_);
-    }
-    bool isGenerator() const { return generatorKind() != js::NotGenerator; }
-    bool isLegacyGenerator() const { return generatorKind() == js::LegacyGenerator; }
-    bool isStarGenerator() const { return generatorKind() == js::StarGenerator; }
-    void setGeneratorKind(js::GeneratorKind kind) {
-        // A script only gets its generator kind set as part of initialization,
-        // so it can only transition from not being a generator.
-        JS_ASSERT(!isGenerator());
-        generatorKindBits_ = GeneratorKindAsBits(kind);
-    }
-
     /*
      * As an optimization, even when argsHasLocalBinding, the function prologue
      * may not need to create an arguments object. This is determined by
      * needsArgsObj which is set by ScriptAnalysis::analyzeSSA before running
      * the script the first time. When !needsArgsObj, the prologue may simply
      * write MagicValue(JS_OPTIMIZED_ARGUMENTS) to 'arguments's slot and any
      * uses of 'arguments' will be guaranteed to handle this magic value.
      * So avoid spurious arguments object creation, we maintain the invariant
@@ -1167,19 +1143,17 @@ class LazyScript : public js::gc::Cell
 #if JS_BITS_PER_WORD == 32
     uint32_t padding;
 #endif
 
     // Assorted bits that should really be in ScriptSourceObject.
     uint32_t version_ : 8;
 
     uint32_t numFreeVariables_ : 24;
-    uint32_t numInnerFunctions_ : 24;
-
-    uint32_t generatorKindBits_:2;
+    uint32_t numInnerFunctions_ : 26;
 
     // N.B. These are booleans but need to be uint32_t to pack correctly on MSVC.
     uint32_t strict_ : 1;
     uint32_t bindingsAccessedDynamically_ : 1;
     uint32_t hasDebuggerStatement_ : 1;
     uint32_t directlyInsideEval_:1;
     uint32_t usesArgumentsAndApply_:1;
     uint32_t hasBeenCloned_:1;
@@ -1235,33 +1209,16 @@ class LazyScript : public js::gc::Cell
 
     uint32_t numInnerFunctions() const {
         return numInnerFunctions_;
     }
     HeapPtrFunction *innerFunctions() {
         return (HeapPtrFunction *)&freeVariables()[numFreeVariables()];
     }
 
-    GeneratorKind generatorKind() const { return GeneratorKindFromBits(generatorKindBits_); }
-
-    bool isGenerator() const { return generatorKind() != NotGenerator; }
-
-    bool isLegacyGenerator() const { return generatorKind() == LegacyGenerator; }
-
-    bool isStarGenerator() const { return generatorKind() == StarGenerator; }
-
-    void setGeneratorKind(GeneratorKind kind) {
-        // A script only gets its generator kind set as part of initialization,
-        // so it can only transition from NotGenerator.
-        JS_ASSERT(!isGenerator());
-        // Legacy generators cannot currently be lazy.
-        JS_ASSERT(kind != LegacyGenerator);
-        generatorKindBits_ = GeneratorKindAsBits(kind);
-    }
-
     bool strict() const {
         return strict_;
     }
     void setStrict() {
         strict_ = true;
     }
 
     bool bindingsAccessedDynamically() const {
deleted file mode 100644
--- a/js/src/tests/ecma_6/Generators/shell.js
+++ /dev/null
@@ -1,1 +0,0 @@
-version(0);
deleted file mode 100644
--- a/js/src/tests/ecma_6/Generators/syntax.js
+++ /dev/null
@@ -1,97 +0,0 @@
-// This file was written by Andy Wingo <wingo@igalia.com> and originally
-// contributed to V8 as generators-parsing.js, available here:
-//
-// http://code.google.com/p/v8/source/browse/branches/bleeding_edge/test/mjsunit/harmony/generators-parsing.js
-
-function assertSyntaxError(str) {
-    var msg;
-    var evil = eval;
-    try {
-        // Non-direct eval.
-        evil(str);
-    } catch (exc) {
-        if (exc instanceof SyntaxError)
-            return;
-        msg = "Assertion failed: expected SyntaxError, got " + exc;
-    }
-    if (msg === undefined)
-        msg = "Assertion failed: expected SyntaxError, but no exception thrown";
-    throw new Error(msg + " - " + str);
-}
-
-// Yield statements.
-function* g() { yield 3; yield 4; }
-
-// Yield expressions.
-function* g() { (yield 3) + (yield 4); }
-
-// You can have a generator in strict mode.
-function* g() { "use strict"; yield 3; yield 4; }
-
-// Generators can have return statements also, which internally parse to a kind
-// of yield expression.
-function* g() { yield 1; return; }
-function* g() { yield 1; return 2; }
-function* g() { yield 1; return 2; yield "dead"; }
-
-// Generator expression.
-(function* () { yield 3; });
-
-// Named generator expression.
-(function* g() { yield 3; });
-
-// Generators do not have to contain yield expressions.
-function* g() { }
-
-// YieldExpressions can occur in the RHS of a YieldExpression.
-function* g() { yield yield 1; }
-function* g() { yield 3 + (yield 4); }
-
-// Generator definitions with a name of "yield" are not specifically ruled out
-// by the spec, as the `yield' name is outside the generator itself.  However,
-// in strict-mode, "yield" is an invalid identifier.
-function* yield() { (yield 3) + (yield 4); }
-assertSyntaxError("function* yield() { 'use strict'; (yield 3) + (yield 4); }");
-
-// In classic mode, yield is a normal identifier, outside of generators.
-function yield(yield) { yield: yield (yield + yield (0)); }
-
-// Yield is always valid as a key in an object literal.
-({ yield: 1 });
-function* g() { yield ({ yield: 1 }) }
-function* g() { yield ({ get yield() { return 1; }}) }
-
-// Yield is a valid property name.
-function* g(obj) { yield obj.yield; }
-
-// Checks that yield is a valid label in classic mode, but not valid in a strict
-// mode or in generators.
-function f() { yield: 1 }
-assertSyntaxError("function f() { 'use strict'; yield: 1 }")
-assertSyntaxError("function* g() { yield: 1 }")
-
-// Yield is only a keyword in the body of the generator, not in nested
-// functions.
-function* g() { function f(yield) { yield (yield + yield (0)); } }
-
-// Yield needs a RHS.
-assertSyntaxError("function* g() { yield; }");
-
-// Yield in a generator is not an identifier.
-assertSyntaxError("function* g() { yield = 10; }");
-
-// Yield binds very loosely, so this parses as "yield (3 + yield 4)", which is
-// invalid.
-assertSyntaxError("function* g() { yield 3 + yield 4; }");
-
-// Yield is still a future-reserved-word in strict mode
-assertSyntaxError("function f() { 'use strict'; var yield = 13; }");
-
-// The name of the NFE is let-bound in G, so is invalid.
-assertSyntaxError("function* g() { yield (function yield() {}); }");
-
-// In generators, yield is invalid as a formal argument name.
-assertSyntaxError("function* g(yield) { yield (10); }");
-
-if (typeof reportCompare == "function")
-    reportCompare(true, true);
--- a/js/src/vm/CommonPropertyNames.h
+++ b/js/src/vm/CommonPropertyNames.h
@@ -147,17 +147,16 @@
     macro(useAsm, useAsm, "use asm") \
     macro(useStrict, useStrict, "use strict") \
     macro(value, value, "value") \
     macro(valueOf, valueOf, "valueOf") \
     macro(var, var, "var") \
     macro(void0, void0, "(void 0)") \
     macro(watch, watch, "watch") \
     macro(writable, writable, "writable") \
-    macro(yield, yield, "yield") \
     /* Type names must be contiguous and ordered; see js::TypeName. */ \
     macro(undefined, undefined, "undefined") \
     macro(object, object, "object") \
     macro(function, function, "function") \
     macro(string, string, "string") \
     macro(number, number, "number") \
     macro(boolean, boolean, "boolean") \
     macro(null, null, "null")
--- a/js/src/vm/Keywords.h
+++ b/js/src/vm/Keywords.h
@@ -67,19 +67,15 @@
     /* ES5 future reserved keywords in strict mode. */ \
     macro(implements, implements, TOK_STRICT_RESERVED, JSVERSION_DEFAULT) \
     macro(interface, interface, TOK_STRICT_RESERVED, JSVERSION_DEFAULT) \
     macro(package, package, TOK_STRICT_RESERVED, JSVERSION_DEFAULT) \
     macro(private, private_, TOK_STRICT_RESERVED, JSVERSION_DEFAULT) \
     macro(protected, protected_, TOK_STRICT_RESERVED, JSVERSION_DEFAULT) \
     macro(public, public_, TOK_STRICT_RESERVED, JSVERSION_DEFAULT) \
     macro(static, static_, TOK_STRICT_RESERVED, JSVERSION_DEFAULT) \
-    /* \
-     * ES5 future reserved keyword in strict mode, keyword in JS1.7 even when \
-     * not strict, keyword inside function* in all versions.  Punt logic to \
-     * parser. \
-     */ \
-    macro(yield, yield, TOK_YIELD, JSVERSION_DEFAULT) \
+    /* ES5 future reserved keyword in strict mode, keyword in JS1.7 even when not strict. */ \
+    macro(yield, yield, TOK_YIELD, JSVERSION_1_7) \
     /* Various conditional keywords. */ \
     FOR_CONST_KEYWORD(macro) \
     FOR_LET_KEYWORD(macro)
 
 #endif /* vm_Keywords_h */