nsHtml5TreeBuilderHSupplement.h (9304B)
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/. */ 4 5 #define NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH 512 6 private: 7 using Encoding = mozilla::Encoding; 8 template <typename T> 9 using NotNull = mozilla::NotNull<T>; 10 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; 22 int32_t mHandlesUsed; 23 nsTArray<mozilla::UniquePtr<nsIContent*[]>> mOldHandles; 24 nsHtml5TreeOpStage* mSpeculativeLoadStage; 25 nsresult mBroken; 26 int32_t isInSVGOddPCData = 0; 27 // Controls whether the current HTML script goes through the more complex 28 // path that accommodates the possibility of the script becoming a 29 // parser-blocking script and the possibility of the script inserting 30 // content into this parse using document.write (as it is observable from 31 // the Web). 32 // 33 // Notably, in some cases scripts that do NOT NEED the more complex path 34 // BREAK the parse if they incorrectly go onto the complex path as their 35 // other handling doesn't necessarily take care of the responsibilities 36 // associated with the more complex path. See comments in 37 // `nsHtml5TreeBuilder::createElement` in the CppSupplement for details. 38 bool mCurrentHtmlScriptCannotDocumentWriteOrBlock; 39 bool mPreventScriptExecution; 40 /** 41 * Whether to actually generate speculative load operations that actually 42 * represent speculative loads as opposed to other operations traveling 43 * in the same queue. True for normal loads and false for XHR, plain text, 44 * and View Source. Needed, because we can't just null-check 45 * mSpeculativeLoadStage, since it is used for transferring encoding 46 * information even in the XHR/plain text/View Source cases. 47 */ 48 bool mGenerateSpeculativeLoads; 49 50 bool mHasSeenImportMap; 51 #ifdef DEBUG 52 bool mActive; 53 #endif 54 55 // DocumentModeHandler 56 /** 57 * Tree builder uses this to report quirkiness of the document 58 */ 59 void documentMode(nsHtml5DocumentMode m); 60 61 nsIContentHandle* getDocumentFragmentForTemplate(nsIContentHandle* aTemplate); 62 void setDocumentFragmentForTemplate(nsIContentHandle* aTemplate, 63 nsIContentHandle* aFragment); 64 65 nsIContentHandle* getShadowRootFromHost( 66 nsIContentHandle* aHost, nsIContentHandle* aTemplateNode, 67 nsHtml5String aShadowRootMode, bool aShadowRootIsClonable, 68 bool aShadowRootIsSerializable, bool aShadowRootDelegatesFocus, 69 nsHtml5String aShadowRootReferenceTarget); 70 71 nsIContentHandle* getFormPointerForContext(nsIContentHandle* aContext); 72 73 /** 74 * Using nsIContent** instead of nsIContent* is the parser deals with DOM 75 * nodes in a way that works off the main thread. Non-main-thread code 76 * can't refcount or otherwise touch nsIContent objects in any way. 77 * Yet, the off-the-main-thread code needs to have a way to hold onto a 78 * particular node and repeatedly operate on the same node. 79 * 80 * The way this works is that the off-the-main-thread code has an 81 * nsIContent** for each DOM node and a given nsIContent** is only ever 82 * actually dereferenced into an actual nsIContent* on the main thread. 83 * When the off-the-main-thread code requests a new node, it gets an 84 * nsIContent** immediately and a tree op is enqueued for later allocating 85 * an actual nsIContent object and writing a pointer to it into the memory 86 * location pointed to by the nsIContent**. 87 * 88 * Since tree ops are in a queue, the node creating tree op will always 89 * run before tree ops that try to further operate on the node that the 90 * nsIContent** is a handle to. 91 * 92 * On-the-main-thread parts of the parser use nsIContent* instead of 93 * nsIContent**. Since both cases share the same parser core, the parser 94 * core casts both to nsIContentHandle*. 95 */ 96 nsIContentHandle* AllocateContentHandle(); 97 98 void accumulateCharactersForced(const char16_t* aBuf, int32_t aStart, 99 int32_t aLength) { 100 accumulateCharacters(aBuf, aStart, aLength); 101 } 102 103 void MarkAsBrokenAndRequestSuspensionWithBuilder(nsresult aRv) { 104 mBuilder->MarkAsBroken(aRv); 105 requestSuspension(); 106 } 107 108 void MarkAsBrokenAndRequestSuspensionWithoutBuilder(nsresult aRv) { 109 MarkAsBroken(aRv); 110 requestSuspension(); 111 } 112 113 void MarkAsBrokenFromPortability(nsresult aRv); 114 115 public: 116 explicit nsHtml5TreeBuilder(nsHtml5OplessBuilder* aBuilder); 117 118 nsHtml5TreeBuilder(nsAHtml5TreeOpSink* aOpSink, nsHtml5TreeOpStage* aStage, 119 bool aGenerateSpeculativeLoads); 120 121 ~nsHtml5TreeBuilder(); 122 123 bool WantsLineAndColumn() { 124 // Perhaps just checking mBuilder would be sufficient. 125 // For createContextualFragment, we have non-null mBuilder and 126 // false for mPreventScriptExecution. However, do the line and 127 // column that get attached to script elements make any sense 128 // anyway in that case? 129 return !(mBuilder && mPreventScriptExecution); 130 } 131 132 void StartPlainTextViewSource(const nsAutoString& aTitle); 133 134 void StartPlainText(); 135 136 void StartPlainTextBody(); 137 138 bool HasScriptThatMayDocumentWriteOrBlock(); 139 140 void SetOpSink(nsAHtml5TreeOpSink* aOpSink) { mOpSink = aOpSink; } 141 142 void ClearOps() { mOpQueue.Clear(); } 143 144 /** 145 * Flushes tree ops. 146 * @return Ok(true) if there were ops to flush, Ok(false) 147 * if there were no ops to flush and Err() on OOM. 148 */ 149 mozilla::Result<bool, nsresult> Flush(bool aDiscretionary = false); 150 151 void FlushLoads(); 152 153 /** 154 * Sets the document charset via the speculation queue. 155 * 156 * @param aCommitEncodingSpeculation true iff the main thread should 157 * treat the first speculation as an 158 * encoding speculation. 159 */ 160 void SetDocumentCharset(NotNull<const Encoding*> aEncoding, 161 nsCharsetSource aCharsetSource, 162 bool aCommitEncodingSpeculation); 163 164 /** 165 * Updates the charset source via the op queue. 166 */ 167 void UpdateCharsetSource(nsCharsetSource aCharsetSource); 168 169 void StreamEnded(); 170 171 void NeedsCharsetSwitchTo(NotNull<const Encoding*> aEncoding, int32_t aSource, 172 int32_t aLineNumber); 173 174 void MaybeComplainAboutCharset(const char* aMsgId, bool aError, 175 int32_t aLineNumber); 176 177 void TryToEnableEncodingMenu(); 178 179 void AddSnapshotToScript(nsAHtml5TreeBuilderState* aSnapshot, int32_t aLine); 180 181 void DropHandles(); 182 183 void SetPreventScriptExecution(bool aPrevent) { 184 mPreventScriptExecution = aPrevent; 185 } 186 187 bool HasBuilder() { return mBuilder; } 188 189 /** 190 * Makes sure the buffers are large enough to be able to tokenize aLength 191 * UTF-16 code units before having to make the buffers larger. 192 * 193 * @param aLength the number of UTF-16 code units to be tokenized before the 194 * next call to this method. 195 * @return true if successful; false if out of memory 196 */ 197 bool EnsureBufferSpace(int32_t aLength); 198 199 void EnableViewSource(nsHtml5Highlighter* aHighlighter); 200 201 void errDeepTree(); 202 203 void errStrayStartTag(nsAtom* aName); 204 205 void errStrayEndTag(nsAtom* aName); 206 207 void errUnclosedElements(int32_t aIndex, nsAtom* aName); 208 209 void errUnclosedElementsImplied(int32_t aIndex, nsAtom* aName); 210 211 void errUnclosedElementsCell(int32_t aIndex); 212 213 void errStrayDoctype(); 214 215 void errAlmostStandardsDoctype(); 216 217 void errQuirkyDoctype(); 218 219 void errNonSpaceInTrailer(); 220 221 void errNonSpaceAfterFrameset(); 222 223 void errNonSpaceInFrameset(); 224 225 void errNonSpaceAfterBody(); 226 227 void errNonSpaceInColgroupInFragment(); 228 229 void errNonSpaceInNoscriptInHead(); 230 231 void errFooBetweenHeadAndBody(nsAtom* aName); 232 233 void errStartTagWithoutDoctype(); 234 235 void errNoSelectInTableScope(); 236 237 void errStartSelectWhereEndSelectExpected(); 238 239 void errStartTagWithSelectOpen(nsAtom* aName); 240 241 void errBadStartTagInNoscriptInHead(nsAtom* aName); 242 243 void errImage(); 244 245 void errIsindex(); 246 247 void errFooSeenWhenFooOpen(nsAtom* aName); 248 249 void errHeadingWhenHeadingOpen(); 250 251 void errFramesetStart(); 252 253 void errNoCellToClose(); 254 255 void errStartTagInTable(nsAtom* aName); 256 257 void errFormWhenFormOpen(); 258 259 void errTableSeenWhileTableOpen(); 260 261 void errStartTagInTableBody(nsAtom* aName); 262 263 void errEndTagSeenWithoutDoctype(); 264 265 void errEndTagAfterBody(); 266 267 void errEndTagSeenWithSelectOpen(nsAtom* aName); 268 269 void errGarbageInColgroup(); 270 271 void errEndTagBr(); 272 273 void errNoElementToCloseButEndTagSeen(nsAtom* aName); 274 275 void errHtmlStartTagInForeignContext(nsAtom* aName); 276 277 void errNoTableRowToClose(); 278 279 void errNonSpaceInTable(); 280 281 void errUnclosedChildrenInRuby(); 282 283 void errStartTagSeenWithoutRuby(nsAtom* aName); 284 285 void errSelfClosing(); 286 287 void errNoCheckUnclosedElementsOnStack(); 288 289 void errEndTagDidNotMatchCurrentOpenElement(nsAtom* aName, nsAtom* aOther); 290 291 void errEndTagViolatesNestingRules(nsAtom* aName); 292 293 void errEndWithUnclosedElements(nsAtom* aName); 294 295 void errListUnclosedStartTags(int32_t aIgnored); 296 297 void MarkAsBroken(nsresult aRv); 298 299 /** 300 * Checks if this parser is broken. Returns a non-NS_OK (i.e. non-0) 301 * value if broken. 302 */ 303 nsresult IsBroken() { return mBroken; }