summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMoonchild <moonchild@palemoon.org>2020-07-06 20:31:14 +0000
committerMoonchild <moonchild@palemoon.org>2020-07-06 20:31:14 +0000
commitc053de708817a3b7c90edcd53fe3742007b8a41e (patch)
treed616be09d75333065416cb35432eac7b821c4aa9
parentfd602fbffbaf8e7d7e58c9ffe9b0b188cb7c65de (diff)
parent2dff89b658d6ab2592865c226f3f1078f418151d (diff)
downloadUXP-c053de708817a3b7c90edcd53fe3742007b8a41e.tar
UXP-c053de708817a3b7c90edcd53fe3742007b8a41e.tar.gz
UXP-c053de708817a3b7c90edcd53fe3742007b8a41e.tar.lz
UXP-c053de708817a3b7c90edcd53fe3742007b8a41e.tar.xz
UXP-c053de708817a3b7c90edcd53fe3742007b8a41e.zip
Merge branch 'es-modules-work'
-rw-r--r--dom/base/nsJSUtils.cpp13
-rw-r--r--dom/base/nsJSUtils.h8
-rw-r--r--dom/base/test/jsmodules/test_syntaxError.html15
-rw-r--r--dom/base/test/jsmodules/test_syntaxErrorAsync.html15
-rw-r--r--dom/base/test/jsmodules/test_syntaxErrorInline.html15
-rw-r--r--dom/base/test/jsmodules/test_syntaxErrorInlineAsync.html15
-rw-r--r--dom/script/ModuleLoadRequest.cpp53
-rw-r--r--dom/script/ModuleLoadRequest.h6
-rw-r--r--dom/script/ModuleScript.cpp80
-rw-r--r--dom/script/ModuleScript.h28
-rw-r--r--dom/script/ScriptLoader.cpp263
-rw-r--r--dom/script/ScriptLoader.h1
-rw-r--r--js/src/builtin/Module.js534
-rw-r--r--js/src/builtin/ModuleObject.cpp148
-rw-r--r--js/src/builtin/ModuleObject.h56
-rw-r--r--js/src/builtin/ReflectParse.cpp2
-rw-r--r--js/src/builtin/SelfHostingDefines.h18
-rw-r--r--js/src/builtin/Utilities.js19
-rw-r--r--js/src/frontend/BytecodeCompiler.cpp2
-rw-r--r--js/src/frontend/BytecodeEmitter.cpp2
-rw-r--r--js/src/frontend/Parser.cpp2
-rw-r--r--js/src/jit-test/tests/modules/ambiguous-star-export.js15
-rw-r--r--js/src/jit-test/tests/modules/bad-namespace-created.js17
-rw-r--r--js/src/jit-test/tests/modules/bug-1284486.js39
-rw-r--r--js/src/jit-test/tests/modules/bug-1287410.js2
-rw-r--r--js/src/jit-test/tests/modules/bug-1394492.js6
-rw-r--r--js/src/jit-test/tests/modules/global-scope.js18
-rw-r--r--js/src/jit-test/tests/modules/module-evaluation.js33
-rw-r--r--js/src/js.msg10
-rw-r--r--js/src/jsapi.cpp20
-rw-r--r--js/src/jsapi.h19
-rw-r--r--js/src/vm/CommonPropertyNames.h4
-rw-r--r--js/src/vm/SelfHosting.cpp65
33 files changed, 1097 insertions, 446 deletions
diff --git a/dom/base/nsJSUtils.cpp b/dom/base/nsJSUtils.cpp
index c24adc739..65965d74b 100644
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -308,17 +308,18 @@ nsJSUtils::CompileModule(JSContext* aCx,
}
nsresult
-nsJSUtils::ModuleDeclarationInstantiation(JSContext* aCx, JS::Handle<JSObject*> aModule)
+nsJSUtils::ModuleInstantiate(JSContext* aCx, JS::Handle<JSObject*> aModule)
{
- PROFILER_LABEL("nsJSUtils", "ModuleDeclarationInstantiation",
+ PROFILER_LABEL("nsJSUtils", "ModuleInstantiate",
js::ProfileEntry::Category::JS);
MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(nsContentUtils::IsInMicroTask());
NS_ENSURE_TRUE(xpc::Scriptability::Get(aModule).Allowed(), NS_OK);
- if (!JS::ModuleDeclarationInstantiation(aCx, aModule)) {
+ if (!JS::ModuleInstantiate(aCx, aModule)) {
return NS_ERROR_FAILURE;
}
@@ -326,9 +327,9 @@ nsJSUtils::ModuleDeclarationInstantiation(JSContext* aCx, JS::Handle<JSObject*>
}
nsresult
-nsJSUtils::ModuleEvaluation(JSContext* aCx, JS::Handle<JSObject*> aModule)
+nsJSUtils::ModuleEvaluate(JSContext* aCx, JS::Handle<JSObject*> aModule)
{
- PROFILER_LABEL("nsJSUtils", "ModuleEvaluation",
+ PROFILER_LABEL("nsJSUtils", "ModuleEvaluate",
js::ProfileEntry::Category::JS);
MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
@@ -338,7 +339,7 @@ nsJSUtils::ModuleEvaluation(JSContext* aCx, JS::Handle<JSObject*> aModule)
NS_ENSURE_TRUE(xpc::Scriptability::Get(aModule).Allowed(), NS_OK);
- if (!JS::ModuleEvaluation(aCx, aModule)) {
+ if (!JS::ModuleEvaluate(aCx, aModule)) {
return NS_ERROR_FAILURE;
}
diff --git a/dom/base/nsJSUtils.h b/dom/base/nsJSUtils.h
index 4affab2d3..9eea6ae83 100644
--- a/dom/base/nsJSUtils.h
+++ b/dom/base/nsJSUtils.h
@@ -116,11 +116,11 @@ public:
JS::CompileOptions &aCompileOptions,
JS::MutableHandle<JSObject*> aModule);
- static nsresult ModuleDeclarationInstantiation(JSContext* aCx,
- JS::Handle<JSObject*> aModule);
+ static nsresult ModuleInstantiate(JSContext* aCx,
+ JS::Handle<JSObject*> aModule);
- static nsresult ModuleEvaluation(JSContext* aCx,
- JS::Handle<JSObject*> aModule);
+ static nsresult ModuleEvaluate(JSContext* aCx,
+ JS::Handle<JSObject*> aModule);
// Returns false if an exception got thrown on aCx. Passing a null
// aElement is allowed; that wil produce an empty aScopeChain.
diff --git a/dom/base/test/jsmodules/test_syntaxError.html b/dom/base/test/jsmodules/test_syntaxError.html
index 53f95c96c..5bd688fe3 100644
--- a/dom/base/test/jsmodules/test_syntaxError.html
+++ b/dom/base/test/jsmodules/test_syntaxError.html
@@ -4,20 +4,27 @@
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script>
var wasRun = false;
- var hadSyntaxError = false;
+ var errorCount = 0;
+ var syntaxErrorCount = 0;
+ var eventCount = 0;
SimpleTest.waitForExplicitFinish();
window.onerror = handleError;
function handleError(message, url, line, column, error) {
- hadSyntaxError = error instanceof SyntaxError;
+ errorCount++;
+ if (error instanceof SyntaxError) {
+ syntaxErrorCount++;
+ }
}
function testError() {
ok(!wasRun, 'Check script was not run');
- ok(hadSyntaxError, 'Check that a SyntaxError was thrown');
+ ok(errorCount == 1, 'Check that an error was reported');
+ ok(syntaxErrorCount == 1, 'Check that a syntax error was reported');
+ ok(eventCount == 0, 'Check that no error event was fired');
SimpleTest.finish();
}
</script>
-<script type="module" src="module_badSyntax.js"></script>
+<script type="module" src="module_badSyntax.js" onerror="eventCount++"></script>
<body onload='testError()'></body>
diff --git a/dom/base/test/jsmodules/test_syntaxErrorAsync.html b/dom/base/test/jsmodules/test_syntaxErrorAsync.html
index 35d923755..3593d9dd7 100644
--- a/dom/base/test/jsmodules/test_syntaxErrorAsync.html
+++ b/dom/base/test/jsmodules/test_syntaxErrorAsync.html
@@ -4,20 +4,27 @@
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script>
var wasRun = false;
- var hadSyntaxError = false;
+ var errorCount = 0;
+ var syntaxErrorCount = 0;
+ var eventCount = 0;
SimpleTest.waitForExplicitFinish();
window.onerror = handleError;
function handleError(message, url, line, column, error) {
- hadSyntaxError = error instanceof SyntaxError;
+ errorCount++;
+ if (error instanceof SyntaxError) {
+ syntaxErrorCount++;
+ }
}
function testError() {
ok(!wasRun, 'Check script was not run');
- ok(hadSyntaxError, 'Check that a SyntaxError was thrown');
+ ok(errorCount == 1, 'Check that an error was reported');
+ ok(syntaxErrorCount == 1, 'Check that a syntax error was reported');
+ ok(eventCount == 0, 'Check that no error event was fired');
SimpleTest.finish();
}
</script>
-<script type="module" src="module_badSyntax.js" async></script>
+<script type="module" src="module_badSyntax.js" async onerror="eventCount++"></script>
<body onload='testError()'></body>
diff --git a/dom/base/test/jsmodules/test_syntaxErrorInline.html b/dom/base/test/jsmodules/test_syntaxErrorInline.html
index 705bc5902..b85b954ec 100644
--- a/dom/base/test/jsmodules/test_syntaxErrorInline.html
+++ b/dom/base/test/jsmodules/test_syntaxErrorInline.html
@@ -4,22 +4,29 @@
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script>
var wasRun = false;
- var hadSyntaxError = false;
+ var errorCount = 0;
+ var syntaxErrorCount = 0;
+ var eventCount = 0;
SimpleTest.waitForExplicitFinish();
window.onerror = handleError;
function handleError(message, url, line, column, error) {
- hadSyntaxError = error instanceof SyntaxError;
+ errorCount++;
+ if (error instanceof SyntaxError) {
+ syntaxErrorCount++;
+ }
}
function testError() {
ok(!wasRun, 'Check script was not run');
- ok(hadSyntaxError, 'Check that a SyntaxError was thrown');
+ ok(errorCount == 1, 'Check that an error was reported');
+ ok(syntaxErrorCount == 1, 'Check that a syntax error was reported');
+ ok(eventCount == 0, 'Check that no error event was fired');
SimpleTest.finish();
}
</script>
-<script type="module">
+<script type="module" onerror="eventCount++">
// Module with a syntax error.
some invalid js syntax;
wasRun = true;
diff --git a/dom/base/test/jsmodules/test_syntaxErrorInlineAsync.html b/dom/base/test/jsmodules/test_syntaxErrorInlineAsync.html
index 5e7992823..cc4bf1257 100644
--- a/dom/base/test/jsmodules/test_syntaxErrorInlineAsync.html
+++ b/dom/base/test/jsmodules/test_syntaxErrorInlineAsync.html
@@ -4,22 +4,29 @@
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script>
var wasRun = false;
- var hadSyntaxError = false;
+ var errorCount = 0;
+ var syntaxErrorCount = 0;
+ var eventCount = 0;
SimpleTest.waitForExplicitFinish();
window.onerror = handleError;
function handleError(message, url, line, column, error) {
- hadSyntaxError = error instanceof SyntaxError;
+ errorCount++;
+ if (error instanceof SyntaxError) {
+ syntaxErrorCount++;
+ }
}
function testError() {
ok(!wasRun, 'Check script was not run');
- ok(hadSyntaxError, 'Check that a SyntaxError was thrown');
+ ok(errorCount == 1, 'Check that an error was reported');
+ ok(syntaxErrorCount == 1, 'Check that a syntax error was reported');
+ ok(eventCount == 0, 'Check that no error event was fired');
SimpleTest.finish();
}
</script>
-<script type="module" async>
+<script type="module" async onerror="eventCount++">
// Module with a syntax error.
some invalid js syntax;
wasRun = true;
diff --git a/dom/script/ModuleLoadRequest.cpp b/dom/script/ModuleLoadRequest.cpp
index e72edca2e..d62214304 100644
--- a/dom/script/ModuleLoadRequest.cpp
+++ b/dom/script/ModuleLoadRequest.cpp
@@ -43,15 +43,29 @@ void ModuleLoadRequest::Cancel()
ScriptLoadRequest::Cancel();
mModuleScript = nullptr;
mProgress = ScriptLoadRequest::Progress::Ready;
+ CancelImports();
+ mReady.RejectIfExists(NS_ERROR_DOM_ABORT_ERR, __func__);
+}
+
+void
+ModuleLoadRequest::CancelImports()
+{
for (size_t i = 0; i < mImports.Length(); i++) {
mImports[i]->Cancel();
}
- mReady.RejectIfExists(NS_ERROR_FAILURE, __func__);
}
void
ModuleLoadRequest::SetReady()
{
+ // Mark a module as ready to execute. This means that this module and all it
+ // dependencies have had their source loaded, parsed as a module and the
+ // modules instantiated.
+ //
+ // The mReady promise is used to ensure that when all dependencies of a module
+ // have become ready, DependenciesLoaded is called on that module
+ // request. This is set up in StartFetchingModuleDependencies.
+
#ifdef DEBUG
for (size_t i = 0; i < mImports.Length(); i++) {
MOZ_ASSERT(mImports[i]->IsReadyToRun());
@@ -69,30 +83,53 @@ ModuleLoadRequest::ModuleLoaded()
// been loaded.
mModuleScript = mLoader->GetFetchedModule(mURI);
+ if (!mModuleScript || mModuleScript->IsErrored()) {
+ ModuleErrored();
+ return;
+ }
+
mLoader->StartFetchingModuleDependencies(this);
}
void
+ModuleLoadRequest::ModuleErrored()
+{
+ mLoader->CheckModuleDependenciesLoaded(this);
+ MOZ_ASSERT(!mModuleScript || mModuleScript->IsErrored());
+
+ CancelImports();
+ SetReady();
+ LoadFinished();
+}
+
+void
ModuleLoadRequest::DependenciesLoaded()
{
// The module and all of its dependencies have been successfully fetched and
// compiled.
- if (!mLoader->InstantiateModuleTree(this)) {
- LoadFailed();
- return;
- }
+ MOZ_ASSERT(mModuleScript);
+ mLoader->CheckModuleDependenciesLoaded(this);
SetReady();
- mLoader->ProcessLoadedModuleTree(this);
- mLoader = nullptr;
- mParent = nullptr;
+ LoadFinished();
}
void
ModuleLoadRequest::LoadFailed()
{
+ // We failed to load the source text or an error occurred unrelated to the
+ // content of the module (e.g. OOM).
+
+ MOZ_ASSERT(!mModuleScript);
+
Cancel();
+ LoadFinished();
+}
+
+void
+ModuleLoadRequest::LoadFinished()
+{
mLoader->ProcessLoadedModuleTree(this);
mLoader = nullptr;
mParent = nullptr;
diff --git a/dom/script/ModuleLoadRequest.h b/dom/script/ModuleLoadRequest.h
index 0119fad38..7b06dd2cf 100644
--- a/dom/script/ModuleLoadRequest.h
+++ b/dom/script/ModuleLoadRequest.h
@@ -45,9 +45,15 @@ public:
void Cancel() override;
void ModuleLoaded();
+ void ModuleErrored();
void DependenciesLoaded();
void LoadFailed();
+private:
+ void LoadFinished();
+ void CancelImports();
+
+public:
// Is this a request for a top level module script or an import?
bool mIsTopLevel;
diff --git a/dom/script/ModuleScript.cpp b/dom/script/ModuleScript.cpp
index 34ef4dec4..28b97a3cb 100644
--- a/dom/script/ModuleScript.cpp
+++ b/dom/script/ModuleScript.cpp
@@ -26,6 +26,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ModuleScript)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mLoader)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBaseURL)
tmp->UnlinkModuleRecord();
+ tmp->mError.setUndefined();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ModuleScript)
@@ -34,28 +35,20 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ModuleScript)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mModuleRecord)
- NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mException)
+ NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mError)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(ModuleScript)
NS_IMPL_CYCLE_COLLECTING_RELEASE(ModuleScript)
-ModuleScript::ModuleScript(ScriptLoader *aLoader, nsIURI* aBaseURL,
- JS::Handle<JSObject*> aModuleRecord)
+ModuleScript::ModuleScript(ScriptLoader *aLoader, nsIURI* aBaseURL)
: mLoader(aLoader),
- mBaseURL(aBaseURL),
- mModuleRecord(aModuleRecord),
- mInstantiationState(Uninstantiated)
+ mBaseURL(aBaseURL)
{
MOZ_ASSERT(mLoader);
MOZ_ASSERT(mBaseURL);
- MOZ_ASSERT(mModuleRecord);
- MOZ_ASSERT(mException.isUndefined());
-
- // Make module's host defined field point to this module script object.
- // This is cleared in the UnlinkModuleRecord().
- JS::SetModuleHostDefinedField(mModuleRecord, JS::PrivateValue(this));
- HoldJSObjects(this);
+ MOZ_ASSERT(!mModuleRecord);
+ MOZ_ASSERT(mError.isUndefined());
}
void
@@ -66,34 +59,63 @@ ModuleScript::UnlinkModuleRecord()
MOZ_ASSERT(JS::GetModuleHostDefinedField(mModuleRecord).toPrivate() ==
this);
JS::SetModuleHostDefinedField(mModuleRecord, JS::UndefinedValue());
+ mModuleRecord = nullptr;
}
- mModuleRecord = nullptr;
- mException.setUndefined();
}
ModuleScript::~ModuleScript()
{
- if (mModuleRecord) {
- // The object may be destroyed without being unlinked first.
- UnlinkModuleRecord();
- }
+ // The object may be destroyed without being unlinked first.
+ UnlinkModuleRecord();
DropJSObjects(this);
}
void
-ModuleScript::SetInstantiationResult(JS::Handle<JS::Value> aMaybeException)
+ModuleScript::SetModuleRecord(JS::Handle<JSObject*> aModuleRecord)
{
- MOZ_ASSERT(mInstantiationState == Uninstantiated);
- MOZ_ASSERT(mModuleRecord);
- MOZ_ASSERT(mException.isUndefined());
+ MOZ_ASSERT(!mModuleRecord);
+ MOZ_ASSERT(mError.isUndefined());
- if (aMaybeException.isUndefined()) {
- mInstantiationState = Instantiated;
- } else {
- mModuleRecord = nullptr;
- mException = aMaybeException;
- mInstantiationState = Errored;
+ mModuleRecord = aModuleRecord;
+
+ // Make module's host defined field point to this module script object.
+ // This is cleared in the UnlinkModuleRecord().
+ JS::SetModuleHostDefinedField(mModuleRecord, JS::PrivateValue(this));
+ HoldJSObjects(this);
+}
+
+void
+ModuleScript::SetPreInstantiationError(const JS::Value& aError)
+{
+ MOZ_ASSERT(!aError.isUndefined());
+
+ UnlinkModuleRecord();
+ mError = aError;
+
+ HoldJSObjects(this);
+}
+
+bool
+ModuleScript::IsErrored() const
+{
+ if (!mModuleRecord) {
+ MOZ_ASSERT(!mError.isUndefined());
+ return true;
}
+
+ return JS::IsModuleErrored(mModuleRecord);
+}
+
+JS::Value
+ModuleScript::Error() const
+{
+ MOZ_ASSERT(IsErrored());
+
+ if (!mModuleRecord) {
+ return mError;
+ }
+
+ return JS::GetModuleError(mModuleRecord);
}
} // dom namespace
diff --git a/dom/script/ModuleScript.h b/dom/script/ModuleScript.h
index dd0d07e84..571359859 100644
--- a/dom/script/ModuleScript.h
+++ b/dom/script/ModuleScript.h
@@ -20,17 +20,10 @@ class ScriptLoader;
class ModuleScript final : public nsISupports
{
- enum InstantiationState {
- Uninstantiated,
- Instantiated,
- Errored
- };
-
RefPtr<ScriptLoader> mLoader;
nsCOMPtr<nsIURI> mBaseURL;
JS::Heap<JSObject*> mModuleRecord;
- JS::Heap<JS::Value> mException;
- InstantiationState mInstantiationState;
+ JS::Heap<JS::Value> mError;
~ModuleScript();
@@ -39,24 +32,17 @@ public:
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ModuleScript)
ModuleScript(ScriptLoader* aLoader,
- nsIURI* aBaseURL,
- JS::Handle<JSObject*> aModuleRecord);
+ nsIURI* aBaseURL);
+
+ void SetModuleRecord(JS::Handle<JSObject*> aModuleRecord);
+ void SetPreInstantiationError(const JS::Value& aError);
ScriptLoader* Loader() const { return mLoader; }
JSObject* ModuleRecord() const { return mModuleRecord; }
- JS::Value Exception() const { return mException; }
nsIURI* BaseURL() const { return mBaseURL; }
- void SetInstantiationResult(JS::Handle<JS::Value> aMaybeException);
- bool IsUninstantiated() const {
- return mInstantiationState == Uninstantiated;
- }
- bool IsInstantiated() const {
- return mInstantiationState == Instantiated;
- }
- bool InstantiationFailed() const {
- return mInstantiationState == Errored;
- }
+ bool IsErrored() const;
+ JS::Value Error() const;
void UnlinkModuleRecord();
};
diff --git a/dom/script/ScriptLoader.cpp b/dom/script/ScriptLoader.cpp
index adc046b7c..a53098974 100644
--- a/dom/script/ScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -418,21 +418,23 @@ void
ScriptLoader::SetModuleFetchFinishedAndResumeWaitingRequests(ModuleLoadRequest *aRequest,
nsresult aResult)
{
- // Update module map with the result of fetching a single module script. The
- // module script pointer is nullptr on error.
-
- MOZ_ASSERT(!aRequest->IsReadyToRun());
+ // Update module map with the result of fetching a single module script.
+ //
+ // If any requests for the same URL are waiting on this one to complete, they
+ // will have ModuleLoaded or LoadFailed on them when the promise is
+ // resolved/rejected. This is set up in StartLoad.
RefPtr<GenericPromise::Private> promise;
MOZ_ALWAYS_TRUE(mFetchingModules.Get(aRequest->mURI, getter_AddRefs(promise)));
mFetchingModules.Remove(aRequest->mURI);
- RefPtr<ModuleScript> ms(aRequest->mModuleScript);
- MOZ_ASSERT(NS_SUCCEEDED(aResult) == (ms != nullptr));
- mFetchedModules.Put(aRequest->mURI, ms);
+ RefPtr<ModuleScript> moduleScript(aRequest->mModuleScript);
+ MOZ_ASSERT(NS_FAILED(aResult) == !moduleScript);
+
+ mFetchedModules.Put(aRequest->mURI, moduleScript);
if (promise) {
- if (ms) {
+ if (moduleScript) {
promise->Resolve(true, __func__);
} else {
promise->Reject(aResult, __func__);
@@ -478,19 +480,29 @@ ScriptLoader::ProcessFetchedModuleSource(ModuleLoadRequest* aRequest)
MOZ_ASSERT(!aRequest->mModuleScript);
nsresult rv = CreateModuleScript(aRequest);
+ MOZ_ASSERT(NS_FAILED(rv) == !aRequest->mModuleScript);
+
SetModuleFetchFinishedAndResumeWaitingRequests(aRequest, rv);
free(aRequest->mScriptTextBuf);
aRequest->mScriptTextBuf = nullptr;
aRequest->mScriptTextLength = 0;
- if (NS_SUCCEEDED(rv)) {
+ if (NS_FAILED(rv)) {
+ aRequest->LoadFailed();
+ return rv;
+ }
+
+ if (!aRequest->mModuleScript->IsErrored()) {
StartFetchingModuleDependencies(aRequest);
}
- return rv;
+ return NS_OK;
}
+static nsresult
+ResolveRequestedModules(ModuleLoadRequest* aRequest, nsCOMArray<nsIURI>& aUrls);
+
nsresult
ScriptLoader::CreateModuleScript(ModuleLoadRequest* aRequest)
{
@@ -544,9 +556,34 @@ ScriptLoader::CreateModuleScript(ModuleLoadRequest* aRequest)
}
}
MOZ_ASSERT(NS_SUCCEEDED(rv) == (module != nullptr));
- if (module) {
- aRequest->mModuleScript =
- new ModuleScript(this, aRequest->mBaseURL, module);
+ RefPtr<ModuleScript> moduleScript = new ModuleScript(this, aRequest->mBaseURL);
+ aRequest->mModuleScript = moduleScript;
+
+ if (!module) {
+ // Compilation failed
+ MOZ_ASSERT(aes.HasException());
+ JS::Rooted<JS::Value> error(cx);
+ if (!aes.StealException(&error)) {
+ aRequest->mModuleScript = nullptr;
+ return NS_ERROR_FAILURE;
+ }
+
+ moduleScript->SetPreInstantiationError(error);
+ aRequest->ModuleErrored();
+ return NS_OK;
+ }
+
+ moduleScript->SetModuleRecord(module);
+
+ // Validate requested modules and treat failure to resolve module specifiers
+ // the same as a parse error.
+ nsCOMArray<nsIURI> urls;
+ rv = ResolveRequestedModules(aRequest, urls);
+ if (NS_FAILED(rv)) {
+ // ResolveRequestedModules sets pre-instanitation error on failure.
+ MOZ_ASSERT(moduleScript->IsErrored());
+ aRequest->ModuleErrored();
+ return NS_OK;
}
}
@@ -556,8 +593,8 @@ ScriptLoader::CreateModuleScript(ModuleLoadRequest* aRequest)
}
static bool
-ThrowTypeError(JSContext* aCx, ModuleScript* aScript,
- const nsString& aMessage)
+CreateTypeError(JSContext* aCx, ModuleScript* aScript, const nsString& aMessage,
+ JS::MutableHandle<JS::Value> aError)
{
JS::Rooted<JSObject*> module(aCx, aScript->ModuleRecord());
JS::Rooted<JSScript*> script(aCx, JS::GetModuleScript(aCx, module));
@@ -572,17 +609,11 @@ ThrowTypeError(JSContext* aCx, ModuleScript* aScript,
return false;
}
- JS::Rooted<JS::Value> error(aCx);
- if (!JS::CreateError(aCx, JSEXN_TYPEERR, nullptr, filename, 0, 0, nullptr,
- message, &error)) {
- return false;
- }
-
- JS_SetPendingException(aCx, error);
- return false;
+ return JS::CreateError(aCx, JSEXN_TYPEERR, nullptr, filename, 0, 0, nullptr,
+ message, aError);
}
-static bool
+static nsresult
HandleResolveFailure(JSContext* aCx, ModuleScript* aScript,
const nsAString& aSpecifier)
{
@@ -591,19 +622,13 @@ HandleResolveFailure(JSContext* aCx, ModuleScript* aScript,
nsAutoString message(NS_LITERAL_STRING("Error resolving module specifier: "));
message.Append(aSpecifier);
- return ThrowTypeError(aCx, aScript, message);
-}
-
-static bool
-HandleModuleNotFound(JSContext* aCx, ModuleScript* aScript,
- const nsAString& aSpecifier)
-{
- // TODO: How can we get the line number of the failed import?
-
- nsAutoString message(NS_LITERAL_STRING("Resolved module not found in map: "));
- message.Append(aSpecifier);
+ JS::Rooted<JS::Value> error(aCx);
+ if (!CreateTypeError(aCx, aScript, message, &error)) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
- return ThrowTypeError(aCx, aScript, message);
+ aScript->SetPreInstantiationError(error);
+ return NS_OK;
}
static already_AddRefed<nsIURI>
@@ -701,7 +726,8 @@ ResolveRequestedModules(ModuleLoadRequest* aRequest, nsCOMArray<nsIURI> &aUrls)
ModuleScript* ms = aRequest->mModuleScript;
nsCOMPtr<nsIURI> uri = ResolveModuleSpecifier(ms, specifier);
if (!uri) {
- HandleResolveFailure(cx, ms, specifier);
+ nsresult rv = HandleResolveFailure(cx, ms, specifier);
+ NS_ENSURE_SUCCESS(rv, rv);
return NS_ERROR_FAILURE;
}
@@ -720,13 +746,15 @@ void
ScriptLoader::StartFetchingModuleDependencies(ModuleLoadRequest* aRequest)
{
MOZ_ASSERT(aRequest->mModuleScript);
+ MOZ_ASSERT(!aRequest->mModuleScript->IsErrored());
MOZ_ASSERT(!aRequest->IsReadyToRun());
+
aRequest->mProgress = ModuleLoadRequest::Progress::FetchingImports;
nsCOMArray<nsIURI> urls;
nsresult rv = ResolveRequestedModules(aRequest, urls);
if (NS_FAILED(rv)) {
- aRequest->LoadFailed();
+ aRequest->ModuleErrored();
return;
}
@@ -750,7 +778,7 @@ ScriptLoader::StartFetchingModuleDependencies(ModuleLoadRequest* aRequest)
GenericPromise::All(AbstractThread::GetCurrent(), importsReady);
allReady->Then(AbstractThread::GetCurrent(), __func__, aRequest,
&ModuleLoadRequest::DependenciesLoaded,
- &ModuleLoadRequest::LoadFailed);
+ &ModuleLoadRequest::ModuleErrored);
}
RefPtr<GenericPromise>
@@ -773,6 +801,7 @@ ScriptLoader::StartFetchingModuleAndDependencies(ModuleLoadRequest* aRequest,
nsresult rv = StartLoad(childRequest, NS_LITERAL_STRING("module"), false);
if (NS_FAILED(rv)) {
+ MOZ_ASSERT(!childRequest->mModuleScript);
childRequest->mReady.Reject(rv, __func__);
return ready;
}
@@ -781,6 +810,7 @@ ScriptLoader::StartFetchingModuleAndDependencies(ModuleLoadRequest* aRequest,
return ready;
}
+// 8.1.3.8.1 HostResolveImportedModule(referencingModule, specifier)
bool
HostResolveImportedModule(JSContext* aCx, unsigned argc, JS::Value* vp)
{
@@ -795,31 +825,25 @@ HostResolveImportedModule(JSContext* aCx, unsigned argc, JS::Value* vp)
MOZ_ASSERT(script->ModuleRecord() == module);
// Let url be the result of resolving a module specifier given referencing
- // module script and specifier. If the result is failure, throw a TypeError
- // exception and abort these steps.
+ // module script and specifier.
nsAutoJSString string;
if (!string.init(aCx, specifier)) {
return false;
}
nsCOMPtr<nsIURI> uri = ResolveModuleSpecifier(script, string);
- if (!uri) {
- return HandleResolveFailure(aCx, script, string);
- }
- // Let resolved module script be the value of the entry in module map whose
- // key is url. If no such entry exists, throw a TypeError exception and abort
- // these steps.
+ // This cannot fail because resolving a module specifier must have been
+ // previously successful with these same two arguments.
+ MOZ_ASSERT(uri, "Failed to resolve previously-resolved module specifier");
+
+ // Let resolved module script be moduleMap[url]. (This entry must exist for us
+ // to have gotten to this point.)
+
ModuleScript* ms = script->Loader()->GetFetchedModule(uri);
- if (!ms) {
- return HandleModuleNotFound(aCx, script, string);
- }
+ MOZ_ASSERT(ms, "Resolved module not found in module map");
- if (ms->InstantiationFailed()) {
- JS::Rooted<JS::Value> exception(aCx, ms->Exception());
- JS_SetPendingException(aCx, exception);
- return false;
- }
+ MOZ_ASSERT(!ms->IsErrored());
*vp = JS::ObjectValue(*ms->ModuleRecord());
return true;
@@ -844,9 +868,35 @@ EnsureModuleResolveHook(JSContext* aCx)
}
void
+ScriptLoader::CheckModuleDependenciesLoaded(ModuleLoadRequest* aRequest)
+{
+ RefPtr<ModuleScript> moduleScript = aRequest->mModuleScript;
+ if (moduleScript && !moduleScript->IsErrored()) {
+ for (auto childRequest : aRequest->mImports) {
+ ModuleScript* childScript = childRequest->mModuleScript;
+ if (!childScript) {
+ // Load error
+ aRequest->mModuleScript = nullptr;
+ return;
+ } else if (childScript->IsErrored()) {
+ // Script error
+ moduleScript->SetPreInstantiationError(childScript->Error());
+ return;
+ }
+ }
+ }
+}
+
+void
ScriptLoader::ProcessLoadedModuleTree(ModuleLoadRequest* aRequest)
{
if (aRequest->IsTopLevel()) {
+ ModuleScript* moduleScript = aRequest->mModuleScript;
+ if (moduleScript && !moduleScript->IsErrored()) {
+ if (!InstantiateModuleTree(aRequest)) {
+ aRequest->mModuleScript = nullptr;
+ }
+ }
MaybeMoveToLoadedList(aRequest);
ProcessPendingRequests();
}
@@ -859,60 +909,35 @@ ScriptLoader::ProcessLoadedModuleTree(ModuleLoadRequest* aRequest)
bool
ScriptLoader::InstantiateModuleTree(ModuleLoadRequest* aRequest)
{
- // Perform eager instantiation of the loaded module tree.
+ // Instantiate a top-level module and record any error.
MOZ_ASSERT(aRequest);
+ MOZ_ASSERT(aRequest->IsTopLevel());
- ModuleScript* ms = aRequest->mModuleScript;
- MOZ_ASSERT(ms);
- if (!ms || !ms->ModuleRecord()) {
- return false;
- }
+ ModuleScript* moduleScript = aRequest->mModuleScript;
+ MOZ_ASSERT(moduleScript);
+ MOZ_ASSERT(moduleScript->ModuleRecord());
+ nsAutoMicroTask mt;
AutoJSAPI jsapi;
- if (NS_WARN_IF(!jsapi.Init(ms->ModuleRecord()))) {
+ if (NS_WARN_IF(!jsapi.Init(moduleScript->ModuleRecord()))) {
return false;
}
nsresult rv = EnsureModuleResolveHook(jsapi.cx());
NS_ENSURE_SUCCESS(rv, false);
- JS::Rooted<JSObject*> module(jsapi.cx(), ms->ModuleRecord());
- bool ok = NS_SUCCEEDED(nsJSUtils::ModuleDeclarationInstantiation(jsapi.cx(), module));
+ JS::Rooted<JSObject*> module(jsapi.cx(), moduleScript->ModuleRecord());
+ bool ok = NS_SUCCEEDED(nsJSUtils::ModuleInstantiate(jsapi.cx(), module));
- JS::RootedValue exception(jsapi.cx());
if (!ok) {
MOZ_ASSERT(jsapi.HasException());
+ JS::RootedValue exception(jsapi.cx());
if (!jsapi.StealException(&exception)) {
return false;
}
MOZ_ASSERT(!exception.isUndefined());
- }
-
- // Mark this module and any uninstantiated dependencies found via depth-first
- // search as instantiated and record any error.
-
- mozilla::Vector<ModuleLoadRequest*, 1> requests;
- if (!requests.append(aRequest)) {
- return false;
- }
-
- while (!requests.empty()) {
- ModuleLoadRequest* request = requests.popCopy();
- ModuleScript* ms = request->mModuleScript;
- if (!ms->IsUninstantiated()) {
- continue;
- }
-
- ms->SetInstantiationResult(exception);
-
- for (auto import : request->mImports) {
- if (import->mModuleScript->IsUninstantiated() &&
- !requests.append(import))
- {
- return false;
- }
- }
+ // Ignore the exception. It will be recorded in the module record.
}
return true;
@@ -1427,13 +1452,19 @@ ScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
ModuleLoadRequest* modReq = request->AsModuleRequest();
modReq->mBaseURL = mDocument->GetDocBaseURI();
rv = CreateModuleScript(modReq);
- NS_ENSURE_SUCCESS(rv, false);
- StartFetchingModuleDependencies(modReq);
+ MOZ_ASSERT(NS_FAILED(rv) == !modReq->mModuleScript);
+ if (NS_FAILED(rv)) {
+ modReq->LoadFailed();
+ return false;
+ }
if (aElement->GetScriptAsync()) {
mLoadingAsyncRequests.AppendElement(request);
} else {
AddDeferRequest(request);
}
+ if (!modReq->mModuleScript->IsErrored()) {
+ StartFetchingModuleDependencies(modReq);
+ }
return false;
}
request->mProgress = ScriptLoadRequest::Progress::Ready;
@@ -1511,11 +1542,7 @@ ScriptLoader::ProcessOffThreadRequest(ScriptLoadRequest* aRequest)
if (aRequest->IsModuleRequest()) {
MOZ_ASSERT(aRequest->mOffThreadToken);
ModuleLoadRequest* request = aRequest->AsModuleRequest();
- nsresult rv = ProcessFetchedModuleSource(request);
- if (NS_FAILED(rv)) {
- request->LoadFailed();
- }
- return rv;
+ return ProcessFetchedModuleSource(request);
}
aRequest->SetReady();
@@ -1687,7 +1714,7 @@ ScriptLoader::ProcessRequest(ScriptLoadRequest* aRequest)
if (aRequest->IsModuleRequest() &&
!aRequest->AsModuleRequest()->mModuleScript)
{
- // There was an error parsing a module script. Nothing to do here.
+ // There was an error fetching a module script. Nothing to do here.
FireScriptAvailable(NS_ERROR_FAILURE, aRequest);
return NS_OK;
}
@@ -1909,8 +1936,8 @@ ScriptLoader::EvaluateScript(ScriptLoadRequest* aRequest)
// http://www.whatwg.org/specs/web-apps/current-work/#execute-the-script-block
nsAutoMicroTask mt;
AutoEntryScript aes(globalObject, "<script> element", true);
- JS::Rooted<JSObject*> global(aes.cx(),
- globalObject->GetGlobalJSObject());
+ JSContext* cx = aes.cx();
+ JS::Rooted<JSObject*> global(cx, globalObject->GetGlobalJSObject());
bool oldProcessingScriptTag = context->GetProcessingScriptTag();
context->SetProcessingScriptTag(true);
@@ -1931,28 +1958,38 @@ ScriptLoader::EvaluateScript(ScriptLoadRequest* aRequest)
}
if (aRequest->IsModuleRequest()) {
+ rv = EnsureModuleResolveHook(cx);
+ NS_ENSURE_SUCCESS(rv, rv);
+
ModuleLoadRequest* request = aRequest->AsModuleRequest();
MOZ_ASSERT(request->mModuleScript);
MOZ_ASSERT(!request->mOffThreadToken);
- ModuleScript* ms = request->mModuleScript;
- MOZ_ASSERT(!ms->IsUninstantiated());
- if (ms->InstantiationFailed()) {
- JS::Rooted<JS::Value> exception(aes.cx(), ms->Exception());
- JS_SetPendingException(aes.cx(), exception);
- rv = NS_ERROR_FAILURE;
- } else {
- JS::Rooted<JSObject*> module(aes.cx(), ms->ModuleRecord());
- MOZ_ASSERT(module);
- rv = nsJSUtils::ModuleEvaluation(aes.cx(), module);
+
+ ModuleScript* moduleScript = request->mModuleScript;
+ if (moduleScript->IsErrored()) {
+ // Module has an error status
+ JS::Rooted<JS::Value> error(cx, moduleScript->Error());
+ JS_SetPendingException(cx, error);
+ return NS_OK; // An error is reported by AutoEntryScript.
+ }
+
+ JS::Rooted<JSObject*> module(cx, moduleScript->ModuleRecord());
+ MOZ_ASSERT(module);
+
+ rv = nsJSUtils::ModuleEvaluate(cx, module);
+ MOZ_ASSERT(NS_FAILED(rv) == aes.HasException());
+ if (NS_FAILED(rv)) {
+ // Evaluation failed
+ rv = NS_OK; // An error is reported by AutoEntryScript.
}
} else {
- JS::CompileOptions options(aes.cx());
+ JS::CompileOptions options(cx);
rv = FillCompileOptionsForRequest(aes, aRequest, global, &options);
if (NS_SUCCEEDED(rv)) {
nsAutoString inlineData;
SourceBufferHolder srcBuf = GetScriptSource(aRequest, inlineData);
- rv = nsJSUtils::EvaluateString(aes.cx(), srcBuf, global, options,
+ rv = nsJSUtils::EvaluateString(cx, srcBuf, global, options,
aRequest->OffThreadTokenPtr());
}
}
diff --git a/dom/script/ScriptLoader.h b/dom/script/ScriptLoader.h
index 3c428deea..e6b75bf3b 100644
--- a/dom/script/ScriptLoader.h
+++ b/dom/script/ScriptLoader.h
@@ -580,6 +580,7 @@ private:
nsresult CreateModuleScript(ModuleLoadRequest* aRequest);
nsresult ProcessFetchedModuleSource(ModuleLoadRequest* aRequest);
+ void CheckModuleDependenciesLoaded(ModuleLoadRequest* aRequest);
void ProcessLoadedModuleTree(ModuleLoadRequest* aRequest);
bool InstantiateModuleTree(ModuleLoadRequest* aRequest);
void StartFetchingModuleDependencies(ModuleLoadRequest* aRequest);
diff --git a/js/src/builtin/Module.js b/js/src/builtin/Module.js
index 5c3d5e147..b3365b505 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,401 @@ 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 2
+ if (module.status === MODULE_STATUS_INSTANTIATING ||
+ module.status === MODULE_STATUS_EVALUATING)
+ {
+ ThrowInternalError(JSMSG_BAD_MODULE_STATUS);
+ }
+
+ // Step 3
+ let stack = [];
+
+ // Steps 4-5
+ try {
+ 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);
+ }
+
+ 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 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
- CreateModuleEnvironment(module);
- let env = GetModuleEnvironment(module);
+ assert(stack.length === 0,
+ "Stack should be empty after successful instantiation");
- SetModuleState(this, MODULE_STATE_INSTANTIATED);
+ // Step 8
+ return undefined;
+}
+_SetCanonicalName(ModuleInstantiate, "ModuleInstantiate");
- 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);
+// 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;
+}
- // 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);
+// 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,
+ e.lineNumber, e.columnNumber)
}
+ }
- // 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);
+ // 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,
+ imp.lineNumber, imp.columnNumber);
}
+
+ CreateImportBinding(env, imp.localName, resolution.module, resolution.bindingName);
}
+ }
- // Step 17.a.iii
- InstantiateModuleFunctionDeclarations(module);
- } catch (e) {
- RecordInstantationFailure(module);
- throw e;
+ InstantiateModuleFunctionDeclarations(module);
+}
+
+// 15.2.1.16.4.3 ResolutionError(module)
+function ResolutionError(resolution, kind, name, line, column)
+{
+ 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");
+
+ assert(line > 0,
+ "Line number should be present for all imports and indirect exports");
+
+ let errorNumber;
+ if (kind === "import") {
+ errorNumber = resolution.ambiguous ? JSMSG_AMBIGUOUS_IMPORT
+ : JSMSG_MISSING_IMPORT;
+ } else {
+ errorNumber = resolution.ambiguous ? JSMSG_AMBIGUOUS_INDIRECT_EXPORT
+ : JSMSG_MISSING_INDIRECT_EXPORT;
}
+
+ let message = GetErrorMessage(errorNumber) + ": " + name;
+ let error = CreateModuleSyntaxError(module, line, column, message);
+ 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..09193c9ca 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 \
@@ -69,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
@@ -82,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)
@@ -100,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
};
@@ -118,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)
@@ -129,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;
}
@@ -146,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)
@@ -166,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
};
@@ -191,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)
@@ -203,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;
}
@@ -564,7 +599,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 +723,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 +744,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 +825,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 +941,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 +992,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 +1036,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
};
@@ -1018,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)),
@@ -1045,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());
@@ -1053,7 +1097,9 @@ ModuleBuilder::buildTables()
exportName,
moduleRequest,
importName,
- nullptr);
+ nullptr,
+ exp->lineNumber(),
+ exp->columnNumber());
if (!exportEntry || !indirectExportEntries_.append(exportEntry))
return false;
}
@@ -1062,6 +1108,7 @@ ModuleBuilder::buildTables()
if (!starExportEntries_.append(exp))
return false;
} else {
+ MOZ_ASSERT(exp->lineNumber());
if (!indirectExportEntries_.append(exp))
return false;
}
@@ -1126,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;
}
@@ -1158,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;
@@ -1223,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;
}
}
@@ -1257,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 22db762ac..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;
@@ -192,8 +205,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 +217,8 @@ class ModuleObject : public NativeObject
InitialEnvironmentSlot,
EnvironmentSlot,
NamespaceSlot,
- StateSlot,
+ StatusSlot,
+ ErrorSlot,
HostDefinedSlot,
RequestedModulesSlot,
ImportEntriesSlot,
@@ -215,11 +229,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 +268,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 +280,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 +294,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,
@@ -294,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);
@@ -319,6 +343,7 @@ class MOZ_STACK_CLASS ModuleBuilder
ExclusiveContext* cx_;
RootedModuleObject module_;
+ const frontend::TokenStream& tokenStream_;
RootedAtomVector requestedModules_;
RootedAtomVector importedBoundNames_;
RootedImportEntryVector importEntries_;
@@ -329,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/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/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/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;
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..9c508ebbd 100644
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -573,14 +573,14 @@ 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")
-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..cf5880e03 100644
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -4704,21 +4704,21 @@ 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);
assertSameCompartment(cx, moduleArg);
- return ModuleObject::DeclarationInstantiation(cx, moduleArg.as<ModuleObject>());
+ return ModuleObject::Instantiate(cx, moduleArg.as<ModuleObject>());
}
JS_PUBLIC_API(bool)
-JS::ModuleEvaluation(JSContext* cx, JS::HandleObject moduleArg)
+JS::ModuleEvaluate(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*)
@@ -4739,6 +4739,18 @@ JS::GetModuleScript(JSContext* cx, JS::HandleObject moduleArg)
return moduleArg->as<ModuleObject>().script();
}
+JS_PUBLIC_API(bool)
+JS::IsModuleErrored(JSObject* moduleArg)
+{
+ return moduleArg->as<ModuleObject>().status() == MODULE_STATUS_ERRORED;
+}
+
+JS_PUBLIC_API(JS::Value)
+JS::GetModuleError(JSObject* moduleArg)
+{
+ 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..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
@@ -4396,6 +4395,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)
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..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].
@@ -2060,24 +2104,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
@@ -2351,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),
@@ -2630,8 +2664,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),