Bug 1382306 - Create async function wrapper when instantiating module functions. r=jonco
authorAndré Bargull <andre.bargull@gmail.com>
Fri, 28 Jul 2017 12:55:07 -0700
changeset 423011 81c056ef9e195ac1d93ac4f4f56b04fb3614a7d5
parent 423010 15ace180cf033edf24a4849d16247fee9ebbef22
child 423012 74d5a19b281479b5c52a9bfb9ff283bad3b74451
push id1517
push userjlorenzo@mozilla.com
push dateThu, 14 Sep 2017 16:50:54 +0000
treeherdermozilla-release@3b41fd564418 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjonco
bugs1382306
milestone56.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 1382306 - Create async function wrapper when instantiating module functions. r=jonco
js/src/builtin/ModuleObject.cpp
js/src/tests/ecma_2017/AsyncFunctions/async-function-declaration-in-modules.js
js/src/tests/ecma_2018/AsyncGenerators/async-generator-declaration-in-modules.js
js/src/vm/Interpreter.cpp
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -6,16 +6,18 @@
 
 #include "builtin/ModuleObject.h"
 
 #include "builtin/SelfHostingDefines.h"
 #include "frontend/ParseNode.h"
 #include "frontend/SharedContext.h"
 #include "gc/Policy.h"
 #include "gc/Tracer.h"
+#include "vm/AsyncFunction.h"
+#include "vm/AsyncIteration.h"
 
 #include "jsobjinlines.h"
 #include "jsscriptinlines.h"
 
 using namespace js;
 using namespace js::frontend;
 
 static_assert(MODULE_STATE_FAILED < MODULE_STATE_PARSED &&
@@ -881,25 +883,34 @@ ModuleObject::instantiateFunctionDeclara
     FunctionDeclarationVector* funDecls = self->functionDeclarations();
     if (!funDecls) {
         JS_ReportErrorASCII(cx, "Module function declarations have already been instantiated");
         return false;
     }
 
     RootedModuleEnvironmentObject env(cx, &self->initialEnvironment());
     RootedFunction fun(cx);
+    RootedObject obj(cx);
     RootedValue value(cx);
 
     for (const auto& funDecl : *funDecls) {
         fun = funDecl.fun;
-        RootedObject obj(cx, Lambda(cx, fun, env));
+        obj = Lambda(cx, fun, env);
         if (!obj)
             return false;
 
-        value = ObjectValue(*fun);
+        if (fun->isAsync()) {
+            if (fun->isStarGenerator()) {
+                obj = WrapAsyncGenerator(cx, obj.as<JSFunction>());
+            } else {
+                obj = WrapAsyncFunction(cx, obj.as<JSFunction>());
+            }
+        }
+
+        value = ObjectValue(*obj);
         if (!SetProperty(cx, env, funDecl.name->asPropertyName(), value))
             return false;
     }
 
     js_delete(funDecls);
     self->setReservedSlot(FunctionDeclarationsSlot, UndefinedValue());
     return true;
 }
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_2017/AsyncFunctions/async-function-declaration-in-modules.js
@@ -0,0 +1,13 @@
+// |reftest| module
+
+async function f() {
+    return "success";
+}
+
+var AsyncFunction = (async function(){}).constructor;
+
+assertEq(f instanceof AsyncFunction, true);
+
+f().then(v => {
+    reportCompare("success", v);
+});
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_2018/AsyncGenerators/async-generator-declaration-in-modules.js
@@ -0,0 +1,13 @@
+// |reftest| module skip-if(release_or_beta)
+
+async function* f() {
+    return "success";
+}
+
+var AsyncGenerator = (async function*(){}).constructor;
+
+assertEq(f instanceof AsyncGenerator, true);
+
+f().next().then(v => {
+    reportCompare("success", v.value);
+});
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -4406,36 +4406,36 @@ js::GetProperty(JSContext* cx, HandleVal
     return GetProperty(cx, obj, receiver, name, vp);
 }
 
 JSObject*
 js::Lambda(JSContext* cx, HandleFunction fun, HandleObject parent)
 {
     MOZ_ASSERT(!fun->isArrow());
 
-    RootedObject clone(cx, CloneFunctionObjectIfNotSingleton(cx, fun, parent));
+    JSFunction* clone = CloneFunctionObjectIfNotSingleton(cx, fun, parent);
     if (!clone)
         return nullptr;
 
     MOZ_ASSERT(fun->global() == clone->global());
     return clone;
 }
 
 JSObject*
 js::LambdaArrow(JSContext* cx, HandleFunction fun, HandleObject parent, HandleValue newTargetv)
 {
     MOZ_ASSERT(fun->isArrow());
 
-    RootedObject clone(cx, CloneFunctionObjectIfNotSingleton(cx, fun, parent, nullptr,
-                                                             TenuredObject));
+    JSFunction* clone = CloneFunctionObjectIfNotSingleton(cx, fun, parent, nullptr,
+                                                          TenuredObject);
     if (!clone)
         return nullptr;
 
-    MOZ_ASSERT(clone->as<JSFunction>().isArrow());
-    clone->as<JSFunction>().setExtendedSlot(0, newTargetv);
+    MOZ_ASSERT(clone->isArrow());
+    clone->setExtendedSlot(0, newTargetv);
 
     MOZ_ASSERT(fun->global() == clone->global());
     return clone;
 }
 
 bool
 js::DefFunOperation(JSContext* cx, HandleScript script, HandleObject envChain,
                     HandleFunction fun)