mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-26 02:17:34 +09:00
Merge remote-tracking branch 'origin/master' into custom
This commit is contained in:
commit
3d5ac98e9d
47 changed files with 1435 additions and 608 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
JS::Rooted<JS::Value> error(aCx);
|
||||
if (!CreateTypeError(aCx, aScript, message, &error)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
|
|
@ -843,10 +867,36 @@ EnsureModuleResolveHook(JSContext* aCx)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue