1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #define NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH 512
7 using Encoding
= mozilla::Encoding
;
9 using NotNull
= mozilla::NotNull
<T
>;
11 nsHtml5OplessBuilder
* mBuilder
;
12 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
13 // If mBuilder is not null, the tree op machinery is not in use and
14 // the fields below aren't in use, either.
15 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
16 nsHtml5Highlighter
* mViewSource
;
17 mozilla::ImportScanner mImportScanner
;
18 nsTArray
<nsHtml5TreeOperation
> mOpQueue
;
19 nsTArray
<nsHtml5SpeculativeLoad
> mSpeculativeLoadQueue
;
20 nsAHtml5TreeOpSink
* mOpSink
;
21 mozilla::UniquePtr
<nsIContent
*[]> mHandles
;
23 nsTArray
<mozilla::UniquePtr
<nsIContent
*[]>> mOldHandles
;
24 nsHtml5TreeOpStage
* mSpeculativeLoadStage
;
26 // Controls whether the current HTML script goes through the more complex
27 // path that accommodates the possibility of the script becoming a
28 // parser-blocking script and the possibility of the script inserting
29 // content into this parse using document.write (as it is observable from
32 // Notably, in some cases scripts that do NOT NEED the more complex path
33 // BREAK the parse if they incorrectly go onto the complex path as their
34 // other handling doesn't necessarily take care of the responsibilities
35 // associated with the more complex path. See comments in
36 // `nsHtml5TreeBuilder::createElement` in the CppSupplement for details.
37 bool mCurrentHtmlScriptCannotDocumentWriteOrBlock
;
38 bool mPreventScriptExecution
;
40 * Whether to actually generate speculative load operations that actually
41 * represent speculative loads as opposed to other operations traveling
42 * in the same queue. True for normal loads and false for XHR, plain text,
43 * and View Source. Needed, because we can't just null-check
44 * mSpeculativeLoadStage, since it is used for transferring encoding
45 * information even in the XHR/plain text/View Source cases.
47 bool mGenerateSpeculativeLoads
;
49 bool mHasSeenImportMap
;
54 // DocumentModeHandler
56 * Tree builder uses this to report quirkiness of the document
58 void documentMode(nsHtml5DocumentMode m
);
60 nsIContentHandle
* getDocumentFragmentForTemplate(nsIContentHandle
* aTemplate
);
61 void setDocumentFragmentForTemplate(nsIContentHandle
* aTemplate
,
62 nsIContentHandle
* aFragment
);
64 nsIContentHandle
* getShadowRootFromHost(nsIContentHandle
* aHost
,
65 nsIContentHandle
* aTemplateNode
,
66 nsHtml5String aShadowRootMode
,
67 bool aShadowRootIsClonable
,
68 bool aShadowRootDelegatesFocus
);
70 nsIContentHandle
* getFormPointerForContext(nsIContentHandle
* aContext
);
73 * Using nsIContent** instead of nsIContent* is the parser deals with DOM
74 * nodes in a way that works off the main thread. Non-main-thread code
75 * can't refcount or otherwise touch nsIContent objects in any way.
76 * Yet, the off-the-main-thread code needs to have a way to hold onto a
77 * particular node and repeatedly operate on the same node.
79 * The way this works is that the off-the-main-thread code has an
80 * nsIContent** for each DOM node and a given nsIContent** is only ever
81 * actually dereferenced into an actual nsIContent* on the main thread.
82 * When the off-the-main-thread code requests a new node, it gets an
83 * nsIContent** immediately and a tree op is enqueued for later allocating
84 * an actual nsIContent object and writing a pointer to it into the memory
85 * location pointed to by the nsIContent**.
87 * Since tree ops are in a queue, the node creating tree op will always
88 * run before tree ops that try to further operate on the node that the
89 * nsIContent** is a handle to.
91 * On-the-main-thread parts of the parser use nsIContent* instead of
92 * nsIContent**. Since both cases share the same parser core, the parser
93 * core casts both to nsIContentHandle*.
95 nsIContentHandle
* AllocateContentHandle();
97 void accumulateCharactersForced(const char16_t
* aBuf
, int32_t aStart
,
99 accumulateCharacters(aBuf
, aStart
, aLength
);
102 void MarkAsBrokenAndRequestSuspensionWithBuilder(nsresult aRv
) {
103 mBuilder
->MarkAsBroken(aRv
);
107 void MarkAsBrokenAndRequestSuspensionWithoutBuilder(nsresult aRv
) {
112 void MarkAsBrokenFromPortability(nsresult aRv
);
115 explicit nsHtml5TreeBuilder(nsHtml5OplessBuilder
* aBuilder
);
117 nsHtml5TreeBuilder(nsAHtml5TreeOpSink
* aOpSink
, nsHtml5TreeOpStage
* aStage
,
118 bool aGenerateSpeculativeLoads
);
120 ~nsHtml5TreeBuilder();
122 bool WantsLineAndColumn() {
123 // Perhaps just checking mBuilder would be sufficient.
124 // For createContextualFragment, we have non-null mBuilder and
125 // false for mPreventScriptExecution. However, do the line and
126 // column that get attached to script elements make any sense
127 // anyway in that case?
128 return !(mBuilder
&& mPreventScriptExecution
);
131 void StartPlainTextViewSource(const nsAutoString
& aTitle
);
133 void StartPlainText();
135 void StartPlainTextBody();
137 bool HasScriptThatMayDocumentWriteOrBlock();
139 void SetOpSink(nsAHtml5TreeOpSink
* aOpSink
) { mOpSink
= aOpSink
; }
141 void ClearOps() { mOpQueue
.Clear(); }
145 * @return Ok(true) if there were ops to flush, Ok(false)
146 * if there were no ops to flush and Err() on OOM.
148 mozilla::Result
<bool, nsresult
> Flush(bool aDiscretionary
= false);
153 * Sets the document charset via the speculation queue.
155 * @param aCommitEncodingSpeculation true iff the main thread should
156 * treat the first speculation as an
157 * encoding speculation.
159 void SetDocumentCharset(NotNull
<const Encoding
*> aEncoding
,
160 nsCharsetSource aCharsetSource
,
161 bool aCommitEncodingSpeculation
);
164 * Updates the charset source via the op queue.
166 void UpdateCharsetSource(nsCharsetSource aCharsetSource
);
170 void NeedsCharsetSwitchTo(NotNull
<const Encoding
*> aEncoding
, int32_t aSource
,
171 int32_t aLineNumber
);
173 void MaybeComplainAboutCharset(const char* aMsgId
, bool aError
,
174 int32_t aLineNumber
);
176 void TryToEnableEncodingMenu();
178 void AddSnapshotToScript(nsAHtml5TreeBuilderState
* aSnapshot
, int32_t aLine
);
182 void SetPreventScriptExecution(bool aPrevent
) {
183 mPreventScriptExecution
= aPrevent
;
186 bool HasBuilder() { return mBuilder
; }
189 * Makes sure the buffers are large enough to be able to tokenize aLength
190 * UTF-16 code units before having to make the buffers larger.
192 * @param aLength the number of UTF-16 code units to be tokenized before the
193 * next call to this method.
194 * @return true if successful; false if out of memory
196 bool EnsureBufferSpace(int32_t aLength
);
198 void EnableViewSource(nsHtml5Highlighter
* aHighlighter
);
202 void errStrayStartTag(nsAtom
* aName
);
204 void errStrayEndTag(nsAtom
* aName
);
206 void errUnclosedElements(int32_t aIndex
, nsAtom
* aName
);
208 void errUnclosedElementsImplied(int32_t aIndex
, nsAtom
* aName
);
210 void errUnclosedElementsCell(int32_t aIndex
);
212 void errStrayDoctype();
214 void errAlmostStandardsDoctype();
216 void errQuirkyDoctype();
218 void errNonSpaceInTrailer();
220 void errNonSpaceAfterFrameset();
222 void errNonSpaceInFrameset();
224 void errNonSpaceAfterBody();
226 void errNonSpaceInColgroupInFragment();
228 void errNonSpaceInNoscriptInHead();
230 void errFooBetweenHeadAndBody(nsAtom
* aName
);
232 void errStartTagWithoutDoctype();
234 void errNoSelectInTableScope();
236 void errStartSelectWhereEndSelectExpected();
238 void errStartTagWithSelectOpen(nsAtom
* aName
);
240 void errBadStartTagInNoscriptInHead(nsAtom
* aName
);
246 void errFooSeenWhenFooOpen(nsAtom
* aName
);
248 void errHeadingWhenHeadingOpen();
250 void errFramesetStart();
252 void errNoCellToClose();
254 void errStartTagInTable(nsAtom
* aName
);
256 void errFormWhenFormOpen();
258 void errTableSeenWhileTableOpen();
260 void errStartTagInTableBody(nsAtom
* aName
);
262 void errEndTagSeenWithoutDoctype();
264 void errEndTagAfterBody();
266 void errEndTagSeenWithSelectOpen(nsAtom
* aName
);
268 void errGarbageInColgroup();
272 void errNoElementToCloseButEndTagSeen(nsAtom
* aName
);
274 void errHtmlStartTagInForeignContext(nsAtom
* aName
);
276 void errNoTableRowToClose();
278 void errNonSpaceInTable();
280 void errUnclosedChildrenInRuby();
282 void errStartTagSeenWithoutRuby(nsAtom
* aName
);
284 void errSelfClosing();
286 void errNoCheckUnclosedElementsOnStack();
288 void errEndTagDidNotMatchCurrentOpenElement(nsAtom
* aName
, nsAtom
* aOther
);
290 void errEndTagViolatesNestingRules(nsAtom
* aName
);
292 void errEndWithUnclosedElements(nsAtom
* aName
);
294 void errListUnclosedStartTags(int32_t aIgnored
);
296 void MarkAsBroken(nsresult aRv
);
299 * Checks if this parser is broken. Returns a non-NS_OK (i.e. non-0)
302 nsresult
IsBroken() { return mBroken
; }