Next part 2 of the Implement module type scripting.
parent
2a9d5db8a0
commit
a84aca97e2
|
@ -12446,3 +12446,16 @@ nsIDocument::GetSelection(ErrorResult& aRv)
|
||||||
|
|
||||||
return nsGlobalWindow::Cast(window)->GetSelection(aRv);
|
return nsGlobalWindow::Cast(window)->GetSelection(aRv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
nsIDocument::ModuleScriptsEnabled()
|
||||||
|
{
|
||||||
|
static bool sEnabledForContent = false;
|
||||||
|
static bool sCachedPref = false;
|
||||||
|
if (!sCachedPref) {
|
||||||
|
sCachedPref = true;
|
||||||
|
Preferences::AddBoolVarCache(&sEnabledForContent, "dom.moduleScripts.enabled", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nsContentUtils::IsChromeDoc(this) || sEnabledForContent;
|
||||||
|
}
|
|
@ -2830,6 +2830,8 @@ public:
|
||||||
virtual void ScheduleIntersectionObserverNotification() = 0;
|
virtual void ScheduleIntersectionObserverNotification() = 0;
|
||||||
virtual void NotifyIntersectionObservers() = 0;
|
virtual void NotifyIntersectionObservers() = 0;
|
||||||
|
|
||||||
|
bool ModuleScriptsEnabled();
|
||||||
|
|
||||||
bool ShouldThrowOnDynamicMarkupInsertion()
|
bool ShouldThrowOnDynamicMarkupInsertion()
|
||||||
{
|
{
|
||||||
return mThrowOnDynamicMarkupInsertionCounter;
|
return mThrowOnDynamicMarkupInsertionCounter;
|
||||||
|
|
|
@ -280,12 +280,20 @@ HTMLScriptElement::GetScriptCharset(nsAString& charset)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
HTMLScriptElement::FreezeUriAsyncDefer()
|
HTMLScriptElement::FreezeExecutionAttrs(nsIDocument* aOwnerDoc)
|
||||||
{
|
{
|
||||||
if (mFrozen) {
|
if (mFrozen) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(!mIsModule && !mAsync && !mDefer && !mExternal);
|
||||||
|
|
||||||
|
// Determine whether this is a classic script or a module script.
|
||||||
|
nsAutoString type;
|
||||||
|
GetScriptType(type);
|
||||||
|
mIsModule = aOwnerDoc->ModuleScriptsEnabled() &&
|
||||||
|
!type.IsEmpty() && type.LowerCaseEqualsASCII("module");
|
||||||
|
|
||||||
// variation of this code in nsSVGScriptElement - check if changes
|
// variation of this code in nsSVGScriptElement - check if changes
|
||||||
// need to be transfered when modifying. Note that we don't use GetSrc here
|
// need to be transfered when modifying. Note that we don't use GetSrc here
|
||||||
// because it will return the base URL when the attr value is "".
|
// because it will return the base URL when the attr value is "".
|
||||||
|
@ -300,14 +308,13 @@ HTMLScriptElement::FreezeUriAsyncDefer()
|
||||||
|
|
||||||
// At this point mUri will be null for invalid URLs.
|
// At this point mUri will be null for invalid URLs.
|
||||||
mExternal = true;
|
mExternal = true;
|
||||||
|
|
||||||
bool defer, async;
|
|
||||||
GetAsync(&async);
|
|
||||||
GetDefer(&defer);
|
|
||||||
|
|
||||||
mDefer = !async && defer;
|
|
||||||
mAsync = async;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool defer, async;
|
||||||
|
GetAsync(&async);
|
||||||
|
mAsync = (mExternal || mIsModule) && async;
|
||||||
|
GetDefer(&defer);
|
||||||
|
mDefer = mExternal && !async && defer;
|
||||||
|
|
||||||
mFrozen = true;
|
mFrozen = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ public:
|
||||||
virtual bool GetScriptType(nsAString& type) override;
|
virtual bool GetScriptType(nsAString& type) override;
|
||||||
virtual void GetScriptText(nsAString& text) override;
|
virtual void GetScriptText(nsAString& text) override;
|
||||||
virtual void GetScriptCharset(nsAString& charset) override;
|
virtual void GetScriptCharset(nsAString& charset) override;
|
||||||
virtual void FreezeUriAsyncDefer() override;
|
virtual void FreezeExecutionAttrs(nsIDocument* aOwnerDoc) override;
|
||||||
virtual CORSMode GetCORSMode() const override;
|
virtual CORSMode GetCORSMode() const override;
|
||||||
|
|
||||||
// nsIContent
|
// nsIContent
|
||||||
|
|
|
@ -17,26 +17,54 @@ NS_INTERFACE_MAP_END_INHERITING(ScriptLoadRequest)
|
||||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(ModuleLoadRequest, ScriptLoadRequest,
|
NS_IMPL_CYCLE_COLLECTION_INHERITED(ModuleLoadRequest, ScriptLoadRequest,
|
||||||
mBaseURL,
|
mBaseURL,
|
||||||
mLoader,
|
mLoader,
|
||||||
mParent,
|
|
||||||
mModuleScript,
|
mModuleScript,
|
||||||
mImports)
|
mImports)
|
||||||
|
|
||||||
NS_IMPL_ADDREF_INHERITED(ModuleLoadRequest, ScriptLoadRequest)
|
NS_IMPL_ADDREF_INHERITED(ModuleLoadRequest, ScriptLoadRequest)
|
||||||
NS_IMPL_RELEASE_INHERITED(ModuleLoadRequest, ScriptLoadRequest)
|
NS_IMPL_RELEASE_INHERITED(ModuleLoadRequest, ScriptLoadRequest)
|
||||||
|
|
||||||
ModuleLoadRequest::ModuleLoadRequest(nsIScriptElement* aElement,
|
ModuleLoadRequest::ModuleLoadRequest(nsIURI* aURI,
|
||||||
|
nsIScriptElement* aElement,
|
||||||
uint32_t aVersion,
|
uint32_t aVersion,
|
||||||
CORSMode aCORSMode,
|
CORSMode aCORSMode,
|
||||||
const SRIMetadata &aIntegrity,
|
const SRIMetadata &aIntegrity,
|
||||||
|
nsIURI* aReferrer,
|
||||||
|
mozilla::net::ReferrerPolicy aReferrerPolicy,
|
||||||
ScriptLoader* aLoader)
|
ScriptLoader* aLoader)
|
||||||
: ScriptLoadRequest(ScriptKind::Module,
|
: ScriptLoadRequest(ScriptKind::Module,
|
||||||
|
aURI,
|
||||||
aElement,
|
aElement,
|
||||||
aVersion,
|
aVersion,
|
||||||
aCORSMode,
|
aCORSMode,
|
||||||
aIntegrity),
|
aIntegrity,
|
||||||
|
aReferrer,
|
||||||
|
aReferrerPolicy),
|
||||||
mIsTopLevel(true),
|
mIsTopLevel(true),
|
||||||
mLoader(aLoader)
|
mLoader(aLoader),
|
||||||
{}
|
mVisitedSet(new VisitedURLSet())
|
||||||
|
{
|
||||||
|
mVisitedSet->PutEntry(aURI);
|
||||||
|
}
|
||||||
|
|
||||||
|
ModuleLoadRequest::ModuleLoadRequest(nsIURI* aURI,
|
||||||
|
ModuleLoadRequest* aParent)
|
||||||
|
: ScriptLoadRequest(ScriptKind::Module,
|
||||||
|
aURI,
|
||||||
|
aParent->mElement,
|
||||||
|
aParent->mJSVersion,
|
||||||
|
aParent->mCORSMode,
|
||||||
|
SRIMetadata(),
|
||||||
|
aParent->mURI,
|
||||||
|
aParent->mReferrerPolicy),
|
||||||
|
mIsTopLevel(false),
|
||||||
|
mLoader(aParent->mLoader),
|
||||||
|
mVisitedSet(aParent->mVisitedSet)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mVisitedSet->Contains(aURI));
|
||||||
|
|
||||||
|
mIsInline = false;
|
||||||
|
mScriptMode = aParent->mScriptMode;
|
||||||
|
}
|
||||||
|
|
||||||
void ModuleLoadRequest::Cancel()
|
void ModuleLoadRequest::Cancel()
|
||||||
{
|
{
|
||||||
|
@ -83,7 +111,7 @@ ModuleLoadRequest::ModuleLoaded()
|
||||||
// been loaded.
|
// been loaded.
|
||||||
|
|
||||||
mModuleScript = mLoader->GetFetchedModule(mURI);
|
mModuleScript = mLoader->GetFetchedModule(mURI);
|
||||||
if (!mModuleScript || mModuleScript->IsErrored()) {
|
if (!mModuleScript || mModuleScript->HasParseError()) {
|
||||||
ModuleErrored();
|
ModuleErrored();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -95,7 +123,7 @@ void
|
||||||
ModuleLoadRequest::ModuleErrored()
|
ModuleLoadRequest::ModuleErrored()
|
||||||
{
|
{
|
||||||
mLoader->CheckModuleDependenciesLoaded(this);
|
mLoader->CheckModuleDependenciesLoaded(this);
|
||||||
MOZ_ASSERT(!mModuleScript || mModuleScript->IsErrored());
|
MOZ_ASSERT(!mModuleScript || mModuleScript->HasParseError());
|
||||||
|
|
||||||
CancelImports();
|
CancelImports();
|
||||||
SetReady();
|
SetReady();
|
||||||
|
@ -132,8 +160,7 @@ ModuleLoadRequest::LoadFinished()
|
||||||
{
|
{
|
||||||
mLoader->ProcessLoadedModuleTree(this);
|
mLoader->ProcessLoadedModuleTree(this);
|
||||||
mLoader = nullptr;
|
mLoader = nullptr;
|
||||||
mParent = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // dom namespace
|
} // dom namespace
|
||||||
} // mozilla namespace
|
} // mozilla namespace
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#define mozilla_dom_ModuleLoadRequest_h
|
#define mozilla_dom_ModuleLoadRequest_h
|
||||||
|
|
||||||
#include "mozilla/dom/ScriptLoader.h"
|
#include "mozilla/dom/ScriptLoader.h"
|
||||||
|
#include "nsURIHashKey.h"
|
||||||
#include "mozilla/MozPromise.h"
|
#include "mozilla/MozPromise.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
@ -16,6 +17,16 @@ namespace dom {
|
||||||
class ModuleScript;
|
class ModuleScript;
|
||||||
class ScriptLoader;
|
class ScriptLoader;
|
||||||
|
|
||||||
|
// A reference counted set of URLs we have visited in the process of loading a
|
||||||
|
// module graph.
|
||||||
|
class VisitedURLSet : public nsTHashtable<nsURIHashKey>
|
||||||
|
{
|
||||||
|
NS_INLINE_DECL_REFCOUNTING(VisitedURLSet)
|
||||||
|
|
||||||
|
private:
|
||||||
|
~VisitedURLSet() = default;
|
||||||
|
};
|
||||||
|
|
||||||
// A load request for a module, created for every top level module script and
|
// A load request for a module, created for every top level module script and
|
||||||
// every module import. Load request can share a ModuleScript if there are
|
// every module import. Load request can share a ModuleScript if there are
|
||||||
// multiple imports of the same module.
|
// multiple imports of the same module.
|
||||||
|
@ -31,12 +42,20 @@ public:
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ModuleLoadRequest, ScriptLoadRequest)
|
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ModuleLoadRequest, ScriptLoadRequest)
|
||||||
|
|
||||||
ModuleLoadRequest(nsIScriptElement* aElement,
|
// Create a top-level module load request.
|
||||||
|
ModuleLoadRequest(nsIURI* aURI,
|
||||||
|
nsIScriptElement* aElement,
|
||||||
uint32_t aVersion,
|
uint32_t aVersion,
|
||||||
CORSMode aCORSMode,
|
CORSMode aCORSMode,
|
||||||
const SRIMetadata& aIntegrity,
|
const SRIMetadata& aIntegrity,
|
||||||
|
nsIURI* aReferrer,
|
||||||
|
mozilla::net::ReferrerPolicy,
|
||||||
ScriptLoader* aLoader);
|
ScriptLoader* aLoader);
|
||||||
|
|
||||||
|
// Create a module load request for an imported module.
|
||||||
|
ModuleLoadRequest(nsIURI* aURI,
|
||||||
|
ModuleLoadRequest* aParent);
|
||||||
|
|
||||||
bool IsTopLevel() const {
|
bool IsTopLevel() const {
|
||||||
return mIsTopLevel;
|
return mIsTopLevel;
|
||||||
}
|
}
|
||||||
|
@ -55,7 +74,7 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Is this a request for a top level module script or an import?
|
// Is this a request for a top level module script or an import?
|
||||||
bool mIsTopLevel;
|
const bool mIsTopLevel;
|
||||||
|
|
||||||
// The base URL used for resolving relative module imports.
|
// The base URL used for resolving relative module imports.
|
||||||
nsCOMPtr<nsIURI> mBaseURL;
|
nsCOMPtr<nsIURI> mBaseURL;
|
||||||
|
@ -64,10 +83,6 @@ public:
|
||||||
// finishes.
|
// finishes.
|
||||||
RefPtr<ScriptLoader> mLoader;
|
RefPtr<ScriptLoader> mLoader;
|
||||||
|
|
||||||
// The importing module, or nullptr for top level module scripts. Used to
|
|
||||||
// implement the ancestor list checked when fetching module dependencies.
|
|
||||||
RefPtr<ModuleLoadRequest> mParent;
|
|
||||||
|
|
||||||
// Set to a module script object after a successful load or nullptr on
|
// Set to a module script object after a successful load or nullptr on
|
||||||
// failure.
|
// failure.
|
||||||
RefPtr<ModuleScript> mModuleScript;
|
RefPtr<ModuleScript> mModuleScript;
|
||||||
|
@ -79,9 +94,13 @@ public:
|
||||||
|
|
||||||
// Array of imported modules.
|
// Array of imported modules.
|
||||||
nsTArray<RefPtr<ModuleLoadRequest>> mImports;
|
nsTArray<RefPtr<ModuleLoadRequest>> mImports;
|
||||||
|
|
||||||
|
// Set of module URLs visited while fetching the module graph this request is
|
||||||
|
// part of.
|
||||||
|
RefPtr<VisitedURLSet> mVisitedSet;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // dom namespace
|
} // dom namespace
|
||||||
} // mozilla namespace
|
} // mozilla namespace
|
||||||
|
|
||||||
#endif // mozilla_dom_ModuleLoadRequest_h
|
#endif // mozilla_dom_ModuleLoadRequest_h
|
||||||
|
|
|
@ -26,7 +26,8 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ModuleScript)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mLoader)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mLoader)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBaseURL)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBaseURL)
|
||||||
tmp->UnlinkModuleRecord();
|
tmp->UnlinkModuleRecord();
|
||||||
tmp->mError.setUndefined();
|
tmp->mParseError.setUndefined();
|
||||||
|
tmp->mErrorToRethrow.setUndefined();
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ModuleScript)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ModuleScript)
|
||||||
|
@ -35,7 +36,8 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ModuleScript)
|
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ModuleScript)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mModuleRecord)
|
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mModuleRecord)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mError)
|
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mParseError)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mErrorToRethrow)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(ModuleScript)
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(ModuleScript)
|
||||||
|
@ -48,7 +50,8 @@ ModuleScript::ModuleScript(ScriptLoader *aLoader, nsIURI* aBaseURL)
|
||||||
MOZ_ASSERT(mLoader);
|
MOZ_ASSERT(mLoader);
|
||||||
MOZ_ASSERT(mBaseURL);
|
MOZ_ASSERT(mBaseURL);
|
||||||
MOZ_ASSERT(!mModuleRecord);
|
MOZ_ASSERT(!mModuleRecord);
|
||||||
MOZ_ASSERT(mError.isUndefined());
|
MOZ_ASSERT(!HasParseError());
|
||||||
|
MOZ_ASSERT(!HasErrorToRethrow());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -74,7 +77,8 @@ void
|
||||||
ModuleScript::SetModuleRecord(JS::Handle<JSObject*> aModuleRecord)
|
ModuleScript::SetModuleRecord(JS::Handle<JSObject*> aModuleRecord)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(!mModuleRecord);
|
MOZ_ASSERT(!mModuleRecord);
|
||||||
MOZ_ASSERT(mError.isUndefined());
|
MOZ_ASSERT(!HasParseError());
|
||||||
|
MOZ_ASSERT(!HasErrorToRethrow());
|
||||||
|
|
||||||
mModuleRecord = aModuleRecord;
|
mModuleRecord = aModuleRecord;
|
||||||
|
|
||||||
|
@ -85,37 +89,24 @@ ModuleScript::SetModuleRecord(JS::Handle<JSObject*> aModuleRecord)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ModuleScript::SetPreInstantiationError(const JS::Value& aError)
|
ModuleScript::SetParseError(const JS::Value& aError)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(!aError.isUndefined());
|
MOZ_ASSERT(!aError.isUndefined());
|
||||||
|
MOZ_ASSERT(!HasParseError());
|
||||||
|
MOZ_ASSERT(!HasErrorToRethrow());
|
||||||
|
|
||||||
UnlinkModuleRecord();
|
UnlinkModuleRecord();
|
||||||
mError = aError;
|
mParseError = aError;
|
||||||
|
|
||||||
HoldJSObjects(this);
|
HoldJSObjects(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
ModuleScript::IsErrored() const
|
ModuleScript::SetErrorToRethrow(const JS::Value& aError)
|
||||||
{
|
{
|
||||||
if (!mModuleRecord) {
|
MOZ_ASSERT(!aError.isUndefined());
|
||||||
MOZ_ASSERT(!mError.isUndefined());
|
MOZ_ASSERT(!HasErrorToRethrow());
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return JS::IsModuleErrored(mModuleRecord);
|
mErrorToRethrow = aError;
|
||||||
}
|
|
||||||
|
|
||||||
JS::Value
|
|
||||||
ModuleScript::Error() const
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(IsErrored());
|
|
||||||
|
|
||||||
if (!mModuleRecord) {
|
|
||||||
return mError;
|
|
||||||
}
|
|
||||||
|
|
||||||
return JS::GetModuleError(mModuleRecord);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // dom namespace
|
} // dom namespace
|
||||||
|
|
|
@ -23,7 +23,8 @@ class ModuleScript final : public nsISupports
|
||||||
RefPtr<ScriptLoader> mLoader;
|
RefPtr<ScriptLoader> mLoader;
|
||||||
nsCOMPtr<nsIURI> mBaseURL;
|
nsCOMPtr<nsIURI> mBaseURL;
|
||||||
JS::Heap<JSObject*> mModuleRecord;
|
JS::Heap<JSObject*> mModuleRecord;
|
||||||
JS::Heap<JS::Value> mError;
|
JS::Heap<JS::Value> mParseError;
|
||||||
|
JS::Heap<JS::Value> mErrorToRethrow;
|
||||||
|
|
||||||
~ModuleScript();
|
~ModuleScript();
|
||||||
|
|
||||||
|
@ -35,14 +36,17 @@ public:
|
||||||
nsIURI* aBaseURL);
|
nsIURI* aBaseURL);
|
||||||
|
|
||||||
void SetModuleRecord(JS::Handle<JSObject*> aModuleRecord);
|
void SetModuleRecord(JS::Handle<JSObject*> aModuleRecord);
|
||||||
void SetPreInstantiationError(const JS::Value& aError);
|
void SetParseError(const JS::Value& aError);
|
||||||
|
void SetErrorToRethrow(const JS::Value& aError);
|
||||||
|
|
||||||
ScriptLoader* Loader() const { return mLoader; }
|
ScriptLoader* Loader() const { return mLoader; }
|
||||||
JSObject* ModuleRecord() const { return mModuleRecord; }
|
JSObject* ModuleRecord() const { return mModuleRecord; }
|
||||||
nsIURI* BaseURL() const { return mBaseURL; }
|
nsIURI* BaseURL() const { return mBaseURL; }
|
||||||
|
|
||||||
bool IsErrored() const;
|
JS::Value ParseError() const { return mParseError; }
|
||||||
JS::Value Error() const;
|
JS::Value ErrorToRethrow() const { return mErrorToRethrow; }
|
||||||
|
bool HasParseError() const { return !mParseError.isUndefined(); }
|
||||||
|
bool HasErrorToRethrow() const { return !mErrorToRethrow.isUndefined(); }
|
||||||
|
|
||||||
void UnlinkModuleRecord();
|
void UnlinkModuleRecord();
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,11 +21,11 @@ using namespace mozilla::dom;
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
ScriptElement::ScriptAvailable(nsresult aResult,
|
ScriptElement::ScriptAvailable(nsresult aResult,
|
||||||
nsIScriptElement *aElement,
|
nsIScriptElement *aElement,
|
||||||
bool aIsInline,
|
bool aIsInlineClassicScript,
|
||||||
nsIURI *aURI,
|
nsIURI *aURI,
|
||||||
int32_t aLineNo)
|
int32_t aLineNo)
|
||||||
{
|
{
|
||||||
if (!aIsInline && NS_FAILED(aResult)) {
|
if (!aIsInlineClassicScript && NS_FAILED(aResult)) {
|
||||||
nsCOMPtr<nsIParser> parser = do_QueryReferent(mCreatorParser);
|
nsCOMPtr<nsIParser> parser = do_QueryReferent(mCreatorParser);
|
||||||
if (parser) {
|
if (parser) {
|
||||||
parser->PushDefinedInsertionPoint();
|
parser->PushDefinedInsertionPoint();
|
||||||
|
@ -128,11 +128,11 @@ ScriptElement::MaybeProcessScript()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FreezeUriAsyncDefer();
|
nsIDocument* ownerDoc = cont->OwnerDoc();
|
||||||
|
FreezeExecutionAttrs(ownerDoc);
|
||||||
|
|
||||||
mAlreadyStarted = true;
|
mAlreadyStarted = true;
|
||||||
|
|
||||||
nsIDocument* ownerDoc = cont->OwnerDoc();
|
|
||||||
nsCOMPtr<nsIParser> parser = ((nsIScriptElement*) this)->GetCreatorParser();
|
nsCOMPtr<nsIParser> parser = ((nsIScriptElement*) this)->GetCreatorParser();
|
||||||
if (parser) {
|
if (parser) {
|
||||||
nsCOMPtr<nsIContentSink> sink = parser->GetContentSink();
|
nsCOMPtr<nsIContentSink> sink = parser->GetContentSink();
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -62,17 +62,21 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ScriptLoadRequest(ScriptKind aKind,
|
ScriptLoadRequest(ScriptKind aKind,
|
||||||
|
nsIURI* aURI,
|
||||||
nsIScriptElement* aElement,
|
nsIScriptElement* aElement,
|
||||||
uint32_t aVersion,
|
uint32_t aVersion,
|
||||||
mozilla::CORSMode aCORSMode,
|
mozilla::CORSMode aCORSMode,
|
||||||
const mozilla::dom::SRIMetadata &aIntegrity)
|
const SRIMetadata& aIntegrity,
|
||||||
|
nsIURI* aReferrer,
|
||||||
|
mozilla::net::ReferrerPolicy aReferrerPolicy)
|
||||||
: mKind(aKind),
|
: mKind(aKind),
|
||||||
mElement(aElement),
|
mElement(aElement),
|
||||||
mProgress(Progress::Loading),
|
mProgress(Progress::Loading),
|
||||||
|
mScriptMode(ScriptMode::eBlocking),
|
||||||
mIsInline(true),
|
mIsInline(true),
|
||||||
mHasSourceMapURL(false),
|
mHasSourceMapURL(false),
|
||||||
mIsDefer(false),
|
mInDeferList(false),
|
||||||
mIsAsync(false),
|
mInAsyncList(false),
|
||||||
mIsNonAsyncScriptInserted(false),
|
mIsNonAsyncScriptInserted(false),
|
||||||
mIsXSLT(false),
|
mIsXSLT(false),
|
||||||
mIsCanceled(false),
|
mIsCanceled(false),
|
||||||
|
@ -81,10 +85,12 @@ public:
|
||||||
mScriptTextBuf(nullptr),
|
mScriptTextBuf(nullptr),
|
||||||
mScriptTextLength(0),
|
mScriptTextLength(0),
|
||||||
mJSVersion(aVersion),
|
mJSVersion(aVersion),
|
||||||
|
mURI(aURI),
|
||||||
mLineNo(1),
|
mLineNo(1),
|
||||||
mCORSMode(aCORSMode),
|
mCORSMode(aCORSMode),
|
||||||
mIntegrity(aIntegrity),
|
mIntegrity(aIntegrity),
|
||||||
mReferrerPolicy(mozilla::net::RP_Default)
|
mReferrer(aReferrer),
|
||||||
|
mReferrerPolicy(aReferrerPolicy)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +106,8 @@ public:
|
||||||
|
|
||||||
void FireScriptAvailable(nsresult aResult)
|
void FireScriptAvailable(nsresult aResult)
|
||||||
{
|
{
|
||||||
mElement->ScriptAvailable(aResult, mElement, mIsInline, mURI, mLineNo);
|
bool isInlineClassicScript = mIsInline && !IsModuleRequest();
|
||||||
|
mElement->ScriptAvailable(aResult, mElement, isInlineClassicScript, mURI, mLineNo);
|
||||||
}
|
}
|
||||||
void FireScriptEvaluated(nsresult aResult)
|
void FireScriptEvaluated(nsresult aResult)
|
||||||
{
|
{
|
||||||
|
@ -143,6 +150,29 @@ public:
|
||||||
(IsReadyToRun() && mWasCompiledOMT);
|
(IsReadyToRun() && mWasCompiledOMT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class ScriptMode : uint8_t {
|
||||||
|
eBlocking,
|
||||||
|
eDeferred,
|
||||||
|
eAsync
|
||||||
|
};
|
||||||
|
|
||||||
|
void SetScriptMode(bool aDeferAttr, bool aAsyncAttr);
|
||||||
|
|
||||||
|
bool IsBlockingScript() const
|
||||||
|
{
|
||||||
|
return mScriptMode == ScriptMode::eBlocking;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsDeferredScript() const
|
||||||
|
{
|
||||||
|
return mScriptMode == ScriptMode::eDeferred;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsAsyncScript() const
|
||||||
|
{
|
||||||
|
return mScriptMode == ScriptMode::eAsync;
|
||||||
|
}
|
||||||
|
|
||||||
void MaybeCancelOffThreadScript();
|
void MaybeCancelOffThreadScript();
|
||||||
|
|
||||||
using super::getNext;
|
using super::getNext;
|
||||||
|
@ -151,10 +181,11 @@ public:
|
||||||
const ScriptKind mKind;
|
const ScriptKind mKind;
|
||||||
nsCOMPtr<nsIScriptElement> mElement;
|
nsCOMPtr<nsIScriptElement> mElement;
|
||||||
Progress mProgress; // Are we still waiting for a load to complete?
|
Progress mProgress; // Are we still waiting for a load to complete?
|
||||||
|
ScriptMode mScriptMode; // Whether this script is blocking, deferred or async.
|
||||||
bool mIsInline; // Is the script inline or loaded?
|
bool mIsInline; // Is the script inline or loaded?
|
||||||
bool mHasSourceMapURL; // Does the HTTP header have a source map url?
|
bool mHasSourceMapURL; // Does the HTTP header have a source map url?
|
||||||
bool mIsDefer; // True if we live in mDeferRequests.
|
bool mInDeferList; // True if we live in mDeferRequests.
|
||||||
bool mIsAsync; // True if we live in mLoadingAsyncRequests or mLoadedAsyncRequests.
|
bool mInAsyncList; // True if we live in mLoadingAsyncRequests or mLoadedAsyncRequests.
|
||||||
bool mIsNonAsyncScriptInserted; // True if we live in mNonAsyncExternalScriptInsertedRequests
|
bool mIsNonAsyncScriptInserted; // True if we live in mNonAsyncExternalScriptInsertedRequests
|
||||||
bool mIsXSLT; // True if we live in mXSLTRequests.
|
bool mIsXSLT; // True if we live in mXSLTRequests.
|
||||||
bool mIsCanceled; // True if we have been explicitly canceled.
|
bool mIsCanceled; // True if we have been explicitly canceled.
|
||||||
|
@ -164,13 +195,14 @@ public:
|
||||||
char16_t* mScriptTextBuf; // Holds script text for non-inline scripts. Don't
|
char16_t* mScriptTextBuf; // Holds script text for non-inline scripts. Don't
|
||||||
size_t mScriptTextLength; // use nsString so we can give ownership to jsapi.
|
size_t mScriptTextLength; // use nsString so we can give ownership to jsapi.
|
||||||
uint32_t mJSVersion;
|
uint32_t mJSVersion;
|
||||||
nsCOMPtr<nsIURI> mURI;
|
const nsCOMPtr<nsIURI> mURI;
|
||||||
nsCOMPtr<nsIPrincipal> mOriginPrincipal;
|
nsCOMPtr<nsIPrincipal> mOriginPrincipal;
|
||||||
nsAutoCString mURL; // Keep the URI's filename alive during off thread parsing.
|
nsAutoCString mURL; // Keep the URI's filename alive during off thread parsing.
|
||||||
int32_t mLineNo;
|
int32_t mLineNo;
|
||||||
const mozilla::CORSMode mCORSMode;
|
const mozilla::CORSMode mCORSMode;
|
||||||
const mozilla::dom::SRIMetadata mIntegrity;
|
const SRIMetadata mIntegrity;
|
||||||
mozilla::net::ReferrerPolicy mReferrerPolicy;
|
const nsCOMPtr<nsIURI> mReferrer;
|
||||||
|
const mozilla::net::ReferrerPolicy mReferrerPolicy;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ScriptLoadRequestList : private mozilla::LinkedList<ScriptLoadRequest>
|
class ScriptLoadRequestList : private mozilla::LinkedList<ScriptLoadRequest>
|
||||||
|
@ -452,6 +484,8 @@ public:
|
||||||
const nsAString &aCrossOrigin,
|
const nsAString &aCrossOrigin,
|
||||||
const nsAString& aIntegrity,
|
const nsAString& aIntegrity,
|
||||||
bool aScriptFromHead,
|
bool aScriptFromHead,
|
||||||
|
bool aAsync,
|
||||||
|
bool aDefer,
|
||||||
const mozilla::net::ReferrerPolicy aReferrerPolicy);
|
const mozilla::net::ReferrerPolicy aReferrerPolicy);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -467,12 +501,13 @@ public:
|
||||||
private:
|
private:
|
||||||
virtual ~ScriptLoader();
|
virtual ~ScriptLoader();
|
||||||
|
|
||||||
ScriptLoadRequest* CreateLoadRequest(
|
ScriptLoadRequest* CreateLoadRequest(ScriptKind aKind,
|
||||||
ScriptKind aKind,
|
nsIURI* aURI,
|
||||||
nsIScriptElement* aElement,
|
nsIScriptElement* aElement,
|
||||||
uint32_t aVersion,
|
uint32_t aVersion,
|
||||||
mozilla::CORSMode aCORSMode,
|
mozilla::CORSMode aCORSMode,
|
||||||
const mozilla::dom::SRIMetadata &aIntegrity);
|
const SRIMetadata& aIntegrity,
|
||||||
|
mozilla::net::ReferrerPolicy aReferrerPolicy);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unblocks the creator parser of the parser-blocking scripts.
|
* Unblocks the creator parser of the parser-blocking scripts.
|
||||||
|
@ -500,6 +535,8 @@ private:
|
||||||
nsresult StartLoad(ScriptLoadRequest *aRequest, const nsAString &aType,
|
nsresult StartLoad(ScriptLoadRequest *aRequest, const nsAString &aType,
|
||||||
bool aScriptFromHead);
|
bool aScriptFromHead);
|
||||||
|
|
||||||
|
void HandleLoadError(ScriptLoadRequest *aRequest, nsresult aResult);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process any pending requests asynchronously (i.e. off an event) if there
|
* Process any pending requests asynchronously (i.e. off an event) if there
|
||||||
* are any. Note that this is a no-op if there aren't any currently pending
|
* are any. Note that this is a no-op if there aren't any currently pending
|
||||||
|
@ -534,6 +571,11 @@ private:
|
||||||
return mEnabled && !mBlockerCount;
|
return mEnabled && !mBlockerCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult VerifySRI(ScriptLoadRequest *aRequest,
|
||||||
|
nsIIncrementalStreamLoader* aLoader,
|
||||||
|
nsresult aSRIStatus,
|
||||||
|
SRICheckDataVerifier* aSRIDataVerifier) const;
|
||||||
|
|
||||||
nsresult AttemptAsyncScriptCompile(ScriptLoadRequest* aRequest);
|
nsresult AttemptAsyncScriptCompile(ScriptLoadRequest* aRequest);
|
||||||
nsresult ProcessRequest(ScriptLoadRequest* aRequest);
|
nsresult ProcessRequest(ScriptLoadRequest* aRequest);
|
||||||
nsresult CompileOffThreadOrProcessRequest(ScriptLoadRequest* aRequest);
|
nsresult CompileOffThreadOrProcessRequest(ScriptLoadRequest* aRequest);
|
||||||
|
@ -556,6 +598,7 @@ private:
|
||||||
mozilla::Vector<char16_t> &aString);
|
mozilla::Vector<char16_t> &aString);
|
||||||
|
|
||||||
void AddDeferRequest(ScriptLoadRequest* aRequest);
|
void AddDeferRequest(ScriptLoadRequest* aRequest);
|
||||||
|
void AddAsyncRequest(ScriptLoadRequest* aRequest);
|
||||||
bool MaybeRemovedDeferRequests();
|
bool MaybeRemovedDeferRequests();
|
||||||
|
|
||||||
void MaybeMoveToLoadedList(ScriptLoadRequest* aRequest);
|
void MaybeMoveToLoadedList(ScriptLoadRequest* aRequest);
|
||||||
|
@ -563,30 +606,30 @@ private:
|
||||||
JS::SourceBufferHolder GetScriptSource(ScriptLoadRequest* aRequest,
|
JS::SourceBufferHolder GetScriptSource(ScriptLoadRequest* aRequest,
|
||||||
nsAutoString& inlineData);
|
nsAutoString& inlineData);
|
||||||
|
|
||||||
bool ModuleScriptsEnabled();
|
|
||||||
|
|
||||||
void SetModuleFetchStarted(ModuleLoadRequest *aRequest);
|
void SetModuleFetchStarted(ModuleLoadRequest *aRequest);
|
||||||
void SetModuleFetchFinishedAndResumeWaitingRequests(ModuleLoadRequest *aRequest,
|
void SetModuleFetchFinishedAndResumeWaitingRequests(ModuleLoadRequest *aRequest,
|
||||||
nsresult aResult);
|
nsresult aResult);
|
||||||
|
|
||||||
bool IsFetchingModule(ModuleLoadRequest *aRequest) const;
|
bool IsFetchingModule(ModuleLoadRequest *aRequest) const;
|
||||||
|
|
||||||
bool ModuleMapContainsModule(ModuleLoadRequest *aRequest) const;
|
bool ModuleMapContainsURL(nsIURI* aURL) const;
|
||||||
RefPtr<mozilla::GenericPromise> WaitForModuleFetch(ModuleLoadRequest *aRequest);
|
RefPtr<mozilla::GenericPromise> WaitForModuleFetch(nsIURI* aURL);
|
||||||
ModuleScript* GetFetchedModule(nsIURI* aURL) const;
|
ModuleScript* GetFetchedModule(nsIURI* aURL) const;
|
||||||
|
|
||||||
friend bool
|
friend JSObject*
|
||||||
HostResolveImportedModule(JSContext* aCx, unsigned argc, JS::Value* vp);
|
HostResolveImportedModule(JSContext* aCx, JS::Handle<JSObject*> aModule,
|
||||||
|
JS::Handle<JSString*> aSpecifier);
|
||||||
|
|
||||||
nsresult CreateModuleScript(ModuleLoadRequest* aRequest);
|
nsresult CreateModuleScript(ModuleLoadRequest* aRequest);
|
||||||
nsresult ProcessFetchedModuleSource(ModuleLoadRequest* aRequest);
|
nsresult ProcessFetchedModuleSource(ModuleLoadRequest* aRequest);
|
||||||
void CheckModuleDependenciesLoaded(ModuleLoadRequest* aRequest);
|
void CheckModuleDependenciesLoaded(ModuleLoadRequest* aRequest);
|
||||||
void ProcessLoadedModuleTree(ModuleLoadRequest* aRequest);
|
void ProcessLoadedModuleTree(ModuleLoadRequest* aRequest);
|
||||||
|
JS::Value FindFirstParseError(ModuleLoadRequest* aRequest);
|
||||||
bool InstantiateModuleTree(ModuleLoadRequest* aRequest);
|
bool InstantiateModuleTree(ModuleLoadRequest* aRequest);
|
||||||
void StartFetchingModuleDependencies(ModuleLoadRequest* aRequest);
|
void StartFetchingModuleDependencies(ModuleLoadRequest* aRequest);
|
||||||
|
|
||||||
RefPtr<mozilla::GenericPromise>
|
RefPtr<mozilla::GenericPromise>
|
||||||
StartFetchingModuleAndDependencies(ModuleLoadRequest* aRequest, nsIURI* aURI);
|
StartFetchingModuleAndDependencies(ModuleLoadRequest* aParent, nsIURI* aURI);
|
||||||
|
|
||||||
nsIDocument* mDocument; // [WEAK]
|
nsIDocument* mDocument; // [WEAK]
|
||||||
nsCOMArray<nsIScriptLoaderObserver> mObservers;
|
nsCOMArray<nsIScriptLoaderObserver> mObservers;
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "nsIScriptLoaderObserver.h"
|
#include "nsIScriptLoaderObserver.h"
|
||||||
#include "nsWeakPtr.h"
|
#include "nsWeakPtr.h"
|
||||||
#include "nsIParser.h"
|
#include "nsIParser.h"
|
||||||
|
#include "nsIDocument.h"
|
||||||
#include "nsContentCreatorFunctions.h"
|
#include "nsContentCreatorFunctions.h"
|
||||||
#include "nsIDOMHTMLScriptElement.h"
|
#include "nsIDOMHTMLScriptElement.h"
|
||||||
#include "mozilla/CORSMode.h"
|
#include "mozilla/CORSMode.h"
|
||||||
|
@ -37,6 +38,7 @@ public:
|
||||||
mForceAsync(aFromParser == mozilla::dom::NOT_FROM_PARSER ||
|
mForceAsync(aFromParser == mozilla::dom::NOT_FROM_PARSER ||
|
||||||
aFromParser == mozilla::dom::FROM_PARSER_FRAGMENT),
|
aFromParser == mozilla::dom::FROM_PARSER_FRAGMENT),
|
||||||
mFrozen(false),
|
mFrozen(false),
|
||||||
|
mIsModule(false),
|
||||||
mDefer(false),
|
mDefer(false),
|
||||||
mAsync(false),
|
mAsync(false),
|
||||||
mExternal(false),
|
mExternal(false),
|
||||||
|
@ -73,11 +75,25 @@ public:
|
||||||
virtual void GetScriptCharset(nsAString& charset) = 0;
|
virtual void GetScriptCharset(nsAString& charset) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Freezes the return values of GetScriptDeferred(), GetScriptAsync() and
|
* Freezes the return values of the following methods so that subsequent
|
||||||
* GetScriptURI() so that subsequent modifications to the attributes don't
|
* modifications to the attributes don't change execution behavior:
|
||||||
* change execution behavior.
|
* - GetScriptIsModule()
|
||||||
|
* - GetScriptDeferred()
|
||||||
|
* - GetScriptAsync()
|
||||||
|
* - GetScriptURI()
|
||||||
|
* - GetScriptExternal()
|
||||||
*/
|
*/
|
||||||
virtual void FreezeUriAsyncDefer() = 0;
|
virtual void FreezeExecutionAttrs(nsIDocument* aOwnerDoc) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the script a module script?
|
||||||
|
* Currently only supported by HTML scripts.
|
||||||
|
*/
|
||||||
|
bool GetScriptIsModule()
|
||||||
|
{
|
||||||
|
NS_PRECONDITION(mFrozen, "Execution attributes not yet frozen: Not ready for this call!");
|
||||||
|
return mIsModule;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is the script deferred. Currently only supported by HTML scripts.
|
* Is the script deferred. Currently only supported by HTML scripts.
|
||||||
|
@ -292,6 +308,11 @@ protected:
|
||||||
*/
|
*/
|
||||||
bool mFrozen;
|
bool mFrozen;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The effective moduleness.
|
||||||
|
*/
|
||||||
|
bool mIsModule;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The effective deferredness.
|
* The effective deferredness.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -20,15 +20,16 @@ interface nsIScriptLoaderObserver : nsISupports {
|
||||||
* a script. If this is a failure code, script evaluation
|
* a script. If this is a failure code, script evaluation
|
||||||
* will not occur.
|
* will not occur.
|
||||||
* @param aElement The element being processed.
|
* @param aElement The element being processed.
|
||||||
* @param aIsInline Is this an inline script or externally loaded?
|
* @param aIsInline Is this an inline classic script (as opposed to an
|
||||||
|
* externally loaded classic script or module script)?
|
||||||
* @param aURI What is the URI of the script (the document URI if
|
* @param aURI What is the URI of the script (the document URI if
|
||||||
* it is inline).
|
* it is inline).
|
||||||
* @param aLineNo At what line does the script appear (generally 1
|
* @param aLineNo At what line does the script appear (generally 1
|
||||||
* if it is a loaded script).
|
* if it is a loaded script).
|
||||||
*/
|
*/
|
||||||
void scriptAvailable(in nsresult aResult,
|
void scriptAvailable(in nsresult aResult,
|
||||||
in nsIScriptElement aElement,
|
in nsIScriptElement aElement,
|
||||||
in boolean aIsInline,
|
in boolean aIsInlineClassicScript,
|
||||||
in nsIURI aURI,
|
in nsIURI aURI,
|
||||||
in int32_t aLineNo);
|
in int32_t aLineNo);
|
||||||
|
|
||||||
|
@ -40,7 +41,7 @@ interface nsIScriptLoaderObserver : nsISupports {
|
||||||
* @param aElement The element being processed.
|
* @param aElement The element being processed.
|
||||||
* @param aIsInline Is this an inline script or externally loaded?
|
* @param aIsInline Is this an inline script or externally loaded?
|
||||||
*/
|
*/
|
||||||
void scriptEvaluated(in nsresult aResult,
|
void scriptEvaluated(in nsresult aResult,
|
||||||
in nsIScriptElement aElement,
|
in nsIScriptElement aElement,
|
||||||
in boolean aIsInline);
|
in boolean aIsInline);
|
||||||
|
|
||||||
|
|
|
@ -137,7 +137,7 @@ SVGScriptElement::GetScriptCharset(nsAString& charset)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SVGScriptElement::FreezeUriAsyncDefer()
|
SVGScriptElement::FreezeExecutionAttrs(nsIDocument* aOwnerDoc)
|
||||||
{
|
{
|
||||||
if (mFrozen) {
|
if (mFrozen) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -44,7 +44,7 @@ public:
|
||||||
virtual bool GetScriptType(nsAString& type) override;
|
virtual bool GetScriptType(nsAString& type) override;
|
||||||
virtual void GetScriptText(nsAString& text) override;
|
virtual void GetScriptText(nsAString& text) override;
|
||||||
virtual void GetScriptCharset(nsAString& charset) override;
|
virtual void GetScriptCharset(nsAString& charset) override;
|
||||||
virtual void FreezeUriAsyncDefer() override;
|
virtual void FreezeExecutionAttrs(nsIDocument* aOwnerDoc) override;
|
||||||
virtual CORSMode GetCORSMode() const override;
|
virtual CORSMode GetCORSMode() const override;
|
||||||
|
|
||||||
// ScriptElement
|
// ScriptElement
|
||||||
|
|
|
@ -955,7 +955,7 @@ NS_IMPL_ISUPPORTS(txTransformNotifier,
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
txTransformNotifier::ScriptAvailable(nsresult aResult,
|
txTransformNotifier::ScriptAvailable(nsresult aResult,
|
||||||
nsIScriptElement *aElement,
|
nsIScriptElement *aElement,
|
||||||
bool aIsInline,
|
bool aIsInlineClassicScript,
|
||||||
nsIURI *aURI,
|
nsIURI *aURI,
|
||||||
int32_t aLineNo)
|
int32_t aLineNo)
|
||||||
{
|
{
|
||||||
|
|
|
@ -779,7 +779,7 @@ struct JSClass {
|
||||||
// application.
|
// application.
|
||||||
#define JSCLASS_GLOBAL_APPLICATION_SLOTS 5
|
#define JSCLASS_GLOBAL_APPLICATION_SLOTS 5
|
||||||
#define JSCLASS_GLOBAL_SLOT_COUNT \
|
#define JSCLASS_GLOBAL_SLOT_COUNT \
|
||||||
(JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 46)
|
(JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 45)
|
||||||
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
|
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
|
||||||
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
|
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
|
||||||
#define JSCLASS_GLOBAL_FLAGS \
|
#define JSCLASS_GLOBAL_FLAGS \
|
||||||
|
|
|
@ -67,10 +67,16 @@ function ModuleGetExportedNames(exportStarSet = [])
|
||||||
|
|
||||||
function ModuleSetStatus(module, newStatus)
|
function ModuleSetStatus(module, newStatus)
|
||||||
{
|
{
|
||||||
assert(newStatus >= MODULE_STATUS_ERRORED && newStatus <= MODULE_STATUS_EVALUATED,
|
assert(newStatus >= MODULE_STATUS_UNINSTANTIATED &&
|
||||||
|
newStatus <= MODULE_STATUS_EVALUATED_ERROR,
|
||||||
"Bad new module status in ModuleSetStatus");
|
"Bad new module status in ModuleSetStatus");
|
||||||
if (newStatus !== MODULE_STATUS_ERRORED)
|
|
||||||
assert(newStatus > module.status, "New module status inconsistent with current status");
|
// Note that under OOM conditions we can fail the module instantiation
|
||||||
|
// process even after modules have been marked as instantiated.
|
||||||
|
assert((module.status <= MODULE_STATUS_INSTANTIATED &&
|
||||||
|
newStatus === MODULE_STATUS_UNINSTANTIATED) ||
|
||||||
|
newStatus > module.status,
|
||||||
|
"New module status inconsistent with current status");
|
||||||
|
|
||||||
UnsafeSetReservedSlot(module, MODULE_OBJECT_STATUS_SLOT, newStatus);
|
UnsafeSetReservedSlot(module, MODULE_OBJECT_STATUS_SLOT, newStatus);
|
||||||
}
|
}
|
||||||
|
@ -80,20 +86,15 @@ function ModuleSetStatus(module, newStatus)
|
||||||
// Returns an object describing the location of the resolved export or
|
// Returns an object describing the location of the resolved export or
|
||||||
// indicating a failure.
|
// indicating a failure.
|
||||||
//
|
//
|
||||||
// On success this returns: { resolved: true, module, bindingName }
|
// On success this returns a resolved binding record: { module, bindingName }
|
||||||
//
|
//
|
||||||
// There are three failure cases:
|
// There are two failure cases:
|
||||||
//
|
//
|
||||||
// - The resolution failure can be blamed on a particular module.
|
// - If no definition was found or the request is found to be circular, *null*
|
||||||
// Returns: { resolved: false, module, ambiguous: false }
|
// is returned.
|
||||||
//
|
//
|
||||||
// - No culprit can be determined and the resolution failure was due to star
|
// - If the request is found to be ambiguous, the string `"ambiguous"` is
|
||||||
// export ambiguity.
|
// returned.
|
||||||
// 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 = [])
|
function ModuleResolveExport(exportName, resolveSet = [])
|
||||||
{
|
{
|
||||||
|
@ -106,53 +107,47 @@ function ModuleResolveExport(exportName, resolveSet = [])
|
||||||
let module = this;
|
let module = this;
|
||||||
|
|
||||||
// Step 2
|
// Step 2
|
||||||
assert(module.status !== MODULE_STATUS_ERRORED, "Bad module status in ResolveExport");
|
|
||||||
|
|
||||||
// Step 3
|
|
||||||
for (let i = 0; i < resolveSet.length; i++) {
|
for (let i = 0; i < resolveSet.length; i++) {
|
||||||
let r = resolveSet[i];
|
let r = resolveSet[i];
|
||||||
if (r.module === module && r.exportName === exportName) {
|
if (r.module === module && r.exportName === exportName) {
|
||||||
// This is a circular import request.
|
// This is a circular import request.
|
||||||
return {resolved: false, module: null, ambiguous: false};
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 4
|
// Step 3
|
||||||
_DefineDataProperty(resolveSet, resolveSet.length, {module: module, exportName: exportName});
|
_DefineDataProperty(resolveSet, resolveSet.length, {module: module, exportName: exportName});
|
||||||
|
|
||||||
// Step 5
|
// Step 4
|
||||||
let localExportEntries = module.localExportEntries;
|
let localExportEntries = module.localExportEntries;
|
||||||
for (let i = 0; i < localExportEntries.length; i++) {
|
for (let i = 0; i < localExportEntries.length; i++) {
|
||||||
let e = localExportEntries[i];
|
let e = localExportEntries[i];
|
||||||
if (exportName === e.exportName)
|
if (exportName === e.exportName)
|
||||||
return {resolved: true, module, bindingName: e.localName};
|
return {module, bindingName: e.localName};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 6
|
// Step 5
|
||||||
let indirectExportEntries = module.indirectExportEntries;
|
let indirectExportEntries = module.indirectExportEntries;
|
||||||
for (let i = 0; i < indirectExportEntries.length; i++) {
|
for (let i = 0; i < indirectExportEntries.length; i++) {
|
||||||
let e = indirectExportEntries[i];
|
let e = indirectExportEntries[i];
|
||||||
if (exportName === e.exportName) {
|
if (exportName === e.exportName) {
|
||||||
let importedModule = CallModuleResolveHook(module, e.moduleRequest,
|
let importedModule = CallModuleResolveHook(module, e.moduleRequest,
|
||||||
MODULE_STATUS_UNINSTANTIATED);
|
MODULE_STATUS_UNINSTANTIATED);
|
||||||
let resolution = callFunction(importedModule.resolveExport, importedModule, e.importName,
|
return callFunction(importedModule.resolveExport, importedModule, e.importName,
|
||||||
resolveSet);
|
resolveSet);
|
||||||
if (!resolution.resolved && !resolution.module)
|
|
||||||
resolution.module = module;
|
|
||||||
return resolution;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 7
|
// Step 6
|
||||||
if (exportName === "default") {
|
if (exportName === "default") {
|
||||||
// A default export cannot be provided by an export *.
|
// A default export cannot be provided by an export *.
|
||||||
return {resolved: false, module: null, ambiguous: false};
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 8
|
// Step 7
|
||||||
let starResolution = null;
|
let starResolution = null;
|
||||||
|
|
||||||
// Step 9
|
// Step 8
|
||||||
let starExportEntries = module.starExportEntries;
|
let starExportEntries = module.starExportEntries;
|
||||||
for (let i = 0; i < starExportEntries.length; i++) {
|
for (let i = 0; i < starExportEntries.length; i++) {
|
||||||
let e = starExportEntries[i];
|
let e = starExportEntries[i];
|
||||||
|
@ -160,27 +155,31 @@ function ModuleResolveExport(exportName, resolveSet = [])
|
||||||
MODULE_STATUS_UNINSTANTIATED);
|
MODULE_STATUS_UNINSTANTIATED);
|
||||||
let resolution = callFunction(importedModule.resolveExport, importedModule, exportName,
|
let resolution = callFunction(importedModule.resolveExport, importedModule, exportName,
|
||||||
resolveSet);
|
resolveSet);
|
||||||
if (!resolution.resolved && (resolution.module || resolution.ambiguous))
|
if (resolution === "ambiguous")
|
||||||
return resolution;
|
return resolution;
|
||||||
|
|
||||||
if (resolution.resolved) {
|
if (resolution !== null) {
|
||||||
if (starResolution === null) {
|
if (starResolution === null) {
|
||||||
starResolution = resolution;
|
starResolution = resolution;
|
||||||
} else {
|
} else {
|
||||||
if (resolution.module !== starResolution.module ||
|
if (resolution.module !== starResolution.module ||
|
||||||
resolution.bindingName !== starResolution.bindingName)
|
resolution.bindingName !== starResolution.bindingName)
|
||||||
{
|
{
|
||||||
return {resolved: false, module: null, ambiguous: true};
|
return "ambiguous";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 10
|
// Step 9
|
||||||
if (starResolution !== null)
|
return starResolution;
|
||||||
return starResolution;
|
}
|
||||||
|
|
||||||
return {resolved: false, module: null, ambiguous: false};
|
function IsResolvedBinding(resolution)
|
||||||
|
{
|
||||||
|
assert(resolution === "ambiguous" || typeof resolution === "object",
|
||||||
|
"Bad module resolution result");
|
||||||
|
return typeof resolution === "object" && resolution !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 15.2.1.18 GetModuleNamespace(module)
|
// 15.2.1.18 GetModuleNamespace(module)
|
||||||
|
@ -189,12 +188,12 @@ function GetModuleNamespace(module)
|
||||||
// Step 1
|
// Step 1
|
||||||
assert(IsModule(module), "GetModuleNamespace called with non-module");
|
assert(IsModule(module), "GetModuleNamespace called with non-module");
|
||||||
|
|
||||||
// Step 2
|
// Steps 2-3
|
||||||
assert(module.status !== MODULE_STATUS_UNINSTANTIATED &&
|
assert(module.status !== MODULE_STATUS_UNINSTANTIATED &&
|
||||||
module.status !== MODULE_STATUS_ERRORED,
|
module.status !== MODULE_STATUS_EVALUATED_ERROR,
|
||||||
"Bad module status in GetModuleNamespace");
|
"Bad module status in GetModuleNamespace");
|
||||||
|
|
||||||
// Step 3
|
// Step 4
|
||||||
let namespace = module.namespace;
|
let namespace = module.namespace;
|
||||||
|
|
||||||
if (typeof namespace === "undefined") {
|
if (typeof namespace === "undefined") {
|
||||||
|
@ -203,7 +202,7 @@ function GetModuleNamespace(module)
|
||||||
for (let i = 0; i < exportedNames.length; i++) {
|
for (let i = 0; i < exportedNames.length; i++) {
|
||||||
let name = exportedNames[i];
|
let name = exportedNames[i];
|
||||||
let resolution = callFunction(module.resolveExport, module, name);
|
let resolution = callFunction(module.resolveExport, module, name);
|
||||||
if (resolution.resolved)
|
if (IsResolvedBinding(resolution))
|
||||||
_DefineDataProperty(unambiguousNames, unambiguousNames.length, name);
|
_DefineDataProperty(unambiguousNames, unambiguousNames.length, name);
|
||||||
}
|
}
|
||||||
namespace = ModuleNamespaceCreate(module, unambiguousNames);
|
namespace = ModuleNamespaceCreate(module, unambiguousNames);
|
||||||
|
@ -225,7 +224,7 @@ function ModuleNamespaceCreate(module, exports)
|
||||||
for (let i = 0; i < exports.length; i++) {
|
for (let i = 0; i < exports.length; i++) {
|
||||||
let name = exports[i];
|
let name = exports[i];
|
||||||
let binding = callFunction(module.resolveExport, module, name);
|
let binding = callFunction(module.resolveExport, module, name);
|
||||||
assert(binding.resolved, "Failed to resolve binding");
|
assert(IsResolvedBinding(binding), "Failed to resolve binding");
|
||||||
AddModuleNamespaceBinding(ns, name, binding.module, binding.bindingName);
|
AddModuleNamespaceBinding(ns, name, binding.module, binding.bindingName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,31 +235,16 @@ function GetModuleEnvironment(module)
|
||||||
{
|
{
|
||||||
assert(IsModule(module), "Non-module passed to GetModuleEnvironment");
|
assert(IsModule(module), "Non-module passed to GetModuleEnvironment");
|
||||||
|
|
||||||
// Check for a previous failed attempt to instantiate this module. This can
|
assert(module.status >= MODULE_STATUS_INSTANTIATING,
|
||||||
// only happen due to a bug in the module loader.
|
"Attempt to access module environement before instantation");
|
||||||
if (module.status === MODULE_STATUS_ERRORED)
|
|
||||||
ThrowInternalError(JSMSG_MODULE_INSTANTIATE_FAILED, module.status);
|
|
||||||
|
|
||||||
let env = UnsafeGetReservedSlot(module, MODULE_OBJECT_ENVIRONMENT_SLOT);
|
let env = UnsafeGetReservedSlot(module, MODULE_OBJECT_ENVIRONMENT_SLOT);
|
||||||
assert(env === undefined || IsModuleEnvironment(env),
|
assert(IsModuleEnvironment(env),
|
||||||
"Module environment slot contains unexpected value");
|
"Module environment slot contains unexpected value");
|
||||||
|
|
||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
function RecordModuleError(module, error)
|
|
||||||
{
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
function CountArrayValues(array, value)
|
function CountArrayValues(array, value)
|
||||||
{
|
{
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
@ -280,6 +264,16 @@ function ArrayContains(array, value)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function HandleModuleInstantiationFailure(module)
|
||||||
|
{
|
||||||
|
// Reset the module to the "uninstantiated" state. Don't reset the
|
||||||
|
// environment slot as the environment object will be required by any
|
||||||
|
// possible future instantiation attempt.
|
||||||
|
ModuleSetStatus(module, MODULE_STATUS_UNINSTANTIATED);
|
||||||
|
UnsafeSetReservedSlot(module, MODULE_OBJECT_DFS_INDEX_SLOT, undefined);
|
||||||
|
UnsafeSetReservedSlot(module, MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT, undefined);
|
||||||
|
}
|
||||||
|
|
||||||
// 15.2.1.16.4 ModuleInstantiate()
|
// 15.2.1.16.4 ModuleInstantiate()
|
||||||
function ModuleInstantiate()
|
function ModuleInstantiate()
|
||||||
{
|
{
|
||||||
|
@ -301,38 +295,30 @@ function ModuleInstantiate()
|
||||||
|
|
||||||
// Steps 4-5
|
// Steps 4-5
|
||||||
try {
|
try {
|
||||||
InnerModuleDeclarationInstantiation(module, stack, 0);
|
InnerModuleInstantiation(module, stack, 0);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
for (let i = 0; i < stack.length; i++) {
|
for (let i = 0; i < stack.length; i++) {
|
||||||
let m = stack[i];
|
let m = stack[i];
|
||||||
|
|
||||||
assert(m.status === MODULE_STATUS_INSTANTIATING ||
|
assert(m.status === MODULE_STATUS_INSTANTIATING,
|
||||||
m.status === MODULE_STATUS_ERRORED,
|
"Expected instantiating status during failed instantiation");
|
||||||
"Bad module status after failed instantiation");
|
HandleModuleInstantiationFailure(m);
|
||||||
|
|
||||||
RecordModuleError(m, error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stack.length === 0 &&
|
// Handle OOM when appending to the stack or over-recursion errors.
|
||||||
typeof(UnsafeGetReservedSlot(module, MODULE_OBJECT_ERROR_SLOT)) === "undefined")
|
if (stack.length === 0)
|
||||||
{
|
HandleModuleInstantiationFailure(module);
|
||||||
// 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,
|
assert(module.status === MODULE_STATUS_UNINSTANTIATED,
|
||||||
"Bad module status after failed instantiation");
|
"Expected uninstantiated status after failed instantiation");
|
||||||
assert(SameValue(UnsafeGetReservedSlot(module, MODULE_OBJECT_ERROR_SLOT), error),
|
|
||||||
"Module has different error set after failed instantiation");
|
|
||||||
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 6
|
// Step 6
|
||||||
assert(module.status == MODULE_STATUS_INSTANTIATED ||
|
assert(module.status === MODULE_STATUS_INSTANTIATED ||
|
||||||
module.status == MODULE_STATUS_EVALUATED,
|
module.status === MODULE_STATUS_EVALUATED ||
|
||||||
|
module.status === MODULE_STATUS_EVALUATED_ERROR,
|
||||||
"Bad module status after successful instantiation");
|
"Bad module status after successful instantiation");
|
||||||
|
|
||||||
// Step 7
|
// Step 7
|
||||||
|
@ -344,8 +330,8 @@ function ModuleInstantiate()
|
||||||
}
|
}
|
||||||
_SetCanonicalName(ModuleInstantiate, "ModuleInstantiate");
|
_SetCanonicalName(ModuleInstantiate, "ModuleInstantiate");
|
||||||
|
|
||||||
// 15.2.1.16.4.1 InnerModuleDeclarationInstantiation(module, stack, index)
|
// 15.2.1.16.4.1 InnerModuleInstantiation(module, stack, index)
|
||||||
function InnerModuleDeclarationInstantiation(module, stack, index)
|
function InnerModuleInstantiation(module, stack, index)
|
||||||
{
|
{
|
||||||
// Step 1
|
// Step 1
|
||||||
// TODO: Support module records other than source text module records.
|
// TODO: Support module records other than source text module records.
|
||||||
|
@ -353,42 +339,40 @@ function InnerModuleDeclarationInstantiation(module, stack, index)
|
||||||
// Step 2
|
// Step 2
|
||||||
if (module.status === MODULE_STATUS_INSTANTIATING ||
|
if (module.status === MODULE_STATUS_INSTANTIATING ||
|
||||||
module.status === MODULE_STATUS_INSTANTIATED ||
|
module.status === MODULE_STATUS_INSTANTIATED ||
|
||||||
module.status === MODULE_STATUS_EVALUATED)
|
module.status === MODULE_STATUS_EVALUATED ||
|
||||||
|
module.status === MODULE_STATUS_EVALUATED_ERROR)
|
||||||
{
|
{
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 3
|
// Step 3
|
||||||
if (module.status === MODULE_STATUS_ERRORED)
|
|
||||||
throw module.error;
|
|
||||||
|
|
||||||
// Step 4
|
|
||||||
assert(module.status === MODULE_STATUS_UNINSTANTIATED,
|
assert(module.status === MODULE_STATUS_UNINSTANTIATED,
|
||||||
"Bad module status in ModuleDeclarationInstantiation");
|
"Bad module status in ModuleDeclarationInstantiation");
|
||||||
|
|
||||||
// Steps 5
|
// Step 4
|
||||||
ModuleSetStatus(module, MODULE_STATUS_INSTANTIATING);
|
ModuleSetStatus(module, MODULE_STATUS_INSTANTIATING);
|
||||||
|
|
||||||
// Step 6-8
|
// Steps 5-7
|
||||||
UnsafeSetReservedSlot(module, MODULE_OBJECT_DFS_INDEX_SLOT, index);
|
UnsafeSetReservedSlot(module, MODULE_OBJECT_DFS_INDEX_SLOT, index);
|
||||||
UnsafeSetReservedSlot(module, MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT, index);
|
UnsafeSetReservedSlot(module, MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT, index);
|
||||||
index++;
|
index++;
|
||||||
|
|
||||||
// Step 9
|
// Step 8
|
||||||
_DefineDataProperty(stack, stack.length, module);
|
_DefineDataProperty(stack, stack.length, module);
|
||||||
|
|
||||||
// Step 10
|
// Step 9
|
||||||
let requestedModules = module.requestedModules;
|
let requestedModules = module.requestedModules;
|
||||||
for (let i = 0; i < requestedModules.length; i++) {
|
for (let i = 0; i < requestedModules.length; i++) {
|
||||||
let required = requestedModules[i];
|
let required = requestedModules[i];
|
||||||
let requiredModule = CallModuleResolveHook(module, required, MODULE_STATUS_ERRORED);
|
let requiredModule = CallModuleResolveHook(module, required, MODULE_STATUS_UNINSTANTIATED);
|
||||||
|
|
||||||
index = InnerModuleDeclarationInstantiation(requiredModule, stack, index);
|
index = InnerModuleInstantiation(requiredModule, stack, index);
|
||||||
|
|
||||||
assert(requiredModule.status === MODULE_STATUS_INSTANTIATING ||
|
assert(requiredModule.status === MODULE_STATUS_INSTANTIATING ||
|
||||||
requiredModule.status === MODULE_STATUS_INSTANTIATED ||
|
requiredModule.status === MODULE_STATUS_INSTANTIATED ||
|
||||||
requiredModule.status === MODULE_STATUS_EVALUATED,
|
requiredModule.status === MODULE_STATUS_EVALUATED ||
|
||||||
"Bad required module status after InnerModuleDeclarationInstantiation");
|
requiredModule.status === MODULE_STATUS_EVALUATED_ERROR,
|
||||||
|
"Bad required module status after InnerModuleInstantiation");
|
||||||
|
|
||||||
assert((requiredModule.status === MODULE_STATUS_INSTANTIATING) ===
|
assert((requiredModule.status === MODULE_STATUS_INSTANTIATING) ===
|
||||||
ArrayContains(stack, requiredModule),
|
ArrayContains(stack, requiredModule),
|
||||||
|
@ -404,16 +388,16 @@ function InnerModuleDeclarationInstantiation(module, stack, index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 11
|
// Step 10
|
||||||
ModuleDeclarationEnvironmentSetup(module);
|
ModuleDeclarationEnvironmentSetup(module);
|
||||||
|
|
||||||
// Steps 12-13
|
// Steps 11-12
|
||||||
assert(CountArrayValues(stack, module) === 1,
|
assert(CountArrayValues(stack, module) === 1,
|
||||||
"Current module should appear exactly once in the stack");
|
"Current module should appear exactly once in the stack");
|
||||||
assert(module.dfsAncestorIndex <= module.dfsIndex,
|
assert(module.dfsAncestorIndex <= module.dfsIndex,
|
||||||
"Bad DFS ancestor index");
|
"Bad DFS ancestor index");
|
||||||
|
|
||||||
// Step 14
|
// Step 13
|
||||||
if (module.dfsAncestorIndex === module.dfsIndex) {
|
if (module.dfsAncestorIndex === module.dfsIndex) {
|
||||||
let requiredModule;
|
let requiredModule;
|
||||||
do {
|
do {
|
||||||
|
@ -434,16 +418,14 @@ function ModuleDeclarationEnvironmentSetup(module)
|
||||||
for (let i = 0; i < indirectExportEntries.length; i++) {
|
for (let i = 0; i < indirectExportEntries.length; i++) {
|
||||||
let e = indirectExportEntries[i];
|
let e = indirectExportEntries[i];
|
||||||
let resolution = callFunction(module.resolveExport, module, e.exportName);
|
let resolution = callFunction(module.resolveExport, module, e.exportName);
|
||||||
assert(resolution.resolved || resolution.module,
|
if (!IsResolvedBinding(resolution)) {
|
||||||
"Unexpected failure to resolve export in ModuleDeclarationEnvironmentSetup");
|
ThrowResolutionError(module, resolution, "indirectExport", e.exportName,
|
||||||
if (!resolution.resolved) {
|
e.lineNumber, e.columnNumber);
|
||||||
return ResolutionError(resolution, "indirectExport", e.exportName,
|
|
||||||
e.lineNumber, e.columnNumber)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Steps 5-6
|
// Steps 5-6
|
||||||
CreateModuleEnvironment(module);
|
// Note that we have already created the environment by this point.
|
||||||
let env = GetModuleEnvironment(module);
|
let env = GetModuleEnvironment(module);
|
||||||
|
|
||||||
// Step 8
|
// Step 8
|
||||||
|
@ -458,12 +440,9 @@ function ModuleDeclarationEnvironmentSetup(module)
|
||||||
} else {
|
} else {
|
||||||
let resolution = callFunction(importedModule.resolveExport, importedModule,
|
let resolution = callFunction(importedModule.resolveExport, importedModule,
|
||||||
imp.importName);
|
imp.importName);
|
||||||
if (!resolution.resolved && !resolution.module)
|
if (!IsResolvedBinding(resolution)) {
|
||||||
resolution.module = module;
|
ThrowResolutionError(module, resolution, "import", imp.importName,
|
||||||
|
imp.lineNumber, imp.columnNumber);
|
||||||
if (!resolution.resolved) {
|
|
||||||
return ResolutionError(resolution, "import", imp.importName,
|
|
||||||
imp.lineNumber, imp.columnNumber);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateImportBinding(env, imp.localName, resolution.module, resolution.bindingName);
|
CreateImportBinding(env, imp.localName, resolution.module, resolution.bindingName);
|
||||||
|
@ -473,38 +452,58 @@ function ModuleDeclarationEnvironmentSetup(module)
|
||||||
InstantiateModuleFunctionDeclarations(module);
|
InstantiateModuleFunctionDeclarations(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 15.2.1.16.4.3 ResolutionError(module)
|
function ThrowResolutionError(module, resolution, kind, name, line, column)
|
||||||
function ResolutionError(resolution, kind, name, line, column)
|
|
||||||
{
|
{
|
||||||
let module = resolution.module;
|
assert(module.status === MODULE_STATUS_INSTANTIATING,
|
||||||
assert(module !== null,
|
"Unexpected module status in ThrowResolutionError");
|
||||||
"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",
|
assert(kind === "import" || kind === "indirectExport",
|
||||||
"Unexpected kind in ResolutionError");
|
"Unexpected kind in ThrowResolutionError");
|
||||||
|
|
||||||
assert(line > 0,
|
assert(line > 0,
|
||||||
"Line number should be present for all imports and indirect exports");
|
"Line number should be present for all imports and indirect exports");
|
||||||
|
|
||||||
|
let ambiguous = resolution === "ambiguous";
|
||||||
|
|
||||||
let errorNumber;
|
let errorNumber;
|
||||||
if (kind === "import") {
|
if (kind === "import")
|
||||||
errorNumber = resolution.ambiguous ? JSMSG_AMBIGUOUS_IMPORT
|
errorNumber = ambiguous ? JSMSG_AMBIGUOUS_IMPORT : JSMSG_MISSING_IMPORT;
|
||||||
: JSMSG_MISSING_IMPORT;
|
else
|
||||||
} else {
|
errorNumber = ambiguous ? JSMSG_AMBIGUOUS_INDIRECT_EXPORT : JSMSG_MISSING_INDIRECT_EXPORT;
|
||||||
errorNumber = resolution.ambiguous ? JSMSG_AMBIGUOUS_INDIRECT_EXPORT
|
|
||||||
: JSMSG_MISSING_INDIRECT_EXPORT;
|
|
||||||
}
|
|
||||||
|
|
||||||
let message = GetErrorMessage(errorNumber) + ": " + name;
|
let message = GetErrorMessage(errorNumber) + ": " + name;
|
||||||
let error = CreateModuleSyntaxError(module, line, column, message);
|
let error = CreateModuleSyntaxError(module, line, column, message);
|
||||||
RecordModuleError(module, error);
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function GetModuleEvaluationError(module)
|
||||||
|
{
|
||||||
|
assert(IsObject(module) && IsModule(module),
|
||||||
|
"Non-module passed to GetModuleEvaluationError");
|
||||||
|
assert(module.status === MODULE_STATUS_EVALUATED_ERROR,
|
||||||
|
"Bad module status in GetModuleEvaluationError");
|
||||||
|
return UnsafeGetReservedSlot(module, MODULE_OBJECT_EVALUATION_ERROR_SLOT);
|
||||||
|
}
|
||||||
|
|
||||||
|
function RecordModuleEvaluationError(module, error)
|
||||||
|
{
|
||||||
|
// Set the module's EvaluationError slot to indicate a failed module
|
||||||
|
// evaluation.
|
||||||
|
|
||||||
|
assert(IsObject(module) && IsModule(module),
|
||||||
|
"Non-module passed to RecordModuleEvaluationError");
|
||||||
|
|
||||||
|
if (module.status === MODULE_STATUS_EVALUATED_ERROR) {
|
||||||
|
// It would be nice to assert that |error| is the same as the one we
|
||||||
|
// previously recorded, but that's not always true in the case of out of
|
||||||
|
// memory and over-recursion errors.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModuleSetStatus(module, MODULE_STATUS_EVALUATED_ERROR);
|
||||||
|
UnsafeSetReservedSlot(module, MODULE_OBJECT_EVALUATION_ERROR_SLOT, error);
|
||||||
|
}
|
||||||
|
|
||||||
// 15.2.1.16.5 ModuleEvaluate()
|
// 15.2.1.16.5 ModuleEvaluate()
|
||||||
function ModuleEvaluate()
|
function ModuleEvaluate()
|
||||||
{
|
{
|
||||||
|
@ -515,9 +514,9 @@ function ModuleEvaluate()
|
||||||
let module = this;
|
let module = this;
|
||||||
|
|
||||||
// Step 2
|
// Step 2
|
||||||
if (module.status !== MODULE_STATUS_ERRORED &&
|
if (module.status !== MODULE_STATUS_INSTANTIATED &&
|
||||||
module.status !== MODULE_STATUS_INSTANTIATED &&
|
module.status !== MODULE_STATUS_EVALUATED &&
|
||||||
module.status !== MODULE_STATUS_EVALUATED)
|
module.status !== MODULE_STATUS_EVALUATED_ERROR)
|
||||||
{
|
{
|
||||||
ThrowInternalError(JSMSG_BAD_MODULE_STATUS);
|
ThrowInternalError(JSMSG_BAD_MODULE_STATUS);
|
||||||
}
|
}
|
||||||
|
@ -535,27 +534,20 @@ function ModuleEvaluate()
|
||||||
assert(m.status === MODULE_STATUS_EVALUATING,
|
assert(m.status === MODULE_STATUS_EVALUATING,
|
||||||
"Bad module status after failed evaluation");
|
"Bad module status after failed evaluation");
|
||||||
|
|
||||||
RecordModuleError(m, error);
|
RecordModuleEvaluationError(m, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stack.length === 0 &&
|
// Handle OOM when appending to the stack or over-recursion errors.
|
||||||
typeof(UnsafeGetReservedSlot(module, MODULE_OBJECT_ERROR_SLOT)) === "undefined")
|
if (stack.length === 0)
|
||||||
{
|
RecordModuleEvaluationError(module, error);
|
||||||
// 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,
|
assert(module.status === MODULE_STATUS_EVALUATED_ERROR,
|
||||||
"Bad module status after failed evaluation");
|
"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;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(module.status == MODULE_STATUS_EVALUATED,
|
assert(module.status === MODULE_STATUS_EVALUATED,
|
||||||
"Bad module status after successful evaluation");
|
"Bad module status after successful evaluation");
|
||||||
assert(stack.length === 0,
|
assert(stack.length === 0,
|
||||||
"Stack should be empty after successful evaluation");
|
"Stack should be empty after successful evaluation");
|
||||||
|
@ -571,19 +563,19 @@ function InnerModuleEvaluation(module, stack, index)
|
||||||
// TODO: Support module records other than source text module records.
|
// TODO: Support module records other than source text module records.
|
||||||
|
|
||||||
// Step 2
|
// Step 2
|
||||||
if (module.status === MODULE_STATUS_EVALUATING ||
|
if (module.status === MODULE_STATUS_EVALUATED_ERROR)
|
||||||
module.status === MODULE_STATUS_EVALUATED)
|
throw GetModuleEvaluationError(module);
|
||||||
{
|
|
||||||
|
if (module.status === MODULE_STATUS_EVALUATED)
|
||||||
return index;
|
return index;
|
||||||
}
|
|
||||||
|
|
||||||
// Step 3
|
// Step 3
|
||||||
if (module.status === MODULE_STATUS_ERRORED)
|
if (module.status === MODULE_STATUS_EVALUATING)
|
||||||
throw module.error;
|
return index;
|
||||||
|
|
||||||
// Step 4
|
// Step 4
|
||||||
assert(module.status === MODULE_STATUS_INSTANTIATED,
|
assert(module.status === MODULE_STATUS_INSTANTIATED,
|
||||||
"Bad module status in ModuleEvaluation");
|
"Bad module status in InnerModuleEvaluation");
|
||||||
|
|
||||||
// Step 5
|
// Step 5
|
||||||
ModuleSetStatus(module, MODULE_STATUS_EVALUATING);
|
ModuleSetStatus(module, MODULE_STATUS_EVALUATING);
|
||||||
|
@ -605,8 +597,8 @@ function InnerModuleEvaluation(module, stack, index)
|
||||||
|
|
||||||
index = InnerModuleEvaluation(requiredModule, stack, index);
|
index = InnerModuleEvaluation(requiredModule, stack, index);
|
||||||
|
|
||||||
assert(requiredModule.status == MODULE_STATUS_EVALUATING ||
|
assert(requiredModule.status === MODULE_STATUS_EVALUATING ||
|
||||||
requiredModule.status == MODULE_STATUS_EVALUATED,
|
requiredModule.status === MODULE_STATUS_EVALUATED,
|
||||||
"Bad module status after InnerModuleEvaluation");
|
"Bad module status after InnerModuleEvaluation");
|
||||||
|
|
||||||
assert((requiredModule.status === MODULE_STATUS_EVALUATING) ===
|
assert((requiredModule.status === MODULE_STATUS_EVALUATING) ===
|
||||||
|
|
|
@ -18,10 +18,10 @@
|
||||||
using namespace js;
|
using namespace js;
|
||||||
using namespace js::frontend;
|
using namespace js::frontend;
|
||||||
|
|
||||||
static_assert(MODULE_STATUS_ERRORED < MODULE_STATUS_UNINSTANTIATED &&
|
static_assert(MODULE_STATUS_UNINSTANTIATED < MODULE_STATUS_INSTANTIATING &&
|
||||||
MODULE_STATUS_UNINSTANTIATED < MODULE_STATUS_INSTANTIATING &&
|
|
||||||
MODULE_STATUS_INSTANTIATING < MODULE_STATUS_INSTANTIATED &&
|
MODULE_STATUS_INSTANTIATING < MODULE_STATUS_INSTANTIATED &&
|
||||||
MODULE_STATUS_INSTANTIATED < MODULE_STATUS_EVALUATED,
|
MODULE_STATUS_INSTANTIATED < MODULE_STATUS_EVALUATED &&
|
||||||
|
MODULE_STATUS_EVALUATED < MODULE_STATUS_EVALUATED_ERROR,
|
||||||
"Module statuses are ordered incorrectly");
|
"Module statuses are ordered incorrectly");
|
||||||
|
|
||||||
template<typename T, Value ValueGetter(const T* obj)>
|
template<typename T, Value ValueGetter(const T* obj)>
|
||||||
|
@ -248,21 +248,13 @@ IndirectBindingMap::Binding::Binding(ModuleEnvironmentObject* environment, Shape
|
||||||
: environment(environment), shape(shape)
|
: environment(environment), shape(shape)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
IndirectBindingMap::IndirectBindingMap(Zone* zone)
|
|
||||||
: map_(ZoneAllocPolicy(zone))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
IndirectBindingMap::init()
|
|
||||||
{
|
|
||||||
return map_.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
IndirectBindingMap::trace(JSTracer* trc)
|
IndirectBindingMap::trace(JSTracer* trc)
|
||||||
{
|
{
|
||||||
for (Map::Enum e(map_); !e.empty(); e.popFront()) {
|
if (!map_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (Map::Enum e(*map_); !e.empty(); e.popFront()) {
|
||||||
Binding& b = e.front().value();
|
Binding& b = e.front().value();
|
||||||
TraceEdge(trc, &b.environment, "module bindings environment");
|
TraceEdge(trc, &b.environment, "module bindings environment");
|
||||||
TraceEdge(trc, &b.shape, "module bindings shape");
|
TraceEdge(trc, &b.shape, "module bindings shape");
|
||||||
|
@ -273,12 +265,25 @@ IndirectBindingMap::trace(JSTracer* trc)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
IndirectBindingMap::putNew(JSContext* cx, HandleId name,
|
IndirectBindingMap::put(JSContext* cx, HandleId name,
|
||||||
HandleModuleEnvironmentObject environment, HandleId localName)
|
HandleModuleEnvironmentObject environment, HandleId localName)
|
||||||
{
|
{
|
||||||
|
// This object might have been allocated on the background parsing thread in
|
||||||
|
// different zone to the final module. Lazily allocate the map so we don't
|
||||||
|
// have to switch its zone when merging compartments.
|
||||||
|
if (!map_) {
|
||||||
|
MOZ_ASSERT(!cx->zone()->usedByExclusiveThread);
|
||||||
|
map_.emplace(cx->zone());
|
||||||
|
if (!map_->init()) {
|
||||||
|
map_.reset();
|
||||||
|
ReportOutOfMemory(cx);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RootedShape shape(cx, environment->lookup(cx, localName));
|
RootedShape shape(cx, environment->lookup(cx, localName));
|
||||||
MOZ_ASSERT(shape);
|
MOZ_ASSERT(shape);
|
||||||
if (!map_.putNew(name, Binding(environment, shape))) {
|
if (!map_->put(name, Binding(environment, shape))) {
|
||||||
ReportOutOfMemory(cx);
|
ReportOutOfMemory(cx);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -289,7 +294,10 @@ IndirectBindingMap::putNew(JSContext* cx, HandleId name,
|
||||||
bool
|
bool
|
||||||
IndirectBindingMap::lookup(jsid name, ModuleEnvironmentObject** envOut, Shape** shapeOut) const
|
IndirectBindingMap::lookup(jsid name, ModuleEnvironmentObject** envOut, Shape** shapeOut) const
|
||||||
{
|
{
|
||||||
auto ptr = map_.lookup(name);
|
if (!map_)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto ptr = map_->lookup(name);
|
||||||
if (!ptr)
|
if (!ptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -359,7 +367,7 @@ ModuleNamespaceObject::addBinding(JSContext* cx, HandleAtom exportedName,
|
||||||
RootedModuleEnvironmentObject environment(cx, &targetModule->initialEnvironment());
|
RootedModuleEnvironmentObject environment(cx, &targetModule->initialEnvironment());
|
||||||
RootedId exportedNameId(cx, AtomToId(exportedName));
|
RootedId exportedNameId(cx, AtomToId(exportedName));
|
||||||
RootedId localNameId(cx, AtomToId(localName));
|
RootedId localNameId(cx, AtomToId(localName));
|
||||||
return bindings->putNew(cx, exportedNameId, environment, localNameId);
|
return bindings->put(cx, exportedNameId, environment, localNameId);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char ModuleNamespaceObject::ProxyHandler::family = 0;
|
const char ModuleNamespaceObject::ProxyHandler::family = 0;
|
||||||
|
@ -625,10 +633,9 @@ ModuleObject::create(ExclusiveContext* cx)
|
||||||
RootedModuleObject self(cx, &obj->as<ModuleObject>());
|
RootedModuleObject self(cx, &obj->as<ModuleObject>());
|
||||||
|
|
||||||
Zone* zone = cx->zone();
|
Zone* zone = cx->zone();
|
||||||
IndirectBindingMap* bindings = zone->new_<IndirectBindingMap>(zone);
|
IndirectBindingMap* bindings = zone->new_<IndirectBindingMap>();
|
||||||
if (!bindings || !bindings->init()) {
|
if (!bindings) {
|
||||||
ReportOutOfMemory(cx);
|
ReportOutOfMemory(cx);
|
||||||
js_delete<IndirectBindingMap>(bindings);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -657,14 +664,24 @@ ModuleObject::finalize(js::FreeOp* fop, JSObject* obj)
|
||||||
fop->delete_(funDecls);
|
fop->delete_(funDecls);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModuleEnvironmentObject&
|
||||||
|
ModuleObject::initialEnvironment() const
|
||||||
|
{
|
||||||
|
Value value = getReservedSlot(EnvironmentSlot);
|
||||||
|
return value.toObject().as<ModuleEnvironmentObject>();
|
||||||
|
}
|
||||||
|
|
||||||
ModuleEnvironmentObject*
|
ModuleEnvironmentObject*
|
||||||
ModuleObject::environment() const
|
ModuleObject::environment() const
|
||||||
{
|
{
|
||||||
Value value = getReservedSlot(EnvironmentSlot);
|
MOZ_ASSERT(!hadEvaluationError());
|
||||||
if (value.isUndefined())
|
|
||||||
|
// According to the spec the environment record is created during
|
||||||
|
// instantiation, but we create it earlier than that.
|
||||||
|
if (status() < MODULE_STATUS_INSTANTIATED)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
return &value.toObject().as<ModuleEnvironmentObject>();
|
return &initialEnvironment();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -723,13 +740,13 @@ void
|
||||||
ModuleObject::init(HandleScript script)
|
ModuleObject::init(HandleScript script)
|
||||||
{
|
{
|
||||||
initReservedSlot(ScriptSlot, PrivateValue(script));
|
initReservedSlot(ScriptSlot, PrivateValue(script));
|
||||||
initReservedSlot(StatusSlot, Int32Value(MODULE_STATUS_ERRORED));
|
initReservedSlot(StatusSlot, Int32Value(MODULE_STATUS_UNINSTANTIATED));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ModuleObject::setInitialEnvironment(HandleModuleEnvironmentObject initialEnvironment)
|
ModuleObject::setInitialEnvironment(HandleModuleEnvironmentObject initialEnvironment)
|
||||||
{
|
{
|
||||||
initReservedSlot(InitialEnvironmentSlot, ObjectValue(*initialEnvironment));
|
initReservedSlot(EnvironmentSlot, ObjectValue(*initialEnvironment));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -827,7 +844,8 @@ ModuleObject::script() const
|
||||||
static inline void
|
static inline void
|
||||||
AssertValidModuleStatus(ModuleStatus status)
|
AssertValidModuleStatus(ModuleStatus status)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(status >= MODULE_STATUS_ERRORED && status <= MODULE_STATUS_EVALUATED);
|
MOZ_ASSERT(status >= MODULE_STATUS_UNINSTANTIATED &&
|
||||||
|
status <= MODULE_STATUS_EVALUATED_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
ModuleStatus
|
ModuleStatus
|
||||||
|
@ -838,11 +856,17 @@ ModuleObject::status() const
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value
|
bool
|
||||||
ModuleObject::error() const
|
ModuleObject::hadEvaluationError() const
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(status() == MODULE_STATUS_ERRORED);
|
return status() == MODULE_STATUS_EVALUATED_ERROR;
|
||||||
return getReservedSlot(ErrorSlot);
|
}
|
||||||
|
|
||||||
|
Value
|
||||||
|
ModuleObject::evaluationError() const
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(hadEvaluationError());
|
||||||
|
return getReservedSlot(EvaluationErrorSlot);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value
|
Value
|
||||||
|
@ -857,12 +881,6 @@ ModuleObject::setHostDefinedField(const JS::Value& value)
|
||||||
setReservedSlot(HostDefinedSlot, value);
|
setReservedSlot(HostDefinedSlot, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
ModuleEnvironmentObject&
|
|
||||||
ModuleObject::initialEnvironment() const
|
|
||||||
{
|
|
||||||
return getReservedSlot(InitialEnvironmentSlot).toObject().as<ModuleEnvironmentObject>();
|
|
||||||
}
|
|
||||||
|
|
||||||
Scope*
|
Scope*
|
||||||
ModuleObject::enclosingScope() const
|
ModuleObject::enclosingScope() const
|
||||||
{
|
{
|
||||||
|
@ -888,16 +906,6 @@ ModuleObject::trace(JSTracer* trc, JSObject* obj)
|
||||||
funDecls->trace(trc);
|
funDecls->trace(trc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
ModuleObject::createEnvironment()
|
|
||||||
{
|
|
||||||
// The environment has already been created, we just neet to set it in the
|
|
||||||
// right slot.
|
|
||||||
MOZ_ASSERT(!getReservedSlot(InitialEnvironmentSlot).isUndefined());
|
|
||||||
MOZ_ASSERT(getReservedSlot(EnvironmentSlot).isUndefined());
|
|
||||||
setReservedSlot(EnvironmentSlot, getReservedSlot(InitialEnvironmentSlot));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ModuleObject::noteFunctionDeclaration(ExclusiveContext* cx, HandleAtom name, HandleFunction fun)
|
ModuleObject::noteFunctionDeclaration(ExclusiveContext* cx, HandleAtom name, HandleFunction fun)
|
||||||
{
|
{
|
||||||
|
@ -913,7 +921,10 @@ ModuleObject::noteFunctionDeclaration(ExclusiveContext* cx, HandleAtom name, Han
|
||||||
/* static */ bool
|
/* static */ bool
|
||||||
ModuleObject::instantiateFunctionDeclarations(JSContext* cx, HandleModuleObject self)
|
ModuleObject::instantiateFunctionDeclarations(JSContext* cx, HandleModuleObject self)
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
MOZ_ASSERT(self->status() == MODULE_STATUS_INSTANTIATING);
|
||||||
MOZ_ASSERT(IsFrozen(cx, self));
|
MOZ_ASSERT(IsFrozen(cx, self));
|
||||||
|
#endif
|
||||||
|
|
||||||
FunctionDeclarationVector* funDecls = self->functionDeclarations();
|
FunctionDeclarationVector* funDecls = self->functionDeclarations();
|
||||||
if (!funDecls) {
|
if (!funDecls) {
|
||||||
|
@ -944,7 +955,10 @@ ModuleObject::instantiateFunctionDeclarations(JSContext* cx, HandleModuleObject
|
||||||
/* static */ bool
|
/* static */ bool
|
||||||
ModuleObject::execute(JSContext* cx, HandleModuleObject self, MutableHandleValue rval)
|
ModuleObject::execute(JSContext* cx, HandleModuleObject self, MutableHandleValue rval)
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
MOZ_ASSERT(self->status() == MODULE_STATUS_EVALUATING);
|
||||||
MOZ_ASSERT(IsFrozen(cx, self));
|
MOZ_ASSERT(IsFrozen(cx, self));
|
||||||
|
#endif
|
||||||
|
|
||||||
RootedScript script(cx, self->script());
|
RootedScript script(cx, self->script());
|
||||||
RootedModuleEnvironmentObject scope(cx, self->environment());
|
RootedModuleEnvironmentObject scope(cx, self->environment());
|
||||||
|
@ -967,10 +981,9 @@ ModuleObject::createNamespace(JSContext* cx, HandleModuleObject self, HandleObje
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
Zone* zone = cx->zone();
|
Zone* zone = cx->zone();
|
||||||
IndirectBindingMap* bindings = zone->new_<IndirectBindingMap>(zone);
|
IndirectBindingMap* bindings = zone->new_<IndirectBindingMap>();
|
||||||
if (!bindings || !bindings->init()) {
|
if (!bindings) {
|
||||||
ReportOutOfMemory(cx);
|
ReportOutOfMemory(cx);
|
||||||
js_delete<IndirectBindingMap>(bindings);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1005,7 +1018,7 @@ ModuleObject::Evaluate(JSContext* cx, HandleModuleObject self)
|
||||||
|
|
||||||
DEFINE_GETTER_FUNCTIONS(ModuleObject, namespace_, NamespaceSlot)
|
DEFINE_GETTER_FUNCTIONS(ModuleObject, namespace_, NamespaceSlot)
|
||||||
DEFINE_GETTER_FUNCTIONS(ModuleObject, status, StatusSlot)
|
DEFINE_GETTER_FUNCTIONS(ModuleObject, status, StatusSlot)
|
||||||
DEFINE_GETTER_FUNCTIONS(ModuleObject, error, ErrorSlot)
|
DEFINE_GETTER_FUNCTIONS(ModuleObject, evaluationError, EvaluationErrorSlot)
|
||||||
DEFINE_GETTER_FUNCTIONS(ModuleObject, requestedModules, RequestedModulesSlot)
|
DEFINE_GETTER_FUNCTIONS(ModuleObject, requestedModules, RequestedModulesSlot)
|
||||||
DEFINE_GETTER_FUNCTIONS(ModuleObject, importEntries, ImportEntriesSlot)
|
DEFINE_GETTER_FUNCTIONS(ModuleObject, importEntries, ImportEntriesSlot)
|
||||||
DEFINE_GETTER_FUNCTIONS(ModuleObject, localExportEntries, LocalExportEntriesSlot)
|
DEFINE_GETTER_FUNCTIONS(ModuleObject, localExportEntries, LocalExportEntriesSlot)
|
||||||
|
@ -1020,7 +1033,7 @@ GlobalObject::initModuleProto(JSContext* cx, Handle<GlobalObject*> global)
|
||||||
static const JSPropertySpec protoAccessors[] = {
|
static const JSPropertySpec protoAccessors[] = {
|
||||||
JS_PSG("namespace", ModuleObject_namespace_Getter, 0),
|
JS_PSG("namespace", ModuleObject_namespace_Getter, 0),
|
||||||
JS_PSG("status", ModuleObject_statusGetter, 0),
|
JS_PSG("status", ModuleObject_statusGetter, 0),
|
||||||
JS_PSG("error", ModuleObject_errorGetter, 0),
|
JS_PSG("evaluationError", ModuleObject_evaluationErrorGetter, 0),
|
||||||
JS_PSG("requestedModules", ModuleObject_requestedModulesGetter, 0),
|
JS_PSG("requestedModules", ModuleObject_requestedModulesGetter, 0),
|
||||||
JS_PSG("importEntries", ModuleObject_importEntriesGetter, 0),
|
JS_PSG("importEntries", ModuleObject_importEntriesGetter, 0),
|
||||||
JS_PSG("localExportEntries", ModuleObject_localExportEntriesGetter, 0),
|
JS_PSG("localExportEntries", ModuleObject_localExportEntriesGetter, 0),
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#ifndef builtin_ModuleObject_h
|
#ifndef builtin_ModuleObject_h
|
||||||
#define builtin_ModuleObject_h
|
#define builtin_ModuleObject_h
|
||||||
|
|
||||||
|
#include "mozilla/Maybe.h"
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
#include "jsatom.h"
|
#include "jsatom.h"
|
||||||
|
|
||||||
|
@ -102,27 +104,27 @@ typedef Handle<ExportEntryObject*> HandleExportEntryObject;
|
||||||
class IndirectBindingMap
|
class IndirectBindingMap
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit IndirectBindingMap(Zone* zone);
|
|
||||||
bool init();
|
|
||||||
|
|
||||||
void trace(JSTracer* trc);
|
void trace(JSTracer* trc);
|
||||||
|
|
||||||
bool putNew(JSContext* cx, HandleId name,
|
bool put(JSContext* cx, HandleId name,
|
||||||
HandleModuleEnvironmentObject environment, HandleId localName);
|
HandleModuleEnvironmentObject environment, HandleId localName);
|
||||||
|
|
||||||
size_t count() const {
|
size_t count() const {
|
||||||
return map_.count();
|
return map_ ? map_->count() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has(jsid name) const {
|
bool has(jsid name) const {
|
||||||
return map_.has(name);
|
return map_ ? map_->has(name) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lookup(jsid name, ModuleEnvironmentObject** envOut, Shape** shapeOut) const;
|
bool lookup(jsid name, ModuleEnvironmentObject** envOut, Shape** shapeOut) const;
|
||||||
|
|
||||||
template <typename Func>
|
template <typename Func>
|
||||||
void forEachExportedName(Func func) const {
|
void forEachExportedName(Func func) const {
|
||||||
for (auto r = map_.all(); !r.empty(); r.popFront())
|
if (!map_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (auto r = map_->all(); !r.empty(); r.popFront())
|
||||||
func(r.front().key());
|
func(r.front().key());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +138,7 @@ class IndirectBindingMap
|
||||||
|
|
||||||
typedef HashMap<jsid, Binding, DefaultHasher<jsid>, ZoneAllocPolicy> Map;
|
typedef HashMap<jsid, Binding, DefaultHasher<jsid>, ZoneAllocPolicy> Map;
|
||||||
|
|
||||||
Map map_;
|
mozilla::Maybe<Map> map_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ModuleNamespaceObject : public ProxyObject
|
class ModuleNamespaceObject : public ProxyObject
|
||||||
|
@ -214,11 +216,10 @@ class ModuleObject : public NativeObject
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
ScriptSlot = 0,
|
ScriptSlot = 0,
|
||||||
InitialEnvironmentSlot,
|
|
||||||
EnvironmentSlot,
|
EnvironmentSlot,
|
||||||
NamespaceSlot,
|
NamespaceSlot,
|
||||||
StatusSlot,
|
StatusSlot,
|
||||||
ErrorSlot,
|
EvaluationErrorSlot,
|
||||||
HostDefinedSlot,
|
HostDefinedSlot,
|
||||||
RequestedModulesSlot,
|
RequestedModulesSlot,
|
||||||
ImportEntriesSlot,
|
ImportEntriesSlot,
|
||||||
|
@ -238,8 +239,8 @@ class ModuleObject : public NativeObject
|
||||||
"EnvironmentSlot must match self-hosting define");
|
"EnvironmentSlot must match self-hosting define");
|
||||||
static_assert(StatusSlot == MODULE_OBJECT_STATUS_SLOT,
|
static_assert(StatusSlot == MODULE_OBJECT_STATUS_SLOT,
|
||||||
"StatusSlot must match self-hosting define");
|
"StatusSlot must match self-hosting define");
|
||||||
static_assert(ErrorSlot == MODULE_OBJECT_ERROR_SLOT,
|
static_assert(EvaluationErrorSlot == MODULE_OBJECT_EVALUATION_ERROR_SLOT,
|
||||||
"ErrorSlot must match self-hosting define");
|
"EvaluationErrorSlot must match self-hosting define");
|
||||||
static_assert(DFSIndexSlot == MODULE_OBJECT_DFS_INDEX_SLOT,
|
static_assert(DFSIndexSlot == MODULE_OBJECT_DFS_INDEX_SLOT,
|
||||||
"DFSIndexSlot must match self-hosting define");
|
"DFSIndexSlot must match self-hosting define");
|
||||||
static_assert(DFSAncestorIndexSlot == MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT,
|
static_assert(DFSAncestorIndexSlot == MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT,
|
||||||
|
@ -269,7 +270,8 @@ class ModuleObject : public NativeObject
|
||||||
ModuleEnvironmentObject* environment() const;
|
ModuleEnvironmentObject* environment() const;
|
||||||
ModuleNamespaceObject* namespace_();
|
ModuleNamespaceObject* namespace_();
|
||||||
ModuleStatus status() const;
|
ModuleStatus status() const;
|
||||||
Value error() const;
|
bool hadEvaluationError() const;
|
||||||
|
Value evaluationError() const;
|
||||||
Value hostDefinedField() const;
|
Value hostDefinedField() const;
|
||||||
ArrayObject& requestedModules() const;
|
ArrayObject& requestedModules() const;
|
||||||
ArrayObject& importEntries() const;
|
ArrayObject& importEntries() const;
|
||||||
|
@ -285,9 +287,6 @@ class ModuleObject : public NativeObject
|
||||||
|
|
||||||
void setHostDefinedField(const JS::Value& value);
|
void setHostDefinedField(const JS::Value& value);
|
||||||
|
|
||||||
// For intrinsic_CreateModuleEnvironment.
|
|
||||||
void createEnvironment();
|
|
||||||
|
|
||||||
// For BytecodeEmitter.
|
// For BytecodeEmitter.
|
||||||
bool noteFunctionDeclaration(ExclusiveContext* cx, HandleAtom name, HandleFunction fun);
|
bool noteFunctionDeclaration(ExclusiveContext* cx, HandleAtom name, HandleFunction fun);
|
||||||
|
|
||||||
|
|
|
@ -97,17 +97,17 @@
|
||||||
#define REGEXP_STRING_ITERATOR_FLAGS_SLOT 2
|
#define REGEXP_STRING_ITERATOR_FLAGS_SLOT 2
|
||||||
#define REGEXP_STRING_ITERATOR_DONE_SLOT 3
|
#define REGEXP_STRING_ITERATOR_DONE_SLOT 3
|
||||||
|
|
||||||
#define MODULE_OBJECT_ENVIRONMENT_SLOT 2
|
#define MODULE_OBJECT_ENVIRONMENT_SLOT 1
|
||||||
#define MODULE_OBJECT_STATUS_SLOT 4
|
#define MODULE_OBJECT_STATUS_SLOT 3
|
||||||
#define MODULE_OBJECT_ERROR_SLOT 5
|
#define MODULE_OBJECT_EVALUATION_ERROR_SLOT 4
|
||||||
#define MODULE_OBJECT_DFS_INDEX_SLOT 16
|
#define MODULE_OBJECT_DFS_INDEX_SLOT 15
|
||||||
#define MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT 17
|
#define MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT 16
|
||||||
|
|
||||||
#define MODULE_STATUS_ERRORED 0
|
#define MODULE_STATUS_UNINSTANTIATED 0
|
||||||
#define MODULE_STATUS_UNINSTANTIATED 1
|
#define MODULE_STATUS_INSTANTIATING 1
|
||||||
#define MODULE_STATUS_INSTANTIATING 2
|
#define MODULE_STATUS_INSTANTIATED 2
|
||||||
#define MODULE_STATUS_INSTANTIATED 3
|
#define MODULE_STATUS_EVALUATING 3
|
||||||
#define MODULE_STATUS_EVALUATING 4
|
#define MODULE_STATUS_EVALUATED 4
|
||||||
#define MODULE_STATUS_EVALUATED 5
|
#define MODULE_STATUS_EVALUATED_ERROR 5
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3566,8 +3566,6 @@ GetModuleEnvironment(JSContext* cx, HandleValue moduleValue)
|
||||||
// before they have been instantiated.
|
// before they have been instantiated.
|
||||||
RootedModuleEnvironmentObject env(cx, &module->initialEnvironment());
|
RootedModuleEnvironmentObject env(cx, &module->initialEnvironment());
|
||||||
MOZ_ASSERT(env);
|
MOZ_ASSERT(env);
|
||||||
MOZ_ASSERT_IF(module->environment(), module->environment() == env);
|
|
||||||
|
|
||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3585,6 +3583,9 @@ GetModuleEnvironmentNames(JSContext* cx, unsigned argc, Value* vp)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//- if (module->status() == MODULE_STATUS_ERRORED) {
|
||||||
|
//+ if (module->hadEvaluationError()) {
|
||||||
|
|
||||||
RootedModuleEnvironmentObject env(cx, GetModuleEnvironment(cx, args[0]));
|
RootedModuleEnvironmentObject env(cx, GetModuleEnvironment(cx, args[0]));
|
||||||
Rooted<IdVector> ids(cx, IdVector(cx));
|
Rooted<IdVector> ids(cx, IdVector(cx));
|
||||||
if (!JS_Enumerate(cx, env, &ids))
|
if (!JS_Enumerate(cx, env, &ids))
|
||||||
|
@ -3622,6 +3623,9 @@ GetModuleEnvironmentValue(JSContext* cx, unsigned argc, Value* vp)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//- if (module->status() == MODULE_STATUS_ERRORED) {
|
||||||
|
//+ if (module->hadEvaluationError()) {
|
||||||
|
|
||||||
RootedModuleEnvironmentObject env(cx, GetModuleEnvironment(cx, args[0]));
|
RootedModuleEnvironmentObject env(cx, GetModuleEnvironment(cx, args[0]));
|
||||||
RootedString name(cx, args[1].toString());
|
RootedString name(cx, args[1].toString());
|
||||||
RootedId id(cx);
|
RootedId id(cx);
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
// This tests that attempting to perform ModuleDeclarationInstantation a second
|
// This tests that module instantiation can succeed when executed a second
|
||||||
// time after a failure re-throws the same error.
|
// time after a failure.
|
||||||
//
|
//
|
||||||
// The first attempt fails becuase module 'a' is not available. The second
|
// The first attempt fails becuase module 'a' is not available. The second
|
||||||
// attempt fails because of the previous failure (it would otherwise succeed as
|
// attempt succeeds as 'a' is now available.
|
||||||
// 'a' is now available).
|
|
||||||
|
|
||||||
load(libdir + "dummyModuleResolveHook.js");
|
load(libdir + "dummyModuleResolveHook.js");
|
||||||
|
|
||||||
|
@ -25,12 +24,9 @@ let a = moduleRepo['a'] = parseModule("export var a = 1; export var b = 2;");
|
||||||
let d = moduleRepo['d'] = parseModule("import { a } from 'c'; a;");
|
let d = moduleRepo['d'] = parseModule("import { a } from 'c'; a;");
|
||||||
|
|
||||||
threw = false;
|
threw = false;
|
||||||
let e2;
|
|
||||||
try {
|
try {
|
||||||
d.declarationInstantiation();
|
d.declarationInstantiation();
|
||||||
} catch (exc) {
|
} catch (exc) {
|
||||||
threw = true;
|
threw = true;
|
||||||
e2 = exc;
|
|
||||||
}
|
}
|
||||||
assertEq(threw, true);
|
assertEq(threw, false);
|
||||||
assertEq(e1, e2);
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Test re-instantiation module after failure.
|
||||||
|
|
||||||
|
load(libdir + "asserts.js");
|
||||||
|
load(libdir + "dummyModuleResolveHook.js");
|
||||||
|
|
||||||
|
moduleRepo["good"] = parseModule(`export let x`);
|
||||||
|
|
||||||
|
moduleRepo["y1"] = parseModule(`export let y`);
|
||||||
|
moduleRepo["y2"] = parseModule(`export let y`);
|
||||||
|
moduleRepo["bad"] = parseModule(`export* from "y1"; export* from "y2";`);
|
||||||
|
|
||||||
|
moduleRepo["a"] = parseModule(`import* as ns from "good"; import {y} from "bad";`);
|
||||||
|
|
||||||
|
let b = moduleRepo["b"] = parseModule(`import "a";`);
|
||||||
|
let c = moduleRepo["c"] = parseModule(`import "a";`);
|
||||||
|
|
||||||
|
assertThrowsInstanceOf(() => b.declarationInstantiation(), SyntaxError);
|
||||||
|
assertThrowsInstanceOf(() => c.declarationInstantiation(), SyntaxError);
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
if (!('stackTest' in this))
|
||||||
|
quit();
|
||||||
|
|
||||||
|
let a = parseModule(`throw new Error`);
|
||||||
|
a.declarationInstantiation();
|
||||||
|
stackTest(function() {
|
||||||
|
a.evaluation();
|
||||||
|
});
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
load(libdir + "asserts.js");
|
||||||
|
load(libdir + "dummyModuleResolveHook.js");
|
||||||
|
|
||||||
|
moduleRepo["a"] = parseModule(`throw undefined`);
|
||||||
|
|
||||||
|
let b = moduleRepo["b"] = parseModule(`import "a";`);
|
||||||
|
let c = moduleRepo["c"] = parseModule(`import "a";`);
|
||||||
|
|
||||||
|
b.declarationInstantiation();
|
||||||
|
c.declarationInstantiation();
|
||||||
|
|
||||||
|
let count = 0;
|
||||||
|
try { b.evaluation() } catch (e) { count++; }
|
||||||
|
try { c.evaluation() } catch (e) { count++; }
|
||||||
|
assertEq(count, 2);
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Test re-instantiation module after failure.
|
||||||
|
|
||||||
|
load(libdir + "asserts.js");
|
||||||
|
load(libdir + "dummyModuleResolveHook.js");
|
||||||
|
|
||||||
|
moduleRepo["good"] = parseModule(`export let x`);
|
||||||
|
|
||||||
|
moduleRepo["y1"] = parseModule(`export let y`);
|
||||||
|
moduleRepo["y2"] = parseModule(`export let y`);
|
||||||
|
moduleRepo["bad"] = parseModule(`export* from "y1"; export* from "y2";`);
|
||||||
|
|
||||||
|
moduleRepo["a"] = parseModule(`import {x} from "good"; import {y} from "bad";`);
|
||||||
|
|
||||||
|
let b = moduleRepo["b"] = parseModule(`import "a";`);
|
||||||
|
let c = moduleRepo["c"] = parseModule(`import "a";`);
|
||||||
|
|
||||||
|
assertThrowsInstanceOf(() => b.declarationInstantiation(), SyntaxError);
|
||||||
|
assertThrowsInstanceOf(() => c.declarationInstantiation(), SyntaxError);
|
||||||
|
|
|
@ -579,7 +579,6 @@ MSG_DEF(JSMSG_MISSING_IMPORT, 0, JSEXN_SYNTAXERR, "import not found")
|
||||||
MSG_DEF(JSMSG_AMBIGUOUS_IMPORT, 0, JSEXN_SYNTAXERR, "ambiguous import")
|
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_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_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_STATUS, 0, JSEXN_INTERNALERR, "module record has unexpected status")
|
MSG_DEF(JSMSG_BAD_MODULE_STATUS, 0, JSEXN_INTERNALERR, "module record has unexpected status")
|
||||||
|
|
||||||
// Promise
|
// Promise
|
||||||
|
|
|
@ -4662,21 +4662,16 @@ JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
|
||||||
return ::Evaluate(cx, optionsArg, filename, rval);
|
return ::Evaluate(cx, optionsArg, filename, rval);
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(JSFunction*)
|
JS_PUBLIC_API(JS::ModuleResolveHook)
|
||||||
JS::GetModuleResolveHook(JSContext* cx)
|
JS::GetModuleResolveHook(JSRuntime* rt)
|
||||||
{
|
{
|
||||||
AssertHeapIsIdle(cx);
|
return rt->moduleResolveHook;
|
||||||
CHECK_REQUEST(cx);
|
|
||||||
return cx->global()->moduleResolveHook();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(void)
|
JS_PUBLIC_API(void)
|
||||||
JS::SetModuleResolveHook(JSContext* cx, HandleFunction func)
|
JS::SetModuleResolveHook(JSRuntime* rt, JS::ModuleResolveHook func)
|
||||||
{
|
{
|
||||||
AssertHeapIsIdle(cx);
|
rt->moduleResolveHook = func;
|
||||||
CHECK_REQUEST(cx);
|
|
||||||
assertSameCompartment(cx, func);
|
|
||||||
cx->global()->setModuleResolveHook(func);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(bool)
|
JS_PUBLIC_API(bool)
|
||||||
|
@ -4739,18 +4734,6 @@ JS::GetModuleScript(JSContext* cx, JS::HandleObject moduleArg)
|
||||||
return moduleArg->as<ModuleObject>().script();
|
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_PUBLIC_API(JSObject*)
|
||||||
JS_New(JSContext* cx, HandleObject ctor, const JS::HandleValueArray& inputArgs)
|
JS_New(JSContext* cx, HandleObject ctor, const JS::HandleValueArray& inputArgs)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4322,17 +4322,19 @@ extern JS_PUBLIC_API(bool)
|
||||||
Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
|
Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||||
const char* filename, JS::MutableHandleValue rval);
|
const char* filename, JS::MutableHandleValue rval);
|
||||||
|
|
||||||
/**
|
using ModuleResolveHook = JSObject* (*)(JSContext*, HandleObject, HandleString);
|
||||||
* Get the HostResolveImportedModule hook for a global.
|
|
||||||
*/
|
|
||||||
extern JS_PUBLIC_API(JSFunction*)
|
|
||||||
GetModuleResolveHook(JSContext* cx);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the HostResolveImportedModule hook for a global to the given function.
|
* Get the HostResolveImportedModule hook for the runtime.
|
||||||
|
*/
|
||||||
|
extern JS_PUBLIC_API(ModuleResolveHook)
|
||||||
|
GetModuleResolveHook(JSRuntime* rt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the HostResolveImportedModule hook for the runtime to the given function.
|
||||||
*/
|
*/
|
||||||
extern JS_PUBLIC_API(void)
|
extern JS_PUBLIC_API(void)
|
||||||
SetModuleResolveHook(JSContext* cx, JS::HandleFunction func);
|
SetModuleResolveHook(JSRuntime* rt, ModuleResolveHook func);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the given source buffer as a module in the scope of the current global
|
* Parse the given source buffer as a module in the scope of the current global
|
||||||
|
@ -4395,12 +4397,6 @@ GetRequestedModules(JSContext* cx, JS::HandleObject moduleRecord);
|
||||||
extern JS_PUBLIC_API(JSScript*)
|
extern JS_PUBLIC_API(JSScript*)
|
||||||
GetModuleScript(JSContext* cx, JS::HandleObject moduleRecord);
|
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 */
|
} /* namespace JS */
|
||||||
|
|
||||||
extern JS_PUBLIC_API(bool)
|
extern JS_PUBLIC_API(bool)
|
||||||
|
|
|
@ -274,6 +274,7 @@ struct ShellContext
|
||||||
JS::PersistentRooted<JobQueue> jobQueue;
|
JS::PersistentRooted<JobQueue> jobQueue;
|
||||||
ExclusiveData<ShellAsyncTasks> asyncTasks;
|
ExclusiveData<ShellAsyncTasks> asyncTasks;
|
||||||
bool drainingJobQueue;
|
bool drainingJobQueue;
|
||||||
|
JS::PersistentRootedFunction moduleResolveHook;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Watchdog thread state.
|
* Watchdog thread state.
|
||||||
|
@ -439,7 +440,8 @@ ShellContext::ShellContext(JSContext* cx)
|
||||||
exitCode(0),
|
exitCode(0),
|
||||||
quitting(false),
|
quitting(false),
|
||||||
readLineBufPos(0),
|
readLineBufPos(0),
|
||||||
spsProfilingStackSize(0)
|
spsProfilingStackSize(0),
|
||||||
|
moduleResolveHook(cx)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
static ShellContext*
|
static ShellContext*
|
||||||
|
@ -4030,13 +4032,34 @@ SetModuleResolveHook(JSContext* cx, unsigned argc, Value* vp)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
RootedFunction hook(cx, &args[0].toObject().as<JSFunction>());
|
ShellContext* sc = GetShellContext(cx);
|
||||||
Rooted<GlobalObject*> global(cx, cx->global());
|
sc->moduleResolveHook = &args[0].toObject().as<JSFunction>();
|
||||||
global->setModuleResolveHook(hook);
|
|
||||||
args.rval().setUndefined();
|
args.rval().setUndefined();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static JSObject*
|
||||||
|
CallModuleResolveHook(JSContext* cx, HandleObject module, HandleString specifier)
|
||||||
|
{
|
||||||
|
ShellContext* sc = GetShellContext(cx);
|
||||||
|
|
||||||
|
JS::AutoValueArray<2> args(cx);
|
||||||
|
args[0].setObject(*module);
|
||||||
|
args[1].setString(specifier);
|
||||||
|
|
||||||
|
RootedValue result(cx);
|
||||||
|
if (!JS_CallFunction(cx, nullptr, sc->moduleResolveHook, args, &result))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (!result.isObject() || !result.toObject().is<ModuleObject>()) {
|
||||||
|
JS_ReportErrorASCII(cx, "Module resolve hook did not return Module object");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &result.toObject();
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
GetModuleLoadPath(JSContext* cx, unsigned argc, Value* vp)
|
GetModuleLoadPath(JSContext* cx, unsigned argc, Value* vp)
|
||||||
{
|
{
|
||||||
|
@ -7962,6 +7985,8 @@ main(int argc, char** argv, char** envp)
|
||||||
|
|
||||||
js::SetPreserveWrapperCallback(cx, DummyPreserveWrapperCallback);
|
js::SetPreserveWrapperCallback(cx, DummyPreserveWrapperCallback);
|
||||||
|
|
||||||
|
JS::SetModuleResolveHook(cx->runtime(), CallModuleResolveHook);
|
||||||
|
|
||||||
result = Shell(cx, &op, envp);
|
result = Shell(cx, &op, envp);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
|
@ -491,7 +491,7 @@ ModuleEnvironmentObject::createImportBinding(JSContext* cx, HandleAtom importNam
|
||||||
RootedId importNameId(cx, AtomToId(importName));
|
RootedId importNameId(cx, AtomToId(importName));
|
||||||
RootedId localNameId(cx, AtomToId(localName));
|
RootedId localNameId(cx, AtomToId(localName));
|
||||||
RootedModuleEnvironmentObject env(cx, &module->initialEnvironment());
|
RootedModuleEnvironmentObject env(cx, &module->initialEnvironment());
|
||||||
if (!importBindings().putNew(cx, importNameId, env, localNameId)) {
|
if (!importBindings().put(cx, importNameId, env, localNameId)) {
|
||||||
ReportOutOfMemory(cx);
|
ReportOutOfMemory(cx);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,7 +119,6 @@ class GlobalObject : public NativeObject
|
||||||
DEBUGGERS,
|
DEBUGGERS,
|
||||||
INTRINSICS,
|
INTRINSICS,
|
||||||
FOR_OF_PIC_CHAIN,
|
FOR_OF_PIC_CHAIN,
|
||||||
MODULE_RESOLVE_HOOK,
|
|
||||||
WINDOW_PROXY,
|
WINDOW_PROXY,
|
||||||
GLOBAL_THIS_RESOLVED,
|
GLOBAL_THIS_RESOLVED,
|
||||||
|
|
||||||
|
@ -879,19 +878,6 @@ class GlobalObject : public NativeObject
|
||||||
setReservedSlot(WINDOW_PROXY, ObjectValue(*windowProxy));
|
setReservedSlot(WINDOW_PROXY, ObjectValue(*windowProxy));
|
||||||
}
|
}
|
||||||
|
|
||||||
void setModuleResolveHook(HandleFunction hook) {
|
|
||||||
MOZ_ASSERT(hook);
|
|
||||||
setSlot(MODULE_RESOLVE_HOOK, ObjectValue(*hook));
|
|
||||||
}
|
|
||||||
|
|
||||||
JSFunction* moduleResolveHook() {
|
|
||||||
Value value = getSlotRef(MODULE_RESOLVE_HOOK);
|
|
||||||
if (value.isUndefined())
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return &value.toObject().as<JSFunction>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns either this global's star-generator function prototype, or null
|
// Returns either this global's star-generator function prototype, or null
|
||||||
// if that object was never created. Dodgy; for use only in also-dodgy
|
// if that object was never created. Dodgy; for use only in also-dodgy
|
||||||
// GlobalHelperThreadState::mergeParseTaskCompartment().
|
// GlobalHelperThreadState::mergeParseTaskCompartment().
|
||||||
|
|
|
@ -241,8 +241,10 @@ JSRuntime::JSRuntime(JSRuntime* parentRuntime)
|
||||||
lastAnimationTime(0),
|
lastAnimationTime(0),
|
||||||
performanceMonitoring(thisFromCtor()),
|
performanceMonitoring(thisFromCtor()),
|
||||||
ionLazyLinkListSize_(0),
|
ionLazyLinkListSize_(0),
|
||||||
stackFormat_(parentRuntime ? js::StackFormat::Default
|
stackFormat_(parentRuntime ?
|
||||||
: js::StackFormat::SpiderMonkey)
|
js::StackFormat::Default :
|
||||||
|
js::StackFormat::SpiderMonkey),
|
||||||
|
moduleResolveHook()
|
||||||
{
|
{
|
||||||
setGCStoreBufferPtr(&gc.storeBuffer);
|
setGCStoreBufferPtr(&gc.storeBuffer);
|
||||||
|
|
||||||
|
|
|
@ -1294,6 +1294,9 @@ struct JSRuntime : public JS::shadow::Runtime,
|
||||||
// For inherited heap state accessors.
|
// For inherited heap state accessors.
|
||||||
friend class js::gc::AutoTraceSession;
|
friend class js::gc::AutoTraceSession;
|
||||||
friend class JS::AutoEnterCycleCollection;
|
friend class JS::AutoEnterCycleCollection;
|
||||||
|
|
||||||
|
// The implementation-defined abstract operation HostResolveImportedModule.
|
||||||
|
JS::ModuleResolveHook moduleResolveHook;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
|
@ -2026,36 +2026,26 @@ intrinsic_HostResolveImportedModule(JSContext* cx, unsigned argc, Value* vp)
|
||||||
{
|
{
|
||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
MOZ_ASSERT(args.length() == 2);
|
MOZ_ASSERT(args.length() == 2);
|
||||||
MOZ_ASSERT(args[0].toObject().is<ModuleObject>());
|
RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
|
||||||
MOZ_ASSERT(args[1].isString());
|
RootedString specifier(cx, args[1].toString());
|
||||||
|
|
||||||
RootedFunction moduleResolveHook(cx, cx->global()->moduleResolveHook());
|
JS::ModuleResolveHook moduleResolveHook = cx->runtime()->moduleResolveHook;
|
||||||
if (!moduleResolveHook) {
|
if (!moduleResolveHook) {
|
||||||
JS_ReportErrorASCII(cx, "Module resolve hook not set");
|
JS_ReportErrorASCII(cx, "Module resolve hook not set");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
RootedValue result(cx);
|
RootedObject result(cx);
|
||||||
if (!JS_CallFunction(cx, nullptr, moduleResolveHook, args, &result))
|
result = moduleResolveHook(cx, module, specifier);
|
||||||
|
if (!result)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!result.isObject() || !result.toObject().is<ModuleObject>()) {
|
if (!result->is<ModuleObject>()) {
|
||||||
JS_ReportErrorASCII(cx, "Module resolve hook did not return Module object");
|
JS_ReportErrorASCII(cx, "Module resolve hook did not return Module object");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
args.rval().set(result);
|
args.rval().setObject(*result);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
intrinsic_CreateModuleEnvironment(JSContext* cx, unsigned argc, Value* vp)
|
|
||||||
{
|
|
||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
|
||||||
MOZ_ASSERT(args.length() == 1);
|
|
||||||
RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
|
|
||||||
module->createEnvironment();
|
|
||||||
args.rval().setUndefined();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2087,7 +2077,6 @@ intrinsic_CreateNamespaceBinding(JSContext* cx, unsigned argc, Value* vp)
|
||||||
// the slot directly.
|
// the slot directly.
|
||||||
RootedShape shape(cx, environment->lookup(cx, name));
|
RootedShape shape(cx, environment->lookup(cx, name));
|
||||||
MOZ_ASSERT(shape);
|
MOZ_ASSERT(shape);
|
||||||
MOZ_ASSERT(environment->getSlot(shape->slot()).isMagic(JS_UNINITIALIZED_LEXICAL));
|
|
||||||
environment->setSlot(shape->slot(), args[2]);
|
environment->setSlot(shape->slot(), args[2]);
|
||||||
args.rval().setUndefined();
|
args.rval().setUndefined();
|
||||||
return true;
|
return true;
|
||||||
|
@ -2659,7 +2648,6 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
||||||
CallNonGenericSelfhostedMethod<Is<ModuleObject>>, 2, 0),
|
CallNonGenericSelfhostedMethod<Is<ModuleObject>>, 2, 0),
|
||||||
JS_FN("HostResolveImportedModule", intrinsic_HostResolveImportedModule, 2, 0),
|
JS_FN("HostResolveImportedModule", intrinsic_HostResolveImportedModule, 2, 0),
|
||||||
JS_FN("IsModuleEnvironment", intrinsic_IsInstanceOfBuiltin<ModuleEnvironmentObject>, 1, 0),
|
JS_FN("IsModuleEnvironment", intrinsic_IsInstanceOfBuiltin<ModuleEnvironmentObject>, 1, 0),
|
||||||
JS_FN("CreateModuleEnvironment", intrinsic_CreateModuleEnvironment, 1, 0),
|
|
||||||
JS_FN("CreateImportBinding", intrinsic_CreateImportBinding, 4, 0),
|
JS_FN("CreateImportBinding", intrinsic_CreateImportBinding, 4, 0),
|
||||||
JS_FN("CreateNamespaceBinding", intrinsic_CreateNamespaceBinding, 3, 0),
|
JS_FN("CreateNamespaceBinding", intrinsic_CreateNamespaceBinding, 3, 0),
|
||||||
JS_FN("InstantiateModuleFunctionDeclarations",
|
JS_FN("InstantiateModuleFunctionDeclarations",
|
||||||
|
|
|
@ -6,9 +6,12 @@
|
||||||
#include "nsHtml5TreeOpExecutor.h"
|
#include "nsHtml5TreeOpExecutor.h"
|
||||||
|
|
||||||
nsHtml5SpeculativeLoad::nsHtml5SpeculativeLoad()
|
nsHtml5SpeculativeLoad::nsHtml5SpeculativeLoad()
|
||||||
|
:
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
: mOpCode(eSpeculativeLoadUninitialized)
|
mOpCode(eSpeculativeLoadUninitialized),
|
||||||
#endif
|
#endif
|
||||||
|
mIsAsync(false),
|
||||||
|
mIsDefer(false)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(nsHtml5SpeculativeLoad);
|
MOZ_COUNT_CTOR(nsHtml5SpeculativeLoad);
|
||||||
}
|
}
|
||||||
|
@ -48,11 +51,13 @@ nsHtml5SpeculativeLoad::Perform(nsHtml5TreeOpExecutor* aExecutor)
|
||||||
break;
|
break;
|
||||||
case eSpeculativeLoadScript:
|
case eSpeculativeLoadScript:
|
||||||
aExecutor->PreloadScript(mUrl, mCharset, mTypeOrCharsetSourceOrDocumentMode,
|
aExecutor->PreloadScript(mUrl, mCharset, mTypeOrCharsetSourceOrDocumentMode,
|
||||||
mCrossOrigin, mIntegrity, false);
|
mCrossOrigin, mIntegrity, false,
|
||||||
|
mIsAsync, mIsDefer);
|
||||||
break;
|
break;
|
||||||
case eSpeculativeLoadScriptFromHead:
|
case eSpeculativeLoadScriptFromHead:
|
||||||
aExecutor->PreloadScript(mUrl, mCharset, mTypeOrCharsetSourceOrDocumentMode,
|
aExecutor->PreloadScript(mUrl, mCharset, mTypeOrCharsetSourceOrDocumentMode,
|
||||||
mCrossOrigin, mIntegrity, true);
|
mCrossOrigin, mIntegrity, true,
|
||||||
|
mIsAsync, mIsDefer);
|
||||||
break;
|
break;
|
||||||
case eSpeculativeLoadStyle:
|
case eSpeculativeLoadStyle:
|
||||||
aExecutor->PreloadStyle(mUrl, mCharset, mCrossOrigin, mIntegrity);
|
aExecutor->PreloadStyle(mUrl, mCharset, mCrossOrigin, mIntegrity);
|
||||||
|
|
|
@ -128,7 +128,9 @@ class nsHtml5SpeculativeLoad {
|
||||||
nsHtml5String aType,
|
nsHtml5String aType,
|
||||||
nsHtml5String aCrossOrigin,
|
nsHtml5String aCrossOrigin,
|
||||||
nsHtml5String aIntegrity,
|
nsHtml5String aIntegrity,
|
||||||
bool aParserInHead)
|
bool aParserInHead,
|
||||||
|
bool aAsync,
|
||||||
|
bool aDefer)
|
||||||
{
|
{
|
||||||
NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized,
|
NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized,
|
||||||
"Trying to reinitialize a speculative load!");
|
"Trying to reinitialize a speculative load!");
|
||||||
|
@ -139,6 +141,8 @@ class nsHtml5SpeculativeLoad {
|
||||||
aType.ToString(mTypeOrCharsetSourceOrDocumentMode);
|
aType.ToString(mTypeOrCharsetSourceOrDocumentMode);
|
||||||
aCrossOrigin.ToString(mCrossOrigin);
|
aCrossOrigin.ToString(mCrossOrigin);
|
||||||
aIntegrity.ToString(mIntegrity);
|
aIntegrity.ToString(mIntegrity);
|
||||||
|
mIsAsync = aAsync;
|
||||||
|
mIsDefer = aDefer;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void InitStyle(nsHtml5String aUrl,
|
inline void InitStyle(nsHtml5String aUrl,
|
||||||
|
@ -221,6 +225,13 @@ class nsHtml5SpeculativeLoad {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
eHtml5SpeculativeLoad mOpCode;
|
eHtml5SpeculativeLoad mOpCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the refering element has async and/or defer attributes.
|
||||||
|
*/
|
||||||
|
bool mIsAsync;
|
||||||
|
bool mIsDefer;
|
||||||
|
|
||||||
nsString mUrl;
|
nsString mUrl;
|
||||||
nsString mReferrerPolicy;
|
nsString mReferrerPolicy;
|
||||||
nsString mMetaCSP;
|
nsString mMetaCSP;
|
||||||
|
|
|
@ -185,16 +185,20 @@ nsHtml5TreeBuilder::createElement(int32_t aNamespace,
|
||||||
aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
|
aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
|
||||||
nsHtml5String integrity =
|
nsHtml5String integrity =
|
||||||
aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY);
|
aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY);
|
||||||
|
bool async =
|
||||||
|
aAttributes->contains(nsHtml5AttributeName::ATTR_ASYNC);
|
||||||
|
bool defer =
|
||||||
|
aAttributes->contains(nsHtml5AttributeName::ATTR_DEFER);
|
||||||
mSpeculativeLoadQueue.AppendElement()->InitScript(
|
mSpeculativeLoadQueue.AppendElement()->InitScript(
|
||||||
url,
|
url,
|
||||||
charset,
|
charset,
|
||||||
type,
|
type,
|
||||||
crossOrigin,
|
crossOrigin,
|
||||||
integrity,
|
integrity,
|
||||||
mode == nsHtml5TreeBuilder::IN_HEAD);
|
mode == nsHtml5TreeBuilder::IN_HEAD,
|
||||||
mCurrentHtmlScriptIsAsyncOrDefer =
|
async,
|
||||||
aAttributes->contains(nsHtml5AttributeName::ATTR_ASYNC) ||
|
defer);
|
||||||
aAttributes->contains(nsHtml5AttributeName::ATTR_DEFER);
|
mCurrentHtmlScriptIsAsyncOrDefer = async || defer;
|
||||||
}
|
}
|
||||||
} else if (nsHtml5Atoms::link == aName) {
|
} else if (nsHtml5Atoms::link == aName) {
|
||||||
nsHtml5String rel =
|
nsHtml5String rel =
|
||||||
|
@ -297,7 +301,9 @@ nsHtml5TreeBuilder::createElement(int32_t aNamespace,
|
||||||
type,
|
type,
|
||||||
crossOrigin,
|
crossOrigin,
|
||||||
integrity,
|
integrity,
|
||||||
mode == nsHtml5TreeBuilder::IN_HEAD);
|
mode == nsHtml5TreeBuilder::IN_HEAD,
|
||||||
|
false /* async */,
|
||||||
|
false /* defer */);
|
||||||
}
|
}
|
||||||
} else if (nsHtml5Atoms::style == aName) {
|
} else if (nsHtml5Atoms::style == aName) {
|
||||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||||
|
|
|
@ -921,14 +921,16 @@ nsHtml5TreeOpExecutor::PreloadScript(const nsAString& aURL,
|
||||||
const nsAString& aType,
|
const nsAString& aType,
|
||||||
const nsAString& aCrossOrigin,
|
const nsAString& aCrossOrigin,
|
||||||
const nsAString& aIntegrity,
|
const nsAString& aIntegrity,
|
||||||
bool aScriptFromHead)
|
bool aScriptFromHead,
|
||||||
|
bool aAsync,
|
||||||
|
bool aDefer)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIURI> uri = ConvertIfNotPreloadedYet(aURL);
|
nsCOMPtr<nsIURI> uri = ConvertIfNotPreloadedYet(aURL);
|
||||||
if (!uri) {
|
if (!uri) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mDocument->ScriptLoader()->PreloadURI(uri, aCharset, aType, aCrossOrigin,
|
mDocument->ScriptLoader()->PreloadURI(uri, aCharset, aType, aCrossOrigin,
|
||||||
aIntegrity, aScriptFromHead,
|
aIntegrity, aScriptFromHead, aAsync, aDefer,
|
||||||
mSpeculationReferrerPolicy);
|
mSpeculationReferrerPolicy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -249,7 +249,9 @@ class nsHtml5TreeOpExecutor final : public nsHtml5DocumentBuilder,
|
||||||
const nsAString& aType,
|
const nsAString& aType,
|
||||||
const nsAString& aCrossOrigin,
|
const nsAString& aCrossOrigin,
|
||||||
const nsAString& aIntegrity,
|
const nsAString& aIntegrity,
|
||||||
bool aScriptFromHead);
|
bool aScriptFromHead,
|
||||||
|
bool aAsync,
|
||||||
|
bool aDefer);
|
||||||
|
|
||||||
void PreloadStyle(const nsAString& aURL, const nsAString& aCharset,
|
void PreloadStyle(const nsAString& aURL, const nsAString& aCharset,
|
||||||
const nsAString& aCrossOrigin,
|
const nsAString& aCrossOrigin,
|
||||||
|
|
|
@ -1076,7 +1076,7 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder,
|
||||||
nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(node);
|
nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(node);
|
||||||
NS_ASSERTION(sele, "Node didn't QI to script.");
|
NS_ASSERTION(sele, "Node didn't QI to script.");
|
||||||
sele->SetScriptLineNumber(mFour.integer);
|
sele->SetScriptLineNumber(mFour.integer);
|
||||||
sele->FreezeUriAsyncDefer();
|
sele->FreezeExecutionAttrs(node->OwnerDoc());
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
case eTreeOpSvgLoad: {
|
case eTreeOpSvgLoad: {
|
||||||
|
|
Loading…
Reference in New Issue