Bug 1530324 - Part 5: Store result promise in the internal generator object of async functions. r=arai
authorAndré Bargull <andre.bargull@gmail.com>
Mon, 25 Feb 2019 05:12:16 -0800
changeset 461675 48fb1e2b6e97f1f089c259d4f3209ee26a274e74
parent 461674 135c13d4ceba69ab9b70c4803198b107c8f0cc06
child 461676 b84fd1d91da2afcbd1d73bc16bc374fbe43c634c
push id35626
push usercsabou@mozilla.com
push dateThu, 28 Feb 2019 11:31:08 +0000
treeherdermozilla-central@2ea0c1db7e60 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersarai
bugs1530324
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1530324 - Part 5: Store result promise in the internal generator object of async functions. r=arai
js/src/builtin/Promise.cpp
js/src/builtin/Promise.h
js/src/jit-test/tests/debug/onEnterFrame-async-resumption-06.js
js/src/vm/AsyncFunction.cpp
js/src/vm/AsyncFunction.h
js/src/vm/GeneratorObject.cpp
js/src/vm/GeneratorObject.h
js/src/vm/SelfHosting.cpp
--- a/js/src/builtin/Promise.cpp
+++ b/js/src/builtin/Promise.cpp
@@ -1475,33 +1475,30 @@ static MOZ_MUST_USE bool DefaultResolvin
 
 static MOZ_MUST_USE bool AsyncFunctionPromiseReactionJob(
     JSContext* cx, Handle<PromiseReactionRecord*> reaction,
     MutableHandleValue rval) {
   MOZ_ASSERT(reaction->isAsyncFunction());
 
   RootedValue handlerVal(cx, reaction->handler());
   RootedValue argument(cx, reaction->handlerArg());
-  Rooted<PromiseObject*> resultPromise(
-      cx, &reaction->promise()->as<PromiseObject>());
   Rooted<AsyncFunctionGeneratorObject*> generator(
       cx, reaction->asyncFunctionGenerator());
 
   int32_t handlerNum = handlerVal.toInt32();
 
-  // Await's handlers don't return a value, nor throw exception.
+  // Await's handlers don't return a value, nor throw an exception.
   // They fail only on OOM.
   if (handlerNum == PromiseHandlerAsyncFunctionAwaitedFulfilled) {
-    if (!AsyncFunctionAwaitedFulfilled(cx, resultPromise, generator,
-                                       argument)) {
+    if (!AsyncFunctionAwaitedFulfilled(cx, generator, argument)) {
       return false;
     }
   } else {
     MOZ_ASSERT(handlerNum == PromiseHandlerAsyncFunctionAwaitedRejected);
-    if (!AsyncFunctionAwaitedRejected(cx, resultPromise, generator, argument)) {
+    if (!AsyncFunctionAwaitedRejected(cx, generator, argument)) {
       return false;
     }
   }
 
   rval.setUndefined();
   return true;
 }
 
@@ -3272,16 +3269,17 @@ static PromiseReactionRecord* NewReactio
       JSObject* unwrappedPromise = UncheckedUnwrap(resultCapability.promise());
       MOZ_ASSERT(unwrappedPromise->is<PromiseObject>());
       MOZ_ASSERT(!resultCapability.resolve());
       MOZ_ASSERT(!resultCapability.reject());
     }
   } else {
     // `resultCapability.promise` is null for the following cases:
     //   * resulting Promise is known to be unused
+    //   * Async Function
     //   * Async Generator
     // In any case, other fields are also not used.
     MOZ_ASSERT(!resultCapability.resolve());
     MOZ_ASSERT(!resultCapability.reject());
     MOZ_ASSERT(incumbentGlobalObjectOption == IncumbentGlobalObject::Yes);
   }
 #endif
 
@@ -3511,43 +3509,33 @@ MOZ_MUST_USE PromiseObject* js::CreatePr
   return promise;
 }
 
 bool js::IsPromiseForAsync(JSObject* promise) {
   return promise->is<PromiseObject>() &&
          PromiseHasAnyFlag(promise->as<PromiseObject>(), PROMISE_FLAG_ASYNC);
 }
 
