From e9d41c99681e3a8d910e5490db61e9ff81f7a241 Mon Sep 17 00:00:00 2001
From: adeshkp <adeshkp@users.noreply.github.com>
Date: Mon, 8 Jun 2020 09:17:35 -0400
Subject: Issue #1542 - Fix a typo in wasm which was causing build failure on
 ARM

---
 js/src/wasm/WasmBaselineCompile.cpp | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

(limited to 'js')

diff --git a/js/src/wasm/WasmBaselineCompile.cpp b/js/src/wasm/WasmBaselineCompile.cpp
index 8dc5c104f..7162e3338 100644
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -3391,7 +3391,7 @@ class BaseCompiler
 #ifdef JS_CODEGEN_ARM
     void
     loadI32(MemoryAccessDesc access, bool isSigned, RegI32 ptr, Register rt) {
-        if (access.byteSize() > 1 && IsUnaligned(ins->access())) {
+        if (access.byteSize() > 1 && IsUnaligned(access)) {
             masm.add32(HeapReg, ptr.reg);
             SecondScratchRegisterScope scratch(*this);
             masm.emitUnalignedLoad(isSigned, access.byteSize(), ptr.reg, scratch, rt, 0);
@@ -3405,7 +3405,7 @@ class BaseCompiler
 
     void
     storeI32(MemoryAccessDesc access, RegI32 ptr, Register rt) {
-        if (access.byteSize() > 1 && IsUnaligned(ins->access())) {
+        if (access.byteSize() > 1 && IsUnaligned(access)) {
             masm.add32(HeapReg, ptr.reg);
             masm.emitUnalignedStore(access.byteSize(), ptr.reg, rt, 0);
         } else {
@@ -3419,7 +3419,7 @@ class BaseCompiler
 
     void
     loadI64(MemoryAccessDesc access, RegI32 ptr, RegI64 dest) {
-        if (IsUnaligned(ins->access())) {
+        if (IsUnaligned(access)) {
             masm.add32(HeapReg, ptr.reg);
             SecondScratchRegisterScope scratch(*this);
             masm.emitUnalignedLoad(IsSigned(false), ByteSize(4), ptr.reg, scratch, dest.reg.low,
@@ -3440,7 +3440,7 @@ class BaseCompiler
 
     void
     storeI64(MemoryAccessDesc access, RegI32 ptr, RegI64 src) {
-        if (IsUnaligned(ins->access())) {
+        if (IsUnaligned(access)) {
             masm.add32(HeapReg, ptr.reg);
             masm.emitUnalignedStore(ByteSize(4), ptr.reg, src.reg.low, 0);
             masm.emitUnalignedStore(ByteSize(4), ptr.reg, src.reg.high, 4);
@@ -3459,7 +3459,7 @@ class BaseCompiler
     void
     loadF32(MemoryAccessDesc access, RegI32 ptr, RegF32 dest, RegI32 tmp1) {
         masm.add32(HeapReg, ptr.reg);
-        if (IsUnaligned(ins->access())) {
+        if (IsUnaligned(access)) {
             SecondScratchRegisterScope scratch(*this);
             masm.emitUnalignedLoad(IsSigned(false), ByteSize(4), ptr.reg, scratch, tmp1.reg, 0);
             masm.ma_vxfer(tmp1.reg, dest.reg);
@@ -3473,7 +3473,7 @@ class BaseCompiler
     void
     storeF32(MemoryAccessDesc access, RegI32 ptr, RegF32 src, RegI32 tmp1) {
         masm.add32(HeapReg, ptr.reg);
-        if (IsUnaligned(ins->access())) {
+        if (IsUnaligned(access)) {
             masm.ma_vxfer(src.reg, tmp1.reg);
             masm.emitUnalignedStore(ByteSize(4), ptr.reg, tmp1.reg, 0);
         } else {
@@ -3486,7 +3486,7 @@ class BaseCompiler
     void
     loadF64(MemoryAccessDesc access, RegI32 ptr, RegF64 dest, RegI32 tmp1, RegI32 tmp2) {
         masm.add32(HeapReg, ptr.reg);
-        if (IsUnaligned(ins->access())) {
+        if (IsUnaligned(access)) {
             SecondScratchRegisterScope scratch(*this);
             masm.emitUnalignedLoad(IsSigned(false), ByteSize(4), ptr.reg, scratch, tmp1.reg, 0);
             masm.emitUnalignedLoad(IsSigned(false), ByteSize(4), ptr.reg, scratch, tmp2.reg, 4);
@@ -3501,7 +3501,7 @@ class BaseCompiler
     void
     storeF64(MemoryAccessDesc access, RegI32 ptr, RegF64 src, RegI32 tmp1, RegI32 tmp2) {
         masm.add32(HeapReg, ptr.reg);
-        if (IsUnaligned(ins->access())) {
+        if (IsUnaligned(access)) {
             masm.ma_vxfer(src.reg, tmp1.reg, tmp2.reg);
             masm.emitUnalignedStore(ByteSize(4), ptr.reg, tmp1.reg, 0);
             masm.emitUnalignedStore(ByteSize(4), ptr.reg, tmp2.reg, 4);
-- 
cgit v1.2.3


From 0633844f46858135ee62d396829c6292492ca117 Mon Sep 17 00:00:00 2001
From: Moonchild <moonchild@palemoon.org>
Date: Tue, 30 Jun 2020 11:32:07 +0000
Subject: Issue #1603 - Part 1: Reorganize ScriptLoader/ScriptElement

- Moves scripting parts of DOM into 'dom/script'
- Renames nsScript{Loader/Element} to Script{Loader/Element}
- Adjusts all callers
---
 js/xpconnect/loader/mozJSSubScriptLoader.cpp | 12 ++++++------
 js/xpconnect/src/XPCJSContext.cpp            |  6 +++---
 2 files changed, 9 insertions(+), 9 deletions(-)

(limited to 'js')

diff --git a/js/xpconnect/loader/mozJSSubScriptLoader.cpp b/js/xpconnect/loader/mozJSSubScriptLoader.cpp
index f23e5833a..baf7a9392 100644
--- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp
+++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp
@@ -15,7 +15,6 @@
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
 #include "nsIFileURL.h"
-#include "nsScriptLoader.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsThreadUtils.h"
 
@@ -26,6 +25,7 @@
 #include "jswrapper.h"
 
 #include "mozilla/dom/Promise.h"
+#include "mozilla/dom/ScriptLoader.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "mozilla/HoldDropJSObjects.h"
 #include "mozilla/scache/StartupCache.h"
@@ -139,8 +139,8 @@ PrepareScript(nsIURI* uri,
         size_t scriptLength = 0;
 
         nsresult rv =
-            nsScriptLoader::ConvertToUTF16(nullptr, reinterpret_cast<const uint8_t*>(buf), len,
-                                           charset, nullptr, scriptBuf, scriptLength);
+            ScriptLoader::ConvertToUTF16(nullptr, reinterpret_cast<const uint8_t*>(buf), len,
+                                         charset, nullptr, scriptBuf, scriptLength);
 
         JS::SourceBufferHolder srcBuf(scriptBuf, scriptLength,
                                       JS::SourceBufferHolder::GiveOwnership);
@@ -826,9 +826,9 @@ ScriptPrecompiler::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
     // Convert data to char16_t* and prepare to call CompileOffThread.
     nsAutoString hintCharset;
     nsresult rv =
-        nsScriptLoader::ConvertToUTF16(mChannel, aString, aLength,
-                                       hintCharset, nullptr,
-                                       mScriptBuf, mScriptLength);
+        ScriptLoader::ConvertToUTF16(mChannel, aString, aLength,
+                                     hintCharset, nullptr,
+                                     mScriptBuf, mScriptLength);
 
     NS_ENSURE_SUCCESS(rv, NS_OK);
 
diff --git a/js/xpconnect/src/XPCJSContext.cpp b/js/xpconnect/src/XPCJSContext.cpp
index bde949a96..511bc8a98 100644
--- a/js/xpconnect/src/XPCJSContext.cpp
+++ b/js/xpconnect/src/XPCJSContext.cpp
@@ -35,13 +35,13 @@
 #include "nsCCUncollectableMarker.h"
 #include "nsCycleCollectionNoteRootCallback.h"
 #include "nsCycleCollector.h"
-#include "nsScriptLoader.h"
 #include "jsapi.h"
 #include "jsprf.h"
 #include "js/MemoryMetrics.h"
 #include "mozilla/dom/GeneratedAtomList.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/Element.h"
+#include "mozilla/dom/ScriptLoader.h"
 #include "mozilla/dom/WindowBinding.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "mozilla/Atomics.h"
@@ -3035,8 +3035,8 @@ ReadSourceFromFilename(JSContext* cx, const char* filename, char16_t** src, size
         ptr += bytesRead;
     }
 
-    rv = nsScriptLoader::ConvertToUTF16(scriptChannel, buf.get(), rawLen, EmptyString(),
-                                        nullptr, *src, *len);
+    rv = ScriptLoader::ConvertToUTF16(scriptChannel, buf.get(), rawLen, EmptyString(),
+                                      nullptr, *src, *len);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (!*src)
-- 
cgit v1.2.3


From 3f25d0c8e4d9296f0d45c85c251eab71f076937b Mon Sep 17 00:00:00 2001
From: Moonchild <moonchild@palemoon.org>
Date: Fri, 3 Jul 2020 13:56:49 +0000
Subject: Issue #618 - Align module instantiation/errors with the updated spec.

Store and re-throw module instantiation and evaluation errors.
Ref: BZ 1374239, 1394492
---
 js/src/builtin/Module.js                           | 533 +++++++++++++++++----
 js/src/builtin/ModuleObject.cpp                    |  69 +--
 js/src/builtin/ModuleObject.h                      |  30 +-
 js/src/builtin/SelfHostingDefines.h                |  18 +-
 js/src/builtin/Utilities.js                        |  19 +-
 .../tests/modules/ambiguous-star-export.js         |  15 +-
 .../tests/modules/bad-namespace-created.js         |  17 +
 js/src/jit-test/tests/modules/bug-1284486.js       |  39 +-
 js/src/jit-test/tests/modules/bug-1287410.js       |   2 +
 js/src/jit-test/tests/modules/bug-1394492.js       |   6 +
 js/src/jit-test/tests/modules/global-scope.js      |  18 +-
 js/src/jit-test/tests/modules/module-evaluation.js |  33 +-
 js/src/js.msg                                      |   2 +-
 js/src/jsapi.cpp                                   |   4 +-
 js/src/vm/CommonPropertyNames.h                    |   4 +-
 js/src/vm/SelfHosting.cpp                          |  19 +-
 16 files changed, 611 insertions(+), 217 deletions(-)
 create mode 100644 js/src/jit-test/tests/modules/bad-namespace-created.js
 create mode 100644 js/src/jit-test/tests/modules/bug-1394492.js

(limited to 'js')

diff --git a/js/src/builtin/Module.js b/js/src/builtin/Module.js
index 5c3d5e147..064293670 100644
--- a/js/src/builtin/Module.js
+++ b/js/src/builtin/Module.js
@@ -2,11 +2,11 @@
  * 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/. */
 
-function CallModuleResolveHook(module, specifier, expectedMinimumState)
+function CallModuleResolveHook(module, specifier, expectedMinimumStatus)
 {
     let requestedModule = HostResolveImportedModule(module, specifier);
-    if (requestedModule.state < expectedMinimumState)
-        ThrowInternalError(JSMSG_BAD_MODULE_STATE);
+    if (requestedModule.state < expectedMinimumStatus)
+        ThrowInternalError(JSMSG_BAD_MODULE_STATUS);
 
     return requestedModule;
 }
@@ -65,7 +65,36 @@ function ModuleGetExportedNames(exportStarSet = [])
     return exportedNames;
 }
 
+function ModuleSetStatus(module, newStatus)
+{
+    assert(newStatus >= MODULE_STATUS_ERRORED && newStatus <= MODULE_STATUS_EVALUATED,
+           "Bad new module status in ModuleSetStatus");
+    if (newStatus !== MODULE_STATUS_ERRORED)
+        assert(newStatus > module.status, "New module status inconsistent with current status");
+
+    UnsafeSetReservedSlot(module, MODULE_OBJECT_STATUS_SLOT, newStatus);
+}
+
 // 15.2.1.16.3 ResolveExport(exportName, resolveSet)
+//
+// Returns an object describing the location of the resolved export or
+// indicating a failure.
+//
+// On success this returns: { resolved: true, module, bindingName }
+//
+// There are three failure cases:
+//
+//  - The resolution failure can be blamed on a particular module.
+//    Returns: { resolved: false, module, ambiguous: false }
+//
+//  - No culprit can be determined and the resolution failure was due to star
+//    export ambiguity.
+//    Returns: { resolved: false, module: null, ambiguous: true }
+//
+//  - No culprit can be determined and the resolution failure was not due to
+//    star export ambiguity.
+//    Returns: { resolved: false, module: null, ambiguous: false }
+//
 function ModuleResolveExport(exportName, resolveSet = [])
 {
     if (!IsObject(this) || !IsModule(this)) {
@@ -77,88 +106,104 @@ function ModuleResolveExport(exportName, resolveSet = [])
     let module = this;
 
     // Step 2
+    assert(module.status !== MODULE_STATUS_ERRORED, "Bad module status in ResolveExport");
+    
+    // Step 3
     for (let i = 0; i < resolveSet.length; i++) {
         let r = resolveSet[i];
-        if (r.module === module && r.exportName === exportName)
-            return null;
+        if (r.module === module && r.exportName === exportName) {
+            // This is a circular import request.
+            return {resolved: false, module: null, ambiguous: false};
+        }
     }
 
-    // Step 3
+    // Step 4
     _DefineDataProperty(resolveSet, resolveSet.length, {module: module, exportName: exportName});
 
-    // Step 4
+    // Step 5
     let localExportEntries = module.localExportEntries;
     for (let i = 0; i < localExportEntries.length; i++) {
         let e = localExportEntries[i];
         if (exportName === e.exportName)
-            return {module: module, bindingName: e.localName};
+            return {resolved: true, module, bindingName: e.localName};
     }
 
-    // Step 5
+    // Step 6
     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_PARSED);
-            return callFunction(importedModule.resolveExport, importedModule, e.importName,
-                                resolveSet);
+                                                       MODULE_STATUS_UNINSTANTIATED);
+            let resolution = callFunction(importedModule.resolveExport, importedModule, e.importName,
+                                          resolveSet);
+            if (!resolution.resolved && !resolution.module)
+                resolution.module = module;
+            return resolution;
         }
     }
 
-    // Step 6
+    // Step 7
     if (exportName === "default") {
         // A default export cannot be provided by an export *.
-        return null;
+        return {resolved: false, module: null, ambiguous: false};
     }
 
-    // Step 7
+    // Step 8
     let starResolution = null;
 
-    // Step 8
+    // Step 9
     let starExportEntries = module.starExportEntries;
     for (let i = 0; i < starExportEntries.length; i++) {
         let e = starExportEntries[i];
         let importedModule = CallModuleResolveHook(module, e.moduleRequest,
-                                                   MODULE_STATE_PARSED);
-        let resolution = callFunction(importedModule.resolveExport, importedModule,
-                                      exportName, resolveSet);
-        if (resolution === "ambiguous")
+                                                   MODULE_STATUS_UNINSTANTIATED);
+        let resolution = callFunction(importedModule.resolveExport, importedModule, exportName,
+                                      resolveSet);
+        if (!resolution.resolved && (resolution.module || resolution.ambiguous))
             return resolution;
 
-        if (resolution !== null) {
+        if (resolution.resolved) {
             if (starResolution === null) {
                 starResolution = resolution;
             } else {
                 if (resolution.module !== starResolution.module ||
-                    resolution.exportName !== starResolution.exportName)
+                    resolution.bindingName !== starResolution.bindingName)
                 {
-                    return "ambiguous";
+                    return {resolved: false, module: null, ambiguous: true};
                 }
             }
         }
     }
 
-    // Step 9
-    return starResolution;
+    // Step 10
+    if (starResolution !== null)
+        return starResolution;
+
+    return {resolved: false, module: null, ambiguous: false};
 }
 
 // 15.2.1.18 GetModuleNamespace(module)
 function GetModuleNamespace(module)
 {
+    // Step 1
+    assert(IsModule(module), "GetModuleNamespace called with non-module");
+
     // Step 2
-    let namespace = module.namespace;
+    assert(module.status !== MODULE_STATUS_UNINSTANTIATED &&
+           module.status !== MODULE_STATUS_ERRORED,
+           "Bad module status in GetModuleNamespace");
 
     // Step 3
+    let namespace = module.namespace;
+
     if (typeof namespace === "undefined") {
         let exportedNames = callFunction(module.getExportedNames, module);
         let unambiguousNames = [];
         for (let i = 0; i < exportedNames.length; i++) {
             let name = exportedNames[i];
             let resolution = callFunction(module.resolveExport, module, name);
-            if (resolution === null)
-                ThrowSyntaxError(JSMSG_MISSING_NAMESPACE_EXPORT);
-            if (resolution !== "ambiguous")
+            if (resolution.resolved)
                 _DefineDataProperty(unambiguousNames, unambiguousNames.length, name);
         }
         namespace = ModuleNamespaceCreate(module, unambiguousNames);
@@ -180,7 +225,7 @@ function ModuleNamespaceCreate(module, exports)
     for (let i = 0; i < exports.length; i++) {
         let name = exports[i];
         let binding = callFunction(module.resolveExport, module, name);
-        assert(binding !== null && binding !== "ambiguous", "Failed to resolve binding");
+        assert(binding.resolved, "Failed to resolve binding");
         AddModuleNamespaceBinding(ns, name, binding.module, binding.bindingName);
     }
 
@@ -193,8 +238,8 @@ function GetModuleEnvironment(module)
 
     // Check for a previous failed attempt to instantiate this module. This can
     // only happen due to a bug in the module loader.
-    if (module.state == MODULE_STATE_FAILED)
-        ThrowInternalError(JSMSG_MODULE_INSTANTIATE_FAILED);
+    if (module.status === MODULE_STATUS_ERRORED)
+        ThrowInternalError(JSMSG_MODULE_INSTANTIATE_FAILED, module.status);
 
     let env = UnsafeGetReservedSlot(module, MODULE_OBJECT_ENVIRONMENT_SLOT);
     assert(env === undefined || IsModuleEnvironment(env),
@@ -203,112 +248,396 @@ function GetModuleEnvironment(module)
     return env;
 }
 
-function RecordInstantationFailure(module)
+function RecordModuleError(module, error)
 {
-    // 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);
+    // Set the module's status to 'errored' to indicate a failed module
+    // instantiation and record the exception. The environment slot is also
+    // reset to 'undefined'.
+
+    assert(IsObject(module) && IsModule(module), "Non-module passed to RecordModuleError");
+
+    ModuleSetStatus(module, MODULE_STATUS_ERRORED);
+    UnsafeSetReservedSlot(module, MODULE_OBJECT_ERROR_SLOT, error);
     UnsafeSetReservedSlot(module, MODULE_OBJECT_ENVIRONMENT_SLOT, undefined);
 }
 
-// 15.2.1.16.4 ModuleDeclarationInstantiation()
-function ModuleDeclarationInstantiation()
+function CountArrayValues(array, value)
+{
+    let count = 0;
+    for (let i = 0; i < array.length; i++) {
+        if (array[i] === value)
+            count++;
+    }
+    return count;
+}
+
+function ArrayContains(array, value)
+{
+    for (let i = 0; i < array.length; i++) {
+        if (array[i] === value)
+            return true;
+    }
+    return false;
+}
+
+// 15.2.1.16.4 ModuleInstantiate()
+function ModuleInstantiate()
 {
     if (!IsObject(this) || !IsModule(this))
-        return callFunction(CallModuleMethodIfWrapped, this, "ModuleDeclarationInstantiation");
+        return callFunction(CallModuleMethodIfWrapped, this, "ModuleInstantiate");
 
     // Step 1
     let module = this;
 
-    // Step 5
-    if (GetModuleEnvironment(module) !== undefined)
-        return;
-
-    // Step 7
-    CreateModuleEnvironment(module);
-    let env = GetModuleEnvironment(module);
+    // Step 2
+    if (module.status === MODULE_STATUS_INSTANTIATING ||
+        module.status === MODULE_STATUS_EVALUATING)
+    {
+        ThrowInternalError(JSMSG_BAD_MODULE_STATUS);
+    }
 
-    SetModuleState(this, MODULE_STATE_INSTANTIATED);
+    // Step 3
+    let stack = [];
 
+    // Steps 4-5
     try {
-        // Step 8
-        let requestedModules = module.requestedModules;
-        for (let i = 0; i < requestedModules.length; i++) {
-            let required = requestedModules[i];
-            let requiredModule = CallModuleResolveHook(module, required, MODULE_STATE_PARSED);
-            callFunction(requiredModule.declarationInstantiation, requiredModule);
+        InnerModuleDeclarationInstantiation(module, stack, 0);
+    } catch (error) {
+        for (let i = 0; i < stack.length; i++) {
+            let m = stack[i];
+
+            assert(m.status === MODULE_STATUS_INSTANTIATING ||
+                   m.status === MODULE_STATUS_ERRORED,
+                   "Bad module status after failed instantiation");
+
+            RecordModuleError(m, error);
         }
 
-        // Step 9
-        let indirectExportEntries = module.indirectExportEntries;
-        for (let i = 0; i < indirectExportEntries.length; i++) {
-            let e = indirectExportEntries[i];
-            let resolution = callFunction(module.resolveExport, module, e.exportName);
-            if (resolution === null)
-                ThrowSyntaxError(JSMSG_MISSING_INDIRECT_EXPORT, e.exportName);
-            if (resolution === "ambiguous")
-                ThrowSyntaxError(JSMSG_AMBIGUOUS_INDIRECT_EXPORT, e.exportName);
+        if (stack.length === 0 &&
+            typeof(UnsafeGetReservedSlot(module, MODULE_OBJECT_ERROR_SLOT)) === "undefined")
+        {
+            // This can happen due to OOM when appending to the stack.
+            assert(error === "out of memory",
+                   "Stack must contain module unless we hit OOM");
+            RecordModuleError(module, error);
         }
 
-        // Step 12
-        let importEntries = module.importEntries;
-        for (let i = 0; i < importEntries.length; i++) {
-            let imp = importEntries[i];
-            let importedModule = CallModuleResolveHook(module, imp.moduleRequest,
-                                                       MODULE_STATE_INSTANTIATED);
-            if (imp.importName === "*") {
-                let namespace = GetModuleNamespace(importedModule);
-                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);
-            }
+        assert(module.status === MODULE_STATUS_ERRORED,
+               "Bad module status after failed instantiation");
+        assert(SameValue(UnsafeGetReservedSlot(module, MODULE_OBJECT_ERROR_SLOT), error),
+               "Module has different error set after failed instantiation");
+
+        throw error;
+    }
+
+    // Step 6
+    assert(module.status == MODULE_STATUS_INSTANTIATED ||
+           module.status == MODULE_STATUS_EVALUATED,
+           "Bad module status after successful instantiation");
+
+    // Step 7
+    assert(stack.length === 0,
+           "Stack should be empty after successful instantiation");
+
+    // Step 8
+    return undefined;
+}
+_SetCanonicalName(ModuleInstantiate, "ModuleInstantiate");
+
+// 15.2.1.16.4.1 InnerModuleDeclarationInstantiation(module, stack, index)
+function InnerModuleDeclarationInstantiation(module, stack, index)
+{
+    // Step 1
+    // TODO: Support module records other than source text module records.
+
+    // Step 2
+    if (module.status === MODULE_STATUS_INSTANTIATING ||
+        module.status === MODULE_STATUS_INSTANTIATED ||
+        module.status === MODULE_STATUS_EVALUATED)
+    {
+        return index;
+    }
+
+    // Step 3
+    if (module.status === MODULE_STATUS_ERRORED)
+        throw module.error;
+
+    // Step 4
+    assert(module.status === MODULE_STATUS_UNINSTANTIATED,
+          "Bad module status in ModuleDeclarationInstantiation");
+
+    // Steps 5
+    ModuleSetStatus(module, MODULE_STATUS_INSTANTIATING);
+
+    // Step 6-8
+    UnsafeSetReservedSlot(module, MODULE_OBJECT_DFS_INDEX_SLOT, index);
+    UnsafeSetReservedSlot(module, MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT, index);
+    index++;
+
+    // Step 9
+    _DefineDataProperty(stack, stack.length, module);
+
+    // Step 10
+    let requestedModules = module.requestedModules;
+    for (let i = 0; i < requestedModules.length; i++) {
+        let required = requestedModules[i];
+        let requiredModule = CallModuleResolveHook(module, required, MODULE_STATUS_ERRORED);
+
+        index = InnerModuleDeclarationInstantiation(requiredModule, stack, index);
+
+        assert(requiredModule.status === MODULE_STATUS_INSTANTIATING ||
+               requiredModule.status === MODULE_STATUS_INSTANTIATED ||
+               requiredModule.status === MODULE_STATUS_EVALUATED,
+               "Bad required module status after InnerModuleDeclarationInstantiation");
+
+        assert((requiredModule.status === MODULE_STATUS_INSTANTIATING) ===
+               ArrayContains(stack, requiredModule),
+              "Required module should be in the stack iff it is currently being instantiated");
+
+        assert(typeof requiredModule.dfsIndex === "number", "Bad dfsIndex");
+        assert(typeof requiredModule.dfsAncestorIndex === "number", "Bad dfsAncestorIndex");
+
+        if (requiredModule.status === MODULE_STATUS_INSTANTIATING) {
+            UnsafeSetReservedSlot(module, MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT,
+                                  std_Math_min(module.dfsAncestorIndex,
+                                               requiredModule.dfsAncestorIndex));
+        }
+    }
+
+    // Step 11
+    ModuleDeclarationEnvironmentSetup(module);
+
+    // Steps 12-13
+    assert(CountArrayValues(stack, module) === 1,
+           "Current module should appear exactly once in the stack");
+    assert(module.dfsAncestorIndex <= module.dfsIndex,
+           "Bad DFS ancestor index");
+
+    // Step 14
+    if (module.dfsAncestorIndex === module.dfsIndex) {
+        let requiredModule;
+        do {
+            requiredModule = callFunction(std_Array_pop, stack);
+            ModuleSetStatus(requiredModule, MODULE_STATUS_INSTANTIATED);
+        } while (requiredModule !== module);
+    }
+
+    // Step 15
+    return index;
+}
+
+// 15.2.1.16.4.2 ModuleDeclarationEnvironmentSetup(module)
+function ModuleDeclarationEnvironmentSetup(module)
+{
+    // Step 1
+    let indirectExportEntries = module.indirectExportEntries;
+    for (let i = 0; i < indirectExportEntries.length; i++) {
+        let e = indirectExportEntries[i];
+        let resolution = callFunction(module.resolveExport, module, e.exportName);
+        assert(resolution.resolved || resolution.module,
+               "Unexpected failure to resolve export in ModuleDeclarationEnvironmentSetup");
+        if (!resolution.resolved)
+            return ResolutionError(resolution, "indirectExport", e.exportName)
+    }
+
+    // Steps 5-6
+    CreateModuleEnvironment(module);
+    let env = GetModuleEnvironment(module);
+
+    // Step 8
+    let importEntries = module.importEntries;
+    for (let i = 0; i < importEntries.length; i++) {
+        let imp = importEntries[i];
+        let importedModule = CallModuleResolveHook(module, imp.moduleRequest,
+                                                   MODULE_STATUS_INSTANTIATING);
+        if (imp.importName === "*") {
+            let namespace = GetModuleNamespace(importedModule);
+            CreateNamespaceBinding(env, imp.localName, namespace);
+        } else {
+            let resolution = callFunction(importedModule.resolveExport, importedModule,
+                                          imp.importName);
+            if (!resolution.resolved && !resolution.module)
+                resolution.module = module;
+
+            if (!resolution.resolved)
+                return ResolutionError(resolution, "import", imp.importName);
+
+            CreateImportBinding(env, imp.localName, resolution.module, resolution.bindingName);
         }
+    }
+
+    InstantiateModuleFunctionDeclarations(module);
+}
 
-        // Step 17.a.iii
-        InstantiateModuleFunctionDeclarations(module);
-    } catch (e) {
-        RecordInstantationFailure(module);
-        throw e;
+// 15.2.1.16.4.3 ResolutionError(module)
+function ResolutionError(resolution, kind, name)
+{
+    let module = resolution.module;
+    assert(module !== null,
+           "Null module passed to ResolutionError");
+
+    assert(module.status === MODULE_STATUS_UNINSTANTIATED ||
+           module.status === MODULE_STATUS_INSTANTIATING,
+           "Unexpected module status in ResolutionError");
+
+    assert(kind === "import" || kind === "indirectExport",
+           "Unexpected kind in ResolutionError");
+
+    let message;
+    if (kind === "import") {
+        message = resolution.ambiguous ? JSMSG_AMBIGUOUS_IMPORT
+                                       : JSMSG_MISSING_IMPORT;
+    } else {
+        message = resolution.ambiguous ? JSMSG_AMBIGUOUS_INDIRECT_EXPORT
+                                       : JSMSG_MISSING_INDIRECT_EXPORT;
+    }
+
+    try {
+        ThrowSyntaxError(message, name);
+    } catch (error) {
+        RecordModuleError(module, error);
+        throw error;
     }
 }
-_SetCanonicalName(ModuleDeclarationInstantiation, "ModuleDeclarationInstantiation");
 
-// 15.2.1.16.5 ModuleEvaluation()
-function ModuleEvaluation()
+// 15.2.1.16.5 ModuleEvaluate()
+function ModuleEvaluate()
 {
     if (!IsObject(this) || !IsModule(this))
-        return callFunction(CallModuleMethodIfWrapped, this, "ModuleEvaluation");
+        return callFunction(CallModuleMethodIfWrapped, this, "ModuleEvaluatie");
 
     // Step 1
     let module = this;
 
-    if (module.state < MODULE_STATE_INSTANTIATED)
-        ThrowInternalError(JSMSG_BAD_MODULE_STATE);
+    // Step 2
+    if (module.status !== MODULE_STATUS_ERRORED &&
+        module.status !== MODULE_STATUS_INSTANTIATED &&
+        module.status !== MODULE_STATUS_EVALUATED)
+    {
+        ThrowInternalError(JSMSG_BAD_MODULE_STATUS);
+    }
+
+    // Step 3
+    let stack = [];
+
+    // Steps 4-5
+    try {
+        InnerModuleEvaluation(module, stack, 0);
+    } catch (error) {
+        for (let i = 0; i < stack.length; i++) {
+            let m = stack[i];
+
+            assert(m.status === MODULE_STATUS_EVALUATING,
+                   "Bad module status after failed evaluation");
+
+            RecordModuleError(m, error);
+        }
+
+        if (stack.length === 0 &&
+            typeof(UnsafeGetReservedSlot(module, MODULE_OBJECT_ERROR_SLOT)) === "undefined")
+        {
+            // This can happen due to OOM when appending to the stack.
+            assert(error === "out of memory",
+                  "Stack must contain module unless we hit OOM");
+            RecordModuleError(module, error);
+        }
+
+        assert(module.status === MODULE_STATUS_ERRORED,
+               "Bad module status after failed evaluation");
+        assert(SameValue(UnsafeGetReservedSlot(module, MODULE_OBJECT_ERROR_SLOT), error),
+               "Module has different error set after failed evaluation");
+
+        throw error;
+    }
+
+    assert(module.status == MODULE_STATUS_EVALUATED,
+           "Bad module status after successful evaluation");
+    assert(stack.length === 0,
+           "Stack should be empty after successful evaluation");
+
+    return undefined;
+}
+_SetCanonicalName(ModuleEvaluate, "ModuleEvaluate");
+
+// 15.2.1.16.5.1 InnerModuleEvaluation(module, stack, index)
+function InnerModuleEvaluation(module, stack, index)
+{
+    // Step 1
+    // TODO: Support module records other than source text module records.
+
+    // Step 2
+    if (module.status === MODULE_STATUS_EVALUATING ||
+        module.status === MODULE_STATUS_EVALUATED)
+    {
+        return index;
+    }
+
+    // Step 3
+    if (module.status === MODULE_STATUS_ERRORED)
+        throw module.error;
 
     // Step 4
-    if (module.state == MODULE_STATE_EVALUATED)
-        return undefined;
+    assert(module.status === MODULE_STATUS_INSTANTIATED,
+          "Bad module status in ModuleEvaluation");
 
     // Step 5
-    SetModuleState(this, MODULE_STATE_EVALUATED);
+    ModuleSetStatus(module, MODULE_STATUS_EVALUATING);
 
-    // Step 6
+    // Steps 6-8
+    UnsafeSetReservedSlot(module, MODULE_OBJECT_DFS_INDEX_SLOT, index);
+    UnsafeSetReservedSlot(module, MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT, index);
+    index++;
+
+    // Step 9
+    _DefineDataProperty(stack, stack.length, module);
+
+    // Step 10
     let requestedModules = module.requestedModules;
     for (let i = 0; i < requestedModules.length; i++) {
         let required = requestedModules[i];
-        let requiredModule = CallModuleResolveHook(module, required, MODULE_STATE_INSTANTIATED);
-        callFunction(requiredModule.evaluation, requiredModule);
+        let requiredModule =
+            CallModuleResolveHook(module, required, MODULE_STATUS_INSTANTIATED);
+
+        index = InnerModuleEvaluation(requiredModule, stack, index);
+
+        assert(requiredModule.status == MODULE_STATUS_EVALUATING ||
+               requiredModule.status == MODULE_STATUS_EVALUATED,
+              "Bad module status after InnerModuleEvaluation");
+
+        assert((requiredModule.status === MODULE_STATUS_EVALUATING) ===
+               ArrayContains(stack, requiredModule),
+               "Required module should be in the stack iff it is currently being evaluated");
+
+        assert(typeof requiredModule.dfsIndex === "number", "Bad dfsIndex");
+        assert(typeof requiredModule.dfsAncestorIndex === "number", "Bad dfsAncestorIndex");
+
+        if (requiredModule.status === MODULE_STATUS_EVALUATING) {
+            UnsafeSetReservedSlot(module, MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT,
+                                  std_Math_min(module.dfsAncestorIndex,
+                                               requiredModule.dfsAncestorIndex));
+        }
+    }
+
+    // Step 11
+    ExecuteModule(module);
+
+    // Step 12
+    assert(CountArrayValues(stack, module) === 1,
+           "Current module should appear exactly once in the stack");
+
+    // Step 13
+    assert(module.dfsAncestorIndex <= module.dfsIndex,
+           "Bad DFS ancestor index");
+
+    // Step 14
+    if (module.dfsAncestorIndex === module.dfsIndex) {
+        let requiredModule;
+        do {
+            requiredModule = callFunction(std_Array_pop, stack);
+            ModuleSetStatus(requiredModule, MODULE_STATUS_EVALUATED);
+        } while (requiredModule !== module);
     }
 
-    return EvaluateModule(module);
+    // Step 15
+    return index;
 }
-_SetCanonicalName(ModuleEvaluation, "ModuleEvaluation");
diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp
index b275cb968..0a836c75b 100644
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -18,10 +18,11 @@
 using namespace js;
 using namespace js::frontend;
 
-static_assert(MODULE_STATE_FAILED < MODULE_STATE_PARSED &&
-              MODULE_STATE_PARSED < MODULE_STATE_INSTANTIATED &&
-              MODULE_STATE_INSTANTIATED < MODULE_STATE_EVALUATED,
-              "Module states are ordered incorrectly");
+static_assert(MODULE_STATUS_ERRORED < MODULE_STATUS_UNINSTANTIATED &&
+              MODULE_STATUS_UNINSTANTIATED < MODULE_STATUS_INSTANTIATING &&
+              MODULE_STATUS_INSTANTIATING < MODULE_STATUS_INSTANTIATED &&
+              MODULE_STATUS_INSTANTIATED < MODULE_STATUS_EVALUATED,
+              "Module statuses are ordered incorrectly");
 
 template<typename T, Value ValueGetter(const T* obj)>
 static bool
@@ -42,7 +43,7 @@ ModuleValueGetter(JSContext* cx, unsigned argc, Value* vp)
 #define DEFINE_GETTER_FUNCTIONS(cls, name, slot)                              \
     static Value                                                              \
     cls##_##name##Value(const cls* obj) {                                     \
-        return obj->getFixedSlot(cls::slot);                                  \
+        return obj->getReservedSlot(cls::slot);                               \
     }                                                                         \
                                                                               \
     static bool                                                               \
@@ -564,7 +565,7 @@ ModuleObject::class_ = {
     ArrayObject&                                                              \
     cls::name() const                                                         \
     {                                                                         \
-        return getFixedSlot(cls::slot).toObject().as<ArrayObject>();          \
+        return getReservedSlot(cls::slot).toObject().as<ArrayObject>();       \
     }
 
 DEFINE_ARRAY_SLOT_ACCESSOR(ModuleObject, requestedModules, RequestedModulesSlot)
@@ -688,7 +689,7 @@ void
 ModuleObject::init(HandleScript script)
 {
     initReservedSlot(ScriptSlot, PrivateValue(script));
-    initReservedSlot(StateSlot, Int32Value(MODULE_STATE_FAILED));
+    initReservedSlot(StatusSlot, Int32Value(MODULE_STATUS_ERRORED));
 }
 
 void
@@ -709,7 +710,7 @@ ModuleObject::initImportExportData(HandleArrayObject requestedModules,
     initReservedSlot(LocalExportEntriesSlot, ObjectValue(*localExportEntries));
     initReservedSlot(IndirectExportEntriesSlot, ObjectValue(*indirectExportEntries));
     initReservedSlot(StarExportEntriesSlot, ObjectValue(*starExportEntries));
-    setReservedSlot(StateSlot, Int32Value(MODULE_STATE_PARSED));
+    setReservedSlot(StatusSlot, Int32Value(MODULE_STATUS_UNINSTANTIATED));
 }
 
 static bool
@@ -790,17 +791,24 @@ ModuleObject::script() const
 }
 
 static inline void
-AssertValidModuleState(ModuleState state)
+AssertValidModuleStatus(ModuleStatus status)
 {
-    MOZ_ASSERT(state >= MODULE_STATE_FAILED && state <= MODULE_STATE_EVALUATED);
+    MOZ_ASSERT(status >= MODULE_STATUS_ERRORED && status <= MODULE_STATUS_EVALUATED);
 }
 
-ModuleState
-ModuleObject::state() const
+ModuleStatus
+ModuleObject::status() const
 {
-    ModuleState state = getReservedSlot(StateSlot).toInt32();
-    AssertValidModuleState(state);
-    return state;
+    ModuleStatus status = getReservedSlot(StatusSlot).toInt32();
+    AssertValidModuleStatus(status);
+    return status;
+}
+
+Value
+ModuleObject::error() const
+{
+    MOZ_ASSERT(status() == MODULE_STATUS_ERRORED);
+    return getReservedSlot(ErrorSlot);
 }
 
 Value
@@ -899,17 +907,8 @@ ModuleObject::instantiateFunctionDeclarations(JSContext* cx, HandleModuleObject
     return true;
 }
 
-void
-ModuleObject::setState(int32_t newState)
-{
-    AssertValidModuleState(newState);
-    MOZ_ASSERT(state() != MODULE_STATE_FAILED);
-    MOZ_ASSERT(newState == MODULE_STATE_FAILED || newState > state());
-    setReservedSlot(StateSlot, Int32Value(newState));
-}
-
 /* static */ bool
-ModuleObject::evaluate(JSContext* cx, HandleModuleObject self, MutableHandleValue rval)
+ModuleObject::execute(JSContext* cx, HandleModuleObject self, MutableHandleValue rval)
 {
     MOZ_ASSERT(IsFrozen(cx, self));
 
@@ -959,36 +958,42 @@ InvokeSelfHostedMethod(JSContext* cx, HandleModuleObject self, HandlePropertyNam
 }
 
 /* static */ bool
-ModuleObject::DeclarationInstantiation(JSContext* cx, HandleModuleObject self)
+ModuleObject::Instantiate(JSContext* cx, HandleModuleObject self)
 {
-    return InvokeSelfHostedMethod(cx, self, cx->names().ModuleDeclarationInstantiation);
+    return InvokeSelfHostedMethod(cx, self, cx->names().ModuleInstantiate);
 }
 
 /* static */ bool
-ModuleObject::Evaluation(JSContext* cx, HandleModuleObject self)
+ModuleObject::Evaluate(JSContext* cx, HandleModuleObject self)
 {
-    return InvokeSelfHostedMethod(cx, self, cx->names().ModuleEvaluation);
+    return InvokeSelfHostedMethod(cx, self, cx->names().ModuleEvaluate);
 }
 
 DEFINE_GETTER_FUNCTIONS(ModuleObject, namespace_, NamespaceSlot)
-DEFINE_GETTER_FUNCTIONS(ModuleObject, state, StateSlot)
+DEFINE_GETTER_FUNCTIONS(ModuleObject, status, StatusSlot)
+DEFINE_GETTER_FUNCTIONS(ModuleObject, error, ErrorSlot)
 DEFINE_GETTER_FUNCTIONS(ModuleObject, requestedModules, RequestedModulesSlot)
 DEFINE_GETTER_FUNCTIONS(ModuleObject, importEntries, ImportEntriesSlot)
 DEFINE_GETTER_FUNCTIONS(ModuleObject, localExportEntries, LocalExportEntriesSlot)
 DEFINE_GETTER_FUNCTIONS(ModuleObject, indirectExportEntries, IndirectExportEntriesSlot)
 DEFINE_GETTER_FUNCTIONS(ModuleObject, starExportEntries, StarExportEntriesSlot)
+DEFINE_GETTER_FUNCTIONS(ModuleObject, dfsIndex, DFSIndexSlot)
+DEFINE_GETTER_FUNCTIONS(ModuleObject, dfsAncestorIndex, DFSAncestorIndexSlot)
 
 /* static */ bool
 GlobalObject::initModuleProto(JSContext* cx, Handle<GlobalObject*> global)
 {
     static const JSPropertySpec protoAccessors[] = {
         JS_PSG("namespace", ModuleObject_namespace_Getter, 0),
-        JS_PSG("state", ModuleObject_stateGetter, 0),
+        JS_PSG("status", ModuleObject_statusGetter, 0),
+        JS_PSG("error", ModuleObject_errorGetter, 0),
         JS_PSG("requestedModules", ModuleObject_requestedModulesGetter, 0),
         JS_PSG("importEntries", ModuleObject_importEntriesGetter, 0),
         JS_PSG("localExportEntries", ModuleObject_localExportEntriesGetter, 0),
         JS_PSG("indirectExportEntries", ModuleObject_indirectExportEntriesGetter, 0),
         JS_PSG("starExportEntries", ModuleObject_starExportEntriesGetter, 0),
+        JS_PSG("dfsIndex", ModuleObject_dfsIndexGetter, 0),
+        JS_PSG("dfsAncestorIndex", ModuleObject_dfsAncestorIndexGetter, 0),
         JS_PS_END
     };
 
@@ -997,6 +1002,8 @@ GlobalObject::initModuleProto(JSContext* cx, Handle<GlobalObject*> global)
         JS_SELF_HOSTED_FN("resolveExport", "ModuleResolveExport", 2, 0),
         JS_SELF_HOSTED_FN("declarationInstantiation", "ModuleDeclarationInstantiation", 0, 0),
         JS_SELF_HOSTED_FN("evaluation", "ModuleEvaluation", 0, 0),
+        JS_SELF_HOSTED_FN("declarationInstantiation", "ModuleInstantiate", 0, 0),
+        JS_SELF_HOSTED_FN("evaluation", "ModuleEvaluate", 0, 0),
         JS_FS_END
     };
 
diff --git a/js/src/builtin/ModuleObject.h b/js/src/builtin/ModuleObject.h
index 22db762ac..365fcd4bf 100644
--- a/js/src/builtin/ModuleObject.h
+++ b/js/src/builtin/ModuleObject.h
@@ -192,8 +192,8 @@ struct FunctionDeclaration
 
 using FunctionDeclarationVector = GCVector<FunctionDeclaration, 0, ZoneAllocPolicy>;
 
-// Possible values for ModuleState are defined in SelfHostingDefines.h.
-using ModuleState = int32_t;
+// Possible values for ModuleStatus are defined in SelfHostingDefines.h.
+using ModuleStatus = int32_t;
 
 class ModuleObject : public NativeObject
 {
@@ -204,7 +204,8 @@ class ModuleObject : public NativeObject
         InitialEnvironmentSlot,
         EnvironmentSlot,
         NamespaceSlot,
-        StateSlot,
+        StatusSlot,
+        ErrorSlot,
         HostDefinedSlot,
         RequestedModulesSlot,
         ImportEntriesSlot,
@@ -215,11 +216,21 @@ class ModuleObject : public NativeObject
         NamespaceExportsSlot,
         NamespaceBindingsSlot,
         FunctionDeclarationsSlot,
+        DFSIndexSlot,
+        DFSAncestorIndexSlot,
         SlotCount
     };
 
     static_assert(EnvironmentSlot == MODULE_OBJECT_ENVIRONMENT_SLOT,
                   "EnvironmentSlot must match self-hosting define");
+    static_assert(StatusSlot == MODULE_OBJECT_STATUS_SLOT,
+                  "StatusSlot must match self-hosting define");
+    static_assert(ErrorSlot == MODULE_OBJECT_ERROR_SLOT,
+                  "ErrorSlot must match self-hosting define");
+    static_assert(DFSIndexSlot == MODULE_OBJECT_DFS_INDEX_SLOT,
+                  "DFSIndexSlot must match self-hosting define");
+    static_assert(DFSAncestorIndexSlot == MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT,
+                  "DFSAncestorIndexSlot must match self-hosting define");
 
     static const Class class_;
 
@@ -244,7 +255,8 @@ class ModuleObject : public NativeObject
     ModuleEnvironmentObject& initialEnvironment() const;
     ModuleEnvironmentObject* environment() const;
     ModuleNamespaceObject* namespace_();
-    ModuleState state() const;
+    ModuleStatus status() const;
+    Value error() const;
     Value hostDefinedField() const;
     ArrayObject& requestedModules() const;
     ArrayObject& importEntries() const;
@@ -255,8 +267,8 @@ class ModuleObject : public NativeObject
     JSObject* namespaceExports();
     IndirectBindingMap* namespaceBindings();
 
-    static bool DeclarationInstantiation(JSContext* cx, HandleModuleObject self);
-    static bool Evaluation(JSContext* cx, HandleModuleObject self);
+    static bool Instantiate(JSContext* cx, HandleModuleObject self);
+    static bool Evaluate(JSContext* cx, HandleModuleObject self);
 
     void setHostDefinedField(const JS::Value& value);
 
@@ -269,10 +281,8 @@ class ModuleObject : public NativeObject
     // For intrinsic_InstantiateModuleFunctionDeclarations.
     static bool instantiateFunctionDeclarations(JSContext* cx, HandleModuleObject self);
 
-    void setState(ModuleState newState);
-
-    // For intrinsic_EvaluateModule.
-    static bool evaluate(JSContext* cx, HandleModuleObject self, MutableHandleValue rval);
+    // For intrinsic_ExecuteModule.
+    static bool execute(JSContext* cx, HandleModuleObject self, MutableHandleValue rval);
 
     // For intrinsic_NewModuleNamespace.
     static ModuleNamespaceObject* createNamespace(JSContext* cx, HandleModuleObject self,
diff --git a/js/src/builtin/SelfHostingDefines.h b/js/src/builtin/SelfHostingDefines.h
index 117ac7ffd..a06c2aa62 100644
--- a/js/src/builtin/SelfHostingDefines.h
+++ b/js/src/builtin/SelfHostingDefines.h
@@ -97,11 +97,17 @@
 #define REGEXP_STRING_ITERATOR_FLAGS_SLOT 2
 #define REGEXP_STRING_ITERATOR_DONE_SLOT 3
 
-#define MODULE_OBJECT_ENVIRONMENT_SLOT 2
-
-#define MODULE_STATE_FAILED       0
-#define MODULE_STATE_PARSED       1
-#define MODULE_STATE_INSTANTIATED 2
-#define MODULE_STATE_EVALUATED    3
+#define MODULE_OBJECT_ENVIRONMENT_SLOT        2
+#define MODULE_OBJECT_STATUS_SLOT             4
+#define MODULE_OBJECT_ERROR_SLOT              5
+#define MODULE_OBJECT_DFS_INDEX_SLOT          16
+#define MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT 17
+
+#define MODULE_STATUS_ERRORED        0
+#define MODULE_STATUS_UNINSTANTIATED 1
+#define MODULE_STATUS_INSTANTIATING  2
+#define MODULE_STATUS_INSTANTIATED   3
+#define MODULE_STATUS_EVALUATING     4
+#define MODULE_STATUS_EVALUATED      5
 
 #endif
diff --git a/js/src/builtin/Utilities.js b/js/src/builtin/Utilities.js
index d5f233d05..3916311db 100644
--- a/js/src/builtin/Utilities.js
+++ b/js/src/builtin/Utilities.js
@@ -27,13 +27,20 @@
 // Assertions and debug printing, defined here instead of in the header above
 // to make `assert` invisible to C++.
 #ifdef DEBUG
-#define assert(b, info) if (!(b)) AssertionFailed(__FILE__ + ":" + __LINE__ + ": " + info)
-#define dbg(msg) DumpMessage(callFunction(std_Array_pop, \
-                                          StringSplitString(__FILE__, '/')) \
-                             + '#' + __LINE__ + ': ' + msg)
+#define assert(b, info) \
+    do { \
+        if (!(b)) \
+            AssertionFailed(__FILE__ + ":" + __LINE__ + ": " + info) \
+    } while (false)
+#define dbg(msg) \
+    do { \
+        DumpMessage(callFunction(std_Array_pop, \
+                                 StringSplitString(__FILE__, '/')) + \
+                    '#' + __LINE__ + ': ' + msg) \
+    } while (false)
 #else
-#define assert(b, info) // Elided assertion.
-#define dbg(msg) // Elided debugging output.
+#define assert(b, info) do {} while (false) // Elided assertion.
+#define dbg(msg) do {} while (false) // Elided debugging output.
 #endif
 
 // All C++-implemented standard builtins library functions used in self-hosted
diff --git a/js/src/jit-test/tests/modules/ambiguous-star-export.js b/js/src/jit-test/tests/modules/ambiguous-star-export.js
index b8c91445c..94aa7ac4a 100644
--- a/js/src/jit-test/tests/modules/ambiguous-star-export.js
+++ b/js/src/jit-test/tests/modules/ambiguous-star-export.js
@@ -5,10 +5,11 @@
 load(libdir + "asserts.js");
 load(libdir + "dummyModuleResolveHook.js");
 
-function checkModuleEval(source, result) {
+function checkModuleEval(source) {
     let m = parseModule(source);
     m.declarationInstantiation();
-    assertEq(m.evaluation(), result);
+    m.evaluation();
+    return m;
 }
 
 function checkModuleSyntaxError(source) {
@@ -23,17 +24,19 @@ c.declarationInstantiation();
 c.evaluation();
 
 // Check importing/exporting non-ambiguous name works.
-checkModuleEval("import { a } from 'c'; a;", 1);
-checkModuleEval("export { a } from 'c';", undefined);
+let d = checkModuleEval("import { a } from 'c';");
+assertEq(getModuleEnvironmentValue(d, "a"), 1);
+checkModuleEval("export { a } from 'c';");
 
 // Check importing/exporting ambiguous name is a syntax error.
 checkModuleSyntaxError("import { b } from 'c';");
 checkModuleSyntaxError("export { b } from 'c';");
 
 // Check that namespace objects include only non-ambiguous names.
-let m = parseModule("import * as ns from 'c'; ns;");
+let m = parseModule("import * as ns from 'c';");
 m.declarationInstantiation();
-let ns = m.evaluation();
+m.evaluation();
+let ns = c.namespace;
 let names = Object.keys(ns);
 assertEq(names.length, 2);
 assertEq('a' in ns, true);
diff --git a/js/src/jit-test/tests/modules/bad-namespace-created.js b/js/src/jit-test/tests/modules/bad-namespace-created.js
new file mode 100644
index 000000000..127892d6e
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bad-namespace-created.js
@@ -0,0 +1,17 @@
+// Prior to https://github.com/tc39/ecma262/pull/916 it was possible for a
+// module namespace object to be successfully created that was later found to be
+// erroneous. Test that this is no longer the case.
+
+"use strict";
+
+load(libdir + "asserts.js");
+load(libdir + "dummyModuleResolveHook.js");
+
+moduleRepo['A'] = parseModule('import "B"; export {x} from "C"');
+moduleRepo['B'] = parseModule('import * as a from "A"');
+moduleRepo['C'] = parseModule('export * from "D"; export * from "E"');
+moduleRepo['D'] = parseModule('export let x');
+moduleRepo['E'] = parseModule('export let x');
+
+let m = moduleRepo['A'];
+assertThrowsInstanceOf(() => m.declarationInstantiation(), SyntaxError);
diff --git a/js/src/jit-test/tests/modules/bug-1284486.js b/js/src/jit-test/tests/modules/bug-1284486.js
index 9a3244ec3..08286393a 100644
--- a/js/src/jit-test/tests/modules/bug-1284486.js
+++ b/js/src/jit-test/tests/modules/bug-1284486.js
@@ -1,23 +1,36 @@
-// |jit-test| error: InternalError
-
 // This tests that attempting to perform ModuleDeclarationInstantation a second
-// time after a failure throws an error. Doing this would be a bug in the module
-// loader, which is expected to throw away modules if there is an error
-// instantiating them.
+// time after a failure re-throws the same error.
 //
 // The first attempt fails becuase module 'a' is not available. The second
 // attempt fails because of the previous failure (it would otherwise succeed as
 // 'a' is now available).
 
-let moduleRepo = {};
-setModuleResolveHook(function(module, specifier) {
-    return moduleRepo[specifier];
-});
+load(libdir + "dummyModuleResolveHook.js");
+
+let b = moduleRepo['b'] = parseModule("export var b = 3; export var c = 4;");
+let c = moduleRepo['c'] = parseModule("export * from 'a'; export * from 'b';");
+
+let e1;
+let threw = false;
 try {
-    let b = moduleRepo['b'] = parseModule("export var b = 3; export var c = 4;");
-    let c = moduleRepo['c'] = parseModule("export * from 'a'; export * from 'b';");
     c.declarationInstantiation();
-} catch (exc) {}
+} catch (exc) {
+    threw = true;
+    e1 = exc;
+}
+assertEq(threw, true);
+assertEq(typeof e1 === "undefined", false);
+
 let a = moduleRepo['a'] = parseModule("export var a = 1; export var b = 2;");
 let d = moduleRepo['d'] = parseModule("import { a } from 'c'; a;");
-d.declarationInstantiation();
+
+threw = false;
+let e2;
+try {
+    d.declarationInstantiation();
+} catch (exc) {
+    threw = true;
+    e2 = exc;
+}
+assertEq(threw, true);
+assertEq(e1, e2);
diff --git a/js/src/jit-test/tests/modules/bug-1287410.js b/js/src/jit-test/tests/modules/bug-1287410.js
index 8a891372a..7df5621a5 100644
--- a/js/src/jit-test/tests/modules/bug-1287410.js
+++ b/js/src/jit-test/tests/modules/bug-1287410.js
@@ -20,3 +20,5 @@ let d = moduleRepo['d'] = parseModule("import { a } from 'c'; a;");
 // Attempting to instantiate 'd' throws an error because depdency 'a' of
 // instantiated module 'c' is not instantiated.
 d.declarationInstantiation();
+d.evaluation();
+
diff --git a/js/src/jit-test/tests/modules/bug-1394492.js b/js/src/jit-test/tests/modules/bug-1394492.js
new file mode 100644
index 000000000..a0e5d2ac3
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1394492.js
@@ -0,0 +1,6 @@
+// |jit-test| error: NaN
+let m = parseModule(`
+  throw i => { return 5; }, m-1;
+`);
+m.declarationInstantiation();
+m.evaluation();
diff --git a/js/src/jit-test/tests/modules/global-scope.js b/js/src/jit-test/tests/modules/global-scope.js
index 90a9f7026..b99019fa8 100644
--- a/js/src/jit-test/tests/modules/global-scope.js
+++ b/js/src/jit-test/tests/modules/global-scope.js
@@ -1,32 +1,34 @@
 // Test interaction with global object and global lexical scope.
 
-function parseAndEvaluate(source) {
+function evalModuleAndCheck(source, expected) {
     let m = parseModule(source);
     m.declarationInstantiation();
-    return m.evaluation();
+    m.evaluation();
+    assertEq(getModuleEnvironmentValue(m, "r"), expected);
 }
 
 var x = 1;
-assertEq(parseAndEvaluate("let r = x; x = 2; r"), 1);
+evalModuleAndCheck("export let r = x; x = 2;", 1);
 assertEq(x, 2);
 
 let y = 3;
-assertEq(parseAndEvaluate("let r = y; y = 4; r"), 3);
+evalModuleAndCheck("export let r = y; y = 4;", 3);
 assertEq(y, 4);
 
 if (helperThreadCount() == 0)
     quit();
 
-function offThreadParseAndEvaluate(source) {
+function offThreadEvalModuleAndCheck(source, expected) {
     offThreadCompileModule(source);
     let m = finishOffThreadModule();
     print("compiled");
     m.declarationInstantiation();
-    return m.evaluation();
+    m.evaluation();
+    assertEq(getModuleEnvironmentValue(m, "r"), expected);
 }
 
-assertEq(offThreadParseAndEvaluate("let r = x; x = 5; r"), 2);
+offThreadEvalModuleAndCheck("export let r = x; x = 5;", 2);
 assertEq(x, 5);
 
-assertEq(offThreadParseAndEvaluate("let r = y; y = 6; r"), 4);
+offThreadEvalModuleAndCheck("export let r = y; y = 6;", 4);
 assertEq(y, 6);
diff --git a/js/src/jit-test/tests/modules/module-evaluation.js b/js/src/jit-test/tests/modules/module-evaluation.js
index eec13c040..84d88f19c 100644
--- a/js/src/jit-test/tests/modules/module-evaluation.js
+++ b/js/src/jit-test/tests/modules/module-evaluation.js
@@ -6,16 +6,17 @@ load(libdir + "dummyModuleResolveHook.js");
 function parseAndEvaluate(source) {
     let m = parseModule(source);
     m.declarationInstantiation();
-    return m.evaluation();
+    m.evaluation();
+    return m;
 }
 
 // Check the evaluation of an empty module succeeds.
-assertEq(typeof parseAndEvaluate(""), "undefined");
+parseAndEvaluate("");
 
 // Check evaluation returns evaluation result the first time, then undefined.
 let m = parseModule("1");
 m.declarationInstantiation();
-assertEq(m.evaluation(), 1);
+assertEq(m.evaluation(), undefined);
 assertEq(typeof m.evaluation(), "undefined");
 
 // Check top level variables are initialized by evaluation.
@@ -60,31 +61,35 @@ parseAndEvaluate("export default class { constructor() {} };");
 parseAndEvaluate("export default class foo { constructor() {} };");
 
 // Test default import
-m = parseModule("import a from 'a'; a;")
+m = parseModule("import a from 'a'; export { a };")
 m.declarationInstantiation();
-assertEq(m.evaluation(), 2);
+m.evaluation();
+assertEq(getModuleEnvironmentValue(m, "a"), 2);
 
 // Test named import
-m = parseModule("import { x as y } from 'a'; y;")
+m = parseModule("import { x as y } from 'a'; export { y };")
 m.declarationInstantiation();
-assertEq(m.evaluation(), 1);
+m.evaluation();
+assertEq(getModuleEnvironmentValue(m, "y"), 1);
 
 // Call exported function
-m = parseModule("import { f } from 'a'; f(3);")
+m = parseModule("import { f } from 'a'; export let x = f(3);")
 m.declarationInstantiation();
-assertEq(m.evaluation(), 4);
+m.evaluation();
+assertEq(getModuleEnvironmentValue(m, "x"), 4);
 
 // Test importing an indirect export
 moduleRepo['b'] = parseModule("export { x as z } from 'a';");
-assertEq(parseAndEvaluate("import { z } from 'b'; z"), 1);
+m = parseAndEvaluate("import { z } from 'b'; export { z }");
+assertEq(getModuleEnvironmentValue(m, "z"), 1);
 
 // Test cyclic dependencies
 moduleRepo['c1'] = parseModule("export var x = 1; export {y} from 'c2'");
 moduleRepo['c2'] = parseModule("export var y = 2; export {x} from 'c1'");
-assertDeepEq(parseAndEvaluate(`import { x as x1, y as y1 } from 'c1';
-                               import { x as x2, y as y2 } from 'c2';
-                               [x1, y1, x2, y2]`),
-             [1, 2, 1, 2]);
+m = parseAndEvaluate(`import { x as x1, y as y1 } from 'c1';
+                      import { x as x2, y as y2 } from 'c2';
+                      export let z = [x1, y1, x2, y2]`),
+assertDeepEq(getModuleEnvironmentValue(m, "z"), [1, 2, 1, 2]);
 
 // Import access in functions
 m = parseModule("import { x } from 'a'; function f() { return x; }")
diff --git a/js/src/js.msg b/js/src/js.msg
index 9dc5f4e9f..ee74c8dd5 100644
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -580,7 +580,7 @@ MSG_DEF(JSMSG_AMBIGUOUS_IMPORT,          1, JSEXN_SYNTAXERR, "ambiguous import '
 MSG_DEF(JSMSG_MISSING_NAMESPACE_EXPORT,  0, JSEXN_SYNTAXERR, "export not found for namespace")
 MSG_DEF(JSMSG_MISSING_EXPORT,            1, JSEXN_SYNTAXERR, "local binding for export '{0}' not found")
 MSG_DEF(JSMSG_MODULE_INSTANTIATE_FAILED, 0, JSEXN_INTERNALERR, "attempt to re-instantiate module after failure")
-MSG_DEF(JSMSG_BAD_MODULE_STATE,          0, JSEXN_INTERNALERR, "module record in unexpected state")
+MSG_DEF(JSMSG_BAD_MODULE_STATUS,         0, JSEXN_INTERNALERR, "module record has unexpected status")
 
 // Promise
 MSG_DEF(JSMSG_CANNOT_RESOLVE_PROMISE_WITH_ITSELF,       0, JSEXN_TYPEERR, "A promise cannot be resolved with itself.")
diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
index d75a3c33a..53ea4ebc6 100644
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -4709,7 +4709,7 @@ JS::ModuleDeclarationInstantiation(JSContext* cx, JS::HandleObject moduleArg)
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, moduleArg);
-    return ModuleObject::DeclarationInstantiation(cx, moduleArg.as<ModuleObject>());
+    return ModuleObject::Instantiate(cx, moduleArg.as<ModuleObject>());
 }
 
 JS_PUBLIC_API(bool)
@@ -4718,7 +4718,7 @@ JS::ModuleEvaluation(JSContext* cx, JS::HandleObject moduleArg)
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, moduleArg);
-    return ModuleObject::Evaluation(cx, moduleArg.as<ModuleObject>());
+    return ModuleObject::Evaluate(cx, moduleArg.as<ModuleObject>());
 }
 
 JS_PUBLIC_API(JSObject*)
diff --git a/js/src/vm/CommonPropertyNames.h b/js/src/vm/CommonPropertyNames.h
index b4a2de6f3..aa555886e 100644
--- a/js/src/vm/CommonPropertyNames.h
+++ b/js/src/vm/CommonPropertyNames.h
@@ -227,8 +227,8 @@
     macro(missingArguments, missingArguments, "missingArguments") \
     macro(module, module, "module") \
     macro(Module, Module, "Module") \
-    macro(ModuleDeclarationInstantiation, ModuleDeclarationInstantiation, "ModuleDeclarationInstantiation") \
-    macro(ModuleEvaluation, ModuleEvaluation, "ModuleEvaluation") \
+    macro(ModuleInstantiate, ModuleInstantiate, "ModuleInstantiate") \
+    macro(ModuleEvaluate, ModuleEvaluate, "ModuleEvaluate") \
     macro(month, month, "month") \
     macro(multiline, multiline, "multiline") \
     macro(name, name, "name") \
diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp
index 2216bf91e..89750d61a 100644
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -2060,24 +2060,12 @@ intrinsic_InstantiateModuleFunctionDeclarations(JSContext* cx, unsigned argc, Va
 }
 
 static bool
-intrinsic_SetModuleState(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    MOZ_ASSERT(args.length() == 2);
-    RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
-    ModuleState newState = args[1].toInt32();
-    module->setState(newState);
-    args.rval().setUndefined();
-    return true;
-}
-
-static bool
-intrinsic_EvaluateModule(JSContext* cx, unsigned argc, Value* vp)
+intrinsic_ExecuteModule(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     MOZ_ASSERT(args.length() == 1);
     RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
-    return ModuleObject::evaluate(cx, module, args.rval());
+    return ModuleObject::execute(cx, module, args.rval());
 }
 
 static bool
@@ -2630,8 +2618,7 @@ static const JSFunctionSpec intrinsic_functions[] = {
     JS_FN("CreateNamespaceBinding", intrinsic_CreateNamespaceBinding, 3, 0),
     JS_FN("InstantiateModuleFunctionDeclarations",
           intrinsic_InstantiateModuleFunctionDeclarations, 1, 0),
-    JS_FN("SetModuleState", intrinsic_SetModuleState, 1, 0),
-    JS_FN("EvaluateModule", intrinsic_EvaluateModule, 1, 0),
+    JS_FN("ExecuteModule", intrinsic_ExecuteModule, 1, 0),
     JS_FN("NewModuleNamespace", intrinsic_NewModuleNamespace, 2, 0),
     JS_FN("AddModuleNamespaceBinding", intrinsic_AddModuleNamespaceBinding, 4, 0),
     JS_FN("ModuleNamespaceExports", intrinsic_ModuleNamespaceExports, 1, 0),
-- 
cgit v1.2.3


From 57523a0debf898dc9583bfbc6c12f3e024f40b23 Mon Sep 17 00:00:00 2001
From: Moonchild <moonchild@palemoon.org>
Date: Fri, 3 Jul 2020 14:05:40 +0000
Subject: Issue #618 - Update code comments for ModuleInstantiate

---
 js/src/frontend/BytecodeEmitter.cpp | 2 +-
 js/src/frontend/Parser.cpp          | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

(limited to 'js')

diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
index 18cc7d954..654336a64 100644
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -8261,7 +8261,7 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
     if (topLevelFunction) {
         if (sc->isModuleContext()) {
             // For modules, we record the function and instantiate the binding
-            // during ModuleDeclarationInstantiation(), before the script is run.
+            // during ModuleInstantiate(), before the script is run.
 
             RootedModuleObject module(cx, sc->asModuleContext()->module());
             if (!module->noteFunctionDeclaration(cx, name, fun))
diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
index 810d589be..59783a759 100644
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -5038,7 +5038,7 @@ Parser<FullParseHandler>::namedImportsOrNamespaceImport(TokenKind tt, Node impor
         // Namespace imports are are not indirect bindings but lexical
         // definitions that hold a module namespace object. They are treated
         // as const variables which are initialized during the
-        // ModuleDeclarationInstantiation step.
+        // ModuleInstantiate step.
         RootedPropertyName bindingName(context, importedBinding());
         if (!bindingName)
             return false;
-- 
cgit v1.2.3


From 7bf3e4c46475a7aa936d702eb38d65d9126008f2 Mon Sep 17 00:00:00 2001
From: Moonchild <moonchild@palemoon.org>
Date: Fri, 3 Jul 2020 14:15:55 +0000
Subject: Issue #618 - Add APIs to query module record errors

Ref: BZ 1388728
---
 js/src/jsapi.cpp | 14 ++++++++++++++
 js/src/jsapi.h   |  6 ++++++
 2 files changed, 20 insertions(+)

(limited to 'js')

diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
index 53ea4ebc6..f8c34885b 100644
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -4739,6 +4739,20 @@ JS::GetModuleScript(JSContext* cx, JS::HandleObject moduleArg)
     return moduleArg->as<ModuleObject>().script();
 }
 
+JS_PUBLIC_API(bool)
+JS::IsModuleErrored(JSObject* moduleArg)
+{
+    AssertHeapIsIdle();
+    return moduleArg->as<ModuleObject>().status() == MODULE_STATUS_ERRORED;
+}
+
+JS_PUBLIC_API(JS::Value)
+JS::GetModuleError(JSObject* moduleArg)
+{
+    AssertHeapIsIdle();
+    return moduleArg->as<ModuleObject>().error();
+}
+
 JS_PUBLIC_API(JSObject*)
 JS_New(JSContext* cx, HandleObject ctor, const JS::HandleValueArray& inputArgs)
 {
diff --git a/js/src/jsapi.h b/js/src/jsapi.h
index 9138a4a92..5e0259587 100644
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -4396,6 +4396,12 @@ GetRequestedModules(JSContext* cx, JS::HandleObject moduleRecord);
 extern JS_PUBLIC_API(JSScript*)
 GetModuleScript(JSContext* cx, JS::HandleObject moduleRecord);
 
+extern JS_PUBLIC_API(bool)
+IsModuleErrored(JSObject* moduleRecord);
+
+extern JS_PUBLIC_API(JS::Value)
+GetModuleError(JSObject* moduleRecord);
+
 } /* namespace JS */
 
 extern JS_PUBLIC_API(bool)
-- 
cgit v1.2.3


From ef8d18da70c2c2efedc5e4db1dca0ece30ac5d14 Mon Sep 17 00:00:00 2001
From: Moonchild <moonchild@palemoon.org>
Date: Fri, 3 Jul 2020 14:21:27 +0000
Subject: Issue #618 - Match JSAPI names with the changes in
 9ca74147225eed305e28c7887f9b2251aeeb0f36

Ref: BZ 1388728
---
 js/src/jsapi.cpp |  4 ++--
 js/src/jsapi.h   | 13 ++++++-------
 2 files changed, 8 insertions(+), 9 deletions(-)

(limited to 'js')

diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
index f8c34885b..9c24f1676 100644
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -4704,7 +4704,7 @@ JS::GetModuleHostDefinedField(JSObject* module)
 }
 
 JS_PUBLIC_API(bool)
-JS::ModuleDeclarationInstantiation(JSContext* cx, JS::HandleObject moduleArg)
+JS::ModuleInstantiate(JSContext* cx, JS::HandleObject moduleArg)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
@@ -4713,7 +4713,7 @@ JS::ModuleDeclarationInstantiation(JSContext* cx, JS::HandleObject moduleArg)
 }
 
 JS_PUBLIC_API(bool)
-JS::ModuleEvaluation(JSContext* cx, JS::HandleObject moduleArg)
+JS::ModuleEvaluate(JSContext* cx, JS::HandleObject moduleArg)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
diff --git a/js/src/jsapi.h b/js/src/jsapi.h
index 5e0259587..9c3bf8151 100644
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -4356,28 +4356,27 @@ extern JS_PUBLIC_API(JS::Value)
 GetModuleHostDefinedField(JSObject* module);
 
 /*
- * Perform the ModuleDeclarationInstantiation operation on on the give source
- * text module record.
+ * Perform the ModuleInstantiate operation on the given source text module
+ * record.
  *
  * This transitively resolves all module dependencies (calling the
  * HostResolveImportedModule hook) and initializes the environment record for
  * the module.
  */
 extern JS_PUBLIC_API(bool)
-ModuleDeclarationInstantiation(JSContext* cx, JS::HandleObject moduleRecord);
+ModuleInstantiate(JSContext* cx, JS::HandleObject moduleRecord);
 
 /*
- * Perform the ModuleEvaluation operation on on the give source text module
- * record.
+ * Perform the ModuleEvaluate operation on the given source text module record.
  *
  * This does nothing if this module has already been evaluated. Otherwise, it
  * transitively evaluates all dependences of this module and then evaluates this
  * module.
  *
- * ModuleDeclarationInstantiation must have completed prior to calling this.
+ * ModuleInstantiate must have completed prior to calling this.
  */
 extern JS_PUBLIC_API(bool)
-ModuleEvaluation(JSContext* cx, JS::HandleObject moduleRecord);
+ModuleEvaluate(JSContext* cx, JS::HandleObject moduleRecord);
 
 /*
  * Get a list of the module specifiers used by a source text module
-- 
cgit v1.2.3


From 765c90318f192ba18848095133b0531c3162678d Mon Sep 17 00:00:00 2001
From: Moonchild <moonchild@palemoon.org>
Date: Fri, 3 Jul 2020 15:59:00 +0000
Subject: Issue #618 - Fix JSAPI additions to pass the JS context.

---
 js/src/jsapi.cpp | 10 ++++++----
 js/src/jsapi.h   |  4 ++--
 2 files changed, 8 insertions(+), 6 deletions(-)

(limited to 'js')

diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
index 9c24f1676..cb0851f80 100644
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -4740,16 +4740,18 @@ JS::GetModuleScript(JSContext* cx, JS::HandleObject moduleArg)
 }
 
 JS_PUBLIC_API(bool)
-JS::IsModuleErrored(JSObject* moduleArg)
+JS::IsModuleErrored(JSContext* cx, JSObject* moduleArg)
 {
-    AssertHeapIsIdle();
+    AssertHeapIsIdle(cx);
+    CHECK_REQUEST(cx);
     return moduleArg->as<ModuleObject>().status() == MODULE_STATUS_ERRORED;
 }
 
 JS_PUBLIC_API(JS::Value)
-JS::GetModuleError(JSObject* moduleArg)
+JS::GetModuleError(JSContext* cx, JSObject* moduleArg)
 {
-    AssertHeapIsIdle();
+    AssertHeapIsIdle(cx);
+    CHECK_REQUEST(cx);
     return moduleArg->as<ModuleObject>().error();
 }
 
diff --git a/js/src/jsapi.h b/js/src/jsapi.h
index 9c3bf8151..6d306edc5 100644
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -4396,10 +4396,10 @@ extern JS_PUBLIC_API(JSScript*)
 GetModuleScript(JSContext* cx, JS::HandleObject moduleRecord);
 
 extern JS_PUBLIC_API(bool)
-IsModuleErrored(JSObject* moduleRecord);
+IsModuleErrored(JSContext* cx, JSObject* moduleRecord);
 
 extern JS_PUBLIC_API(JS::Value)
-GetModuleError(JSObject* moduleRecord);
+GetModuleError(JSContext* cx, JSObject* moduleRecord);
 
 } /* namespace JS */
 
-- 
cgit v1.2.3


From 40aad1a2209607b973170f4fb64548e5d8103402 Mon Sep 17 00:00:00 2001
From: Moonchild <moonchild@palemoon.org>
Date: Sat, 4 Jul 2020 12:59:38 +0000
Subject: Issue #618 - Remove context and heap-idle check

For checking if a module is in an error state and what the error is, it
shouldn't matter if we are currently GC-ing or not. So we don't need to check
for it, which removes the requirement to pass in the JS context (needed for
AssertHeapIsIdle's runtime check); this unblocks progress where otherwise we'd
have to figure out what the context is at the module level just to satisfy this
check.
---
 js/src/jsapi.cpp | 8 ++------
 js/src/jsapi.h   | 4 ++--
 2 files changed, 4 insertions(+), 8 deletions(-)

(limited to 'js')

diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
index cb0851f80..cf5880e03 100644
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -4740,18 +4740,14 @@ JS::GetModuleScript(JSContext* cx, JS::HandleObject moduleArg)
 }
 
 JS_PUBLIC_API(bool)
-JS::IsModuleErrored(JSContext* cx, JSObject* moduleArg)
+JS::IsModuleErrored(JSObject* moduleArg)
 {
-    AssertHeapIsIdle(cx);
-    CHECK_REQUEST(cx);
     return moduleArg->as<ModuleObject>().status() == MODULE_STATUS_ERRORED;
 }
 
 JS_PUBLIC_API(JS::Value)
-JS::GetModuleError(JSContext* cx, JSObject* moduleArg)
+JS::GetModuleError(JSObject* moduleArg)
 {
-    AssertHeapIsIdle(cx);
-    CHECK_REQUEST(cx);
     return moduleArg->as<ModuleObject>().error();
 }
 
diff --git a/js/src/jsapi.h b/js/src/jsapi.h
index 6d306edc5..9c3bf8151 100644
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -4396,10 +4396,10 @@ extern JS_PUBLIC_API(JSScript*)
 GetModuleScript(JSContext* cx, JS::HandleObject moduleRecord);
 
 extern JS_PUBLIC_API(bool)
-IsModuleErrored(JSContext* cx, JSObject* moduleRecord);
+IsModuleErrored(JSObject* moduleRecord);
 
 extern JS_PUBLIC_API(JS::Value)
-GetModuleError(JSContext* cx, JSObject* moduleRecord);
+GetModuleError(JSObject* moduleRecord);
 
 } /* namespace JS */
 
-- 
cgit v1.2.3


From 83abc5af599d4531c68c2e7a84caab9545854594 Mon Sep 17 00:00:00 2001
From: Moonchild <moonchild@palemoon.org>
Date: Sat, 4 Jul 2020 23:12:13 +0000
Subject: Issue #618 - Report source position information (line/column)

Report source position information for module export resolution failures.

Ref: BZ 1362098
---
 js/src/builtin/Module.js             | 37 +++++++++--------
 js/src/builtin/ModuleObject.cpp      | 79 ++++++++++++++++++++++++++++++------
 js/src/builtin/ModuleObject.h        | 26 +++++++++---
 js/src/builtin/ReflectParse.cpp      |  2 +-
 js/src/frontend/BytecodeCompiler.cpp |  2 +-
 js/src/js.msg                        |  8 ++--
 js/src/vm/SelfHosting.cpp            | 46 +++++++++++++++++++++
 7 files changed, 161 insertions(+), 39 deletions(-)

(limited to 'js')

diff --git a/js/src/builtin/Module.js b/js/src/builtin/Module.js
index 064293670..b3365b505 100644
--- a/js/src/builtin/Module.js
+++ b/js/src/builtin/Module.js
@@ -436,8 +436,10 @@ function ModuleDeclarationEnvironmentSetup(module)
         let resolution = callFunction(module.resolveExport, module, e.exportName);
         assert(resolution.resolved || resolution.module,
                "Unexpected failure to resolve export in ModuleDeclarationEnvironmentSetup");
-        if (!resolution.resolved)
-            return ResolutionError(resolution, "indirectExport", e.exportName)
+        if (!resolution.resolved) {
+            return ResolutionError(resolution, "indirectExport", e.exportName,
+                                   e.lineNumber, e.columnNumber)
+        }
     }
 
     // Steps 5-6
@@ -459,8 +461,10 @@ function ModuleDeclarationEnvironmentSetup(module)
             if (!resolution.resolved && !resolution.module)
                 resolution.module = module;
 
-            if (!resolution.resolved)
-                return ResolutionError(resolution, "import", imp.importName);
+            if (!resolution.resolved) {
+                return ResolutionError(resolution, "import", imp.importName,
+                                       imp.lineNumber, imp.columnNumber);
+            }
 
             CreateImportBinding(env, imp.localName, resolution.module, resolution.bindingName);
         }
@@ -470,7 +474,7 @@ function ModuleDeclarationEnvironmentSetup(module)
 }
 
 // 15.2.1.16.4.3 ResolutionError(module)
-function ResolutionError(resolution, kind, name)
+function ResolutionError(resolution, kind, name, line, column)
 {
     let module = resolution.module;
     assert(module !== null,
@@ -483,21 +487,22 @@ function ResolutionError(resolution, kind, name)
     assert(kind === "import" || kind === "indirectExport",
            "Unexpected kind in ResolutionError");
 
-    let message;
+    assert(line > 0,
+           "Line number should be present for all imports and indirect exports");
+
+    let errorNumber;
     if (kind === "import") {
-        message = resolution.ambiguous ? JSMSG_AMBIGUOUS_IMPORT
-                                       : JSMSG_MISSING_IMPORT;
+        errorNumber = resolution.ambiguous ? JSMSG_AMBIGUOUS_IMPORT
+                                           : JSMSG_MISSING_IMPORT;
     } else {
-        message = resolution.ambiguous ? JSMSG_AMBIGUOUS_INDIRECT_EXPORT
-                                       : JSMSG_MISSING_INDIRECT_EXPORT;
+        errorNumber = resolution.ambiguous ? JSMSG_AMBIGUOUS_INDIRECT_EXPORT
+                                           : JSMSG_MISSING_INDIRECT_EXPORT;
     }
 
-    try {
-        ThrowSyntaxError(message, name);
-    } catch (error) {
-        RecordModuleError(module, error);
-        throw error;
-    }
+    let message = GetErrorMessage(errorNumber) + ": " + name;
+    let error = CreateModuleSyntaxError(module, line, column, message);
+    RecordModuleError(module, error);
+    throw error;
 }
 
 // 15.2.1.16.5 ModuleEvaluate()
diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp
index 0a836c75b..09193c9ca 100644
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -70,6 +70,15 @@ ModuleValueGetter(JSContext* cx, unsigned argc, Value* vp)
         return &value.toString()->asAtom();                                   \
     }
 
+#define DEFINE_UINT32_ACCESSOR_METHOD(cls, name)                              \
+    uint32_t                                                                  \
+    cls::name() const                                                         \
+    {                                                                         \
+        Value value = cls##_##name##Value(this);                              \
+        MOZ_ASSERT(value.toInt32() >= 0);                                     \
+        return value.toInt32();                                               \
+    }
+
 ///////////////////////////////////////////////////////////////////////////
 // ImportEntryObject
 
@@ -83,10 +92,14 @@ ImportEntryObject::class_ = {
 DEFINE_GETTER_FUNCTIONS(ImportEntryObject, moduleRequest, ModuleRequestSlot)
 DEFINE_GETTER_FUNCTIONS(ImportEntryObject, importName, ImportNameSlot)
 DEFINE_GETTER_FUNCTIONS(ImportEntryObject, localName, LocalNameSlot)
+DEFINE_GETTER_FUNCTIONS(ImportEntryObject, lineNumber, LineNumberSlot)
+DEFINE_GETTER_FUNCTIONS(ImportEntryObject, columnNumber, ColumnNumberSlot)
 
 DEFINE_ATOM_ACCESSOR_METHOD(ImportEntryObject, moduleRequest)
 DEFINE_ATOM_ACCESSOR_METHOD(ImportEntryObject, importName)
 DEFINE_ATOM_ACCESSOR_METHOD(ImportEntryObject, localName)
+DEFINE_UINT32_ACCESSOR_METHOD(ImportEntryObject, lineNumber)
+DEFINE_UINT32_ACCESSOR_METHOD(ImportEntryObject, columnNumber)
 
 /* static */ bool
 ImportEntryObject::isInstance(HandleValue value)
@@ -101,6 +114,8 @@ GlobalObject::initImportEntryProto(JSContext* cx, Handle<GlobalObject*> global)
         JS_PSG("moduleRequest", ImportEntryObject_moduleRequestGetter, 0),
         JS_PSG("importName", ImportEntryObject_importNameGetter, 0),
         JS_PSG("localName", ImportEntryObject_localNameGetter, 0),
+        JS_PSG("lineNumber", ImportEntryObject_lineNumberGetter, 0),
+        JS_PSG("columnNumber", ImportEntryObject_columnNumberGetter, 0),
         JS_PS_END
     };
 
@@ -119,8 +134,12 @@ GlobalObject::initImportEntryProto(JSContext* cx, Handle<GlobalObject*> global)
 ImportEntryObject::create(ExclusiveContext* cx,
                           HandleAtom moduleRequest,
                           HandleAtom importName,
-                          HandleAtom localName)
+                          HandleAtom localName,
+                          uint32_t lineNumber,
+                          uint32_t columnNumber)
 {
+    MOZ_ASSERT(lineNumber > 0);
+
     RootedObject proto(cx, cx->global()->getImportEntryPrototype());
     RootedObject obj(cx, NewObjectWithGivenProto(cx, &class_, proto));
     if (!obj)
@@ -130,6 +149,8 @@ ImportEntryObject::create(ExclusiveContext* cx,
     self->initReservedSlot(ModuleRequestSlot, StringValue(moduleRequest));
     self->initReservedSlot(ImportNameSlot, StringValue(importName));
     self->initReservedSlot(LocalNameSlot, StringValue(localName));
+    self->initReservedSlot(LineNumberSlot, Int32Value(lineNumber));
+    self->initReservedSlot(ColumnNumberSlot, Int32Value(columnNumber));
     return self;
 }
 
@@ -147,11 +168,15 @@ DEFINE_GETTER_FUNCTIONS(ExportEntryObject, exportName, ExportNameSlot)
 DEFINE_GETTER_FUNCTIONS(ExportEntryObject, moduleRequest, ModuleRequestSlot)
 DEFINE_GETTER_FUNCTIONS(ExportEntryObject, importName, ImportNameSlot)
 DEFINE_GETTER_FUNCTIONS(ExportEntryObject, localName, LocalNameSlot)
+DEFINE_GETTER_FUNCTIONS(ExportEntryObject, lineNumber, LineNumberSlot)
+DEFINE_GETTER_FUNCTIONS(ExportEntryObject, columnNumber, ColumnNumberSlot)
 
 DEFINE_ATOM_OR_NULL_ACCESSOR_METHOD(ExportEntryObject, exportName)
 DEFINE_ATOM_OR_NULL_ACCESSOR_METHOD(ExportEntryObject, moduleRequest)
 DEFINE_ATOM_OR_NULL_ACCESSOR_METHOD(ExportEntryObject, importName)
 DEFINE_ATOM_OR_NULL_ACCESSOR_METHOD(ExportEntryObject, localName)
+DEFINE_UINT32_ACCESSOR_METHOD(ExportEntryObject, lineNumber)
+DEFINE_UINT32_ACCESSOR_METHOD(ExportEntryObject, columnNumber)
 
 /* static */ bool
 ExportEntryObject::isInstance(HandleValue value)
@@ -167,6 +192,8 @@ GlobalObject::initExportEntryProto(JSContext* cx, Handle<GlobalObject*> global)
         JS_PSG("moduleRequest", ExportEntryObject_moduleRequestGetter, 0),
         JS_PSG("importName", ExportEntryObject_importNameGetter, 0),
         JS_PSG("localName", ExportEntryObject_localNameGetter, 0),
+        JS_PSG("lineNumber", ExportEntryObject_lineNumberGetter, 0),
+        JS_PSG("columnNumber", ExportEntryObject_columnNumberGetter, 0),
         JS_PS_END
     };
 
@@ -192,8 +219,13 @@ ExportEntryObject::create(ExclusiveContext* cx,
                           HandleAtom maybeExportName,
                           HandleAtom maybeModuleRequest,
                           HandleAtom maybeImportName,
-                          HandleAtom maybeLocalName)
+                          HandleAtom maybeLocalName,
+                          uint32_t lineNumber,
+                          uint32_t columnNumber)
 {
+    // Line and column numbers are optional for export entries since direct
+    // entries are checked at parse time.
+
     RootedObject proto(cx, cx->global()->getExportEntryPrototype());
     RootedObject obj(cx, NewObjectWithGivenProto(cx, &class_, proto));
     if (!obj)
@@ -204,6 +236,8 @@ ExportEntryObject::create(ExclusiveContext* cx,
     self->initReservedSlot(ModuleRequestSlot, StringOrNullValue(maybeModuleRequest));
     self->initReservedSlot(ImportNameSlot, StringOrNullValue(maybeImportName));
     self->initReservedSlot(LocalNameSlot, StringOrNullValue(maybeLocalName));
+    self->initReservedSlot(LineNumberSlot, Int32Value(lineNumber));
+    self->initReservedSlot(ColumnNumberSlot, Int32Value(columnNumber));
     return self;
 }
 
@@ -1025,9 +1059,11 @@ GlobalObject::initModuleProto(JSContext* cx, Handle<GlobalObject*> global)
 ///////////////////////////////////////////////////////////////////////////
 // ModuleBuilder
 
-ModuleBuilder::ModuleBuilder(ExclusiveContext* cx, HandleModuleObject module)
+ModuleBuilder::ModuleBuilder(ExclusiveContext* cx, HandleModuleObject module,
+                             const frontend::TokenStream& tokenStream)
   : cx_(cx),
     module_(cx, module),
+    tokenStream_(tokenStream),
     requestedModules_(cx, AtomVector(cx)),
     importedBoundNames_(cx, AtomVector(cx)),
     importEntries_(cx, ImportEntryVector(cx)),
@@ -1052,6 +1088,7 @@ ModuleBuilder::buildTables()
                     if (!localExportEntries_.append(exp))
                         return false;
                 } else {
+                    MOZ_ASSERT(exp->lineNumber());
                     RootedAtom exportName(cx_, exp->exportName());
                     RootedAtom moduleRequest(cx_, importEntry->moduleRequest());
                     RootedAtom importName(cx_, importEntry->importName());
@@ -1060,7 +1097,9 @@ ModuleBuilder::buildTables()
                                                             exportName,
                                                             moduleRequest,
                                                             importName,
-                                                            nullptr);
+                                                            nullptr,
+                                                            exp->lineNumber(),
+                                                            exp->columnNumber());
                     if (!exportEntry || !indirectExportEntries_.append(exportEntry))
                         return false;
                 }
@@ -1069,6 +1108,7 @@ ModuleBuilder::buildTables()
             if (!starExportEntries_.append(exp))
                 return false;
         } else {
+            MOZ_ASSERT(exp->lineNumber());
             if (!indirectExportEntries_.append(exp))
                 return false;
         }
@@ -1133,8 +1173,12 @@ ModuleBuilder::processImport(frontend::ParseNode* pn)
         if (!importedBoundNames_.append(localName))
             return false;
 
+        uint32_t line;
+        uint32_t column;
+        tokenStream_.srcCoords.lineNumAndColumnIndex(spec->pn_left->pn_pos.begin, &line, &column);
+
         RootedImportEntryObject importEntry(cx_);
-        importEntry = ImportEntryObject::create(cx_, module, importName, localName);
+        importEntry = ImportEntryObject::create(cx_, module, importName, localName, line, column);
         if (!importEntry || !importEntries_.append(importEntry))
             return false;
     }
@@ -1165,7 +1209,7 @@ ModuleBuilder::processExport(frontend::ParseNode* pn)
             MOZ_ASSERT(spec->isKind(PNK_EXPORT_SPEC));
             RootedAtom localName(cx_, spec->pn_left->pn_atom);
             RootedAtom exportName(cx_, spec->pn_right->pn_atom);
-            if (!appendExportEntry(exportName, localName))
+            if (!appendExportEntry(exportName, localName, spec))
                 return false;
         }
         break;
@@ -1230,12 +1274,12 @@ ModuleBuilder::processExportFrom(frontend::ParseNode* pn)
         if (spec->isKind(PNK_EXPORT_SPEC)) {
             RootedAtom bindingName(cx_, spec->pn_left->pn_atom);
             RootedAtom exportName(cx_, spec->pn_right->pn_atom);
-            if (!appendExportFromEntry(exportName, module, bindingName))
+            if (!appendExportFromEntry(exportName, module, bindingName, spec->pn_left))
                 return false;
         } else {
             MOZ_ASSERT(spec->isKind(PNK_EXPORT_BATCH_SPEC));
             RootedAtom importName(cx_, cx_->names().star);
-            if (!appendExportFromEntry(nullptr, module, importName))
+            if (!appendExportFromEntry(nullptr, module, importName, spec))
                 return false;
         }
     }
@@ -1264,19 +1308,30 @@ ModuleBuilder::hasExportedName(JSAtom* name) const
 }
 
 bool
-ModuleBuilder::appendExportEntry(HandleAtom exportName, HandleAtom localName)
+ModuleBuilder::appendExportEntry(HandleAtom exportName, HandleAtom localName, ParseNode* node)
 {
+    uint32_t line = 0;
+    uint32_t column = 0;
+    if (node)
+        tokenStream_.srcCoords.lineNumAndColumnIndex(node->pn_pos.begin, &line, &column);
+
     Rooted<ExportEntryObject*> exportEntry(cx_);
-    exportEntry = ExportEntryObject::create(cx_, exportName, nullptr, nullptr, localName);
+    exportEntry = ExportEntryObject::create(cx_, exportName, nullptr, nullptr, localName,
+                                            line, column);
     return exportEntry && exportEntries_.append(exportEntry);
 }
 
 bool
 ModuleBuilder::appendExportFromEntry(HandleAtom exportName, HandleAtom moduleRequest,
-                                     HandleAtom importName)
+                                     HandleAtom importName, ParseNode* node)
 {
+    uint32_t line;
+    uint32_t column;
+    tokenStream_.srcCoords.lineNumAndColumnIndex(node->pn_pos.begin, &line, &column);
+
     Rooted<ExportEntryObject*> exportEntry(cx_);
-    exportEntry = ExportEntryObject::create(cx_, exportName, moduleRequest, importName, nullptr);
+    exportEntry = ExportEntryObject::create(cx_, exportName, moduleRequest, importName, nullptr,
+                                            line, column);
     return exportEntry && exportEntries_.append(exportEntry);
 }
 
diff --git a/js/src/builtin/ModuleObject.h b/js/src/builtin/ModuleObject.h
index 365fcd4bf..be0315215 100644
--- a/js/src/builtin/ModuleObject.h
+++ b/js/src/builtin/ModuleObject.h
@@ -24,6 +24,7 @@ class ModuleObject;
 
 namespace frontend {
 class ParseNode;
+class TokenStream;
 } /* namespace frontend */
 
 typedef Rooted<ModuleObject*> RootedModuleObject;
@@ -39,6 +40,8 @@ class ImportEntryObject : public NativeObject
         ModuleRequestSlot = 0,
         ImportNameSlot,
         LocalNameSlot,
+        LineNumberSlot,
+        ColumnNumberSlot,
         SlotCount
     };
 
@@ -48,10 +51,14 @@ class ImportEntryObject : public NativeObject
     static ImportEntryObject* create(ExclusiveContext* cx,
                                      HandleAtom moduleRequest,
                                      HandleAtom importName,
-                                     HandleAtom localName);
+                                     HandleAtom localName,
+                                     uint32_t lineNumber,
+                                     uint32_t columnNumber);
     JSAtom* moduleRequest() const;
     JSAtom* importName() const;
     JSAtom* localName() const;
+    uint32_t lineNumber() const;
+    uint32_t columnNumber() const;
 };
 
 typedef Rooted<ImportEntryObject*> RootedImportEntryObject;
@@ -66,6 +73,8 @@ class ExportEntryObject : public NativeObject
         ModuleRequestSlot,
         ImportNameSlot,
         LocalNameSlot,
+        LineNumberSlot,
+        ColumnNumberSlot,
         SlotCount
     };
 
@@ -76,11 +85,15 @@ class ExportEntryObject : public NativeObject
                                      HandleAtom maybeExportName,
                                      HandleAtom maybeModuleRequest,
                                      HandleAtom maybeImportName,
-                                     HandleAtom maybeLocalName);
+                                     HandleAtom maybeLocalName,
+                                     uint32_t lineNumber,
+                                     uint32_t columnNumber);
     JSAtom* exportName() const;
     JSAtom* moduleRequest() const;
     JSAtom* importName() const;
     JSAtom* localName() const;
+    uint32_t lineNumber() const;
+    uint32_t columnNumber() const;
 };
 
 typedef Rooted<ExportEntryObject*> RootedExportEntryObject;
@@ -304,7 +317,8 @@ class ModuleObject : public NativeObject
 class MOZ_STACK_CLASS ModuleBuilder
 {
   public:
-    explicit ModuleBuilder(ExclusiveContext* cx, HandleModuleObject module);
+    explicit ModuleBuilder(ExclusiveContext* cx, HandleModuleObject module,
+                           const frontend::TokenStream& tokenStream);
 
     bool processImport(frontend::ParseNode* pn);
     bool processExport(frontend::ParseNode* pn);
@@ -329,6 +343,7 @@ class MOZ_STACK_CLASS ModuleBuilder
 
     ExclusiveContext* cx_;
     RootedModuleObject module_;
+    const frontend::TokenStream& tokenStream_;
     RootedAtomVector requestedModules_;
     RootedAtomVector importedBoundNames_;
     RootedImportEntryVector importEntries_;
@@ -339,9 +354,10 @@ class MOZ_STACK_CLASS ModuleBuilder
 
     ImportEntryObject* importEntryFor(JSAtom* localName) const;
 
-    bool appendExportEntry(HandleAtom exportName, HandleAtom localName);
+    bool appendExportEntry(HandleAtom exportName, HandleAtom localName,
+                           frontend::ParseNode* node = nullptr);
     bool appendExportFromEntry(HandleAtom exportName, HandleAtom moduleRequest,
-                               HandleAtom importName);
+                               HandleAtom importName, frontend::ParseNode* node);
 
     bool maybeAppendRequestedModule(HandleAtom module);
 
diff --git a/js/src/builtin/ReflectParse.cpp b/js/src/builtin/ReflectParse.cpp
index a8065d6d1..5cb81355f 100644
--- a/js/src/builtin/ReflectParse.cpp
+++ b/js/src/builtin/ReflectParse.cpp
@@ -3741,7 +3741,7 @@ reflect_parse(JSContext* cx, uint32_t argc, Value* vp)
         if (!module)
             return false;
 
-        ModuleBuilder builder(cx, module);
+        ModuleBuilder builder(cx, module, parser.tokenStream);
         ModuleSharedContext modulesc(cx, module, &cx->global()->emptyGlobalScope(), builder);
         pn = parser.moduleBody(&modulesc);
         if (!pn)
diff --git a/js/src/frontend/BytecodeCompiler.cpp b/js/src/frontend/BytecodeCompiler.cpp
index ccfe3cd2e..3c2bcc1ed 100644
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -405,7 +405,7 @@ BytecodeCompiler::compileModule()
 
     module->init(script);
 
-    ModuleBuilder builder(cx, module);
+    ModuleBuilder builder(cx, module, parser->tokenStream);
     ModuleSharedContext modulesc(cx, module, enclosingScope, builder);
     ParseNode* pn = parser->moduleBody(&modulesc);
     if (!pn)
diff --git a/js/src/js.msg b/js/src/js.msg
index ee74c8dd5..9c508ebbd 100644
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -573,10 +573,10 @@ MSG_DEF(JSMSG_REINIT_THIS,       0, JSEXN_REFERENCEERR, "super() called twice in
 
 // Modules
 MSG_DEF(JSMSG_BAD_DEFAULT_EXPORT,        0, JSEXN_SYNTAXERR, "default export cannot be provided by export *")
-MSG_DEF(JSMSG_MISSING_INDIRECT_EXPORT,   1, JSEXN_SYNTAXERR, "indirect export '{0}' not found")
-MSG_DEF(JSMSG_AMBIGUOUS_INDIRECT_EXPORT, 1, JSEXN_SYNTAXERR, "ambiguous indirect export '{0}'")
-MSG_DEF(JSMSG_MISSING_IMPORT,            1, JSEXN_SYNTAXERR, "import '{0}' not found")
-MSG_DEF(JSMSG_AMBIGUOUS_IMPORT,          1, JSEXN_SYNTAXERR, "ambiguous import '{0}'")
+MSG_DEF(JSMSG_MISSING_INDIRECT_EXPORT,   0, JSEXN_SYNTAXERR, "indirect export not found")
+MSG_DEF(JSMSG_AMBIGUOUS_INDIRECT_EXPORT, 0, JSEXN_SYNTAXERR, "ambiguous indirect export")
+MSG_DEF(JSMSG_MISSING_IMPORT,            0, JSEXN_SYNTAXERR, "import not found")
+MSG_DEF(JSMSG_AMBIGUOUS_IMPORT,          0, JSEXN_SYNTAXERR, "ambiguous import")
 MSG_DEF(JSMSG_MISSING_NAMESPACE_EXPORT,  0, JSEXN_SYNTAXERR, "export not found for namespace")
 MSG_DEF(JSMSG_MISSING_EXPORT,            1, JSEXN_SYNTAXERR, "local binding for export '{0}' not found")
 MSG_DEF(JSMSG_MODULE_INSTANTIATE_FAILED, 0, JSEXN_INTERNALERR, "attempt to re-instantiate module after failure")
diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp
index 89750d61a..0dfeffc36 100644
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -345,6 +345,50 @@ intrinsic_ThrowInternalError(JSContext* cx, unsigned argc, Value* vp)
     return false;
 }
 
+static bool
+intrinsic_GetErrorMessage(JSContext* cx, unsigned argc, Value* vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    MOZ_ASSERT(args.length() == 1);
+    MOZ_ASSERT(args[0].isInt32());
+
+    const JSErrorFormatString* errorString = GetErrorMessage(nullptr, args[0].toInt32());
+    MOZ_ASSERT(errorString);
+
+    MOZ_ASSERT(errorString->argCount == 0);
+    RootedString message(cx, JS_NewStringCopyZ(cx, errorString->format));
+    if (!message)
+        return false;
+
+    args.rval().setString(message);
+    return true;
+}
+
+static bool
+intrinsic_CreateModuleSyntaxError(JSContext* cx, unsigned argc, Value* vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    MOZ_ASSERT(args.length() == 4);
+    MOZ_ASSERT(args[0].isObject());
+    MOZ_ASSERT(args[1].isInt32());
+    MOZ_ASSERT(args[2].isInt32());
+    MOZ_ASSERT(args[3].isString());
+
+    RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
+    RootedString filename(cx, JS_NewStringCopyZ(cx, module->script()->filename()));
+    RootedString message(cx, args[3].toString());
+
+    RootedValue error(cx);
+    if (!JS::CreateError(cx, JSEXN_SYNTAXERR, nullptr, filename, args[1].toInt32(),
+                         args[2].toInt32(), nullptr, message, &error))
+    {
+        return false;
+    }
+
+    args.rval().set(error);
+    return true;
+}
+
 /**
  * Handles an assertion failure in self-hosted code just like an assertion
  * failure in C++ code. Information about the failure can be provided in args[0].
@@ -2339,6 +2383,8 @@ static const JSFunctionSpec intrinsic_functions[] = {
     JS_FN("ThrowTypeError",          intrinsic_ThrowTypeError,          4,0),
     JS_FN("ThrowSyntaxError",        intrinsic_ThrowSyntaxError,        4,0),
     JS_FN("ThrowInternalError",      intrinsic_ThrowInternalError,      4,0),
+    JS_FN("GetErrorMessage",         intrinsic_GetErrorMessage,         1,0),
+    JS_FN("CreateModuleSyntaxError", intrinsic_CreateModuleSyntaxError, 4,0),
     JS_FN("AssertionFailed",         intrinsic_AssertionFailed,         1,0),
     JS_FN("DumpMessage",             intrinsic_DumpMessage,             1,0),
     JS_FN("OwnPropertyKeys",         intrinsic_OwnPropertyKeys,         1,0),
-- 
cgit v1.2.3


From e29a8bd113594a55d5087989c90317cc86d03f48 Mon Sep 17 00:00:00 2001
From: Moonchild <moonchild@palemoon.org>
Date: Tue, 7 Jul 2020 12:27:02 +0000
Subject: Issue #618 - Fix typo and remove old function declarations.

---
 js/src/builtin/Module.js        | 2 +-
 js/src/builtin/ModuleObject.cpp | 2 --
 2 files changed, 1 insertion(+), 3 deletions(-)

(limited to 'js')

diff --git a/js/src/builtin/Module.js b/js/src/builtin/Module.js
index b3365b505..64d62d216 100644
--- a/js/src/builtin/Module.js
+++ b/js/src/builtin/Module.js
@@ -509,7 +509,7 @@ function ResolutionError(resolution, kind, name, line, column)
 function ModuleEvaluate()
 {
     if (!IsObject(this) || !IsModule(this))
-        return callFunction(CallModuleMethodIfWrapped, this, "ModuleEvaluatie");
+        return callFunction(CallModuleMethodIfWrapped, this, "ModuleEvaluate");
 
     // Step 1
     let module = this;
diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp
index 09193c9ca..30e7120c0 100644
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -1034,8 +1034,6 @@ GlobalObject::initModuleProto(JSContext* cx, Handle<GlobalObject*> global)
     static const JSFunctionSpec protoFunctions[] = {
         JS_SELF_HOSTED_FN("getExportedNames", "ModuleGetExportedNames", 1, 0),
         JS_SELF_HOSTED_FN("resolveExport", "ModuleResolveExport", 2, 0),
-        JS_SELF_HOSTED_FN("declarationInstantiation", "ModuleDeclarationInstantiation", 0, 0),
-        JS_SELF_HOSTED_FN("evaluation", "ModuleEvaluation", 0, 0),
         JS_SELF_HOSTED_FN("declarationInstantiation", "ModuleInstantiate", 0, 0),
         JS_SELF_HOSTED_FN("evaluation", "ModuleEvaluate", 0, 0),
         JS_FS_END
-- 
cgit v1.2.3


From 407c503fa4f7a57f89195421eb004d3028013105 Mon Sep 17 00:00:00 2001
From: Moonchild <moonchild@palemoon.org>
Date: Thu, 9 Jul 2020 16:01:42 +0000
Subject: [js] Improve readability and control flow of js date string parser.

---
 js/src/jsdate.cpp | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

(limited to 'js')

diff --git a/js/src/jsdate.cpp b/js/src/jsdate.cpp
index c6a369e2d..41722ffa9 100755
--- a/js/src/jsdate.cpp
+++ b/js/src/jsdate.cpp
@@ -21,6 +21,8 @@
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/Sprintf.h"
 
+#include "nsCRT.h"
+
 #include <ctype.h>
 #include <math.h>
 #include <string.h>
@@ -958,11 +960,20 @@ ParseDate(const CharT* s, size_t length, ClippedTime* result)
     while (i < length) {
         int c = s[i];
         i++;
-        if (c <= ' ' || c == ',' || c == '-') {
-            if (c == '-' && '0' <= s[i] && s[i] <= '9')
+        
+        // Spaces, ASCII control characters, and commas are ignored.
+        if (c <= ' ' || c == ',')
+            continue;
+
+        // Dashes are delimiters if they're immediately followed by a number field.
+        // If they're not followed by a number field, they're simply ignored.
+        if (c == '-') {
+            if (i < length && nsCRT::IsAsciiDigit(s[i])) {
                 prevc = c;
+            }
             continue;
         }
+
         if (c == '(') { /* comments) */
             int depth = 1;
             while (i < length) {
@@ -977,7 +988,9 @@ ParseDate(const CharT* s, size_t length, ClippedTime* result)
             }
             continue;
         }
-        if ('0' <= c && c <= '9') {
+
+        // Parse a number field.
+        if (nsCRT::IsAsciiDigit(c)) {        
             int n = c - '0';
             while (i < length && '0' <= (c = s[i]) && c <= '9') {
                 n = n * 10 + c - '0';
-- 
cgit v1.2.3


From 1597b61148692bbaa4194bcaea9823da140c51ab Mon Sep 17 00:00:00 2001
From: Moonchild <moonchild@palemoon.org>
Date: Fri, 10 Jul 2020 16:15:00 +0000
Subject: [js] Get the class pointer from the ObjectGroup in
 NativeObject::slotSpan

This changes NativeObject::slotSpan() to get the class from the object group
rather than getting it from the base shape to avoid a race between
Shape::ensureOwnBaseShape and background sweeping.
---
 js/src/vm/NativeObject.h | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

(limited to 'js')

diff --git a/js/src/vm/NativeObject.h b/js/src/vm/NativeObject.h
index 3a3e50244..e9c59ff7c 100644
--- a/js/src/vm/NativeObject.h
+++ b/js/src/vm/NativeObject.h
@@ -646,7 +646,10 @@ class NativeObject : public ShapedObject
     uint32_t slotSpan() const {
         if (inDictionaryMode())
             return lastProperty()->base()->slotSpan();
-        return lastProperty()->slotSpan();
+
+        // Get the class from the object group rather than the base shape to avoid a
+        // race between Shape::ensureOwnBaseShape and background sweeping.
+        return lastProperty()->slotSpan(getClass());
     }
 
     /* Whether a slot is at a fixed offset from this object. */
-- 
cgit v1.2.3