ScriptLoader.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #ifndef mozilla_dom_ScriptLoader_h
  6. #define mozilla_dom_ScriptLoader_h
  7. #include "nsCOMPtr.h"
  8. #include "nsRefPtrHashtable.h"
  9. #include "nsIUnicodeDecoder.h"
  10. #include "nsIScriptElement.h"
  11. #include "nsCOMArray.h"
  12. #include "nsCycleCollectionParticipant.h"
  13. #include "nsTArray.h"
  14. #include "nsAutoPtr.h"
  15. #include "nsIDocument.h"
  16. #include "nsIIncrementalStreamLoader.h"
  17. #include "nsURIHashKey.h"
  18. #include "mozilla/CORSMode.h"
  19. #include "mozilla/dom/SRIMetadata.h"
  20. #include "mozilla/dom/SRICheck.h"
  21. #include "mozilla/MozPromise.h"
  22. #include "mozilla/net/ReferrerPolicy.h"
  23. #include "mozilla/Vector.h"
  24. class nsIURI;
  25. namespace JS {
  26. class SourceBufferHolder;
  27. } // namespace JS
  28. namespace mozilla {
  29. namespace dom {
  30. class AutoJSAPI;
  31. class ModuleLoadRequest;
  32. class ModuleScript;
  33. class ScriptLoadRequestList;
  34. //////////////////////////////////////////////////////////////
  35. // Per-request data structure
  36. //////////////////////////////////////////////////////////////
  37. enum class ScriptKind {
  38. Classic,
  39. Module
  40. };
  41. class ScriptLoadRequest : public nsISupports,
  42. private mozilla::LinkedListElement<ScriptLoadRequest>
  43. {
  44. typedef LinkedListElement<ScriptLoadRequest> super;
  45. // Allow LinkedListElement<ScriptLoadRequest> to cast us to itself as needed.
  46. friend class mozilla::LinkedListElement<ScriptLoadRequest>;
  47. friend class ScriptLoadRequestList;
  48. protected:
  49. virtual ~ScriptLoadRequest();
  50. public:
  51. ScriptLoadRequest(ScriptKind aKind,
  52. nsIURI* aURI,
  53. nsIScriptElement* aElement,
  54. uint32_t aVersion,
  55. mozilla::CORSMode aCORSMode,
  56. const SRIMetadata& aIntegrity,
  57. nsIURI* aReferrer,
  58. mozilla::net::ReferrerPolicy aReferrerPolicy)
  59. : mKind(aKind),
  60. mElement(aElement),
  61. mProgress(Progress::Loading),
  62. mScriptMode(ScriptMode::eBlocking),
  63. mIsInline(true),
  64. mHasSourceMapURL(false),
  65. mInDeferList(false),
  66. mInAsyncList(false),
  67. mIsNonAsyncScriptInserted(false),
  68. mIsXSLT(false),
  69. mIsCanceled(false),
  70. mWasCompiledOMT(false),
  71. mOffThreadToken(nullptr),
  72. mScriptTextBuf(nullptr),
  73. mScriptTextLength(0),
  74. mJSVersion(aVersion),
  75. mURI(aURI),
  76. mLineNo(1),
  77. mCORSMode(aCORSMode),
  78. mIntegrity(aIntegrity),
  79. mReferrer(aReferrer),
  80. mReferrerPolicy(aReferrerPolicy)
  81. {
  82. }
  83. NS_DECL_CYCLE_COLLECTING_ISUPPORTS
  84. NS_DECL_CYCLE_COLLECTION_CLASS(ScriptLoadRequest)
  85. bool IsModuleRequest() const
  86. {
  87. return mKind == ScriptKind::Module;
  88. }
  89. ModuleLoadRequest* AsModuleRequest();
  90. void FireScriptAvailable(nsresult aResult)
  91. {
  92. bool isInlineClassicScript = mIsInline && !IsModuleRequest();
  93. mElement->ScriptAvailable(aResult, mElement, isInlineClassicScript, mURI, mLineNo);
  94. }
  95. void FireScriptEvaluated(nsresult aResult)
  96. {
  97. mElement->ScriptEvaluated(aResult, mElement, mIsInline);
  98. }
  99. bool IsPreload()
  100. {
  101. return mElement == nullptr;
  102. }
  103. virtual void Cancel();
  104. bool IsCanceled() const
  105. {
  106. return mIsCanceled;
  107. }
  108. virtual void SetReady();
  109. void** OffThreadTokenPtr()
  110. {
  111. return mOffThreadToken ? &mOffThreadToken : nullptr;
  112. }
  113. enum class Progress {
  114. Loading,
  115. Compiling,
  116. FetchingImports,
  117. Ready
  118. };
  119. bool IsReadyToRun() const {
  120. return mProgress == Progress::Ready;
  121. }
  122. bool IsLoading() const {
  123. return mProgress == Progress::Loading;
  124. }
  125. bool InCompilingStage() const {
  126. return mProgress == Progress::Compiling ||
  127. (IsReadyToRun() && mWasCompiledOMT);
  128. }
  129. enum class ScriptMode : uint8_t {
  130. eBlocking,
  131. eDeferred,
  132. eAsync
  133. };
  134. void SetScriptMode(bool aDeferAttr, bool aAsyncAttr);
  135. bool IsBlockingScript() const
  136. {
  137. return mScriptMode == ScriptMode::eBlocking;
  138. }
  139. bool IsDeferredScript() const
  140. {
  141. return mScriptMode == ScriptMode::eDeferred;
  142. }
  143. bool IsAsyncScript() const
  144. {
  145. return mScriptMode == ScriptMode::eAsync;
  146. }
  147. virtual bool IsTopLevel() const
  148. {
  149. // Classic scripts are always top level.
  150. return true;
  151. }
  152. void MaybeCancelOffThreadScript();
  153. using super::getNext;
  154. using super::isInList;
  155. const ScriptKind mKind;
  156. nsCOMPtr<nsIScriptElement> mElement;
  157. Progress mProgress; // Are we still waiting for a load to complete?
  158. ScriptMode mScriptMode; // Whether this script is blocking, deferred or async.
  159. bool mIsInline; // Is the script inline or loaded?
  160. bool mHasSourceMapURL; // Does the HTTP header have a source map url?
  161. bool mInDeferList; // True if we live in mDeferRequests.
  162. bool mInAsyncList; // True if we live in mLoadingAsyncRequests or mLoadedAsyncRequests.
  163. bool mIsNonAsyncScriptInserted; // True if we live in mNonAsyncExternalScriptInsertedRequests
  164. bool mIsXSLT; // True if we live in mXSLTRequests.
  165. bool mIsCanceled; // True if we have been explicitly canceled.
  166. bool mWasCompiledOMT; // True if the script has been compiled off main thread.
  167. void* mOffThreadToken; // Off-thread parsing token.
  168. nsString mSourceMapURL; // Holds source map url for loaded scripts
  169. char16_t* mScriptTextBuf; // Holds script text for non-inline scripts. Don't
  170. size_t mScriptTextLength; // use nsString so we can give ownership to jsapi.
  171. uint32_t mJSVersion;
  172. const nsCOMPtr<nsIURI> mURI;
  173. nsCOMPtr<nsIPrincipal> mOriginPrincipal;
  174. nsAutoCString mURL; // Keep the URI's filename alive during off thread parsing.
  175. int32_t mLineNo;
  176. const mozilla::CORSMode mCORSMode;
  177. const SRIMetadata mIntegrity;
  178. const nsCOMPtr<nsIURI> mReferrer;
  179. const mozilla::net::ReferrerPolicy mReferrerPolicy;
  180. };
  181. class ScriptLoadRequestList : private mozilla::LinkedList<ScriptLoadRequest>
  182. {
  183. typedef mozilla::LinkedList<ScriptLoadRequest> super;
  184. public:
  185. ~ScriptLoadRequestList();
  186. void Clear();
  187. #ifdef DEBUG
  188. bool Contains(ScriptLoadRequest* aElem) const;
  189. #endif // DEBUG
  190. using super::getFirst;
  191. using super::isEmpty;
  192. void AppendElement(ScriptLoadRequest* aElem)
  193. {
  194. MOZ_ASSERT(!aElem->isInList());
  195. NS_ADDREF(aElem);
  196. insertBack(aElem);
  197. }
  198. MOZ_MUST_USE
  199. already_AddRefed<ScriptLoadRequest> Steal(ScriptLoadRequest* aElem)
  200. {
  201. aElem->removeFrom(*this);
  202. return dont_AddRef(aElem);
  203. }
  204. MOZ_MUST_USE
  205. already_AddRefed<ScriptLoadRequest> StealFirst()
  206. {
  207. MOZ_ASSERT(!isEmpty());
  208. return Steal(getFirst());
  209. }
  210. void Remove(ScriptLoadRequest* aElem)
  211. {
  212. aElem->removeFrom(*this);
  213. NS_RELEASE(aElem);
  214. }
  215. };
  216. class ScriptLoadHandler;
  217. //////////////////////////////////////////////////////////////
  218. // Script loader implementation
  219. //////////////////////////////////////////////////////////////
  220. class ScriptLoader final : public nsISupports
  221. {
  222. class MOZ_STACK_CLASS AutoCurrentScriptUpdater
  223. {
  224. public:
  225. AutoCurrentScriptUpdater(ScriptLoader* aScriptLoader,
  226. nsIScriptElement* aCurrentScript)
  227. : mOldScript(aScriptLoader->mCurrentScript)
  228. , mScriptLoader(aScriptLoader)
  229. {
  230. mScriptLoader->mCurrentScript = aCurrentScript;
  231. }
  232. ~AutoCurrentScriptUpdater()
  233. {
  234. mScriptLoader->mCurrentScript.swap(mOldScript);
  235. }
  236. private:
  237. nsCOMPtr<nsIScriptElement> mOldScript;
  238. ScriptLoader* mScriptLoader;
  239. };
  240. friend class ModuleLoadRequest;
  241. friend class ScriptRequestProcessor;
  242. friend class ScriptLoadHandler;
  243. friend class AutoCurrentScriptUpdater;
  244. public:
  245. explicit ScriptLoader(nsIDocument* aDocument);
  246. NS_DECL_CYCLE_COLLECTING_ISUPPORTS
  247. NS_DECL_CYCLE_COLLECTION_CLASS(ScriptLoader)
  248. /**
  249. * The loader maintains a weak reference to the document with
  250. * which it is initialized. This call forces the reference to
  251. * be dropped.
  252. */
  253. void DropDocumentReference()
  254. {
  255. mDocument = nullptr;
  256. }
  257. /**
  258. * Add an observer for all scripts loaded through this loader.
  259. *
  260. * @param aObserver observer for all script processing.
  261. */
  262. nsresult AddObserver(nsIScriptLoaderObserver* aObserver)
  263. {
  264. return mObservers.AppendObject(aObserver) ? NS_OK :
  265. NS_ERROR_OUT_OF_MEMORY;
  266. }
  267. /**
  268. * Remove an observer.
  269. *
  270. * @param aObserver observer to be removed
  271. */
  272. void RemoveObserver(nsIScriptLoaderObserver* aObserver)
  273. {
  274. mObservers.RemoveObject(aObserver);
  275. }
  276. /**
  277. * Process a script element. This will include both loading the
  278. * source of the element if it is not inline and evaluating
  279. * the script itself.
  280. *
  281. * If the script is an inline script that can be executed immediately
  282. * (i.e. there are no other scripts pending) then ScriptAvailable
  283. * and ScriptEvaluated will be called before the function returns.
  284. *
  285. * If true is returned the script could not be executed immediately.
  286. * In this case ScriptAvailable is guaranteed to be called at a later
  287. * point (as well as possibly ScriptEvaluated).
  288. *
  289. * @param aElement The element representing the script to be loaded and
  290. * evaluated.
  291. */
  292. bool ProcessScriptElement(nsIScriptElement* aElement);
  293. /**
  294. * Gets the currently executing script. This is useful if you want to
  295. * generate a unique key based on the currently executing script.
  296. */
  297. nsIScriptElement* GetCurrentScript()
  298. {
  299. return mCurrentScript;
  300. }
  301. nsIScriptElement* GetCurrentParserInsertedScript()
  302. {
  303. return mCurrentParserInsertedScript;
  304. }
  305. /**
  306. * Whether the loader is enabled or not.
  307. * When disabled, processing of new script elements is disabled.
  308. * Any call to ProcessScriptElement() will return false. Note that
  309. * this DOES NOT disable currently loading or executing scripts.
  310. */
  311. bool GetEnabled()
  312. {
  313. return mEnabled;
  314. }
  315. void SetEnabled(bool aEnabled)
  316. {
  317. if (!mEnabled && aEnabled) {
  318. ProcessPendingRequestsAsync();
  319. }
  320. mEnabled = aEnabled;
  321. }
  322. /**
  323. * Add/remove a blocker for parser-blocking scripts (and XSLT
  324. * scripts). Blockers will stop such scripts from executing, but not from
  325. * loading.
  326. */
  327. void AddParserBlockingScriptExecutionBlocker()
  328. {
  329. ++mParserBlockingBlockerCount;
  330. }
  331. void RemoveParserBlockingScriptExecutionBlocker()
  332. {
  333. if (!--mParserBlockingBlockerCount && ReadyToExecuteScripts()) {
  334. ProcessPendingRequestsAsync();
  335. }
  336. }
  337. /**
  338. * Add/remove a blocker for execution of all scripts. Blockers will stop
  339. * scripts from executing, but not from loading.
  340. */
  341. void AddExecuteBlocker()
  342. {
  343. ++mBlockerCount;
  344. }
  345. void RemoveExecuteBlocker()
  346. {
  347. MOZ_ASSERT(mBlockerCount);
  348. if (!--mBlockerCount) {
  349. ProcessPendingRequestsAsync();
  350. }
  351. }
  352. /**
  353. * Convert the given buffer to a UTF-16 string.
  354. * @param aChannel Channel corresponding to the data. May be null.
  355. * @param aData The data to convert
  356. * @param aLength Length of the data
  357. * @param aHintCharset Hint for the character set (e.g., from a charset
  358. * attribute). May be the empty string.
  359. * @param aDocument Document which the data is loaded for. Must not be
  360. * null.
  361. * @param aBufOut [out] char16_t array allocated by ConvertToUTF16 and
  362. * containing data converted to unicode. Caller must
  363. * js_free() this data when no longer needed.
  364. * @param aLengthOut [out] Length of array returned in aBufOut in number
  365. * of char16_t code units.
  366. */
  367. static nsresult ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData,
  368. uint32_t aLength,
  369. const nsAString& aHintCharset,
  370. nsIDocument* aDocument,
  371. char16_t*& aBufOut, size_t& aLengthOut);
  372. /**
  373. * Handle the completion of a stream. This is called by the
  374. * ScriptLoadHandler object which observes the IncrementalStreamLoader
  375. * loading the script.
  376. */
  377. nsresult OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
  378. nsISupports* aContext,
  379. nsresult aChannelStatus,
  380. nsresult aSRIStatus,
  381. mozilla::Vector<char16_t> &aString,
  382. mozilla::dom::SRICheckDataVerifier* aSRIDataVerifier);
  383. /**
  384. * Processes any pending requests that are ready for processing.
  385. */
  386. void ProcessPendingRequests();
  387. /**
  388. * Starts deferring deferred scripts and puts them in the mDeferredRequests
  389. * queue instead.
  390. */
  391. void BeginDeferringScripts()
  392. {
  393. mDeferEnabled = true;
  394. if (mDocument) {
  395. mDocument->BlockOnload();
  396. }
  397. }
  398. /**
  399. * Notifies the script loader that parsing is done. If aTerminated is true,
  400. * this will drop any pending scripts that haven't run yet. Otherwise, it
  401. * will stops deferring scripts and immediately processes the
  402. * mDeferredRequests queue.
  403. *
  404. * WARNING: This function will synchronously execute content scripts, so be
  405. * prepared that the world might change around you.
  406. */
  407. void ParsingComplete(bool aTerminated);
  408. /**
  409. * Returns the number of pending scripts, deferred or not.
  410. */
  411. uint32_t HasPendingOrCurrentScripts()
  412. {
  413. return mCurrentScript || mParserBlockingRequest;
  414. }
  415. /**
  416. * Adds aURI to the preload list and starts loading it.
  417. *
  418. * @param aURI The URI of the external script.
  419. * @param aCharset The charset parameter for the script.
  420. * @param aType The type parameter for the script.
  421. * @param aCrossOrigin The crossorigin attribute for the script.
  422. * Void if not present.
  423. * @param aIntegrity The expect hash url, if avail, of the request
  424. * @param aScriptFromHead Whether or not the script was a child of head
  425. */
  426. virtual void PreloadURI(nsIURI *aURI,
  427. const nsAString &aCharset,
  428. const nsAString &aType,
  429. const nsAString &aCrossOrigin,
  430. const nsAString& aIntegrity,
  431. bool aScriptFromHead,
  432. bool aAsync,
  433. bool aDefer,
  434. bool aNoModule,
  435. const mozilla::net::ReferrerPolicy aReferrerPolicy);
  436. /**
  437. * Process a request that was deferred so that the script could be compiled
  438. * off thread.
  439. */
  440. nsresult ProcessOffThreadRequest(ScriptLoadRequest *aRequest);
  441. bool AddPendingChildLoader(ScriptLoader* aChild) {
  442. return mPendingChildLoaders.AppendElement(aChild) != nullptr;
  443. }
  444. /*
  445. * Clear the map of loaded modules. Called when a Document object is reused
  446. * for a different global.
  447. */
  448. void ClearModuleMap();
  449. private:
  450. virtual ~ScriptLoader();
  451. ScriptLoadRequest* CreateLoadRequest(ScriptKind aKind,
  452. nsIURI* aURI,
  453. nsIScriptElement* aElement,
  454. uint32_t aVersion,
  455. mozilla::CORSMode aCORSMode,
  456. const SRIMetadata& aIntegrity,
  457. mozilla::net::ReferrerPolicy aReferrerPolicy);
  458. /**
  459. * Unblocks the creator parser of the parser-blocking scripts.
  460. */
  461. void UnblockParser(ScriptLoadRequest* aParserBlockingRequest);
  462. /**
  463. * Asynchronously resumes the creator parser of the parser-blocking scripts.
  464. */
  465. void ContinueParserAsync(ScriptLoadRequest* aParserBlockingRequest);
  466. /**
  467. * Helper function to check the content policy for a given request.
  468. */
  469. static nsresult CheckContentPolicy(nsIDocument* aDocument,
  470. nsISupports *aContext,
  471. nsIURI *aURI,
  472. const nsAString &aType,
  473. bool aIsPreLoad);
  474. /**
  475. * Start a load for aRequest's URI.
  476. */
  477. nsresult StartLoad(ScriptLoadRequest *aRequest, const nsAString &aType,
  478. bool aScriptFromHead);
  479. void HandleLoadError(ScriptLoadRequest *aRequest, nsresult aResult);
  480. /**
  481. * Process any pending requests asynchronously (i.e. off an event) if there
  482. * are any. Note that this is a no-op if there aren't any currently pending
  483. * requests.
  484. *
  485. * This function is virtual to allow cross-library calls to SetEnabled()
  486. */
  487. virtual void ProcessPendingRequestsAsync();
  488. /**
  489. * If true, the loader is ready to execute parser-blocking scripts, and so are
  490. * all its ancestors. If the loader itself is ready but some ancestor is not,
  491. * this function will add an execute blocker and ask the ancestor to remove it
  492. * once it becomes ready.
  493. */
  494. bool ReadyToExecuteParserBlockingScripts();
  495. /**
  496. * Return whether just this loader is ready to execute parser-blocking
  497. * scripts.
  498. */
  499. bool SelfReadyToExecuteParserBlockingScripts()
  500. {
  501. return ReadyToExecuteScripts() && !mParserBlockingBlockerCount;
  502. }
  503. /**
  504. * Return whether this loader is ready to execute scripts in general.
  505. */
  506. bool ReadyToExecuteScripts()
  507. {
  508. return mEnabled && !mBlockerCount;
  509. }
  510. nsresult VerifySRI(ScriptLoadRequest *aRequest,
  511. nsIIncrementalStreamLoader* aLoader,
  512. nsresult aSRIStatus,
  513. SRICheckDataVerifier* aSRIDataVerifier) const;
  514. nsresult AttemptAsyncScriptCompile(ScriptLoadRequest* aRequest);
  515. nsresult ProcessRequest(ScriptLoadRequest* aRequest);
  516. nsresult CompileOffThreadOrProcessRequest(ScriptLoadRequest* aRequest);
  517. void FireScriptAvailable(nsresult aResult,
  518. ScriptLoadRequest* aRequest);
  519. void FireScriptEvaluated(nsresult aResult,
  520. ScriptLoadRequest* aRequest);
  521. nsresult EvaluateScript(ScriptLoadRequest* aRequest);
  522. already_AddRefed<nsIScriptGlobalObject> GetScriptGlobalObject();
  523. nsresult FillCompileOptionsForRequest(const mozilla::dom::AutoJSAPI& jsapi,
  524. ScriptLoadRequest* aRequest,
  525. JS::Handle<JSObject*> aScopeChain,
  526. JS::CompileOptions* aOptions);
  527. uint32_t NumberOfProcessors();
  528. nsresult PrepareLoadedRequest(ScriptLoadRequest* aRequest,
  529. nsIIncrementalStreamLoader* aLoader,
  530. nsresult aStatus,
  531. mozilla::Vector<char16_t> &aString);
  532. void AddDeferRequest(ScriptLoadRequest* aRequest);
  533. void AddAsyncRequest(ScriptLoadRequest* aRequest);
  534. bool MaybeRemovedDeferRequests();
  535. void MaybeMoveToLoadedList(ScriptLoadRequest* aRequest);
  536. JS::SourceBufferHolder GetScriptSource(ScriptLoadRequest* aRequest,
  537. nsAutoString& inlineData);
  538. void SetModuleFetchStarted(ModuleLoadRequest *aRequest);
  539. void SetModuleFetchFinishedAndResumeWaitingRequests(ModuleLoadRequest *aRequest,
  540. nsresult aResult);
  541. bool IsFetchingModule(ModuleLoadRequest *aRequest) const;
  542. bool ModuleMapContainsURL(nsIURI* aURL) const;
  543. RefPtr<mozilla::GenericPromise> WaitForModuleFetch(nsIURI* aURL);
  544. ModuleScript* GetFetchedModule(nsIURI* aURL) const;
  545. friend JSObject*
  546. HostResolveImportedModule(JSContext* aCx, JS::Handle<JSObject*> aModule,
  547. JS::Handle<JSString*> aSpecifier);
  548. nsresult CreateModuleScript(ModuleLoadRequest* aRequest);
  549. nsresult ProcessFetchedModuleSource(ModuleLoadRequest* aRequest);
  550. void CheckModuleDependenciesLoaded(ModuleLoadRequest* aRequest);
  551. void ProcessLoadedModuleTree(ModuleLoadRequest* aRequest);
  552. JS::Value FindFirstParseError(ModuleLoadRequest* aRequest);
  553. bool InstantiateModuleTree(ModuleLoadRequest* aRequest);
  554. void StartFetchingModuleDependencies(ModuleLoadRequest* aRequest);
  555. RefPtr<mozilla::GenericPromise>
  556. StartFetchingModuleAndDependencies(ModuleLoadRequest* aParent, nsIURI* aURI);
  557. nsIDocument* mDocument; // [WEAK]
  558. nsCOMArray<nsIScriptLoaderObserver> mObservers;
  559. ScriptLoadRequestList mNonAsyncExternalScriptInsertedRequests;
  560. // mLoadingAsyncRequests holds async requests while they're loading; when they
  561. // have been loaded they are moved to mLoadedAsyncRequests.
  562. ScriptLoadRequestList mLoadingAsyncRequests;
  563. ScriptLoadRequestList mLoadedAsyncRequests;
  564. ScriptLoadRequestList mDeferRequests;
  565. ScriptLoadRequestList mXSLTRequests;
  566. RefPtr<ScriptLoadRequest> mParserBlockingRequest;
  567. // In mRequests, the additional information here is stored by the element.
  568. struct PreloadInfo {
  569. RefPtr<ScriptLoadRequest> mRequest;
  570. nsString mCharset;
  571. };
  572. friend void ImplCycleCollectionUnlink(ScriptLoader::PreloadInfo& aField);
  573. friend void ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
  574. ScriptLoader::PreloadInfo& aField,
  575. const char* aName, uint32_t aFlags);
  576. struct PreloadRequestComparator {
  577. bool Equals(const PreloadInfo &aPi, ScriptLoadRequest * const &aRequest)
  578. const
  579. {
  580. return aRequest == aPi.mRequest;
  581. }
  582. };
  583. struct PreloadURIComparator {
  584. bool Equals(const PreloadInfo &aPi, nsIURI * const &aURI) const;
  585. };
  586. nsTArray<PreloadInfo> mPreloads;
  587. nsCOMPtr<nsIScriptElement> mCurrentScript;
  588. nsCOMPtr<nsIScriptElement> mCurrentParserInsertedScript;
  589. nsTArray< RefPtr<ScriptLoader> > mPendingChildLoaders;
  590. uint32_t mParserBlockingBlockerCount;
  591. uint32_t mBlockerCount;
  592. uint32_t mNumberOfProcessors;
  593. bool mEnabled;
  594. bool mDeferEnabled;
  595. bool mDocumentParsingDone;
  596. bool mBlockingDOMContentLoaded;
  597. // Module map
  598. nsRefPtrHashtable<nsURIHashKey, mozilla::GenericPromise::Private> mFetchingModules;
  599. nsRefPtrHashtable<nsURIHashKey, ModuleScript> mFetchedModules;
  600. nsCOMPtr<nsIConsoleReportCollector> mReporter;
  601. };
  602. class nsAutoScriptLoaderDisabler
  603. {
  604. public:
  605. explicit nsAutoScriptLoaderDisabler(nsIDocument* aDoc)
  606. {
  607. mLoader = aDoc->ScriptLoader();
  608. mWasEnabled = mLoader->GetEnabled();
  609. if (mWasEnabled) {
  610. mLoader->SetEnabled(false);
  611. }
  612. }
  613. ~nsAutoScriptLoaderDisabler()
  614. {
  615. if (mWasEnabled) {
  616. mLoader->SetEnabled(true);
  617. }
  618. }
  619. bool mWasEnabled;
  620. RefPtr<ScriptLoader> mLoader;
  621. };
  622. } // namespace dom
  623. } // namespace mozilla
  624. #endif //mozilla_dom_ScriptLoader_h