Bug 1341298 - Relax expected module state when resolving modules and circular module dependencies are present. r=jonco
authorAndré Bargull <andre.bargull@gmail.com>
Thu, 23 Feb 2017 07:04:20 -0800
changeset 373684 c1e74895212a5eecbe1d1e643c8e36a80852bc40
parent 373683 49abbdfdd1ab01a71ee588a171102aefb85baf30
child 373685 40da4a08377d0d69f76195b7d7f375ac34e2d3a2
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjonco
bugs1341298
milestone54.0a1
Bug 1341298 - Relax expected module state when resolving modules and circular module dependencies are present. r=jonco
js/src/builtin/Module.js
js/src/jit-test/modules/export-circular-nonexisting-binding-1.js
js/src/jit-test/modules/export-circular-nonexisting-binding-2.js
js/src/jit-test/tests/modules/export-circular-nonexisting-binding.js
js/src/vm/EnvironmentObject.cpp
--- a/js/src/builtin/Module.js
+++ b/js/src/builtin/Module.js
@@ -95,17 +95,17 @@ function ModuleResolveExport(exportName,
     }
 
     // Step 5
     let indirectExportEntries = module.indirectExportEntries;
     for (let i = 0; i < indirectExportEntries.length; i++) {
         let e = indirectExportEntries[i];
         if (exportName === e.exportName) {
             let importedModule = CallModuleResolveHook(module, e.moduleRequest,
-                                                       MODULE_STATE_INSTANTIATED);
+                                                       MODULE_STATE_PARSED);
             return callFunction(importedModule.resolveExport, importedModule, e.importName,
                                 resolveSet);
         }
     }
 
     // Step 6
     if (exportName === "default") {
         // A default export cannot be provided by an export *.
@@ -115,17 +115,17 @@ function ModuleResolveExport(exportName,
     // Step 7
     let starResolution = null;
 
     // Step 8
     let starExportEntries = module.starExportEntries;
     for (let i = 0; i < starExportEntries.length; i++) {
         let e = starExportEntries[i];
         let importedModule = CallModuleResolveHook(module, e.moduleRequest,
-                                                   MODULE_STATE_INSTANTIATED);
+                                                   MODULE_STATE_PARSED);
         let resolution = callFunction(importedModule.resolveExport, importedModule,
                                       exportName, resolveSet);
         if (resolution === "ambiguous")
             return resolution;
 
         if (resolution !== null) {
             if (starResolution === null) {
                 starResolution = resolution;
@@ -200,18 +200,18 @@ function GetModuleEnvironment(module)
     assert(env === undefined || IsModuleEnvironment(env),
            "Module environment slot contains unexpected value");
 
     return env;
 }
 
 function RecordInstantationFailure(module)
 {
-    // Set the module's environment slot to 'null' to indicate a failed module
-    // instantiation.
+    // Set the module's state to 'failed' to indicate a failed module
+    // instantiation and reset the environment slot to 'undefined'.
     assert(IsModule(module), "Non-module passed to RecordInstantationFailure");
     SetModuleState(module, MODULE_STATE_FAILED);
     UnsafeSetReservedSlot(module, MODULE_OBJECT_ENVIRONMENT_SLOT, undefined);
 }
 
 // 15.2.1.16.4 ModuleDeclarationInstantiation()
 function ModuleDeclarationInstantiation()
 {
@@ -262,16 +262,18 @@ function ModuleDeclarationInstantiation(
                 CreateNamespaceBinding(env, imp.localName, namespace);
             } else {
                 let resolution = callFunction(importedModule.resolveExport, importedModule,
                                               imp.importName);
                 if (resolution === null)
                     ThrowSyntaxError(JSMSG_MISSING_IMPORT, imp.importName);
                 if (resolution === "ambiguous")
                     ThrowSyntaxError(JSMSG_AMBIGUOUS_IMPORT, imp.importName);
+                if (resolution.module.state < MODULE_STATE_INSTANTIATED)
+                    ThrowInternalError(JSMSG_BAD_MODULE_STATE);
                 CreateImportBinding(env, imp.localName, resolution.module, resolution.bindingName);
             }
         }
 
         // Step 17.a.iii
         InstantiateModuleFunctionDeclarations(module);
     } catch (e) {
         RecordInstantationFailure(module);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/modules/export-circular-nonexisting-binding-1.js
@@ -0,0 +1,4 @@
+import "export-circular-nonexisting-binding-2.js";
+
+export* from "empty.js";
+export {x} from "empty.js";
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/modules/export-circular-nonexisting-binding-2.js
@@ -0,0 +1,1 @@
+export {x} from "export-circular-nonexisting-binding-1.js";
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/modules/export-circular-nonexisting-binding.js
@@ -0,0 +1,3 @@
+// |jit-test| module; error:SyntaxError
+
+import "export-circular-nonexisting-binding-1.js";
--- a/js/src/vm/EnvironmentObject.cpp
+++ b/js/src/vm/EnvironmentObject.cpp
@@ -483,17 +483,17 @@ ModuleEnvironmentObject::importBindings(
 }
 
 bool
 ModuleEnvironmentObject::createImportBinding(JSContext* cx, HandleAtom importName,
                                              HandleModuleObject module, HandleAtom localName)
 {
     RootedId importNameId(cx, AtomToId(importName));
     RootedId localNameId(cx, AtomToId(localName));
-    RootedModuleEnvironmentObject env(cx, module->environment());
+    RootedModuleEnvironmentObject env(cx, &module->initialEnvironment());
     if (!importBindings().putNew(cx, importNameId, env, localNameId)) {
         ReportOutOfMemory(cx);
         return false;
     }
 
     return true;
 }