Bug 1852740: add tests for the `fetchpriority` attribute in Link headers. r=necko...
[gecko.git] / dom / prototype / PrototypeDocumentContentSink.h
blobbdfc1f114c902cccebdcb4443c71c2141236700d
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 https://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_dom_PrototypeDocumentContentSink_h__
8 #define mozilla_dom_PrototypeDocumentContentSink_h__
10 #include "mozilla/Attributes.h"
11 #include "nsIContentSink.h"
12 #include "nsTArray.h"
13 #include "nsCOMPtr.h"
14 #include "nsCRT.h"
15 #include "nsCycleCollectionNoteChild.h"
16 #include "nsCycleCollectionParticipant.h"
17 #include "nsIDTD.h"
18 #include "mozilla/dom/FromParser.h"
19 #include "nsXULPrototypeDocument.h"
20 #include "nsIStreamLoader.h"
21 #include "nsIScriptContext.h"
22 #include "nsICSSLoaderObserver.h"
23 #include "mozilla/Logging.h"
24 #include "js/experimental/JSStencil.h"
25 #include "mozilla/RefPtr.h"
27 class nsIURI;
28 class nsIChannel;
29 class nsIContent;
30 class nsIParser;
31 class nsTextNode;
32 class nsINode;
33 class nsXULPrototypeElement;
34 class nsXULPrototypePI;
35 class nsXULPrototypeScript;
37 namespace mozilla::dom {
38 class Element;
39 class ScriptLoader;
40 class Document;
41 class XMLStylesheetProcessingInstruction;
42 } // namespace mozilla::dom
44 nsresult NS_NewPrototypeDocumentContentSink(nsIContentSink** aResult,
45 mozilla::dom::Document* aDoc,
46 nsIURI* aURI,
47 nsISupports* aContainer,
48 nsIChannel* aChannel);
50 namespace mozilla::dom {
52 class PrototypeDocumentContentSink final : public nsIStreamLoaderObserver,
53 public nsIContentSink,
54 public nsICSSLoaderObserver,
55 public nsIOffThreadScriptReceiver {
56 public:
57 PrototypeDocumentContentSink();
59 nsresult Init(Document* aDoc, nsIURI* aURL, nsISupports* aContainer,
60 nsIChannel* aChannel);
62 // nsISupports
63 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
64 NS_DECL_NSISTREAMLOADEROBSERVER
66 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(PrototypeDocumentContentSink,
67 nsIContentSink)
69 // nsIContentSink
70 NS_IMETHOD WillParse(void) override { return NS_OK; };
71 NS_IMETHOD WillInterrupt(void) override { return NS_OK; };
72 void WillResume() override{};
73 NS_IMETHOD SetParser(nsParserBase* aParser) override;
74 virtual void InitialTranslationCompleted() override;
75 virtual void FlushPendingNotifications(FlushType aType) override{};
76 virtual void SetDocumentCharset(NotNull<const Encoding*> aEncoding) override;
77 virtual nsISupports* GetTarget() override;
78 virtual bool IsScriptExecuting() override;
79 virtual void ContinueInterruptedParsingAsync() override;
81 // nsICSSLoaderObserver
82 NS_IMETHOD StyleSheetLoaded(StyleSheet* aSheet, bool aWasDeferred,
83 nsresult aStatus) override;
85 // nsIOffThreadScriptReceiver
86 NS_IMETHOD OnScriptCompileComplete(JS::Stencil* aStencil,
87 nsresult aStatus) override;
89 nsresult OnPrototypeLoadDone(nsXULPrototypeDocument* aPrototype);
91 protected:
92 virtual ~PrototypeDocumentContentSink();
94 static LazyLogModule gLog;
96 nsIParser* GetParser();
98 void ContinueInterruptedParsingIfEnabled();
99 void StartLayout();
101 virtual nsresult AddAttributes(nsXULPrototypeElement* aPrototype,
102 Element* aElement);
104 RefPtr<nsParserBase> mParser;
105 nsCOMPtr<nsIURI> mDocumentURI;
106 RefPtr<Document> mDocument;
107 RefPtr<ScriptLoader> mScriptLoader;
109 PrototypeDocumentContentSink* mNextSrcLoadWaiter; // [OWNER] but not COMPtr
112 * The prototype-script of the current transcluded script that is being
113 * loaded. For document.write('<script src="nestedwrite.js"><\/script>')
114 * to work, these need to be in a stack element type, and we need to hold
115 * the top of stack here.
117 nsXULPrototypeScript* mCurrentScriptProto;
120 * Whether the current transcluded script is being compiled off thread.
121 * The load event is blocked while this is in progress.
123 bool mOffThreadCompiling;
126 * Wether the prototype document is still be traversed to create the DOM.
127 * Layout will not be started until false.
129 bool mStillWalking;
132 * Number of style sheets still loading. Layout will not start until zero.
134 uint32_t mPendingSheets;
137 * Context stack, which maintains the state of the Builder and allows
138 * it to be interrupted.
140 class ContextStack {
141 protected:
142 struct Entry {
143 nsXULPrototypeElement* mPrototype;
144 nsIContent* mElement;
145 int32_t mIndex;
146 Entry* mNext;
149 Entry* mTop;
150 int32_t mDepth;
152 public:
153 ContextStack();
154 ~ContextStack();
156 int32_t Depth() { return mDepth; }
158 nsresult Push(nsXULPrototypeElement* aPrototype, nsIContent* aElement);
159 nsresult Pop();
160 nsresult Peek(nsXULPrototypeElement** aPrototype, nsIContent** aElement,
161 int32_t* aIndex);
163 nsresult SetTopIndex(int32_t aIndex);
165 void Traverse(nsCycleCollectionTraversalCallback& aCallback,
166 const char* aName, uint32_t aFlags = 0);
167 void Clear();
169 // Cycle collector helpers for ContextStack.
170 friend void ImplCycleCollectionUnlink(
171 PrototypeDocumentContentSink::ContextStack& aField) {
172 aField.Clear();
175 friend void ImplCycleCollectionTraverse(
176 nsCycleCollectionTraversalCallback& aCallback,
177 PrototypeDocumentContentSink::ContextStack& aField, const char* aName,
178 uint32_t aFlags = 0) {
179 aField.Traverse(aCallback, aName, aFlags);
183 friend class ContextStack;
184 ContextStack mContextStack;
187 * The current prototype that we are walking to construct the
188 * content model.
190 RefPtr<nsXULPrototypeDocument> mCurrentPrototype;
191 nsresult CreateAndInsertPI(const nsXULPrototypePI* aProtoPI);
192 nsresult ExecuteScript(nsXULPrototypeScript* aScript);
193 nsresult LoadScript(nsXULPrototypeScript* aScriptProto, bool* aBlock);
196 * A wrapper around ResumeWalkInternal to report walking errors.
198 nsresult ResumeWalk();
201 * Resume (or initiate) an interrupted (or newly prepared)
202 * prototype walk.
204 nsresult ResumeWalkInternal();
207 * Called at the end of ResumeWalk(), from StyleSheetLoaded(),
208 * and from DocumentL10n.
209 * If walking, stylesheets and l10n are not blocking, it
210 * will trigger `DoneWalking()`.
212 nsresult MaybeDoneWalking();
215 * Called from `MaybeDoneWalking()`.
216 * Expects that both the prototype document walk is complete and
217 * all referenced stylesheets finished loading.
219 nsresult DoneWalking();
222 * Create a delegate content model element from a prototype.
223 * Note that the resulting content node is not bound to any tree
225 nsresult CreateElementFromPrototype(nsXULPrototypeElement* aPrototype,
226 Element** aResult, nsIContent* aParent);
228 * Prepare to walk the current prototype.
230 nsresult PrepareToWalk();
232 * Creates a processing instruction based on aProtoPI and inserts
233 * it to the DOM.
235 nsresult CreateAndInsertPI(const nsXULPrototypePI* aProtoPI, nsINode* aParent,
236 nsINode* aBeforeThis);
239 * Inserts the passed <?xml-stylesheet ?> PI at the specified
240 * index. Loads and applies the associated stylesheet
241 * asynchronously.
242 * The prototype document walk can happen before the stylesheets
243 * are loaded, but the final steps in the load process (see
244 * DoneWalking()) are not run before all the stylesheets are done
245 * loading.
247 nsresult InsertXMLStylesheetPI(const nsXULPrototypePI* aProtoPI,
248 nsINode* aParent, nsINode* aBeforeThis,
249 XMLStylesheetProcessingInstruction* aPINode);
250 void CloseElement(Element* aElement, bool aHadChildren);
253 } // namespace mozilla::dom
255 #endif // mozilla_dom_PrototypeDocumentContentSink_h__