Backed out changeset f69f493b2f3c (bug 1800641) for causing non-unified build bustages on LoadedScript.cpp. CLOSED TREE

This commit is contained in:
Cosmin Sabou
2023-12-25 08:38:51 +02:00
parent d60b4bd3b1
commit 78d82c8098
20 changed files with 361 additions and 616 deletions

View File

@@ -7,23 +7,27 @@
#ifndef js_loader_ScriptLoadRequest_h
#define js_loader_ScriptLoadRequest_h
#include "js/AllocPolicy.h"
#include "js/RootingAPI.h"
#include "js/SourceText.h"
#include "js/TypeDecls.h"
#include "mozilla/Atomics.h"
#include "mozilla/Assertions.h"
#include "mozilla/CORSMode.h"
#include "mozilla/dom/SRIMetadata.h"
#include "mozilla/dom/ReferrerPolicyBinding.h"
#include "mozilla/LinkedList.h"
#include "mozilla/Maybe.h"
#include "mozilla/MaybeOneOf.h"
#include "mozilla/PreloaderBase.h"
#include "mozilla/StaticPrefs_dom.h"
#include "mozilla/Utf8.h" // mozilla::Utf8Unit
#include "mozilla/Variant.h"
#include "mozilla/Vector.h"
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIGlobalObject.h"
#include "LoadedScript.h"
#include "ScriptKind.h"
#include "ScriptFetchOptions.h"
#include "nsIScriptElement.h"
class nsICacheInfoChannel;
@@ -44,10 +48,94 @@ class ComponentLoadContext;
namespace JS {
namespace loader {
using Utf8Unit = mozilla::Utf8Unit;
class LoadContextBase;
class ModuleLoadRequest;
class ScriptLoadRequestList;
// https://fetch.spec.whatwg.org/#concept-request-parser-metadata
// All scripts are either "parser-inserted" or "not-parser-inserted", so
// the empty string is not necessary.
enum class ParserMetadata {
NotParserInserted,
ParserInserted,
};
/*
* ScriptFetchOptions loosely corresponds to HTML's "script fetch options",
* https://html.spec.whatwg.org/multipage/webappapis.html#script-fetch-options
* with the exception of the following properties:
* integrity metadata
* The integrity metadata used for the initial fetch. This is
* implemented in ScriptLoadRequest, as it changes for every
* ScriptLoadRequest.
*
* referrerPolicy
* For a module script, its referrerPolicy will be updated if there is a
* HTTP Response 'REFERRER-POLICY' header, given this value may be different
* for every ScriptLoadRequest, so we store it directly in
* ScriptLoadRequest.
*
* In the case of classic scripts without dynamic import, this object is
* used once. For modules, this object is propogated throughout the module
* tree. If there is a dynamically imported module in any type of script,
* the ScriptFetchOptions object will be propogated from its importer.
*/
class ScriptFetchOptions {
~ScriptFetchOptions();
public:
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(ScriptFetchOptions)
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(ScriptFetchOptions)
ScriptFetchOptions(mozilla::CORSMode aCORSMode, const nsAString& aNonce,
mozilla::dom::RequestPriority aFetchPriority,
const ParserMetadata aParserMetadata,
nsIPrincipal* aTriggeringPrincipal,
mozilla::dom::Element* aElement = nullptr);
/*
* The credentials mode used for the initial fetch (for module scripts)
* and for fetching any imported modules (for both module scripts and
* classic scripts)
*/
const mozilla::CORSMode mCORSMode;
/*
* The cryptographic nonce metadata used for the initial fetch and for
* fetching any imported modules.
*/
const nsString mNonce;
/*
* <https://html.spec.whatwg.org/multipage/webappapis.html#script-fetch-options>.
*/
const mozilla::dom::RequestPriority mFetchPriority;
/*
* The parser metadata used for the initial fetch and for fetching any
* imported modules
*/
const ParserMetadata mParserMetadata;
/*
* Used to determine CSP and if we are on the About page.
* Only used in DOM content scripts.
* TODO: Move to ScriptLoadContext
*/
nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
/*
* Represents fields populated by DOM elements (nonce, parser metadata)
* Leave this field as a nullptr for any fetch that requires the
* default classic script options.
* (https://html.spec.whatwg.org/multipage/webappapis.html#default-classic-script-fetch-options)
* TODO: extract necessary fields rather than passing this object
*/
nsCOMPtr<mozilla::dom::Element> mElement;
};
/*
* ScriptLoadRequest
*
@@ -77,9 +165,9 @@ class ScriptLoadRequestList;
*
*/
class ScriptLoadRequest : public nsISupports,
private mozilla::LinkedListElement<ScriptLoadRequest>,
public LoadedScriptDelegate<ScriptLoadRequest> {
class ScriptLoadRequest
: public nsISupports,
private mozilla::LinkedListElement<ScriptLoadRequest> {
using super = LinkedListElement<ScriptLoadRequest>;
// Allow LinkedListElement<ScriptLoadRequest> to cast us to itself as needed.
@@ -103,9 +191,18 @@ class ScriptLoadRequest : public nsISupports,
using super::getNext;
using super::isInList;
template <typename T>
using VariantType = mozilla::VariantType<T>;
template <typename... Ts>
using Variant = mozilla::Variant<Ts...>;
template <typename T, typename D = JS::DeletePolicy<T>>
using UniquePtr = mozilla::UniquePtr<T, D>;
using MaybeSourceText =
mozilla::MaybeOneOf<JS::SourceText<char16_t>, JS::SourceText<Utf8Unit>>;
bool IsModuleRequest() const { return mKind == ScriptKind::eModule; }
bool IsImportMapRequest() const { return mKind == ScriptKind::eImportMap; }
@@ -119,7 +216,6 @@ class ScriptLoadRequest : public nsISupports,
virtual void SetReady();
enum class State : uint8_t {
CheckingCache,
Fetching,
Compiling,
LoadingImports,
@@ -127,14 +223,6 @@ class ScriptLoadRequest : public nsISupports,
Canceled
};
// Before any attempt at fetching resources from the cache we should first
// make sure that the resource does not yet exists in the cache. In which case
// we might simply alias its LoadedScript. Otherwise a new one would be
// created.
bool IsCheckingCache() const { return mState == State::CheckingCache; }
// Setup and load resources, to fill the LoadedScript and make it usable by
// the JavaScript engine.
bool IsFetching() const { return mState == State::Fetching; }
bool IsCompiling() const { return mState == State::Compiling; }
bool IsLoadingImports() const { return mState == State::LoadingImports; }
@@ -146,6 +234,64 @@ class ScriptLoadRequest : public nsISupports,
return mState == State::Ready || mState == State::Canceled;
}
// Type of data provided by the nsChannel.
enum class DataType : uint8_t { eUnknown, eTextSource, eBytecode };
bool IsUnknownDataType() const { return mDataType == DataType::eUnknown; }
bool IsTextSource() const { return mDataType == DataType::eTextSource; }
bool IsSource() const { return IsTextSource(); }
void SetUnknownDataType() {
mDataType = DataType::eUnknown;
mScriptData.reset();
}
void SetTextSource() {
MOZ_ASSERT(IsUnknownDataType());
mDataType = DataType::eTextSource;
mScriptData.emplace(VariantType<ScriptTextBuffer<Utf8Unit>>());
}
// Use a vector backed by the JS allocator for script text so that contents
// can be transferred in constant time to the JS engine, not copied in linear
// time.
template <typename Unit>
using ScriptTextBuffer = mozilla::Vector<Unit, 0, js::MallocAllocPolicy>;
bool IsUTF16Text() const {
return mScriptData->is<ScriptTextBuffer<char16_t>>();
}
bool IsUTF8Text() const {
return mScriptData->is<ScriptTextBuffer<Utf8Unit>>();
}
template <typename Unit>
const ScriptTextBuffer<Unit>& ScriptText() const {
MOZ_ASSERT(IsTextSource());
return mScriptData->as<ScriptTextBuffer<Unit>>();
}
template <typename Unit>
ScriptTextBuffer<Unit>& ScriptText() {
MOZ_ASSERT(IsTextSource());
return mScriptData->as<ScriptTextBuffer<Unit>>();
}
size_t ScriptTextLength() const {
MOZ_ASSERT(IsTextSource());
return IsUTF16Text() ? ScriptText<char16_t>().length()
: ScriptText<Utf8Unit>().length();
}
// Get source text. On success |aMaybeSource| will contain either UTF-8 or
// UTF-16 source; on failure it will remain in its initial state.
nsresult GetScriptSource(JSContext* aCx, MaybeSourceText* aMaybeSource);
void ClearScriptText() {
MOZ_ASSERT(IsTextSource());
return IsUTF16Text() ? ScriptText<char16_t>().clearAndFree()
: ScriptText<Utf8Unit>().clearAndFree();
}
mozilla::dom::RequestPriority FetchPriority() const {
return mFetchOptions->mFetchPriority;
}
@@ -168,19 +314,16 @@ class ScriptLoadRequest : public nsISupports,
return mFetchOptions->mTriggeringPrincipal;
}
// Convert a CheckingCache ScriptLoadRequest into a Fetching one, by creating
// a new LoadedScript which is matching the ScriptKind provided when
// constructing this ScriptLoadRequest.
void NoCacheEntryFound();
// Convert a CheckingCache ScriptLoadRequest into a Fetching one, while
// not creating a new LoadedScript, for error cases.
void SkipCacheOnError() { mState = State::Fetching; }
void ClearScriptSource();
void MarkForBytecodeEncoding(JSScript* aScript);
bool IsMarkedForBytecodeEncoding() const;
bool IsBytecode() const { return mDataType == DataType::eBytecode; }
void SetBytecode();
mozilla::CORSMode CORSMode() const { return mFetchOptions->mCORSMode; }
void DropBytecodeCacheReferences();
@@ -197,25 +340,37 @@ class ScriptLoadRequest : public nsISupports,
mozilla::dom::WorkletLoadContext* GetWorkletLoadContext();
const LoadedScript* getLoadedScript() const { return mLoadedScript.get(); }
LoadedScript* getLoadedScript() { return mLoadedScript.get(); }
const ScriptKind mKind; // Whether this is a classic script or a module
// request.
// script.
State mState; // Are we still waiting for a load to complete?
bool mFetchSourceOnly; // Request source, not cached bytecode.
DataType mDataType; // Does this contain Source or Bytecode?
// The referrer policy used for the initial fetch and for fetching any
// imported modules
enum mozilla::dom::ReferrerPolicy mReferrerPolicy;
RefPtr<ScriptFetchOptions> mFetchOptions;
const SRIMetadata mIntegrity;
const nsCOMPtr<nsIURI> mReferrer;
mozilla::Maybe<nsString>
mSourceMapURL; // Holds source map url for loaded scripts
// Holds script source data for non-inline scripts.
mozilla::Maybe<
Variant<ScriptTextBuffer<char16_t>, ScriptTextBuffer<Utf8Unit>>>
mScriptData;
// The length of script source text, set when reading completes. This is used
// since mScriptData is cleared when the source is passed to the JS engine.
size_t mScriptTextLength;
// Holds the SRI serialized hash and the script bytecode for non-inline
// scripts. The data is laid out according to ScriptBytecodeDataLayout
// or, if compression is enabled, ScriptBytecodeCompressedDataLayout.
mozilla::Vector<uint8_t> mScriptBytecode;
uint32_t mBytecodeOffset; // Offset of the bytecode in mScriptBytecode
const nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIPrincipal> mOriginPrincipal;
@@ -227,14 +382,6 @@ class ScriptLoadRequest : public nsISupports,
// The base URL used for resolving relative module imports.
nsCOMPtr<nsIURI> mBaseURL;
// The loaded script holds the source / bytecode which is loaded.
//
// Currently it is used to hold information which are needed by the Debugger.
// Soon it would be used as a way to dissociate the LoadRequest from the
// loaded value, such that multiple request referring to the same content
// would share the same loaded script.
RefPtr<LoadedScript> mLoadedScript;
// Holds the top-level JSScript that corresponds to the current source, once
// it is parsed, and planned to be saved in the bytecode cache.
//