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"
15 #include "nsCycleCollectionNoteChild.h"
16 #include "nsCycleCollectionParticipant.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"
33 class nsXULPrototypeElement
;
34 class nsXULPrototypePI
;
35 class nsXULPrototypeScript
;
37 namespace mozilla::dom
{
41 class XMLStylesheetProcessingInstruction
;
42 } // namespace mozilla::dom
44 nsresult
NS_NewPrototypeDocumentContentSink(nsIContentSink
** aResult
,
45 mozilla::dom::Document
* aDoc
,
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
{
57 PrototypeDocumentContentSink();
59 nsresult
Init(Document
* aDoc
, nsIURI
* aURL
, nsISupports
* aContainer
,
60 nsIChannel
* aChannel
);
63 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
64 NS_DECL_NSISTREAMLOADEROBSERVER
66 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(PrototypeDocumentContentSink
,
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
);
92 virtual ~PrototypeDocumentContentSink();
94 static LazyLogModule gLog
;
96 nsIParser
* GetParser();
98 void ContinueInterruptedParsingIfEnabled();
101 virtual nsresult
AddAttributes(nsXULPrototypeElement
* aPrototype
,
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.
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.
143 nsXULPrototypeElement
* mPrototype
;
144 nsIContent
* mElement
;
156 int32_t Depth() { return mDepth
; }
158 nsresult
Push(nsXULPrototypeElement
* aPrototype
, nsIContent
* aElement
);
160 nsresult
Peek(nsXULPrototypeElement
** aPrototype
, nsIContent
** aElement
,
163 nsresult
SetTopIndex(int32_t aIndex
);
165 void Traverse(nsCycleCollectionTraversalCallback
& aCallback
,
166 const char* aName
, uint32_t aFlags
= 0);
169 // Cycle collector helpers for ContextStack.
170 friend void ImplCycleCollectionUnlink(
171 PrototypeDocumentContentSink::ContextStack
& aField
) {
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
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)
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
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
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
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__