Bug 1845715 - Check for failure when getting RegExp match result template r=iain
[gecko.git] / parser / html / nsHtml5TreeBuilderCppSupplement.h
blobf78f254b9779264965a2906ce14522ba2d48f5fc
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 sw=2 et tw=78: */
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 http://mozilla.org/MPL/2.0/. */
7 #include "ErrorList.h"
8 #include "nsError.h"
9 #include "nsNetUtil.h"
10 #include "mozilla/CheckedInt.h"
11 #include "mozilla/Likely.h"
12 #include "mozilla/StaticPrefs_dom.h"
13 #include "mozilla/StaticPrefs_network.h"
14 #include "mozilla/UniquePtr.h"
15 #include "mozilla/UniquePtrExtensions.h"
17 nsHtml5TreeBuilder::nsHtml5TreeBuilder(nsHtml5OplessBuilder* aBuilder)
18 : mode(0),
19 originalMode(0),
20 framesetOk(false),
21 tokenizer(nullptr),
22 scriptingEnabled(false),
23 needToDropLF(false),
24 fragment(false),
25 contextName(nullptr),
26 contextNamespace(kNameSpaceID_None),
27 contextNode(nullptr),
28 templateModePtr(0),
29 stackNodesIdx(0),
30 numStackNodes(0),
31 currentPtr(0),
32 listPtr(0),
33 formPointer(nullptr),
34 headPointer(nullptr),
35 charBufferLen(0),
36 quirks(false),
37 forceNoQuirks(false),
38 mBuilder(aBuilder),
39 mViewSource(nullptr),
40 mOpSink(nullptr),
41 mHandles(nullptr),
42 mHandlesUsed(0),
43 mSpeculativeLoadStage(nullptr),
44 mBroken(NS_OK),
45 mCurrentHtmlScriptIsAsyncOrDefer(false),
46 mPreventScriptExecution(false),
47 mGenerateSpeculativeLoads(false),
48 mHasSeenImportMap(false)
49 #ifdef DEBUG
51 mActive(false)
52 #endif
54 MOZ_COUNT_CTOR(nsHtml5TreeBuilder);
57 nsHtml5TreeBuilder::nsHtml5TreeBuilder(nsAHtml5TreeOpSink* aOpSink,
58 nsHtml5TreeOpStage* aStage,
59 bool aGenerateSpeculativeLoads)
60 : mode(0),
61 originalMode(0),
62 framesetOk(false),
63 tokenizer(nullptr),
64 scriptingEnabled(false),
65 needToDropLF(false),
66 fragment(false),
67 contextName(nullptr),
68 contextNamespace(kNameSpaceID_None),
69 contextNode(nullptr),
70 templateModePtr(0),
71 stackNodesIdx(0),
72 numStackNodes(0),
73 currentPtr(0),
74 listPtr(0),
75 formPointer(nullptr),
76 headPointer(nullptr),
77 charBufferLen(0),
78 quirks(false),
79 forceNoQuirks(false),
80 mBuilder(nullptr),
81 mViewSource(nullptr),
82 mOpSink(aOpSink),
83 mHandles(new nsIContent*[NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH]),
84 mHandlesUsed(0),
85 mSpeculativeLoadStage(aStage),
86 mBroken(NS_OK),
87 mCurrentHtmlScriptIsAsyncOrDefer(false),
88 mPreventScriptExecution(false),
89 mGenerateSpeculativeLoads(aGenerateSpeculativeLoads),
90 mHasSeenImportMap(false)
91 #ifdef DEBUG
93 mActive(false)
94 #endif
96 MOZ_ASSERT(!(!aStage && aGenerateSpeculativeLoads),
97 "Must not generate speculative loads without a stage");
98 MOZ_COUNT_CTOR(nsHtml5TreeBuilder);
101 nsHtml5TreeBuilder::~nsHtml5TreeBuilder() {
102 MOZ_COUNT_DTOR(nsHtml5TreeBuilder);
103 NS_ASSERTION(!mActive,
104 "nsHtml5TreeBuilder deleted without ever calling end() on it!");
105 mOpQueue.Clear();
108 nsIContentHandle* nsHtml5TreeBuilder::createElement(
109 int32_t aNamespace, nsAtom* aName, nsHtml5HtmlAttributes* aAttributes,
110 nsIContentHandle* aIntendedParent, nsHtml5ContentCreatorFunction aCreator) {
111 MOZ_ASSERT(aAttributes, "Got null attributes.");
112 MOZ_ASSERT(aName, "Got null name.");
113 MOZ_ASSERT(aNamespace == kNameSpaceID_XHTML ||
114 aNamespace == kNameSpaceID_SVG ||
115 aNamespace == kNameSpaceID_MathML,
116 "Bogus namespace.");
118 if (mBuilder) {
119 nsIContent* intendedParent =
120 aIntendedParent ? static_cast<nsIContent*>(aIntendedParent) : nullptr;
122 // intendedParent == nullptr is a special case where the
123 // intended parent is the document.
124 nsNodeInfoManager* nodeInfoManager =
125 intendedParent ? intendedParent->OwnerDoc()->NodeInfoManager()
126 : mBuilder->GetNodeInfoManager();
128 nsIContent* elem;
129 if (aNamespace == kNameSpaceID_XHTML) {
130 elem = nsHtml5TreeOperation::CreateHTMLElement(
131 aName, aAttributes, mozilla::dom::FROM_PARSER_FRAGMENT,
132 nodeInfoManager, mBuilder, aCreator.html);
133 } else if (aNamespace == kNameSpaceID_SVG) {
134 elem = nsHtml5TreeOperation::CreateSVGElement(
135 aName, aAttributes, mozilla::dom::FROM_PARSER_FRAGMENT,
136 nodeInfoManager, mBuilder, aCreator.svg);
137 } else {
138 MOZ_ASSERT(aNamespace == kNameSpaceID_MathML);
139 elem = nsHtml5TreeOperation::CreateMathMLElement(
140 aName, aAttributes, nodeInfoManager, mBuilder);
142 if (MOZ_UNLIKELY(aAttributes != tokenizer->GetAttributes() &&
143 aAttributes != nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES)) {
144 delete aAttributes;
146 return elem;
149 nsIContentHandle* content = AllocateContentHandle();
150 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
151 if (MOZ_UNLIKELY(!treeOp)) {
152 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
153 return nullptr;
156 if (aNamespace == kNameSpaceID_XHTML) {
157 opCreateHTMLElement opeation(
158 content, aName, aAttributes, aCreator.html, aIntendedParent,
159 (!!mSpeculativeLoadStage) ? mozilla::dom::FROM_PARSER_NETWORK
160 : mozilla::dom::FROM_PARSER_DOCUMENT_WRITE);
161 treeOp->Init(mozilla::AsVariant(opeation));
162 } else if (aNamespace == kNameSpaceID_SVG) {
163 opCreateSVGElement operation(
164 content, aName, aAttributes, aCreator.svg, aIntendedParent,
165 (!!mSpeculativeLoadStage) ? mozilla::dom::FROM_PARSER_NETWORK
166 : mozilla::dom::FROM_PARSER_DOCUMENT_WRITE);
167 treeOp->Init(mozilla::AsVariant(operation));
168 } else {
169 // kNameSpaceID_MathML
170 opCreateMathMLElement operation(content, aName, aAttributes,
171 aIntendedParent);
172 treeOp->Init(mozilla::AsVariant(operation));
175 // mSpeculativeLoadStage is non-null only in the off-the-main-thread
176 // tree builder, which handles the network stream
178 // Start wall of code for speculative loading and line numbers
180 if (mGenerateSpeculativeLoads && mode != IN_TEMPLATE) {
181 switch (aNamespace) {
182 case kNameSpaceID_XHTML:
183 if (nsGkAtoms::img == aName) {
184 nsHtml5String loading =
185 aAttributes->getValue(nsHtml5AttributeName::ATTR_LOADING);
186 if (!mozilla::StaticPrefs::dom_image_lazy_loading_enabled() ||
187 !loading.LowerCaseEqualsASCII("lazy")) {
188 nsHtml5String url =
189 aAttributes->getValue(nsHtml5AttributeName::ATTR_SRC);
190 nsHtml5String srcset =
191 aAttributes->getValue(nsHtml5AttributeName::ATTR_SRCSET);
192 nsHtml5String crossOrigin =
193 aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
194 nsHtml5String referrerPolicy = aAttributes->getValue(
195 nsHtml5AttributeName::ATTR_REFERRERPOLICY);
196 nsHtml5String sizes =
197 aAttributes->getValue(nsHtml5AttributeName::ATTR_SIZES);
198 mSpeculativeLoadQueue.AppendElement()->InitImage(
199 url, crossOrigin, /* aMedia = */ nullptr, referrerPolicy,
200 srcset, sizes, false);
202 } else if (nsGkAtoms::source == aName) {
203 nsHtml5String srcset =
204 aAttributes->getValue(nsHtml5AttributeName::ATTR_SRCSET);
205 // Sources without srcset cannot be selected. The source could also be
206 // for a media element, but in that context doesn't use srcset. See
207 // comments in nsHtml5SpeculativeLoad.h about <picture> preloading
208 if (srcset) {
209 nsHtml5String sizes =
210 aAttributes->getValue(nsHtml5AttributeName::ATTR_SIZES);
211 nsHtml5String type =
212 aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE);
213 nsHtml5String media =
214 aAttributes->getValue(nsHtml5AttributeName::ATTR_MEDIA);
215 mSpeculativeLoadQueue.AppendElement()->InitPictureSource(
216 srcset, sizes, type, media);
218 } else if (nsGkAtoms::script == aName) {
219 nsHtml5TreeOperation* treeOp =
220 mOpQueue.AppendElement(mozilla::fallible);
221 if (MOZ_UNLIKELY(!treeOp)) {
222 MarkAsBrokenAndRequestSuspensionWithoutBuilder(
223 NS_ERROR_OUT_OF_MEMORY);
224 return nullptr;
226 opSetScriptLineAndColumnNumberAndFreeze operation(
227 content, tokenizer->getLineNumber(),
228 tokenizer->getColumnNumber());
229 treeOp->Init(mozilla::AsVariant(operation));
231 nsHtml5String type =
232 aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE);
233 nsAutoString typeString;
234 type.ToString(typeString);
235 if (!mHasSeenImportMap) {
236 // If we see an importmap, we don't want to later start speculative
237 // loads for modulepreloads, since such load might finish before
238 // the importmap is created. This also applies to module scripts so
239 // that any modulepreload integrity checks can be performed before
240 // the modules scripts are loaded.
241 mHasSeenImportMap =
242 typeString.LowerCaseFindASCII("importmap") != kNotFound;
244 nsHtml5String url =
245 aAttributes->getValue(nsHtml5AttributeName::ATTR_SRC);
246 if (url && !(mHasSeenImportMap &&
247 typeString.LowerCaseFindASCII("module") != kNotFound)) {
248 nsHtml5String charset =
249 aAttributes->getValue(nsHtml5AttributeName::ATTR_CHARSET);
250 nsHtml5String crossOrigin =
251 aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
252 nsHtml5String nonce =
253 aAttributes->getValue(nsHtml5AttributeName::ATTR_NONCE);
254 nsHtml5String integrity =
255 aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY);
256 nsHtml5String referrerPolicy = aAttributes->getValue(
257 nsHtml5AttributeName::ATTR_REFERRERPOLICY);
258 bool async =
259 aAttributes->contains(nsHtml5AttributeName::ATTR_ASYNC);
260 bool defer =
261 aAttributes->contains(nsHtml5AttributeName::ATTR_DEFER);
262 bool noModule =
263 aAttributes->contains(nsHtml5AttributeName::ATTR_NOMODULE);
264 mSpeculativeLoadQueue.AppendElement()->InitScript(
265 url, charset, type, crossOrigin, /* aMedia = */ nullptr, nonce,
266 integrity, referrerPolicy, mode == nsHtml5TreeBuilder::IN_HEAD,
267 async, defer, noModule, false);
268 mCurrentHtmlScriptIsAsyncOrDefer = async || defer;
270 } else if (nsGkAtoms::link == aName) {
271 nsHtml5String rel =
272 aAttributes->getValue(nsHtml5AttributeName::ATTR_REL);
273 // Not splitting on space here is bogus but the old parser didn't even
274 // do a case-insensitive check.
275 if (rel) {
276 if (rel.LowerCaseEqualsASCII("stylesheet")) {
277 nsHtml5String url =
278 aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
279 if (url) {
280 nsHtml5String charset =
281 aAttributes->getValue(nsHtml5AttributeName::ATTR_CHARSET);
282 nsHtml5String crossOrigin = aAttributes->getValue(
283 nsHtml5AttributeName::ATTR_CROSSORIGIN);
284 nsHtml5String nonce =
285 aAttributes->getValue(nsHtml5AttributeName::ATTR_NONCE);
286 nsHtml5String integrity =
287 aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY);
288 nsHtml5String referrerPolicy = aAttributes->getValue(
289 nsHtml5AttributeName::ATTR_REFERRERPOLICY);
290 nsHtml5String media =
291 aAttributes->getValue(nsHtml5AttributeName::ATTR_MEDIA);
292 mSpeculativeLoadQueue.AppendElement()->InitStyle(
293 url, charset, crossOrigin, media, referrerPolicy, nonce,
294 integrity, false);
296 } else if (rel.LowerCaseEqualsASCII("preconnect")) {
297 nsHtml5String url =
298 aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
299 if (url) {
300 nsHtml5String crossOrigin = aAttributes->getValue(
301 nsHtml5AttributeName::ATTR_CROSSORIGIN);
302 mSpeculativeLoadQueue.AppendElement()->InitPreconnect(
303 url, crossOrigin);
305 } else if (mozilla::StaticPrefs::network_preload() &&
306 rel.LowerCaseEqualsASCII("preload")) {
307 nsHtml5String url =
308 aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
309 if (url) {
310 nsHtml5String as =
311 aAttributes->getValue(nsHtml5AttributeName::ATTR_AS);
312 nsHtml5String charset =
313 aAttributes->getValue(nsHtml5AttributeName::ATTR_CHARSET);
314 nsHtml5String crossOrigin = aAttributes->getValue(
315 nsHtml5AttributeName::ATTR_CROSSORIGIN);
316 nsHtml5String nonce =
317 aAttributes->getValue(nsHtml5AttributeName::ATTR_NONCE);
318 nsHtml5String integrity =
319 aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY);
320 nsHtml5String referrerPolicy = aAttributes->getValue(
321 nsHtml5AttributeName::ATTR_REFERRERPOLICY);
322 nsHtml5String media =
323 aAttributes->getValue(nsHtml5AttributeName::ATTR_MEDIA);
325 // Note that respective speculative loaders for scripts and
326 // styles check all additional attributes to be equal to use the
327 // speculative load. So, if any of them is specified and the
328 // preload has to take the expected effect, those attributes
329 // must also be specified on the actual tag to use the preload.
330 // Omitting an attribute on both will make the values equal
331 // (empty) and thus use the preload.
332 if (as.LowerCaseEqualsASCII("script")) {
333 nsHtml5String type =
334 aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE);
335 mSpeculativeLoadQueue.AppendElement()->InitScript(
336 url, charset, type, crossOrigin, media, nonce, integrity,
337 referrerPolicy, mode == nsHtml5TreeBuilder::IN_HEAD,
338 false, false, false, true);
339 } else if (as.LowerCaseEqualsASCII("style")) {
340 mSpeculativeLoadQueue.AppendElement()->InitStyle(
341 url, charset, crossOrigin, media, referrerPolicy, nonce,
342 integrity, true);
343 } else if (as.LowerCaseEqualsASCII("image")) {
344 nsHtml5String srcset = aAttributes->getValue(
345 nsHtml5AttributeName::ATTR_IMAGESRCSET);
346 nsHtml5String sizes = aAttributes->getValue(
347 nsHtml5AttributeName::ATTR_IMAGESIZES);
348 mSpeculativeLoadQueue.AppendElement()->InitImage(
349 url, crossOrigin, media, referrerPolicy, srcset, sizes,
350 true);
351 } else if (as.LowerCaseEqualsASCII("font")) {
352 mSpeculativeLoadQueue.AppendElement()->InitFont(
353 url, crossOrigin, media, referrerPolicy);
354 } else if (as.LowerCaseEqualsASCII("fetch")) {
355 mSpeculativeLoadQueue.AppendElement()->InitFetch(
356 url, crossOrigin, media, referrerPolicy);
358 // Other "as" values will be supported later.
360 } else if (mozilla::StaticPrefs::network_modulepreload() &&
361 rel.LowerCaseEqualsASCII("modulepreload") &&
362 !mHasSeenImportMap) {
363 nsHtml5String url =
364 aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
365 if (url && url.Length() != 0) {
366 nsHtml5String as =
367 aAttributes->getValue(nsHtml5AttributeName::ATTR_AS);
368 nsAutoString asString;
369 as.ToString(asString);
370 if (mozilla::net::IsScriptLikeOrInvalid(asString)) {
371 nsHtml5String charset =
372 aAttributes->getValue(nsHtml5AttributeName::ATTR_CHARSET);
373 RefPtr<nsAtom> moduleType = nsGkAtoms::_module;
374 nsHtml5String type =
375 nsHtml5String::FromAtom(moduleType.forget());
376 nsHtml5String crossOrigin = aAttributes->getValue(
377 nsHtml5AttributeName::ATTR_CROSSORIGIN);
378 nsHtml5String media =
379 aAttributes->getValue(nsHtml5AttributeName::ATTR_MEDIA);
380 nsHtml5String nonce =
381 aAttributes->getValue(nsHtml5AttributeName::ATTR_NONCE);
382 nsHtml5String integrity = aAttributes->getValue(
383 nsHtml5AttributeName::ATTR_INTEGRITY);
384 nsHtml5String referrerPolicy = aAttributes->getValue(
385 nsHtml5AttributeName::ATTR_REFERRERPOLICY);
386 mSpeculativeLoadQueue.AppendElement()->InitScript(
387 url, charset, type, crossOrigin, media, nonce, integrity,
388 referrerPolicy, mode == nsHtml5TreeBuilder::IN_HEAD,
389 false, false, false, true);
394 } else if (nsGkAtoms::video == aName) {
395 nsHtml5String url =
396 aAttributes->getValue(nsHtml5AttributeName::ATTR_POSTER);
397 if (url) {
398 mSpeculativeLoadQueue.AppendElement()->InitImage(
399 url, nullptr, nullptr, nullptr, nullptr, nullptr, false);
401 } else if (nsGkAtoms::style == aName) {
402 mImportScanner.Start();
403 nsHtml5TreeOperation* treeOp =
404 mOpQueue.AppendElement(mozilla::fallible);
405 if (MOZ_UNLIKELY(!treeOp)) {
406 MarkAsBrokenAndRequestSuspensionWithoutBuilder(
407 NS_ERROR_OUT_OF_MEMORY);
408 return nullptr;
410 opSetStyleLineNumber operation(content, tokenizer->getLineNumber());
411 treeOp->Init(mozilla::AsVariant(operation));
412 } else if (nsGkAtoms::html == aName) {
413 nsHtml5String url =
414 aAttributes->getValue(nsHtml5AttributeName::ATTR_MANIFEST);
415 mSpeculativeLoadQueue.AppendElement()->InitManifest(url);
416 } else if (nsGkAtoms::base == aName) {
417 nsHtml5String url =
418 aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
419 if (url) {
420 mSpeculativeLoadQueue.AppendElement()->InitBase(url);
422 } else if (nsGkAtoms::meta == aName) {
423 if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
424 "content-security-policy",
425 aAttributes->getValue(
426 nsHtml5AttributeName::ATTR_HTTP_EQUIV))) {
427 nsHtml5String csp =
428 aAttributes->getValue(nsHtml5AttributeName::ATTR_CONTENT);
429 if (csp) {
430 mSpeculativeLoadQueue.AppendElement()->InitMetaCSP(csp);
432 } else if (nsHtml5Portability::
433 lowerCaseLiteralEqualsIgnoreAsciiCaseString(
434 "referrer",
435 aAttributes->getValue(
436 nsHtml5AttributeName::ATTR_NAME))) {
437 nsHtml5String referrerPolicy =
438 aAttributes->getValue(nsHtml5AttributeName::ATTR_CONTENT);
439 if (referrerPolicy) {
440 mSpeculativeLoadQueue.AppendElement()->InitMetaReferrerPolicy(
441 referrerPolicy);
445 break;
446 case kNameSpaceID_SVG:
447 if (nsGkAtoms::image == aName) {
448 nsHtml5String url =
449 aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
450 if (!url) {
451 url = aAttributes->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF);
453 if (url) {
454 mSpeculativeLoadQueue.AppendElement()->InitImage(
455 url, nullptr, nullptr, nullptr, nullptr, nullptr, false);
457 } else if (nsGkAtoms::script == aName) {
458 nsHtml5TreeOperation* treeOp =
459 mOpQueue.AppendElement(mozilla::fallible);
460 if (MOZ_UNLIKELY(!treeOp)) {
461 MarkAsBrokenAndRequestSuspensionWithoutBuilder(
462 NS_ERROR_OUT_OF_MEMORY);
463 return nullptr;
465 opSetScriptLineAndColumnNumberAndFreeze operation(
466 content, tokenizer->getLineNumber(),
467 tokenizer->getColumnNumber());
468 treeOp->Init(mozilla::AsVariant(operation));
470 nsHtml5String url =
471 aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
472 if (!url) {
473 url = aAttributes->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF);
475 if (url) {
476 nsHtml5String type =
477 aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE);
478 nsHtml5String crossOrigin =
479 aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
480 nsHtml5String nonce =
481 aAttributes->getValue(nsHtml5AttributeName::ATTR_NONCE);
482 nsHtml5String integrity =
483 aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY);
484 nsHtml5String referrerPolicy = aAttributes->getValue(
485 nsHtml5AttributeName::ATTR_REFERRERPOLICY);
486 mSpeculativeLoadQueue.AppendElement()->InitScript(
487 url, nullptr, type, crossOrigin, /* aMedia = */ nullptr, nonce,
488 integrity, referrerPolicy, mode == nsHtml5TreeBuilder::IN_HEAD,
489 false, false, false, false);
491 } else if (nsGkAtoms::style == aName) {
492 mImportScanner.Start();
493 nsHtml5TreeOperation* treeOp =
494 mOpQueue.AppendElement(mozilla::fallible);
495 if (MOZ_UNLIKELY(!treeOp)) {
496 MarkAsBrokenAndRequestSuspensionWithoutBuilder(
497 NS_ERROR_OUT_OF_MEMORY);
498 return nullptr;
500 opSetStyleLineNumber operation(content, tokenizer->getLineNumber());
501 treeOp->Init(mozilla::AsVariant(operation));
503 break;
505 } else if (aNamespace != kNameSpaceID_MathML) {
506 // No speculative loader--just line numbers and defer/async check
507 if (nsGkAtoms::style == aName) {
508 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
509 if (MOZ_UNLIKELY(!treeOp)) {
510 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
511 return nullptr;
513 opSetStyleLineNumber operation(content, tokenizer->getLineNumber());
514 treeOp->Init(mozilla::AsVariant(operation));
515 } else if (nsGkAtoms::script == aName) {
516 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
517 if (MOZ_UNLIKELY(!treeOp)) {
518 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
519 return nullptr;
521 opSetScriptLineAndColumnNumberAndFreeze operation(
522 content, tokenizer->getLineNumber(), tokenizer->getColumnNumber());
523 treeOp->Init(mozilla::AsVariant(operation));
524 if (aNamespace == kNameSpaceID_XHTML) {
525 mCurrentHtmlScriptIsAsyncOrDefer =
526 aAttributes->contains(nsHtml5AttributeName::ATTR_SRC) &&
527 (aAttributes->contains(nsHtml5AttributeName::ATTR_ASYNC) ||
528 aAttributes->contains(nsHtml5AttributeName::ATTR_DEFER));
530 } else if (aNamespace == kNameSpaceID_XHTML) {
531 if (nsGkAtoms::html == aName) {
532 nsHtml5String url =
533 aAttributes->getValue(nsHtml5AttributeName::ATTR_MANIFEST);
534 nsHtml5TreeOperation* treeOp =
535 mOpQueue.AppendElement(mozilla::fallible);
536 if (MOZ_UNLIKELY(!treeOp)) {
537 MarkAsBrokenAndRequestSuspensionWithoutBuilder(
538 NS_ERROR_OUT_OF_MEMORY);
539 return nullptr;
541 if (url) {
542 nsString
543 urlString; // Not Auto, because using it to hold nsStringBuffer*
544 url.ToString(urlString);
545 opProcessOfflineManifest operation(ToNewUnicode(urlString));
546 treeOp->Init(mozilla::AsVariant(operation));
547 } else {
548 opProcessOfflineManifest operation(ToNewUnicode(u""_ns));
549 treeOp->Init(mozilla::AsVariant(operation));
551 } else if (nsGkAtoms::base == aName && mViewSource) {
552 nsHtml5String url =
553 aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
554 if (url) {
555 mViewSource->AddBase(url);
561 // End wall of code for speculative loading
563 return content;
566 nsIContentHandle* nsHtml5TreeBuilder::createElement(
567 int32_t aNamespace, nsAtom* aName, nsHtml5HtmlAttributes* aAttributes,
568 nsIContentHandle* aFormElement, nsIContentHandle* aIntendedParent,
569 nsHtml5ContentCreatorFunction aCreator) {
570 nsIContentHandle* content =
571 createElement(aNamespace, aName, aAttributes, aIntendedParent, aCreator);
572 if (aFormElement) {
573 if (mBuilder) {
574 nsHtml5TreeOperation::SetFormElement(
575 static_cast<nsIContent*>(content),
576 static_cast<nsIContent*>(aFormElement));
577 } else {
578 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
579 if (MOZ_UNLIKELY(!treeOp)) {
580 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
581 return nullptr;
583 opSetFormElement operation(content, aFormElement);
584 treeOp->Init(mozilla::AsVariant(operation));
587 return content;
590 nsIContentHandle* nsHtml5TreeBuilder::createHtmlElementSetAsRoot(
591 nsHtml5HtmlAttributes* aAttributes) {
592 nsHtml5ContentCreatorFunction creator;
593 // <html> uses NS_NewHTMLSharedElement creator
594 creator.html = NS_NewHTMLSharedElement;
595 nsIContentHandle* content = createElement(kNameSpaceID_XHTML, nsGkAtoms::html,
596 aAttributes, nullptr, creator);
597 if (mBuilder) {
598 nsresult rv = nsHtml5TreeOperation::AppendToDocument(
599 static_cast<nsIContent*>(content), mBuilder);
600 if (NS_FAILED(rv)) {
601 MarkAsBrokenAndRequestSuspensionWithBuilder(rv);
603 } else {
604 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
605 if (MOZ_UNLIKELY(!treeOp)) {
606 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
607 return nullptr;
609 opAppendToDocument operation(content);
610 treeOp->Init(mozilla::AsVariant(operation));
612 return content;
615 nsIContentHandle* nsHtml5TreeBuilder::createAndInsertFosterParentedElement(
616 int32_t aNamespace, nsAtom* aName, nsHtml5HtmlAttributes* aAttributes,
617 nsIContentHandle* aFormElement, nsIContentHandle* aTable,
618 nsIContentHandle* aStackParent, nsHtml5ContentCreatorFunction aCreator) {
619 MOZ_ASSERT(aTable, "Null table");
620 MOZ_ASSERT(aStackParent, "Null stack parent");
622 if (mBuilder) {
623 // Get the foster parent to use as the intended parent when creating
624 // the child element.
625 nsIContent* fosterParent = nsHtml5TreeOperation::GetFosterParent(
626 static_cast<nsIContent*>(aTable),
627 static_cast<nsIContent*>(aStackParent));
629 nsIContentHandle* child = createElement(
630 aNamespace, aName, aAttributes, aFormElement, fosterParent, aCreator);
632 insertFosterParentedChild(child, aTable, aStackParent);
634 return child;
637 // Tree op to get the foster parent that we use as the intended parent
638 // when creating the child element.
639 nsHtml5TreeOperation* fosterParentTreeOp = mOpQueue.AppendElement();
640 NS_ASSERTION(fosterParentTreeOp, "Tree op allocation failed.");
641 nsIContentHandle* fosterParentHandle = AllocateContentHandle();
642 opGetFosterParent operation(aTable, aStackParent, fosterParentHandle);
643 fosterParentTreeOp->Init(mozilla::AsVariant(operation));
645 // Create the element with the correct intended parent.
646 nsIContentHandle* child =
647 createElement(aNamespace, aName, aAttributes, aFormElement,
648 fosterParentHandle, aCreator);
650 // Insert the child into the foster parent.
651 insertFosterParentedChild(child, aTable, aStackParent);
653 return child;
656 void nsHtml5TreeBuilder::detachFromParent(nsIContentHandle* aElement) {
657 MOZ_ASSERT(aElement, "Null element");
659 if (mBuilder) {
660 nsHtml5TreeOperation::Detach(static_cast<nsIContent*>(aElement), mBuilder);
661 return;
664 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
665 if (MOZ_UNLIKELY(!treeOp)) {
666 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
667 return;
669 opDetach operation(aElement);
670 treeOp->Init(mozilla::AsVariant(operation));
673 void nsHtml5TreeBuilder::appendElement(nsIContentHandle* aChild,
674 nsIContentHandle* aParent) {
675 MOZ_ASSERT(aChild, "Null child");
676 MOZ_ASSERT(aParent, "Null parent");
678 if (mBuilder) {
679 nsresult rv = nsHtml5TreeOperation::Append(
680 static_cast<nsIContent*>(aChild), static_cast<nsIContent*>(aParent),
681 mozilla::dom::FROM_PARSER_FRAGMENT, mBuilder);
682 if (NS_FAILED(rv)) {
683 MarkAsBrokenAndRequestSuspensionWithBuilder(rv);
685 return;
688 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
689 if (MOZ_UNLIKELY(!treeOp)) {
690 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
691 return;
694 opAppend operation(aChild, aParent,
695 (!!mSpeculativeLoadStage)
696 ? mozilla::dom::FROM_PARSER_NETWORK
697 : mozilla::dom::FROM_PARSER_DOCUMENT_WRITE);
698 treeOp->Init(mozilla::AsVariant(operation));
701 void nsHtml5TreeBuilder::appendChildrenToNewParent(
702 nsIContentHandle* aOldParent, nsIContentHandle* aNewParent) {
703 MOZ_ASSERT(aOldParent, "Null old parent");
704 MOZ_ASSERT(aNewParent, "Null new parent");
706 if (mBuilder) {
707 nsresult rv = nsHtml5TreeOperation::AppendChildrenToNewParent(
708 static_cast<nsIContent*>(aOldParent),
709 static_cast<nsIContent*>(aNewParent), mBuilder);
710 if (NS_FAILED(rv)) {
711 MarkAsBrokenAndRequestSuspensionWithBuilder(rv);
713 return;
716 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
717 if (MOZ_UNLIKELY(!treeOp)) {
718 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
719 return;
721 opAppendChildrenToNewParent operation(aOldParent, aNewParent);
722 treeOp->Init(mozilla::AsVariant(operation));
725 void nsHtml5TreeBuilder::insertFosterParentedCharacters(
726 char16_t* aBuffer, int32_t aStart, int32_t aLength,
727 nsIContentHandle* aTable, nsIContentHandle* aStackParent) {
728 MOZ_ASSERT(aBuffer, "Null buffer");
729 MOZ_ASSERT(aTable, "Null table");
730 MOZ_ASSERT(aStackParent, "Null stack parent");
731 MOZ_ASSERT(!aStart, "aStart must always be zero.");
733 if (mBuilder) {
734 nsresult rv = nsHtml5TreeOperation::FosterParentText(
735 static_cast<nsIContent*>(aStackParent),
736 aBuffer, // XXX aStart always ignored???
737 aLength, static_cast<nsIContent*>(aTable), mBuilder);
738 if (NS_FAILED(rv)) {
739 MarkAsBrokenAndRequestSuspensionWithBuilder(rv);
741 return;
744 auto bufferCopy = mozilla::MakeUniqueFallible<char16_t[]>(aLength);
745 if (!bufferCopy) {
746 // Just assigning mBroken instead of generating tree op. The caller
747 // of tokenizeBuffer() will call MarkAsBroken() as appropriate.
748 mBroken = NS_ERROR_OUT_OF_MEMORY;
749 requestSuspension();
750 return;
753 memcpy(bufferCopy.get(), aBuffer, aLength * sizeof(char16_t));
755 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
756 if (MOZ_UNLIKELY(!treeOp)) {
757 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
758 return;
760 opFosterParentText operation(aStackParent, bufferCopy.release(), aTable,
761 aLength);
762 treeOp->Init(mozilla::AsVariant(operation));
765 void nsHtml5TreeBuilder::insertFosterParentedChild(
766 nsIContentHandle* aChild, nsIContentHandle* aTable,
767 nsIContentHandle* aStackParent) {
768 MOZ_ASSERT(aChild, "Null child");
769 MOZ_ASSERT(aTable, "Null table");
770 MOZ_ASSERT(aStackParent, "Null stack parent");
772 if (mBuilder) {
773 nsresult rv = nsHtml5TreeOperation::FosterParent(
774 static_cast<nsIContent*>(aChild),
775 static_cast<nsIContent*>(aStackParent),
776 static_cast<nsIContent*>(aTable), mBuilder);
777 if (NS_FAILED(rv)) {
778 MarkAsBrokenAndRequestSuspensionWithBuilder(rv);
780 return;
783 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
784 if (MOZ_UNLIKELY(!treeOp)) {
785 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
786 return;
788 opFosterParent operation(aChild, aStackParent, aTable);
789 treeOp->Init(mozilla::AsVariant(operation));
792 void nsHtml5TreeBuilder::appendCharacters(nsIContentHandle* aParent,
793 char16_t* aBuffer, int32_t aStart,
794 int32_t aLength) {
795 MOZ_ASSERT(aBuffer, "Null buffer");
796 MOZ_ASSERT(aParent, "Null parent");
797 MOZ_ASSERT(!aStart, "aStart must always be zero.");
799 if (mBuilder) {
800 nsresult rv = nsHtml5TreeOperation::AppendText(
801 aBuffer, // XXX aStart always ignored???
802 aLength, static_cast<nsIContent*>(aParent), mBuilder);
803 if (NS_FAILED(rv)) {
804 MarkAsBrokenAndRequestSuspensionWithBuilder(rv);
806 return;
809 auto bufferCopy = mozilla::MakeUniqueFallible<char16_t[]>(aLength);
810 if (!bufferCopy) {
811 // Just assigning mBroken instead of generating tree op. The caller
812 // of tokenizeBuffer() will call MarkAsBroken() as appropriate.
813 mBroken = NS_ERROR_OUT_OF_MEMORY;
814 requestSuspension();
815 return;
818 memcpy(bufferCopy.get(), aBuffer, aLength * sizeof(char16_t));
820 if (mImportScanner.ShouldScan()) {
821 nsTArray<nsString> imports =
822 mImportScanner.Scan(mozilla::Span(aBuffer, aLength));
823 for (nsString& url : imports) {
824 mSpeculativeLoadQueue.AppendElement()->InitImportStyle(std::move(url));
828 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
829 if (MOZ_UNLIKELY(!treeOp)) {
830 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
831 return;
833 opAppendText operation(aParent, bufferCopy.release(), aLength);
834 treeOp->Init(mozilla::AsVariant(operation));
837 void nsHtml5TreeBuilder::appendComment(nsIContentHandle* aParent,
838 char16_t* aBuffer, int32_t aStart,
839 int32_t aLength) {
840 MOZ_ASSERT(aBuffer, "Null buffer");
841 MOZ_ASSERT(aParent, "Null parent");
842 MOZ_ASSERT(!aStart, "aStart must always be zero.");
844 if (mBuilder) {
845 nsresult rv = nsHtml5TreeOperation::AppendComment(
846 static_cast<nsIContent*>(aParent),
847 aBuffer, // XXX aStart always ignored???
848 aLength, mBuilder);
849 if (NS_FAILED(rv)) {
850 MarkAsBrokenAndRequestSuspensionWithBuilder(rv);
852 return;
855 auto bufferCopy = mozilla::MakeUniqueFallible<char16_t[]>(aLength);
856 if (!bufferCopy) {
857 // Just assigning mBroken instead of generating tree op. The caller
858 // of tokenizeBuffer() will call MarkAsBroken() as appropriate.
859 mBroken = NS_ERROR_OUT_OF_MEMORY;
860 requestSuspension();
861 return;
864 memcpy(bufferCopy.get(), aBuffer, aLength * sizeof(char16_t));
866 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
867 if (MOZ_UNLIKELY(!treeOp)) {
868 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
869 return;
871 opAppendComment operation(aParent, bufferCopy.release(), aLength);
872 treeOp->Init(mozilla::AsVariant(operation));
875 void nsHtml5TreeBuilder::appendCommentToDocument(char16_t* aBuffer,
876 int32_t aStart,
877 int32_t aLength) {
878 MOZ_ASSERT(aBuffer, "Null buffer");
879 MOZ_ASSERT(!aStart, "aStart must always be zero.");
881 if (mBuilder) {
882 nsresult rv = nsHtml5TreeOperation::AppendCommentToDocument(
883 aBuffer, // XXX aStart always ignored???
884 aLength, mBuilder);
885 if (NS_FAILED(rv)) {
886 MarkAsBrokenAndRequestSuspensionWithBuilder(rv);
888 return;
891 auto bufferCopy = mozilla::MakeUniqueFallible<char16_t[]>(aLength);
892 if (!bufferCopy) {
893 // Just assigning mBroken instead of generating tree op. The caller
894 // of tokenizeBuffer() will call MarkAsBroken() as appropriate.
895 mBroken = NS_ERROR_OUT_OF_MEMORY;
896 requestSuspension();
897 return;
900 memcpy(bufferCopy.get(), aBuffer, aLength * sizeof(char16_t));
902 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
903 if (MOZ_UNLIKELY(!treeOp)) {
904 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
905 return;
907 opAppendCommentToDocument data(bufferCopy.release(), aLength);
908 treeOp->Init(mozilla::AsVariant(data));
911 void nsHtml5TreeBuilder::addAttributesToElement(
912 nsIContentHandle* aElement, nsHtml5HtmlAttributes* aAttributes) {
913 MOZ_ASSERT(aElement, "Null element");
914 MOZ_ASSERT(aAttributes, "Null attributes");
916 if (aAttributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
917 return;
920 if (mBuilder) {
921 MOZ_ASSERT(
922 aAttributes == tokenizer->GetAttributes(),
923 "Using attribute other than the tokenizer's to add to body or html.");
924 nsresult rv = nsHtml5TreeOperation::AddAttributes(
925 static_cast<nsIContent*>(aElement), aAttributes, mBuilder);
926 if (NS_FAILED(rv)) {
927 MarkAsBrokenAndRequestSuspensionWithBuilder(rv);
929 return;
932 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
933 if (MOZ_UNLIKELY(!treeOp)) {
934 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
935 return;
937 opAddAttributes opeation(aElement, aAttributes);
938 treeOp->Init(mozilla::AsVariant(opeation));
941 void nsHtml5TreeBuilder::markMalformedIfScript(nsIContentHandle* aElement) {
942 MOZ_ASSERT(aElement, "Null element");
944 if (mBuilder) {
945 nsHtml5TreeOperation::MarkMalformedIfScript(
946 static_cast<nsIContent*>(aElement));
947 return;
950 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
951 if (MOZ_UNLIKELY(!treeOp)) {
952 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
953 return;
955 opMarkMalformedIfScript operation(aElement);
956 treeOp->Init(mozilla::AsVariant(operation));
959 void nsHtml5TreeBuilder::start(bool fragment) {
960 mCurrentHtmlScriptIsAsyncOrDefer = false;
961 #ifdef DEBUG
962 mActive = true;
963 #endif
966 void nsHtml5TreeBuilder::end() {
967 mOpQueue.Clear();
968 #ifdef DEBUG
969 mActive = false;
970 #endif
973 void nsHtml5TreeBuilder::appendDoctypeToDocument(nsAtom* aName,
974 nsHtml5String aPublicId,
975 nsHtml5String aSystemId) {
976 MOZ_ASSERT(aName, "Null name");
977 nsString publicId; // Not Auto, because using it to hold nsStringBuffer*
978 nsString systemId; // Not Auto, because using it to hold nsStringBuffer*
979 aPublicId.ToString(publicId);
980 aSystemId.ToString(systemId);
981 if (mBuilder) {
982 nsresult rv = nsHtml5TreeOperation::AppendDoctypeToDocument(
983 aName, publicId, systemId, mBuilder);
984 if (NS_FAILED(rv)) {
985 MarkAsBrokenAndRequestSuspensionWithBuilder(rv);
987 return;
990 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
991 if (MOZ_UNLIKELY(!treeOp)) {
992 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
993 return;
995 opAppendDoctypeToDocument operation(aName, publicId, systemId);
996 treeOp->Init(mozilla::AsVariant(operation));
997 // nsXMLContentSink can flush here, but what's the point?
998 // It can also interrupt here, but we can't.
1001 void nsHtml5TreeBuilder::elementPushed(int32_t aNamespace, nsAtom* aName,
1002 nsIContentHandle* aElement) {
1003 NS_ASSERTION(aNamespace == kNameSpaceID_XHTML ||
1004 aNamespace == kNameSpaceID_SVG ||
1005 aNamespace == kNameSpaceID_MathML,
1006 "Element isn't HTML, SVG or MathML!");
1007 NS_ASSERTION(aName, "Element doesn't have local name!");
1008 NS_ASSERTION(aElement, "No element!");
1010 * The frame constructor uses recursive algorithms, so it can't deal with
1011 * arbitrarily deep trees. This is especially a problem on Windows where
1012 * the permitted depth of the runtime stack is rather small.
1014 * The following is a protection against author incompetence--not against
1015 * malice. There are other ways to make the DOM deep anyway.
1017 * The basic idea is that when the tree builder stack gets too deep,
1018 * append operations no longer append to the node that the HTML parsing
1019 * algorithm says they should but instead text nodes are append to the last
1020 * element that was seen before a magic tree builder stack threshold was
1021 * reached and element and comment nodes aren't appended to the DOM at all.
1023 * However, for security reasons, non-child descendant text nodes inside an
1024 * SVG script or style element should not become children. Also, non-cell
1025 * table elements shouldn't be used as surrogate parents for user experience
1026 * reasons.
1028 if (aNamespace != kNameSpaceID_XHTML) {
1029 return;
1031 if (aName == nsGkAtoms::body || aName == nsGkAtoms::frameset) {
1032 if (mBuilder) {
1033 // InnerHTML and DOMParser shouldn't start layout anyway
1034 return;
1036 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
1037 if (MOZ_UNLIKELY(!treeOp)) {
1038 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
1039 return;
1041 treeOp->Init(mozilla::AsVariant(opStartLayout()));
1042 return;
1044 if (nsIContent::RequiresDoneCreatingElement(kNameSpaceID_XHTML, aName)) {
1045 if (mBuilder) {
1046 nsHtml5TreeOperation::DoneCreatingElement(
1047 static_cast<nsIContent*>(aElement));
1048 } else {
1049 opDoneCreatingElement operation(aElement);
1050 mOpQueue.AppendElement()->Init(mozilla::AsVariant(operation));
1052 return;
1054 if (mGenerateSpeculativeLoads && aName == nsGkAtoms::picture) {
1055 // See comments in nsHtml5SpeculativeLoad.h about <picture> preloading
1056 mSpeculativeLoadQueue.AppendElement()->InitOpenPicture();
1057 return;
1059 if (aName == nsGkAtoms::_template) {
1060 if (tokenizer->TemplatePushedOrHeadPopped()) {
1061 requestSuspension();
1066 void nsHtml5TreeBuilder::elementPopped(int32_t aNamespace, nsAtom* aName,
1067 nsIContentHandle* aElement) {
1068 NS_ASSERTION(aNamespace == kNameSpaceID_XHTML ||
1069 aNamespace == kNameSpaceID_SVG ||
1070 aNamespace == kNameSpaceID_MathML,
1071 "Element isn't HTML, SVG or MathML!");
1072 NS_ASSERTION(aName, "Element doesn't have local name!");
1073 NS_ASSERTION(aElement, "No element!");
1074 if (aNamespace == kNameSpaceID_MathML) {
1075 return;
1077 // we now have only SVG and HTML
1078 if (aName == nsGkAtoms::script) {
1079 if (mPreventScriptExecution) {
1080 if (mBuilder) {
1081 nsHtml5TreeOperation::PreventScriptExecution(
1082 static_cast<nsIContent*>(aElement));
1083 return;
1085 opPreventScriptExecution operation(aElement);
1086 mOpQueue.AppendElement()->Init(mozilla::AsVariant(operation));
1087 return;
1089 if (mBuilder) {
1090 return;
1092 if (mCurrentHtmlScriptIsAsyncOrDefer) {
1093 NS_ASSERTION(aNamespace == kNameSpaceID_XHTML,
1094 "Only HTML scripts may be async/defer.");
1095 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
1096 if (MOZ_UNLIKELY(!treeOp)) {
1097 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
1098 return;
1100 opRunScriptAsyncDefer operation(aElement);
1101 treeOp->Init(mozilla::AsVariant(operation));
1102 mCurrentHtmlScriptIsAsyncOrDefer = false;
1103 return;
1105 requestSuspension();
1106 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
1107 if (MOZ_UNLIKELY(!treeOp)) {
1108 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
1109 return;
1111 opRunScript operation(aElement, nullptr);
1112 treeOp->Init(mozilla::AsVariant(operation));
1113 return;
1115 // Some nodes need DoneAddingChildren() called to initialize
1116 // properly (e.g. form state restoration).
1117 if (nsIContent::RequiresDoneAddingChildren(aNamespace, aName)) {
1118 if (mBuilder) {
1119 nsHtml5TreeOperation::DoneAddingChildren(
1120 static_cast<nsIContent*>(aElement));
1121 return;
1123 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
1124 if (MOZ_UNLIKELY(!treeOp)) {
1125 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
1126 return;
1128 opDoneAddingChildren operation(aElement);
1129 treeOp->Init(mozilla::AsVariant(operation));
1130 if (aNamespace == kNameSpaceID_XHTML && aName == nsGkAtoms::head) {
1131 if (tokenizer->TemplatePushedOrHeadPopped()) {
1132 requestSuspension();
1135 return;
1137 if (aName == nsGkAtoms::style ||
1138 (aNamespace == kNameSpaceID_XHTML && aName == nsGkAtoms::link)) {
1139 if (mBuilder) {
1140 MOZ_ASSERT(!nsContentUtils::IsSafeToRunScript(),
1141 "Scripts must be blocked.");
1142 mBuilder->UpdateStyleSheet(static_cast<nsIContent*>(aElement));
1143 return;
1146 if (aName == nsGkAtoms::style) {
1147 nsTArray<nsString> imports = mImportScanner.Stop();
1148 for (nsString& url : imports) {
1149 mSpeculativeLoadQueue.AppendElement()->InitImportStyle(std::move(url));
1153 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
1154 if (MOZ_UNLIKELY(!treeOp)) {
1155 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
1156 return;
1158 opUpdateStyleSheet operation(aElement);
1159 treeOp->Init(mozilla::AsVariant(operation));
1160 return;
1162 if (aNamespace == kNameSpaceID_SVG) {
1163 if (aName == nsGkAtoms::svg) {
1164 if (!scriptingEnabled || mPreventScriptExecution) {
1165 return;
1167 if (mBuilder) {
1168 nsHtml5TreeOperation::SvgLoad(static_cast<nsIContent*>(aElement));
1169 return;
1171 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
1172 if (MOZ_UNLIKELY(!treeOp)) {
1173 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
1174 return;
1176 opSvgLoad operation(aElement);
1177 treeOp->Init(mozilla::AsVariant(operation));
1179 return;
1182 if (mGenerateSpeculativeLoads && aName == nsGkAtoms::picture) {
1183 // See comments in nsHtml5SpeculativeLoad.h about <picture> preloading
1184 mSpeculativeLoadQueue.AppendElement()->InitEndPicture();
1185 return;
1189 void nsHtml5TreeBuilder::accumulateCharacters(const char16_t* aBuf,
1190 int32_t aStart, int32_t aLength) {
1191 MOZ_RELEASE_ASSERT(charBufferLen + aLength <= charBuffer.length,
1192 "About to memcpy past the end of the buffer!");
1193 memcpy(charBuffer + charBufferLen, aBuf + aStart, sizeof(char16_t) * aLength);
1194 charBufferLen += aLength;
1197 // INT32_MAX is (2^31)-1. Therefore, the highest power-of-two that fits
1198 // is 2^30. Note that this is counting char16_t units. The underlying
1199 // bytes will be twice that, but they fit even in 32-bit size_t even
1200 // if a contiguous chunk of memory of that size is pretty unlikely to
1201 // be available on a 32-bit system.
1202 #define MAX_POWER_OF_TWO_IN_INT32 0x40000000
1204 bool nsHtml5TreeBuilder::EnsureBufferSpace(int32_t aLength) {
1205 // TODO: Unify nsHtml5Tokenizer::strBuf and nsHtml5TreeBuilder::charBuffer
1206 // so that this method becomes unnecessary.
1207 mozilla::CheckedInt<int32_t> worstCase(charBufferLen);
1208 worstCase += aLength;
1209 if (!worstCase.isValid()) {
1210 return false;
1212 if (worstCase.value() > MAX_POWER_OF_TWO_IN_INT32) {
1213 return false;
1215 if (!charBuffer) {
1216 if (worstCase.value() < MAX_POWER_OF_TWO_IN_INT32) {
1217 // Add one to round to the next power of two to avoid immediate
1218 // reallocation once there are a few characters in the buffer.
1219 worstCase += 1;
1221 charBuffer = jArray<char16_t, int32_t>::newFallibleJArray(
1222 mozilla::RoundUpPow2(worstCase.value()));
1223 if (!charBuffer) {
1224 return false;
1226 } else if (worstCase.value() > charBuffer.length) {
1227 jArray<char16_t, int32_t> newBuf =
1228 jArray<char16_t, int32_t>::newFallibleJArray(
1229 mozilla::RoundUpPow2(worstCase.value()));
1230 if (!newBuf) {
1231 return false;
1233 memcpy(newBuf, charBuffer, sizeof(char16_t) * size_t(charBufferLen));
1234 charBuffer = newBuf;
1236 return true;
1239 nsIContentHandle* nsHtml5TreeBuilder::AllocateContentHandle() {
1240 if (MOZ_UNLIKELY(mBuilder)) {
1241 MOZ_ASSERT_UNREACHABLE("Must never allocate a handle with builder.");
1242 return nullptr;
1244 if (mHandlesUsed == NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH) {
1245 mOldHandles.AppendElement(std::move(mHandles));
1246 mHandles = mozilla::MakeUnique<nsIContent*[]>(
1247 NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH);
1248 mHandlesUsed = 0;
1250 #ifdef DEBUG
1251 mHandles[mHandlesUsed] = reinterpret_cast<nsIContent*>(uintptr_t(0xC0DEDBAD));
1252 #endif
1253 return &mHandles[mHandlesUsed++];
1256 bool nsHtml5TreeBuilder::HasScript() {
1257 uint32_t len = mOpQueue.Length();
1258 if (!len) {
1259 return false;
1261 return mOpQueue.ElementAt(len - 1).IsRunScript();
1264 mozilla::Result<bool, nsresult> nsHtml5TreeBuilder::Flush(bool aDiscretionary) {
1265 if (MOZ_UNLIKELY(mBuilder)) {
1266 MOZ_ASSERT_UNREACHABLE("Must never flush with builder.");
1267 return false;
1269 if (NS_SUCCEEDED(mBroken)) {
1270 if (!aDiscretionary || !(charBufferLen && currentPtr >= 0 &&
1271 stack[currentPtr]->isFosterParenting())) {
1272 // Don't flush text on discretionary flushes if the current element on
1273 // the stack is a foster-parenting element and there's pending text,
1274 // because flushing in that case would make the tree shape dependent on
1275 // where the flush points fall.
1276 flushCharacters();
1278 FlushLoads();
1280 if (mOpSink) {
1281 bool hasOps = !mOpQueue.IsEmpty();
1282 if (hasOps) {
1283 // If the builder is broken and mOpQueue is not empty, there must be
1284 // one op and it must be eTreeOpMarkAsBroken.
1285 if (NS_FAILED(mBroken)) {
1286 MOZ_ASSERT(mOpQueue.Length() == 1,
1287 "Tree builder is broken with a non-empty op queue whose "
1288 "length isn't 1.");
1289 MOZ_ASSERT(mOpQueue[0].IsMarkAsBroken(),
1290 "Tree builder is broken but the op in queue is not marked "
1291 "as broken.");
1293 if (!mOpSink->MoveOpsFrom(mOpQueue)) {
1294 return mozilla::Err(NS_ERROR_OUT_OF_MEMORY);
1297 return hasOps;
1299 // no op sink: throw away ops
1300 mOpQueue.Clear();
1301 return false;
1304 void nsHtml5TreeBuilder::FlushLoads() {
1305 if (MOZ_UNLIKELY(mBuilder)) {
1306 MOZ_ASSERT_UNREACHABLE("Must never flush loads with builder.");
1307 return;
1309 if (!mSpeculativeLoadQueue.IsEmpty()) {
1310 mSpeculativeLoadStage->MoveSpeculativeLoadsFrom(mSpeculativeLoadQueue);
1314 void nsHtml5TreeBuilder::SetDocumentCharset(NotNull<const Encoding*> aEncoding,
1315 nsCharsetSource aCharsetSource,
1316 bool aCommitEncodingSpeculation) {
1317 MOZ_ASSERT(!mBuilder, "How did we call this with builder?");
1318 MOZ_ASSERT(mSpeculativeLoadStage,
1319 "How did we call this without a speculative load stage?");
1320 mSpeculativeLoadQueue.AppendElement()->InitSetDocumentCharset(
1321 aEncoding, aCharsetSource, aCommitEncodingSpeculation);
1324 void nsHtml5TreeBuilder::UpdateCharsetSource(nsCharsetSource aCharsetSource) {
1325 MOZ_ASSERT(!mBuilder, "How did we call this with builder?");
1326 MOZ_ASSERT(mSpeculativeLoadStage,
1327 "How did we call this without a speculative load stage (even "
1328 "though we don't need it right here)?");
1329 if (mViewSource) {
1330 mViewSource->UpdateCharsetSource(aCharsetSource);
1331 return;
1333 opUpdateCharsetSource operation(aCharsetSource);
1334 mOpQueue.AppendElement()->Init(mozilla::AsVariant(operation));
1337 void nsHtml5TreeBuilder::StreamEnded() {
1338 MOZ_ASSERT(!mBuilder, "Must not call StreamEnded with builder.");
1339 MOZ_ASSERT(!fragment, "Must not parse fragments off the main thread.");
1340 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
1341 if (MOZ_UNLIKELY(!treeOp)) {
1342 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
1343 return;
1345 treeOp->Init(mozilla::AsVariant(opStreamEnded()));
1348 void nsHtml5TreeBuilder::NeedsCharsetSwitchTo(
1349 NotNull<const Encoding*> aEncoding, int32_t aCharsetSource,
1350 int32_t aLineNumber) {
1351 if (MOZ_UNLIKELY(mBuilder)) {
1352 MOZ_ASSERT_UNREACHABLE("Must never switch charset with builder.");
1353 return;
1355 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
1356 if (MOZ_UNLIKELY(!treeOp)) {
1357 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
1358 return;
1360 opCharsetSwitchTo opeation(aEncoding, aCharsetSource, aLineNumber);
1361 treeOp->Init(mozilla::AsVariant(opeation));
1364 void nsHtml5TreeBuilder::MaybeComplainAboutCharset(const char* aMsgId,
1365 bool aError,
1366 int32_t aLineNumber) {
1367 if (MOZ_UNLIKELY(mBuilder)) {
1368 MOZ_ASSERT_UNREACHABLE("Must never complain about charset with builder.");
1369 return;
1372 if (mSpeculativeLoadStage) {
1373 mSpeculativeLoadQueue.AppendElement()->InitMaybeComplainAboutCharset(
1374 aMsgId, aError, aLineNumber);
1375 } else {
1376 opMaybeComplainAboutCharset opeartion(const_cast<char*>(aMsgId), aError,
1377 aLineNumber);
1378 mOpQueue.AppendElement()->Init(mozilla::AsVariant(opeartion));
1382 void nsHtml5TreeBuilder::TryToEnableEncodingMenu() {
1383 if (MOZ_UNLIKELY(mBuilder)) {
1384 MOZ_ASSERT_UNREACHABLE("Must never disable encoding menu with builder.");
1385 return;
1387 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
1388 NS_ASSERTION(treeOp, "Tree op allocation failed.");
1389 treeOp->Init(mozilla::AsVariant(opEnableEncodingMenu()));
1392 void nsHtml5TreeBuilder::AddSnapshotToScript(
1393 nsAHtml5TreeBuilderState* aSnapshot, int32_t aLine) {
1394 if (MOZ_UNLIKELY(mBuilder)) {
1395 MOZ_ASSERT_UNREACHABLE("Must never use snapshots with builder.");
1396 return;
1398 MOZ_ASSERT(HasScript(), "No script to add a snapshot to!");
1399 MOZ_ASSERT(aSnapshot, "Got null snapshot.");
1400 mOpQueue.ElementAt(mOpQueue.Length() - 1).SetSnapshot(aSnapshot, aLine);
1403 void nsHtml5TreeBuilder::DropHandles() {
1404 MOZ_ASSERT(!mBuilder, "Must not drop handles with builder.");
1405 mOldHandles.Clear();
1406 mHandlesUsed = 0;
1409 void nsHtml5TreeBuilder::MarkAsBroken(nsresult aRv) {
1410 if (MOZ_UNLIKELY(mBuilder)) {
1411 MOZ_ASSERT_UNREACHABLE("Must not call this with builder.");
1412 return;
1414 mBroken = aRv;
1415 mOpQueue.Clear(); // Previous ops don't matter anymore
1416 opMarkAsBroken operation(aRv);
1417 mOpQueue.AppendElement()->Init(mozilla::AsVariant(operation));
1420 void nsHtml5TreeBuilder::MarkAsBrokenFromPortability(nsresult aRv) {
1421 if (mBuilder) {
1422 MarkAsBrokenAndRequestSuspensionWithBuilder(aRv);
1423 return;
1425 mBroken = aRv;
1426 requestSuspension();
1429 void nsHtml5TreeBuilder::StartPlainTextViewSource(const nsAutoString& aTitle) {
1430 MOZ_ASSERT(!mBuilder, "Must not view source with builder.");
1432 startTag(nsHtml5ElementName::ELT_META,
1433 nsHtml5ViewSourceUtils::NewMetaViewportAttributes(), false);
1435 startTag(nsHtml5ElementName::ELT_TITLE,
1436 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES, false);
1438 // XUL will add the "Source of: " prefix.
1439 uint32_t length = aTitle.Length();
1440 if (length > INT32_MAX) {
1441 length = INT32_MAX;
1443 characters(aTitle.get(), 0, (int32_t)length);
1444 endTag(nsHtml5ElementName::ELT_TITLE);
1446 startTag(nsHtml5ElementName::ELT_LINK,
1447 nsHtml5ViewSourceUtils::NewLinkAttributes(), false);
1449 startTag(nsHtml5ElementName::ELT_BODY,
1450 nsHtml5ViewSourceUtils::NewBodyAttributes(), false);
1452 StartPlainTextBody();
1455 void nsHtml5TreeBuilder::StartPlainText() {
1456 MOZ_ASSERT(!mBuilder, "Must not view source with builder.");
1457 setForceNoQuirks(true);
1458 startTag(nsHtml5ElementName::ELT_LINK,
1459 nsHtml5PlainTextUtils::NewLinkAttributes(), false);
1461 startTag(nsHtml5ElementName::ELT_BODY,
1462 nsHtml5PlainTextUtils::NewBodyAttributes(), false);
1464 StartPlainTextBody();
1467 void nsHtml5TreeBuilder::StartPlainTextBody() {
1468 MOZ_ASSERT(!mBuilder, "Must not view source with builder.");
1469 startTag(nsHtml5ElementName::ELT_PRE, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES,
1470 false);
1471 needToDropLF = false;
1474 // DocumentModeHandler
1475 void nsHtml5TreeBuilder::documentMode(nsHtml5DocumentMode m) {
1476 if (mBuilder) {
1477 mBuilder->SetDocumentMode(m);
1478 return;
1480 if (mSpeculativeLoadStage) {
1481 mSpeculativeLoadQueue.AppendElement()->InitSetDocumentMode(m);
1482 return;
1484 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
1485 if (MOZ_UNLIKELY(!treeOp)) {
1486 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
1487 return;
1489 treeOp->Init(mozilla::AsVariant(m));
1492 nsIContentHandle* nsHtml5TreeBuilder::getDocumentFragmentForTemplate(
1493 nsIContentHandle* aTemplate) {
1494 if (mBuilder) {
1495 return nsHtml5TreeOperation::GetDocumentFragmentForTemplate(
1496 static_cast<nsIContent*>(aTemplate));
1498 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
1499 if (MOZ_UNLIKELY(!treeOp)) {
1500 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
1501 return nullptr;
1503 nsIContentHandle* fragHandle = AllocateContentHandle();
1504 opGetDocumentFragmentForTemplate operation(aTemplate, fragHandle);
1505 treeOp->Init(mozilla::AsVariant(operation));
1506 return fragHandle;
1509 nsIContentHandle* nsHtml5TreeBuilder::getFormPointerForContext(
1510 nsIContentHandle* aContext) {
1511 MOZ_ASSERT(mBuilder, "Must have builder.");
1512 if (!aContext) {
1513 return nullptr;
1516 MOZ_ASSERT(NS_IsMainThread());
1518 // aContext must always be an element that already exists
1519 // in the document.
1520 nsIContent* contextNode = static_cast<nsIContent*>(aContext);
1521 nsIContent* currentAncestor = contextNode;
1523 // We traverse the ancestors of the context node to find the nearest
1524 // form pointer. This traversal is why aContext must not be an emtpy handle.
1525 nsIContent* nearestForm = nullptr;
1526 while (currentAncestor) {
1527 if (currentAncestor->IsHTMLElement(nsGkAtoms::form)) {
1528 nearestForm = currentAncestor;
1529 break;
1531 currentAncestor = currentAncestor->GetParent();
1534 if (!nearestForm) {
1535 return nullptr;
1538 return nearestForm;
1541 // Error reporting
1543 void nsHtml5TreeBuilder::EnableViewSource(nsHtml5Highlighter* aHighlighter) {
1544 MOZ_ASSERT(!mBuilder, "Must not view source with builder.");
1545 mViewSource = aHighlighter;
1548 void nsHtml5TreeBuilder::errDeepTree() {
1549 if (MOZ_UNLIKELY(mViewSource)) {
1550 mViewSource->AddErrorToCurrentRun("errDeepTree");
1551 } else if (!mBuilder) {
1552 nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
1553 MOZ_ASSERT(treeOp, "Tree op allocation failed.");
1554 opMaybeComplainAboutDeepTree operation(tokenizer->getLineNumber());
1555 treeOp->Init(mozilla::AsVariant(operation));
1559 void nsHtml5TreeBuilder::errStrayStartTag(nsAtom* aName) {
1560 if (MOZ_UNLIKELY(mViewSource)) {
1561 mViewSource->AddErrorToCurrentRun("errStrayStartTag2", aName);
1565 void nsHtml5TreeBuilder::errStrayEndTag(nsAtom* aName) {
1566 if (MOZ_UNLIKELY(mViewSource)) {
1567 mViewSource->AddErrorToCurrentRun("errStrayEndTag", aName);
1571 void nsHtml5TreeBuilder::errUnclosedElements(int32_t aIndex, nsAtom* aName) {
1572 if (MOZ_UNLIKELY(mViewSource)) {
1573 mViewSource->AddErrorToCurrentRun("errUnclosedElements", aName);
1577 void nsHtml5TreeBuilder::errUnclosedElementsImplied(int32_t aIndex,
1578 nsAtom* aName) {
1579 if (MOZ_UNLIKELY(mViewSource)) {
1580 mViewSource->AddErrorToCurrentRun("errUnclosedElementsImplied", aName);
1584 void nsHtml5TreeBuilder::errUnclosedElementsCell(int32_t aIndex) {
1585 if (MOZ_UNLIKELY(mViewSource)) {
1586 mViewSource->AddErrorToCurrentRun("errUnclosedElementsCell");
1590 void nsHtml5TreeBuilder::errStrayDoctype() {
1591 if (MOZ_UNLIKELY(mViewSource)) {
1592 mViewSource->AddErrorToCurrentRun("errStrayDoctype");
1596 void nsHtml5TreeBuilder::errAlmostStandardsDoctype() {
1597 if (MOZ_UNLIKELY(mViewSource) && !forceNoQuirks) {
1598 mViewSource->AddErrorToCurrentRun("errAlmostStandardsDoctype");
1602 void nsHtml5TreeBuilder::errQuirkyDoctype() {
1603 if (MOZ_UNLIKELY(mViewSource) && !forceNoQuirks) {
1604 mViewSource->AddErrorToCurrentRun("errQuirkyDoctype");
1608 void nsHtml5TreeBuilder::errNonSpaceInTrailer() {
1609 if (MOZ_UNLIKELY(mViewSource)) {
1610 mViewSource->AddErrorToCurrentRun("errNonSpaceInTrailer");
1614 void nsHtml5TreeBuilder::errNonSpaceAfterFrameset() {
1615 if (MOZ_UNLIKELY(mViewSource)) {
1616 mViewSource->AddErrorToCurrentRun("errNonSpaceAfterFrameset");
1620 void nsHtml5TreeBuilder::errNonSpaceInFrameset() {
1621 if (MOZ_UNLIKELY(mViewSource)) {
1622 mViewSource->AddErrorToCurrentRun("errNonSpaceInFrameset");
1626 void nsHtml5TreeBuilder::errNonSpaceAfterBody() {
1627 if (MOZ_UNLIKELY(mViewSource)) {
1628 mViewSource->AddErrorToCurrentRun("errNonSpaceAfterBody");
1632 void nsHtml5TreeBuilder::errNonSpaceInColgroupInFragment() {
1633 if (MOZ_UNLIKELY(mViewSource)) {
1634 mViewSource->AddErrorToCurrentRun("errNonSpaceInColgroupInFragment");
1638 void nsHtml5TreeBuilder::errNonSpaceInNoscriptInHead() {
1639 if (MOZ_UNLIKELY(mViewSource)) {
1640 mViewSource->AddErrorToCurrentRun("errNonSpaceInNoscriptInHead");
1644 void nsHtml5TreeBuilder::errFooBetweenHeadAndBody(nsAtom* aName) {
1645 if (MOZ_UNLIKELY(mViewSource)) {
1646 mViewSource->AddErrorToCurrentRun("errFooBetweenHeadAndBody", aName);
1650 void nsHtml5TreeBuilder::errStartTagWithoutDoctype() {
1651 if (MOZ_UNLIKELY(mViewSource) && !forceNoQuirks) {
1652 mViewSource->AddErrorToCurrentRun("errStartTagWithoutDoctype");
1656 void nsHtml5TreeBuilder::errNoSelectInTableScope() {
1657 if (MOZ_UNLIKELY(mViewSource)) {
1658 mViewSource->AddErrorToCurrentRun("errNoSelectInTableScope");
1662 void nsHtml5TreeBuilder::errStartSelectWhereEndSelectExpected() {
1663 if (MOZ_UNLIKELY(mViewSource)) {
1664 mViewSource->AddErrorToCurrentRun("errStartSelectWhereEndSelectExpected");
1668 void nsHtml5TreeBuilder::errStartTagWithSelectOpen(nsAtom* aName) {
1669 if (MOZ_UNLIKELY(mViewSource)) {
1670 mViewSource->AddErrorToCurrentRun("errStartTagWithSelectOpen", aName);
1674 void nsHtml5TreeBuilder::errBadStartTagInNoscriptInHead(nsAtom* aName) {
1675 if (MOZ_UNLIKELY(mViewSource)) {
1676 mViewSource->AddErrorToCurrentRun("errBadStartTagInNoscriptInHead", aName);
1680 void nsHtml5TreeBuilder::errImage() {
1681 if (MOZ_UNLIKELY(mViewSource)) {
1682 mViewSource->AddErrorToCurrentRun("errImage");
1686 void nsHtml5TreeBuilder::errIsindex() {
1687 if (MOZ_UNLIKELY(mViewSource)) {
1688 mViewSource->AddErrorToCurrentRun("errIsindex");
1692 void nsHtml5TreeBuilder::errFooSeenWhenFooOpen(nsAtom* aName) {
1693 if (MOZ_UNLIKELY(mViewSource)) {
1694 mViewSource->AddErrorToCurrentRun("errFooSeenWhenFooOpen2", aName);
1698 void nsHtml5TreeBuilder::errHeadingWhenHeadingOpen() {
1699 if (MOZ_UNLIKELY(mViewSource)) {
1700 mViewSource->AddErrorToCurrentRun("errHeadingWhenHeadingOpen");
1704 void nsHtml5TreeBuilder::errFramesetStart() {
1705 if (MOZ_UNLIKELY(mViewSource)) {
1706 mViewSource->AddErrorToCurrentRun("errFramesetStart");
1710 void nsHtml5TreeBuilder::errNoCellToClose() {
1711 if (MOZ_UNLIKELY(mViewSource)) {
1712 mViewSource->AddErrorToCurrentRun("errNoCellToClose");
1716 void nsHtml5TreeBuilder::errStartTagInTable(nsAtom* aName) {
1717 if (MOZ_UNLIKELY(mViewSource)) {
1718 mViewSource->AddErrorToCurrentRun("errStartTagInTable", aName);
1722 void nsHtml5TreeBuilder::errFormWhenFormOpen() {
1723 if (MOZ_UNLIKELY(mViewSource)) {
1724 mViewSource->AddErrorToCurrentRun("errFormWhenFormOpen");
1728 void nsHtml5TreeBuilder::errTableSeenWhileTableOpen() {
1729 if (MOZ_UNLIKELY(mViewSource)) {
1730 mViewSource->AddErrorToCurrentRun("errTableSeenWhileTableOpen");
1734 void nsHtml5TreeBuilder::errStartTagInTableBody(nsAtom* aName) {
1735 if (MOZ_UNLIKELY(mViewSource)) {
1736 mViewSource->AddErrorToCurrentRun("errStartTagInTableBody", aName);
1740 void nsHtml5TreeBuilder::errEndTagSeenWithoutDoctype() {
1741 if (MOZ_UNLIKELY(mViewSource) && !forceNoQuirks) {
1742 mViewSource->AddErrorToCurrentRun("errEndTagSeenWithoutDoctype");
1746 void nsHtml5TreeBuilder::errEndTagAfterBody() {
1747 if (MOZ_UNLIKELY(mViewSource)) {
1748 mViewSource->AddErrorToCurrentRun("errEndTagAfterBody");
1752 void nsHtml5TreeBuilder::errEndTagSeenWithSelectOpen(nsAtom* aName) {
1753 if (MOZ_UNLIKELY(mViewSource)) {
1754 mViewSource->AddErrorToCurrentRun("errEndTagSeenWithSelectOpen", aName);
1758 void nsHtml5TreeBuilder::errGarbageInColgroup() {
1759 if (MOZ_UNLIKELY(mViewSource)) {
1760 mViewSource->AddErrorToCurrentRun("errGarbageInColgroup");
1764 void nsHtml5TreeBuilder::errEndTagBr() {
1765 if (MOZ_UNLIKELY(mViewSource)) {
1766 mViewSource->AddErrorToCurrentRun("errEndTagBr");
1770 void nsHtml5TreeBuilder::errNoElementToCloseButEndTagSeen(nsAtom* aName) {
1771 if (MOZ_UNLIKELY(mViewSource)) {
1772 mViewSource->AddErrorToCurrentRun("errNoElementToCloseButEndTagSeen",
1773 aName);
1777 void nsHtml5TreeBuilder::errHtmlStartTagInForeignContext(nsAtom* aName) {
1778 if (MOZ_UNLIKELY(mViewSource)) {
1779 mViewSource->AddErrorToCurrentRun("errHtmlStartTagInForeignContext", aName);
1783 void nsHtml5TreeBuilder::errNoTableRowToClose() {
1784 if (MOZ_UNLIKELY(mViewSource)) {
1785 mViewSource->AddErrorToCurrentRun("errNoTableRowToClose");
1789 void nsHtml5TreeBuilder::errNonSpaceInTable() {
1790 if (MOZ_UNLIKELY(mViewSource)) {
1791 mViewSource->AddErrorToCurrentRun("errNonSpaceInTable");
1795 void nsHtml5TreeBuilder::errUnclosedChildrenInRuby() {
1796 if (MOZ_UNLIKELY(mViewSource)) {
1797 mViewSource->AddErrorToCurrentRun("errUnclosedChildrenInRuby");
1801 void nsHtml5TreeBuilder::errStartTagSeenWithoutRuby(nsAtom* aName) {
1802 if (MOZ_UNLIKELY(mViewSource)) {
1803 mViewSource->AddErrorToCurrentRun("errStartTagSeenWithoutRuby", aName);
1807 void nsHtml5TreeBuilder::errSelfClosing() {
1808 if (MOZ_UNLIKELY(mViewSource)) {
1809 mViewSource->AddErrorToCurrentSlash("errSelfClosing");
1813 void nsHtml5TreeBuilder::errNoCheckUnclosedElementsOnStack() {
1814 if (MOZ_UNLIKELY(mViewSource)) {
1815 mViewSource->AddErrorToCurrentRun("errNoCheckUnclosedElementsOnStack");
1819 void nsHtml5TreeBuilder::errEndTagDidNotMatchCurrentOpenElement(
1820 nsAtom* aName, nsAtom* aOther) {
1821 if (MOZ_UNLIKELY(mViewSource)) {
1822 mViewSource->AddErrorToCurrentRun("errEndTagDidNotMatchCurrentOpenElement",
1823 aName, aOther);
1827 void nsHtml5TreeBuilder::errEndTagViolatesNestingRules(nsAtom* aName) {
1828 if (MOZ_UNLIKELY(mViewSource)) {
1829 mViewSource->AddErrorToCurrentRun("errEndTagViolatesNestingRules", aName);
1833 void nsHtml5TreeBuilder::errEndWithUnclosedElements(nsAtom* aName) {
1834 if (MOZ_UNLIKELY(mViewSource)) {
1835 mViewSource->AddErrorToCurrentRun("errEndWithUnclosedElements", aName);
1839 void nsHtml5TreeBuilder::errListUnclosedStartTags(int32_t aIgnored) {
1840 if (MOZ_UNLIKELY(mViewSource)) {
1841 mViewSource->AddErrorToCurrentRun("errListUnclosedStartTags");