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 * If the current transcluded script is being compiled off thread, the
127 * source for that script.
129 Utf8Unit
* mOffThreadCompileStringBuf
;
130 size_t mOffThreadCompileStringLength
;
133 * Wether the prototype document is still be traversed to create the DOM.
134 * Layout will not be started until false.
139 * Number of style sheets still loading. Layout will not start until zero.
141 uint32_t mPendingSheets
;
144 * Context stack, which maintains the state of the Builder and allows
145 * it to be interrupted.
150 nsXULPrototypeElement
* mPrototype
;
151 nsIContent
* mElement
;
163 int32_t Depth() { return mDepth
; }
165 nsresult
Push(nsXULPrototypeElement
* aPrototype
, nsIContent
* aElement
);
167 nsresult
Peek(nsXULPrototypeElement
** aPrototype
, nsIContent
** aElement
,
170 nsresult
SetTopIndex(int32_t aIndex
);
172 void Traverse(nsCycleCollectionTraversalCallback
& aCallback
,
173 const char* aName
, uint32_t aFlags
= 0);
176 // Cycle collector helpers for ContextStack.
177 friend void ImplCycleCollectionUnlink(
178 PrototypeDocumentContentSink::ContextStack
& aField
) {
182 friend void ImplCycleCollectionTraverse(
183 nsCycleCollectionTraversalCallback
& aCallback
,
184 PrototypeDocumentContentSink::ContextStack
& aField
, const char* aName
,
185 uint32_t aFlags
= 0) {
186 aField
.Traverse(aCallback
, aName
, aFlags
);
190 friend class ContextStack
;
191 ContextStack mContextStack
;
194 * The current prototype that we are walking to construct the
197 RefPtr
<nsXULPrototypeDocument
> mCurrentPrototype
;
198 nsresult
CreateAndInsertPI(const nsXULPrototypePI
* aProtoPI
);
199 nsresult
ExecuteScript(nsXULPrototypeScript
* aScript
);
200 nsresult
LoadScript(nsXULPrototypeScript
* aScriptProto
, bool* aBlock
);
203 * A wrapper around ResumeWalkInternal to report walking errors.
205 nsresult
ResumeWalk();
208 * Resume (or initiate) an interrupted (or newly prepared)
211 nsresult
ResumeWalkInternal();
214 * Called at the end of ResumeWalk(), from StyleSheetLoaded(),
215 * and from DocumentL10n.
216 * If walking, stylesheets and l10n are not blocking, it
217 * will trigger `DoneWalking()`.
219 nsresult
MaybeDoneWalking();
222 * Called from `MaybeDoneWalking()`.
223 * Expects that both the prototype document walk is complete and
224 * all referenced stylesheets finished loading.
226 nsresult
DoneWalking();
229 * Create a delegate content model element from a prototype.
230 * Note that the resulting content node is not bound to any tree
232 nsresult
CreateElementFromPrototype(nsXULPrototypeElement
* aPrototype
,
233 Element
** aResult
, nsIContent
* aParent
);
235 * Prepare to walk the current prototype.
237 nsresult
PrepareToWalk();
239 * Creates a processing instruction based on aProtoPI and inserts
242 nsresult
CreateAndInsertPI(const nsXULPrototypePI
* aProtoPI
, nsINode
* aParent
,
243 nsINode
* aBeforeThis
);
246 * Inserts the passed <?xml-stylesheet ?> PI at the specified
247 * index. Loads and applies the associated stylesheet
249 * The prototype document walk can happen before the stylesheets
250 * are loaded, but the final steps in the load process (see
251 * DoneWalking()) are not run before all the stylesheets are done
254 nsresult
InsertXMLStylesheetPI(const nsXULPrototypePI
* aProtoPI
,
255 nsINode
* aParent
, nsINode
* aBeforeThis
,
256 XMLStylesheetProcessingInstruction
* aPINode
);
257 void CloseElement(Element
* aElement
, bool aHadChildren
);
260 } // namespace mozilla::dom
262 #endif // mozilla_dom_PrototypeDocumentContentSink_h__