diff options
author | Moonchild <moonchild@palemoon.org> | 2020-07-01 10:15:24 +0000 |
---|---|---|
committer | Moonchild <moonchild@palemoon.org> | 2020-07-10 18:29:02 +0000 |
commit | 5ffe27bb03d8ac7b979007721c2699e891c77268 (patch) | |
tree | 433a153c67bb17f4455c76d2bb8a9787c9330890 /dom/script/ScriptLoader.cpp | |
parent | 0633844f46858135ee62d396829c6292492ca117 (diff) | |
download | UXP-5ffe27bb03d8ac7b979007721c2699e891c77268.tar UXP-5ffe27bb03d8ac7b979007721c2699e891c77268.tar.gz UXP-5ffe27bb03d8ac7b979007721c2699e891c77268.tar.lz UXP-5ffe27bb03d8ac7b979007721c2699e891c77268.tar.xz UXP-5ffe27bb03d8ac7b979007721c2699e891c77268.zip |
Issue #1603 - Part 2: Split some classes out of ScriptLoader.cpp
This splits ScriptLoader up the same way Mozilla did with the exception of
ScriptRequest due to the fact that ScriptLoader and ScriptRequest are
interdependent and would create a circular dependency if split apart when not
using unified building.
Diffstat (limited to 'dom/script/ScriptLoader.cpp')
-rw-r--r-- | dom/script/ScriptLoader.cpp | 486 |
1 files changed, 4 insertions, 482 deletions
diff --git a/dom/script/ScriptLoader.cpp b/dom/script/ScriptLoader.cpp index b5c8053e8..adc046b7c 100644 --- a/dom/script/ScriptLoader.cpp +++ b/dom/script/ScriptLoader.cpp @@ -4,11 +4,10 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* - * A class that handles loading and evaluation of <script> elements. - */ - #include "ScriptLoader.h" +#include "ScriptLoadHandler.h" +#include "ModuleLoadRequest.h" +#include "ModuleScript.h" #include "prsystem.h" #include "jsapi.h" @@ -134,96 +133,6 @@ ScriptLoadRequest::MaybeCancelOffThreadScript() mOffThreadToken = nullptr; } -////////////////////////////////////////////////////////////// -// ModuleLoadRequest -////////////////////////////////////////////////////////////// - -// 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 -// multiple imports of the same module. - -class ModuleLoadRequest final : public ScriptLoadRequest -{ - ~ModuleLoadRequest() {} - - ModuleLoadRequest(const ModuleLoadRequest& aOther) = delete; - ModuleLoadRequest(ModuleLoadRequest&& aOther) = delete; - -public: - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ModuleLoadRequest, ScriptLoadRequest) - - ModuleLoadRequest(nsIScriptElement* aElement, - uint32_t aVersion, - CORSMode aCORSMode, - const SRIMetadata& aIntegrity, - ScriptLoader* aLoader); - - bool IsTopLevel() const { - return mIsTopLevel; - } - - void SetReady() override; - void Cancel() override; - - void ModuleLoaded(); - void DependenciesLoaded(); - void LoadFailed(); - - // Is this a request for a top level module script or an import? - bool mIsTopLevel; - - // The base URL used for resolving relative module imports. - nsCOMPtr<nsIURI> mBaseURL; - - // Pointer to the script loader, used to trigger actions when the module load - // finishes. - 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 - // failure. - RefPtr<ModuleScript> mModuleScript; - - // A promise that is completed on successful load of this module and all of - // its dependencies, indicating that the module is ready for instantiation and - // evaluation. - MozPromiseHolder<GenericPromise> mReady; - - // Array of imported modules. - nsTArray<RefPtr<ModuleLoadRequest>> mImports; -}; - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ModuleLoadRequest) -NS_INTERFACE_MAP_END_INHERITING(ScriptLoadRequest) - -NS_IMPL_CYCLE_COLLECTION_INHERITED(ModuleLoadRequest, ScriptLoadRequest, - mBaseURL, - mLoader, - mParent, - mModuleScript, - mImports) - -NS_IMPL_ADDREF_INHERITED(ModuleLoadRequest, ScriptLoadRequest) -NS_IMPL_RELEASE_INHERITED(ModuleLoadRequest, ScriptLoadRequest) - -ModuleLoadRequest::ModuleLoadRequest(nsIScriptElement* aElement, - uint32_t aVersion, - CORSMode aCORSMode, - const SRIMetadata &aIntegrity, - ScriptLoader* aLoader) - : ScriptLoadRequest(ScriptKind::Module, - aElement, - aVersion, - aCORSMode, - aIntegrity), - mIsTopLevel(true), - mLoader(aLoader) -{} - inline ModuleLoadRequest* ScriptLoadRequest::AsModuleRequest() { @@ -231,194 +140,6 @@ ScriptLoadRequest::AsModuleRequest() return static_cast<ModuleLoadRequest*>(this); } -void ModuleLoadRequest::Cancel() -{ - ScriptLoadRequest::Cancel(); - mModuleScript = nullptr; - mProgress = ScriptLoadRequest::Progress::Ready; - for (size_t i = 0; i < mImports.Length(); i++) { - mImports[i]->Cancel(); - } - mReady.RejectIfExists(NS_ERROR_FAILURE, __func__); -} - -void -ModuleLoadRequest::SetReady() -{ -#ifdef DEBUG - for (size_t i = 0; i < mImports.Length(); i++) { - MOZ_ASSERT(mImports[i]->IsReadyToRun()); - } -#endif - - ScriptLoadRequest::SetReady(); - mReady.ResolveIfExists(true, __func__); -} - -void -ModuleLoadRequest::ModuleLoaded() -{ - // A module that was found to be marked as fetching in the module map has now - // been loaded. - - mModuleScript = mLoader->GetFetchedModule(mURI); - mLoader->StartFetchingModuleDependencies(this); -} - -void -ModuleLoadRequest::DependenciesLoaded() -{ - // The module and all of its dependencies have been successfully fetched and - // compiled. - - if (!mLoader->InstantiateModuleTree(this)) { - LoadFailed(); - return; - } - - SetReady(); - mLoader->ProcessLoadedModuleTree(this); - mLoader = nullptr; - mParent = nullptr; -} - -void -ModuleLoadRequest::LoadFailed() -{ - Cancel(); - mLoader->ProcessLoadedModuleTree(this); - mLoader = nullptr; - mParent = nullptr; -} - -////////////////////////////////////////////////////////////// -// ModuleScript -////////////////////////////////////////////////////////////// - -// A single module script. May be used to satisfy multiple load requests. - -class ModuleScript final : public nsISupports -{ - enum InstantiationState { - Uninstantiated, - Instantiated, - Errored - }; - - RefPtr<ScriptLoader> mLoader; - nsCOMPtr<nsIURI> mBaseURL; - JS::Heap<JSObject*> mModuleRecord; - JS::Heap<JS::Value> mException; - InstantiationState mInstantiationState; - - ~ModuleScript(); - -public: - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ModuleScript) - - ModuleScript(ScriptLoader* aLoader, - nsIURI* aBaseURL, - JS::Handle<JSObject*> aModuleRecord); - - ScriptLoader* Loader() const { return mLoader; } - JSObject* ModuleRecord() const { return mModuleRecord; } - JS::Value Exception() const { return mException; } - nsIURI* BaseURL() const { return mBaseURL; } - - void SetInstantiationResult(JS::Handle<JS::Value> aMaybeException); - bool IsUninstantiated() const { - return mInstantiationState == Uninstantiated; - } - bool IsInstantiated() const { - return mInstantiationState == Instantiated; - } - bool InstantiationFailed() const { - return mInstantiationState == Errored; - } - - void UnlinkModuleRecord(); -}; - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ModuleScript) -NS_INTERFACE_MAP_END - -NS_IMPL_CYCLE_COLLECTION_CLASS(ModuleScript) - -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ModuleScript) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mLoader) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mBaseURL) - tmp->UnlinkModuleRecord(); -NS_IMPL_CYCLE_COLLECTION_UNLINK_END - -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ModuleScript) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoader) -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END - -NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ModuleScript) - NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mModuleRecord) - NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mException) -NS_IMPL_CYCLE_COLLECTION_TRACE_END - -NS_IMPL_CYCLE_COLLECTING_ADDREF(ModuleScript) -NS_IMPL_CYCLE_COLLECTING_RELEASE(ModuleScript) - -ModuleScript::ModuleScript(ScriptLoader *aLoader, nsIURI* aBaseURL, - JS::Handle<JSObject*> aModuleRecord) - : mLoader(aLoader), - mBaseURL(aBaseURL), - mModuleRecord(aModuleRecord), - mInstantiationState(Uninstantiated) -{ - MOZ_ASSERT(mLoader); - MOZ_ASSERT(mBaseURL); - MOZ_ASSERT(mModuleRecord); - MOZ_ASSERT(mException.isUndefined()); - - // Make module's host defined field point to this module script object. - // This is cleared in the UnlinkModuleRecord(). - JS::SetModuleHostDefinedField(mModuleRecord, JS::PrivateValue(this)); - HoldJSObjects(this); -} - -void -ModuleScript::UnlinkModuleRecord() -{ - // Remove module's back reference to this object request if present. - if (mModuleRecord) { - MOZ_ASSERT(JS::GetModuleHostDefinedField(mModuleRecord).toPrivate() == - this); - JS::SetModuleHostDefinedField(mModuleRecord, JS::UndefinedValue()); - } - mModuleRecord = nullptr; - mException.setUndefined(); -} - -ModuleScript::~ModuleScript() -{ - if (mModuleRecord) { - // The object may be destroyed without being unlinked first. - UnlinkModuleRecord(); - } - DropJSObjects(this); -} - -void -ModuleScript::SetInstantiationResult(JS::Handle<JS::Value> aMaybeException) -{ - MOZ_ASSERT(mInstantiationState == Uninstantiated); - MOZ_ASSERT(mModuleRecord); - MOZ_ASSERT(mException.isUndefined()); - - if (aMaybeException.isUndefined()) { - mInstantiationState = Instantiated; - } else { - mModuleRecord = nullptr; - mException = aMaybeException; - mInstantiationState = Errored; - } -} - ////////////////////////////////////////////////////////////// // ScriptLoadRequestList @@ -2860,204 +2581,5 @@ ScriptLoader::MaybeRemovedDeferRequests() return false; } -////////////////////////////////////////////////////////////// -// ScriptLoadHandler -////////////////////////////////////////////////////////////// - -ScriptLoadHandler::ScriptLoadHandler(ScriptLoader *aScriptLoader, - ScriptLoadRequest *aRequest, - mozilla::dom::SRICheckDataVerifier *aSRIDataVerifier) - : mScriptLoader(aScriptLoader), - mRequest(aRequest), - mSRIDataVerifier(aSRIDataVerifier), - mSRIStatus(NS_OK), - mDecoder(), - mBuffer() -{} - -ScriptLoadHandler::~ScriptLoadHandler() -{} - -NS_IMPL_ISUPPORTS(ScriptLoadHandler, nsIIncrementalStreamLoaderObserver) - -NS_IMETHODIMP -ScriptLoadHandler::OnIncrementalData(nsIIncrementalStreamLoader* aLoader, - nsISupports* aContext, - uint32_t aDataLength, - const uint8_t* aData, - uint32_t *aConsumedLength) -{ - if (mRequest->IsCanceled()) { - // If request cancelled, ignore any incoming data. - *aConsumedLength = aDataLength; - return NS_OK; - } - - if (!EnsureDecoder(aLoader, aData, aDataLength, - /* aEndOfStream = */ false)) { - return NS_OK; - } - - // Below we will/shall consume entire data chunk. - *aConsumedLength = aDataLength; - - // Decoder has already been initialized. -- trying to decode all loaded bytes. - nsresult rv = TryDecodeRawData(aData, aDataLength, - /* aEndOfStream = */ false); - NS_ENSURE_SUCCESS(rv, rv); - - // If SRI is required for this load, appending new bytes to the hash. - if (mSRIDataVerifier && NS_SUCCEEDED(mSRIStatus)) { - mSRIStatus = mSRIDataVerifier->Update(aDataLength, aData); - } - - return rv; -} - -nsresult -ScriptLoadHandler::TryDecodeRawData(const uint8_t* aData, - uint32_t aDataLength, - bool aEndOfStream) -{ - int32_t srcLen = aDataLength; - const char* src = reinterpret_cast<const char *>(aData); - int32_t dstLen; - nsresult rv = - mDecoder->GetMaxLength(src, srcLen, &dstLen); - - NS_ENSURE_SUCCESS(rv, rv); - - uint32_t haveRead = mBuffer.length(); - - CheckedInt<uint32_t> capacity = haveRead; - capacity += dstLen; - - if (!capacity.isValid() || !mBuffer.reserve(capacity.value())) { - return NS_ERROR_OUT_OF_MEMORY; - } - - rv = mDecoder->Convert(src, - &srcLen, - mBuffer.begin() + haveRead, - &dstLen); - - NS_ENSURE_SUCCESS(rv, rv); - - haveRead += dstLen; - MOZ_ASSERT(haveRead <= capacity.value(), "mDecoder produced more data than expected"); - MOZ_ALWAYS_TRUE(mBuffer.resizeUninitialized(haveRead)); - - return NS_OK; -} - -bool -ScriptLoadHandler::EnsureDecoder(nsIIncrementalStreamLoader *aLoader, - const uint8_t* aData, - uint32_t aDataLength, - bool aEndOfStream) -{ - // Check if decoder has already been created. - if (mDecoder) { - return true; - } - - nsAutoCString charset; - - // JavaScript modules are always UTF-8. - if (mRequest->IsModuleRequest()) { - charset = "UTF-8"; - mDecoder = EncodingUtils::DecoderForEncoding(charset); - return true; - } - - // Determine if BOM check should be done. This occurs either - // if end-of-stream has been reached, or at least 3 bytes have - // been read from input. - if (!aEndOfStream && (aDataLength < 3)) { - return false; - } - - // Do BOM detection. - if (nsContentUtils::CheckForBOM(aData, aDataLength, charset)) { - mDecoder = EncodingUtils::DecoderForEncoding(charset); - return true; - } - - // BOM detection failed, check content stream for charset. - nsCOMPtr<nsIRequest> req; - nsresult rv = aLoader->GetRequest(getter_AddRefs(req)); - NS_ASSERTION(req, "StreamLoader's request went away prematurely"); - NS_ENSURE_SUCCESS(rv, false); - - nsCOMPtr<nsIChannel> channel = do_QueryInterface(req); - - if (channel && - NS_SUCCEEDED(channel->GetContentCharset(charset)) && - EncodingUtils::FindEncodingForLabel(charset, charset)) { - mDecoder = EncodingUtils::DecoderForEncoding(charset); - return true; - } - - // Check the hint charset from the script element or preload - // request. - nsAutoString hintCharset; - if (!mRequest->IsPreload()) { - mRequest->mElement->GetScriptCharset(hintCharset); - } else { - nsTArray<ScriptLoader::PreloadInfo>::index_type i = - mScriptLoader->mPreloads.IndexOf(mRequest, 0, - ScriptLoader::PreloadRequestComparator()); - - NS_ASSERTION(i != mScriptLoader->mPreloads.NoIndex, - "Incorrect preload bookkeeping"); - hintCharset = mScriptLoader->mPreloads[i].mCharset; - } - - if (EncodingUtils::FindEncodingForLabel(hintCharset, charset)) { - mDecoder = EncodingUtils::DecoderForEncoding(charset); - return true; - } - - // Get the charset from the charset of the document. - if (mScriptLoader->mDocument) { - charset = mScriptLoader->mDocument->GetDocumentCharacterSet(); - mDecoder = EncodingUtils::DecoderForEncoding(charset); - return true; - } - - // Curiously, there are various callers that don't pass aDocument. The - // fallback in the old code was ISO-8859-1, which behaved like - // windows-1252. Saying windows-1252 for clarity and for compliance - // with the Encoding Standard. - charset = "windows-1252"; - mDecoder = EncodingUtils::DecoderForEncoding(charset); - return true; -} - -NS_IMETHODIMP -ScriptLoadHandler::OnStreamComplete(nsIIncrementalStreamLoader* aLoader, - nsISupports* aContext, - nsresult aStatus, - uint32_t aDataLength, - const uint8_t* aData) -{ - if (!mRequest->IsCanceled()) { - DebugOnly<bool> encoderSet = - EnsureDecoder(aLoader, aData, aDataLength, /* aEndOfStream = */ true); - MOZ_ASSERT(encoderSet); - DebugOnly<nsresult> rv = TryDecodeRawData(aData, aDataLength, - /* aEndOfStream = */ true); - - // If SRI is required for this load, appending new bytes to the hash. - if (mSRIDataVerifier && NS_SUCCEEDED(mSRIStatus)) { - mSRIStatus = mSRIDataVerifier->Update(aDataLength, aData); - } - } - - // we have to mediate and use mRequest. - return mScriptLoader->OnStreamComplete(aLoader, mRequest, aStatus, mSRIStatus, - mBuffer, mSRIDataVerifier); -} - } // dom namespace -} // mozilla namespace
\ No newline at end of file +} // mozilla namespace |