From 76dd7b746defdb6b60287e55368108b51f79e5d7 Mon Sep 17 00:00:00 2001
From: Jon Coppeard <jcoppeard@mozilla.com>
Date: Wed, 31 Aug 2022 14:18:26 +0000
Subject: [PATCH] Bug 1787926 - Don't add async dependency on modules that have
 finished evaluating. r=yulia, a=RyanVM

The problem is that we're waiting for an import to finish evaluation after it
already has.

I think this a problem with the spec, related to the change from
AsyncEvaluating to AsyncEvaluation here:

https://github.com/tc39/proposal-top-level-await/commit/c2375dbd6ecb0d5e9a415f6a812fc0974a2935b7#diff-181371b08d71216599b0acccbaabd03c306da6de142ea6275c2135810999805aL588-R589

Previously we wouldn't add an async dependency when the required module's
AsyncEvaluating field was false, which was the case after evaluation had
finished. Now this is never set to false so we always add the dependency here
and there's nothing to trigger evaluation of the importing module.

Differential Revision: https://phabricator.services.mozilla.com/D155968
---
 js/src/jit-test/tests/modules/bug-1787926.js | 16 ++++++++++++++++
 js/src/vm/Modules.cpp                        |  3 ++-
 2 files changed, 18 insertions(+), 1 deletion(-)
 create mode 100644 js/src/jit-test/tests/modules/bug-1787926.js

diff --git a/js/src/jit-test/tests/modules/bug-1787926.js b/js/src/jit-test/tests/modules/bug-1787926.js
new file mode 100644
index 0000000000000..fb710143599ee
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1787926.js
@@ -0,0 +1,16 @@
+let m = registerModule('m', parseModule(`import {} from "s";`));
+let l = registerModule('l', parseModule(`import {} from "s";`));
+let s = registerModule('s', parseModule(`await 0;`));
+
+let state = "init";
+
+moduleLink(m);
+moduleEvaluate(m).then(() => { state = "loaded"; });
+drainJobQueue();
+
+assertEq(state, "loaded");
+
+import("l").then(() => { state = "complete"; });
+drainJobQueue();
+
+assertEq(state, "complete");
diff --git a/js/src/vm/Modules.cpp b/js/src/vm/Modules.cpp
index d717ab15169b0..d4ba5f1aafa1d 100644
--- a/js/src/vm/Modules.cpp
+++ b/js/src/vm/Modules.cpp
@@ -1467,7 +1467,8 @@ static bool InnerModuleEvaluation(JSContext* cx, Handle<ModuleObject*> module,
     }
 
     // Step 11.d.v. If requiredModule.[[AsyncEvaluation]] is true, then:
-    if (requiredModule->isAsyncEvaluating()) {
+    if (requiredModule->isAsyncEvaluating() &&
+        requiredModule->status() != ModuleStatus::Evaluated) {
       // Step 11.d.v.2. Append module to requiredModule.[[AsyncParentModules]].
       if (!ModuleObject::appendAsyncParentModule(cx, requiredModule, module)) {
         return false;
-- 
GitLab