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