-// ES 2018 draft 25.5.5.2 steps 3.f, 3.g.
+// ES2019 draft rev 7428c89bef626548084cd4e697a19ece7168f24c
+// 25.7.5.1 AsyncFunctionStart, steps 3.f-g.
 MOZ_MUST_USE bool js::AsyncFunctionThrown(
     JSContext* cx, Handle<PromiseObject*> resultPromise) {
-  // Step 3.f.
   RootedValue exc(cx);
   if (!MaybeGetAndClearException(cx, &exc)) {
     return false;
   }
 
-  if (!RejectPromiseInternal(cx, resultPromise, exc)) {
-    return false;
-  }
-
-  // Step 3.g.
-  return true;
+  return RejectPromiseInternal(cx, resultPromise, exc);
 }
 
-// ES 2018 draft 25.5.5.2 steps 3.d-e, 3.g.
+// ES2019 draft rev 7428c89bef626548084cd4e697a19ece7168f24c
+// 25.7.5.1 AsyncFunctionStart, steps 3.d-e, 3.g.
 MOZ_MUST_USE bool js::AsyncFunctionReturned(
     JSContext* cx, Handle<PromiseObject*> resultPromise, HandleValue value) {
-  // Steps 3.d-e.
-  if (!ResolvePromiseInternal(cx, resultPromise, value)) {
-    return false;
-  }
-
-  // Step 3.g.
-  return true;
+  return ResolvePromiseInternal(cx, resultPromise, value);
 }
 
 // Helper function that performs the equivalent steps as
 // Async Iteration proposal 4.1 Await steps 2-3, 6-9 or similar.
 template <typename T>
 static MOZ_MUST_USE bool InternalAwait(JSContext* cx, HandleValue value,
                                        HandleObject resultPromise,
                                        HandleValue onFulfilled,
@@ -3582,29 +3570,28 @@ static MOZ_MUST_USE bool InternalAwait(J
 
   // Step 9.
   return PerformPromiseThenWithReaction(cx, promise, reaction);
 }
 
 // ES 2018 draft 25.5.5.3 steps 2-10.
 MOZ_MUST_USE bool js::AsyncFunctionAwait(
     JSContext* cx, Handle<AsyncFunctionGeneratorObject*> genObj,
-    Handle<PromiseObject*> resultPromise, HandleValue value) {
+    HandleValue value) {
   // Steps 4-5.
   RootedValue onFulfilled(
       cx, Int32Value(PromiseHandlerAsyncFunctionAwaitedFulfilled));
   RootedValue onRejected(
       cx, Int32Value(PromiseHandlerAsyncFunctionAwaitedRejected));
 
   // Steps 2-3, 6-10.
   auto extra = [&](Handle<PromiseReactionRecord*> reaction) {
     reaction->setIsAsyncFunction(genObj);
   };
-  return InternalAwait(cx, value, resultPromise, onFulfilled, onRejected,
-                       extra);
+  return InternalAwait(cx, value, nullptr, onFulfilled, onRejected, extra);
 }
 
 // Async Iteration proposal 4.1 Await steps 2-9.
 MOZ_MUST_USE bool js::AsyncGeneratorAwait(
     JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
     HandleValue value) {
   // Steps 4-5.
   RootedValue onFulfilled(
--- a/js/src/builtin/Promise.h
+++ b/js/src/builtin/Promise.h
@@ -249,17 +249,17 @@ MOZ_MUST_USE bool AsyncFunctionReturned(
                                         Handle<PromiseObject*> resultPromise,
                                         HandleValue value);
 
 MOZ_MUST_USE bool AsyncFunctionThrown(JSContext* cx,
                                       Handle<PromiseObject*> resultPromise);
 
 MOZ_MUST_USE bool AsyncFunctionAwait(
     JSContext* cx, Handle<AsyncFunctionGeneratorObject*> genObj,
-    Handle<PromiseObject*> resultPromise, HandleValue value);
+    HandleValue value);
 
 // If the await operation can be skipped and the resolution value for `val` can
 // be acquired, stored the resolved value to `resolved` and `true` to
 // `*canSkip`.  Otherwise, stores `false` to `*canSkip`.
 MOZ_MUST_USE bool TrySkipAwait(JSContext* cx, HandleValue val, bool* canSkip,
                                MutableHandleValue resolved);
 
 class AsyncGeneratorObject;
--- a/js/src/jit-test/tests/debug/onEnterFrame-async-resumption-06.js
+++ b/js/src/jit-test/tests/debug/onEnterFrame-async-resumption-06.js
@@ -36,14 +36,14 @@ assertEq(hits, 1);
 
 drainJobQueue();
 
 assertEq(hits, 1);
 
 let pw2 = gw.makeDebuggeeValue(p2);
 assertEq(pw2.isPromise, true);
 assertEq(pw2.promiseState, "fulfilled");
-assertEq(pw2.promiseValue, undefined);
+assertEq(pw2.promiseValue, "moar ponies");
 
 let pw = gw.makeDebuggeeValue(p);
 assertEq(pw.isPromise, true);
 assertEq(pw.promiseState, "fulfilled");
 assertEq(pw.promiseValue, "moar ponies");
--- a/js/src/vm/AsyncFunction.cpp
+++ b/js/src/vm/AsyncFunction.cpp
@@ -10,16 +10,18 @@
 
 #include "builtin/Promise.h"
 #include "vm/GeneratorObject.h"
 #include "vm/GlobalObject.h"
 #include "vm/Interpreter.h"
 #include "vm/Realm.h"
 #include "vm/SelfHosting.h"
 
+#include "vm/JSObject-inl.h"
+
 using namespace js;
 
 using mozilla::Maybe;
 
 /* static */ bool GlobalObject::initAsyncFunction(
     JSContext* cx, Handle<GlobalObject*> global) {
   if (global->getReservedSlot(ASYNC_FUNCTION_PROTO).isObject()) {
     return true;
@@ -55,18 +57,17 @@ using mozilla::Maybe;
 
   global->setReservedSlot(ASYNC_FUNCTION, ObjectValue(*asyncFunction));
   global->setReservedSlot(ASYNC_FUNCTION_PROTO,
                           ObjectValue(*asyncFunctionProto));
   return true;
 }
 
 static MOZ_MUST_USE bool AsyncFunctionStart(
-    JSContext* cx, Handle<PromiseObject*> resultPromise,
-    Handle<AsyncFunctionGeneratorObject*> generator);
+    JSContext* cx, Handle<AsyncFunctionGeneratorObject*> generator);
 
 #define UNWRAPPED_ASYNC_WRAPPED_SLOT 1
 #define WRAPPED_ASYNC_UNWRAPPED_SLOT 0
 
 // Async Functions proposal 1.1.8 and 1.2.14.
 static bool WrappedAsyncFunction(JSContext* cx, unsigned argc, Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
 
@@ -87,31 +88,25 @@ static bool WrappedAsyncFunction(JSConte
     if (!generatorVal.isObject() ||
         !generatorVal.toObject().is<AsyncFunctionGeneratorObject>()) {
       JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                                 JSMSG_UNEXPECTED_TYPE, "return value",
                                 JS::InformalValueTypeName(generatorVal));
       return false;
     }
 
-    // Step 1.
-    Rooted<PromiseObject*> resultPromise(cx, CreatePromiseObjectForAsync(cx));
-    if (!resultPromise) {
-      return false;
-    }
-
     // Step 3.
     Rooted<AsyncFunctionGeneratorObject*> generator(
         cx, &generatorVal.toObject().as<AsyncFunctionGeneratorObject>());
-    if (!AsyncFunctionStart(cx, resultPromise, generator)) {
+    if (!AsyncFunctionStart(cx, generator)) {
       return false;
     }
 
     // Step 5.
-    args.rval().setObject(*resultPromise);
+    args.rval().setObject(*generator->promise());
     return true;
   }
 
   if (!cx->isExceptionPending()) {
     return false;
   }
 
   // Steps 1, 4.
@@ -186,32 +181,38 @@ JSObject* js::WrapAsyncFunction(JSContex
 enum class ResumeKind { Normal, Throw };
 
 // Async Functions proposal 2.2 steps 3.f, 3.g.
 // Async Functions proposal 2.2 steps 3.d-e, 3.g.
 // Implemented in js/src/builtin/Promise.cpp
 
 // Async Functions proposal 2.2 steps 3-8, 2.4 steps 2-7, 2.5 steps 2-7.
 static bool AsyncFunctionResume(JSContext* cx,
-                                Handle<PromiseObject*> resultPromise,
                                 Handle<AsyncFunctionGeneratorObject*> generator,
                                 ResumeKind kind, HandleValue valueOrReason) {
-  RootedObject stack(cx, resultPromise->allocationSite());
+  Rooted<PromiseObject*> resultPromise(cx, generator->promise());
+
+  RootedObject stack(cx);
   Maybe<JS::AutoSetAsyncStackForNewCalls> asyncStack;
-  if (stack) {
-    asyncStack.emplace(
-        cx, stack, "async",
-        JS::AutoSetAsyncStackForNewCalls::AsyncCallKind::EXPLICIT);
+  if (JSObject* allocationSite = resultPromise->allocationSite()) {
+    // The promise is created within the activation of the async function, so
+    // use the parent frame as the starting point for async stacks.
+    stack = allocationSite->as<SavedFrame>().getParent();
+    if (stack) {
+      asyncStack.emplace(
+          cx, stack, "async",
+          JS::AutoSetAsyncStackForNewCalls::AsyncCallKind::EXPLICIT);
+    }
   }
 
   // This case can only happen when the debugger force-returned the same
   // generator object for two async function calls. It doesn't matter how we
   // handle it, as long as we don't crash.
   if (generator->isClosed() || !generator->isSuspended()) {
-    return AsyncFunctionReturned(cx, resultPromise, UndefinedHandleValue);
+    return true;
   }
 
   // Execution context switching is handled in generator.
   HandlePropertyName funName = kind == ResumeKind::Normal
                                    ? cx->names().AsyncFunctionNext
                                    : cx->names().AsyncFunctionThrow;
   FixedInvokeArgs<1> args(cx);
   args[0].set(valueOrReason);
@@ -220,53 +221,50 @@ static bool AsyncFunctionResume(JSContex
                               &generatorOrValue)) {
     if (!generator->isClosed()) {
       generator->setClosed();
     }
     return AsyncFunctionThrown(cx, resultPromise);
   }
 
   if (generator->isAfterAwait()) {
-    return AsyncFunctionAwait(cx, generator, resultPromise, generatorOrValue);
+    return AsyncFunctionAwait(cx, generator, generatorOrValue);
   }
 
   return AsyncFunctionReturned(cx, resultPromise, generatorOrValue);
 }
 
 // Async Functions proposal 2.2 steps 3-8.
 static MOZ_MUST_USE bool AsyncFunctionStart(
-    JSContext* cx, Handle<PromiseObject*> resultPromise,
-    Handle<AsyncFunctionGeneratorObject*> generator) {
-  return AsyncFunctionResume(cx, resultPromise, generator, ResumeKind::Normal,
+    JSContext* cx, Handle<AsyncFunctionGeneratorObject*> generator) {
+  return AsyncFunctionResume(cx, generator, ResumeKind::Normal,
                              UndefinedHandleValue);
 }
 
 // Async Functions proposal 2.3 steps 1-8.
 // Implemented in js/src/builtin/Promise.cpp
 
 // Async Functions proposal 2.4.
 MOZ_MUST_USE bool js::AsyncFunctionAwaitedFulfilled(
-    JSContext* cx, Handle<PromiseObject*> resultPromise,
-    Handle<AsyncFunctionGeneratorObject*> generator, HandleValue value) {
+    JSContext* cx, Handle<AsyncFunctionGeneratorObject*> generator,
+    HandleValue value) {
   // Step 1 (implicit).
 
   // Steps 2-7.
-  return AsyncFunctionResume(cx, resultPromise, generator, ResumeKind::Normal,
-                             value);
+  return AsyncFunctionResume(cx, generator, ResumeKind::Normal, value);
 }
 
 // Async Functions proposal 2.5.
 MOZ_MUST_USE bool js::AsyncFunctionAwaitedRejected(
-    JSContext* cx, Handle<PromiseObject*> resultPromise,
-    Handle<AsyncFunctionGeneratorObject*> generator, HandleValue reason) {
+    JSContext* cx, Handle<AsyncFunctionGeneratorObject*> generator,
+    HandleValue reason) {
   // Step 1 (implicit).
 
   // Step 2-7.
-  return AsyncFunctionResume(cx, resultPromise, generator, ResumeKind::Throw,
-                             reason);
+  return AsyncFunctionResume(cx, generator, ResumeKind::Throw, reason);
 }
 
 JSFunction* js::GetWrappedAsyncFunction(JSFunction* unwrapped) {
   MOZ_ASSERT(unwrapped->isAsync());
   return &unwrapped->getExtendedSlot(UNWRAPPED_ASYNC_WRAPPED_SLOT)
               .toObject()
               .as<JSFunction>();
 }
@@ -279,8 +277,30 @@ JSFunction* js::GetUnwrappedAsyncFunctio
            .as<JSFunction>();
   MOZ_ASSERT(unwrapped->isAsync());
   return unwrapped;
 }
 
 bool js::IsWrappedAsyncFunction(JSFunction* fun) {
   return fun->maybeNative() == WrappedAsyncFunction;
 }
+
+const Class AsyncFunctionGeneratorObject::class_ = {
+    "AsyncFunctionGenerator",
+    JSCLASS_HAS_RESERVED_SLOTS(AsyncFunctionGeneratorObject::RESERVED_SLOTS)};
+
+AsyncFunctionGeneratorObject* AsyncFunctionGeneratorObject::create(
+    JSContext* cx, HandleFunction fun) {
+  MOZ_ASSERT(fun->isAsync() && !fun->isGenerator());
+
+  Rooted<PromiseObject*> resultPromise(cx, CreatePromiseObjectForAsync(cx));
+  if (!resultPromise) {
+    return nullptr;
+  }
+
+  auto* obj = NewBuiltinClassInstance<AsyncFunctionGeneratorObject>(cx);
+  if (!obj) {
+    return nullptr;
+  }
+  obj->initFixedSlot(PROMISE_SLOT, ObjectValue(*resultPromise));
+
+  return obj;
+}
--- a/js/src/vm/AsyncFunction.h
+++ b/js/src/vm/AsyncFunction.h
@@ -2,23 +2,24 @@
  * vim: set ts=8 sts=2 et sw=2 tw=80:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef vm_AsyncFunction_h
 #define vm_AsyncFunction_h
 
+#include "builtin/Promise.h"
+#include "js/Class.h"
+#include "vm/GeneratorObject.h"
 #include "vm/JSContext.h"
 #include "vm/JSObject.h"
 
 namespace js {
 
-class AsyncFunctionGeneratorObject;
-
 // An async function is implemented using two function objects, which are
 // referred to as the "unwrapped" and the "wrapped" async function object.
 // The unwrapped function is a generator function compiled from the async
 // function's script. |await| expressions within the async function are
 // compiled like |yield| expression for the generator function with dedicated
 // opcode,. The unwrapped function is never exposed to user script.
 // The wrapped function is a native function which wraps the generator function,
 // hence its name, and is the publicly exposed object of the async function.
@@ -40,22 +41,42 @@ bool IsWrappedAsyncFunction(JSFunction* 
 // prototype object.
 JSObject* WrapAsyncFunctionWithProto(JSContext* cx, HandleFunction unwrapped,
                                      HandleObject proto);
 
 // Create a wrapped async function from unwrapped async function with default
 // prototype object.
 JSObject* WrapAsyncFunction(JSContext* cx, HandleFunction unwrapped);
 
+class AsyncFunctionGeneratorObject;
+
 // Resume the async function when the `await` operand resolves.
 // Split into two functions depending on whether the awaited value was
 // fulfilled or rejected.
 MOZ_MUST_USE bool AsyncFunctionAwaitedFulfilled(
-    JSContext* cx, Handle<PromiseObject*> resultPromise,
-    Handle<AsyncFunctionGeneratorObject*> generator, HandleValue value);
+    JSContext* cx, Handle<AsyncFunctionGeneratorObject*> generator,
+    HandleValue value);
 
 MOZ_MUST_USE bool AsyncFunctionAwaitedRejected(
-    JSContext* cx, Handle<PromiseObject*> resultPromise,
-    Handle<AsyncFunctionGeneratorObject*> generator, HandleValue reason);
+    JSContext* cx, Handle<AsyncFunctionGeneratorObject*> generator,
+    HandleValue reason);
+
+class AsyncFunctionGeneratorObject : public AbstractGeneratorObject {
+ public:
+  enum {
+    PROMISE_SLOT = AbstractGeneratorObject::RESERVED_SLOTS,
+
+    RESERVED_SLOTS
+  };
+
+  static const Class class_;
+
+  static AsyncFunctionGeneratorObject* create(JSContext* cx,
+                                              HandleFunction asyncGen);
+
+  PromiseObject* promise() {
+    return &getFixedSlot(PROMISE_SLOT).toObject().as<PromiseObject>();
+  }
+};
 
 }  // namespace js
 
 #endif /* vm_AsyncFunction_h */
--- a/js/src/vm/GeneratorObject.cpp
+++ b/js/src/vm/GeneratorObject.cpp
@@ -2,16 +2,17 @@
  * vim: set ts=8 sts=2 et sw=2 tw=80:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "vm/GeneratorObject.h"
 
 #include "js/PropertySpec.h"
+#include "vm/AsyncFunction.h"
 #include "vm/AsyncIteration.h"
 #include "vm/JSObject.h"
 
 #include "vm/ArrayObject-inl.h"
 #include "vm/Debugger-inl.h"
 #include "vm/JSAtom-inl.h"
 #include "vm/JSScript-inl.h"
 #include "vm/NativeObject-inl.h"
@@ -28,18 +29,17 @@ JSObject* AbstractGeneratorObject::creat
   RootedFunction fun(cx, frame.callee());
 
   Rooted<AbstractGeneratorObject*> genObj(cx);
   if (!fun->isAsync()) {
     genObj = GeneratorObject::create(cx, fun);
   } else if (fun->isGenerator()) {
     genObj = AsyncGeneratorObject::create(cx, fun);
   } else {
-    RootedObject proto(cx, nullptr);
-    genObj = NewObjectWithGivenProto<AsyncFunctionGeneratorObject>(cx, proto);
+    genObj = AsyncFunctionGeneratorObject::create(cx, fun);
   }
   if (!genObj) {
     return nullptr;
   }
 
   genObj->setCallee(*frame.callee());
   genObj->setEnvironmentChain(*frame.environmentChain());
   if (frame.script()->needsArgsObj()) {
@@ -216,20 +216,16 @@ GeneratorObject* GeneratorObject::create
 const Class GeneratorObject::class_ = {
     "Generator", JSCLASS_HAS_RESERVED_SLOTS(GeneratorObject::RESERVED_SLOTS)};
 
 static const JSFunctionSpec generator_methods[] = {
     JS_SELF_HOSTED_FN("next", "GeneratorNext", 1, 0),
     JS_SELF_HOSTED_FN("throw", "GeneratorThrow", 1, 0),
     JS_SELF_HOSTED_FN("return", "GeneratorReturn", 1, 0), JS_FS_END};
 
-const Class AsyncFunctionGeneratorObject::class_ = {
-    "AsyncFunctionGenerator",
-    JSCLASS_HAS_RESERVED_SLOTS(AsyncFunctionGeneratorObject::RESERVED_SLOTS)};
-
 JSObject* js::NewSingletonObjectWithFunctionPrototype(
     JSContext* cx, Handle<GlobalObject*> global) {
   RootedObject proto(cx,
                      GlobalObject::getOrCreateFunctionPrototype(cx, global));
   if (!proto) {
     return nullptr;
   }
   return NewObjectWithGivenProto<PlainObject>(cx, proto, SingletonObject);
--- a/js/src/vm/GeneratorObject.h
+++ b/js/src/vm/GeneratorObject.h
@@ -2,16 +2,17 @@
  * vim: set ts=8 sts=2 et sw=2 tw=80:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef vm_GeneratorObject_h
 #define vm_GeneratorObject_h
 
+#include "js/Class.h"
 #include "vm/ArgumentsObject.h"
 #include "vm/ArrayObject.h"
 #include "vm/JSContext.h"
 #include "vm/JSObject.h"
 #include "vm/Stack.h"
 
 namespace js {
 
@@ -205,23 +206,16 @@ class GeneratorObject : public AbstractG
  public:
   enum { RESERVED_SLOTS = AbstractGeneratorObject::RESERVED_SLOTS };
 
   static const Class class_;
 
   static GeneratorObject* create(JSContext* cx, HandleFunction fun);
 };
 
-class AsyncFunctionGeneratorObject : public AbstractGeneratorObject {
- public:
-  enum { RESERVED_SLOTS = AbstractGeneratorObject::RESERVED_SLOTS };
-
-  static const Class class_;
-};
-
 bool GeneratorThrowOrReturn(JSContext* cx, AbstractFramePtr frame,
                             Handle<AbstractGeneratorObject*> obj,
                             HandleValue val, uint32_t resumeKind);
 
 /**
  * Return the generator object associated with the given frame. The frame must
  * be a call frame for a generator. If the generator object hasn't been created
  * yet, or hasn't been stored in the stack slot yet, this returns null.
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -38,16 +38,17 @@
 #include "js/CharacterEncoding.h"
 #include "js/CompilationAndEvaluation.h"
 #include "js/Date.h"
 #include "js/PropertySpec.h"
 #include "js/StableStringChars.h"
 #include "js/Wrapper.h"
 #include "util/StringBuffer.h"
 #include "vm/ArgumentsObject.h"
+#include "vm/AsyncFunction.h"
 #include "vm/AsyncIteration.h"
 #include "vm/Compression.h"
 #include "vm/GeneratorObject.h"
 #include "vm/Interpreter.h"
 #include "vm/Iteration.h"
 #include "vm/JSContext.h"
 #include "vm/JSFunction.h"
 #include "vm/JSObject.h"