Line data Source code
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/. */
6 :
7 : #include "nsError.h"
8 : #include "nsIPresShell.h"
9 : #include "nsNodeUtils.h"
10 : #include "nsIFrame.h"
11 : #include "mozilla/Likely.h"
12 : #include "mozilla/UniquePtr.h"
13 :
14 0 : nsHtml5TreeBuilder::nsHtml5TreeBuilder(nsHtml5OplessBuilder* aBuilder)
15 : : scriptingEnabled(false)
16 : , fragment(false)
17 : , contextName(nullptr)
18 : , contextNamespace(kNameSpaceID_None)
19 : , contextNode(nullptr)
20 : , formPointer(nullptr)
21 : , headPointer(nullptr)
22 : , mBuilder(aBuilder)
23 : , mViewSource(nullptr)
24 : , mOpSink(nullptr)
25 : , mHandles(nullptr)
26 : , mHandlesUsed(0)
27 : , mSpeculativeLoadStage(nullptr)
28 : , mBroken(NS_OK)
29 : , mCurrentHtmlScriptIsAsyncOrDefer(false)
30 : , mPreventScriptExecution(false)
31 : #ifdef DEBUG
32 0 : , mActive(false)
33 : #endif
34 : {
35 0 : MOZ_COUNT_CTOR(nsHtml5TreeBuilder);
36 0 : }
37 :
38 4 : nsHtml5TreeBuilder::nsHtml5TreeBuilder(nsAHtml5TreeOpSink* aOpSink,
39 4 : nsHtml5TreeOpStage* aStage)
40 : : scriptingEnabled(false)
41 : , fragment(false)
42 : , contextName(nullptr)
43 : , contextNamespace(kNameSpaceID_None)
44 : , contextNode(nullptr)
45 : , formPointer(nullptr)
46 : , headPointer(nullptr)
47 : , mBuilder(nullptr)
48 : , mViewSource(nullptr)
49 : , mOpSink(aOpSink)
50 4 : , mHandles(new nsIContent*[NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH])
51 : , mHandlesUsed(0)
52 : , mSpeculativeLoadStage(aStage)
53 : , mBroken(NS_OK)
54 : , mCurrentHtmlScriptIsAsyncOrDefer(false)
55 : , mPreventScriptExecution(false)
56 : #ifdef DEBUG
57 8 : , mActive(false)
58 : #endif
59 : {
60 4 : MOZ_COUNT_CTOR(nsHtml5TreeBuilder);
61 4 : }
62 :
63 3 : nsHtml5TreeBuilder::~nsHtml5TreeBuilder()
64 : {
65 1 : MOZ_COUNT_DTOR(nsHtml5TreeBuilder);
66 1 : NS_ASSERTION(!mActive, "nsHtml5TreeBuilder deleted without ever calling end() on it!");
67 1 : mOpQueue.Clear();
68 3 : }
69 :
70 : nsIContentHandle*
71 14 : nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName,
72 : nsHtml5HtmlAttributes* aAttributes,
73 : nsIContentHandle* aIntendedParent)
74 : {
75 14 : NS_PRECONDITION(aAttributes, "Got null attributes.");
76 14 : NS_PRECONDITION(aName, "Got null name.");
77 14 : NS_PRECONDITION(aNamespace == kNameSpaceID_XHTML ||
78 : aNamespace == kNameSpaceID_SVG ||
79 : aNamespace == kNameSpaceID_MathML,
80 : "Bogus namespace.");
81 :
82 14 : if (mBuilder) {
83 0 : nsCOMPtr<nsIAtom> name = nsHtml5TreeOperation::Reget(aName);
84 :
85 : nsIContent* intendedParent = aIntendedParent ?
86 0 : static_cast<nsIContent*>(aIntendedParent) : nullptr;
87 :
88 : // intendedParent == nullptr is a special case where the
89 : // intended parent is the document.
90 0 : nsNodeInfoManager* nodeInfoManager = intendedParent ?
91 0 : intendedParent->OwnerDoc()->NodeInfoManager() :
92 0 : mBuilder->GetNodeInfoManager();
93 :
94 : nsIContent* elem =
95 0 : nsHtml5TreeOperation::CreateElement(aNamespace,
96 : name,
97 : aAttributes,
98 : mozilla::dom::FROM_PARSER_FRAGMENT,
99 : nodeInfoManager,
100 0 : mBuilder);
101 0 : if (MOZ_UNLIKELY(aAttributes != tokenizer->GetAttributes() &&
102 : aAttributes != nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES)) {
103 0 : delete aAttributes;
104 : }
105 0 : return elem;
106 : }
107 :
108 14 : nsIContentHandle* content = AllocateContentHandle();
109 14 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
110 14 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
111 14 : treeOp->Init(aNamespace,
112 : aName,
113 : aAttributes,
114 : content,
115 : aIntendedParent,
116 28 : !!mSpeculativeLoadStage);
117 : // mSpeculativeLoadStage is non-null only in the off-the-main-thread
118 : // tree builder, which handles the network stream
119 :
120 : // Start wall of code for speculative loading and line numbers
121 :
122 14 : if (mSpeculativeLoadStage) {
123 14 : switch (aNamespace) {
124 : case kNameSpaceID_XHTML:
125 14 : if (nsGkAtoms::img == aName) {
126 : nsHtml5String url =
127 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_SRC);
128 : nsHtml5String srcset =
129 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_SRCSET);
130 : nsHtml5String crossOrigin =
131 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
132 : nsHtml5String referrerPolicy =
133 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_REFERRERPOLICY);
134 : nsHtml5String sizes =
135 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_SIZES);
136 0 : mSpeculativeLoadQueue.AppendElement()->InitImage(
137 0 : url, crossOrigin, referrerPolicy, srcset, sizes);
138 14 : } else if (nsGkAtoms::source == aName) {
139 : nsHtml5String srcset =
140 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_SRCSET);
141 : // Sources without srcset cannot be selected. The source could also be
142 : // for a media element, but in that context doesn't use srcset. See
143 : // comments in nsHtml5SpeculativeLoad.h about <picture> preloading
144 0 : if (srcset) {
145 : nsHtml5String sizes =
146 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_SIZES);
147 : nsHtml5String type =
148 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE);
149 : nsHtml5String media =
150 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_MEDIA);
151 0 : mSpeculativeLoadQueue.AppendElement()->InitPictureSource(
152 0 : srcset, sizes, type, media);
153 : }
154 14 : } else if (nsGkAtoms::script == aName) {
155 5 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
156 5 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
157 5 : treeOp->Init(eTreeOpSetScriptLineNumberAndFreeze, content, tokenizer->getLineNumber());
158 :
159 : nsHtml5String url =
160 5 : aAttributes->getValue(nsHtml5AttributeName::ATTR_SRC);
161 5 : if (url) {
162 : nsHtml5String charset =
163 4 : aAttributes->getValue(nsHtml5AttributeName::ATTR_CHARSET);
164 : nsHtml5String type =
165 4 : aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE);
166 : nsHtml5String crossOrigin =
167 4 : aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
168 : nsHtml5String integrity =
169 4 : aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY);
170 4 : mSpeculativeLoadQueue.AppendElement()->InitScript(
171 : url,
172 : charset,
173 : type,
174 : crossOrigin,
175 : integrity,
176 8 : mode == nsHtml5TreeBuilder::IN_HEAD);
177 4 : mCurrentHtmlScriptIsAsyncOrDefer =
178 8 : aAttributes->contains(nsHtml5AttributeName::ATTR_ASYNC) ||
179 4 : aAttributes->contains(nsHtml5AttributeName::ATTR_DEFER);
180 : }
181 9 : } else if (nsGkAtoms::link == aName) {
182 : nsHtml5String rel =
183 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_REL);
184 : // Not splitting on space here is bogus but the old parser didn't even
185 : // do a case-insensitive check.
186 0 : if (rel) {
187 0 : if (rel.LowerCaseEqualsASCII("stylesheet")) {
188 : nsHtml5String url =
189 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
190 0 : if (url) {
191 : nsHtml5String charset =
192 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_CHARSET);
193 : nsHtml5String crossOrigin =
194 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
195 : nsHtml5String integrity =
196 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY);
197 0 : mSpeculativeLoadQueue.AppendElement()->InitStyle(
198 0 : url, charset, crossOrigin, integrity);
199 : }
200 0 : } else if (rel.LowerCaseEqualsASCII("preconnect")) {
201 : nsHtml5String url =
202 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
203 0 : if (url) {
204 : nsHtml5String crossOrigin =
205 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
206 0 : mSpeculativeLoadQueue.AppendElement()->InitPreconnect(
207 0 : url, crossOrigin);
208 : }
209 : }
210 : }
211 9 : } else if (nsGkAtoms::video == aName) {
212 : nsHtml5String url =
213 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_POSTER);
214 0 : if (url) {
215 0 : mSpeculativeLoadQueue.AppendElement()->InitImage(
216 0 : url, nullptr, nullptr, nullptr, nullptr);
217 : }
218 9 : } else if (nsGkAtoms::style == aName) {
219 0 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
220 0 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
221 0 : treeOp->Init(eTreeOpSetStyleLineNumber, content, tokenizer->getLineNumber());
222 9 : } else if (nsGkAtoms::html == aName) {
223 : nsHtml5String url =
224 2 : aAttributes->getValue(nsHtml5AttributeName::ATTR_MANIFEST);
225 2 : mSpeculativeLoadQueue.AppendElement()->InitManifest(url);
226 7 : } else if (nsGkAtoms::base == aName) {
227 : nsHtml5String url =
228 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
229 0 : if (url) {
230 0 : mSpeculativeLoadQueue.AppendElement()->InitBase(url);
231 : }
232 7 : } else if (nsGkAtoms::meta == aName) {
233 2 : if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
234 : "content-security-policy",
235 : aAttributes->getValue(nsHtml5AttributeName::ATTR_HTTP_EQUIV))) {
236 : nsHtml5String csp =
237 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_CONTENT);
238 0 : if (csp) {
239 0 : mSpeculativeLoadQueue.AppendElement()->InitMetaCSP(csp);
240 : }
241 : }
242 2 : else if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
243 : "referrer",
244 : aAttributes->getValue(nsHtml5AttributeName::ATTR_NAME))) {
245 : nsHtml5String referrerPolicy =
246 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_CONTENT);
247 0 : if (referrerPolicy) {
248 0 : mSpeculativeLoadQueue.AppendElement()->InitMetaReferrerPolicy(
249 0 : referrerPolicy);
250 : }
251 : }
252 : }
253 14 : break;
254 : case kNameSpaceID_SVG:
255 0 : if (nsGkAtoms::image == aName) {
256 : nsHtml5String url =
257 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF);
258 0 : if (url) {
259 0 : mSpeculativeLoadQueue.AppendElement()->InitImage(
260 0 : url, nullptr, nullptr, nullptr, nullptr);
261 : }
262 0 : } else if (nsGkAtoms::script == aName) {
263 0 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
264 0 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
265 0 : treeOp->Init(eTreeOpSetScriptLineNumberAndFreeze, content, tokenizer->getLineNumber());
266 :
267 : nsHtml5String url =
268 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF);
269 0 : if (url) {
270 : nsHtml5String type =
271 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE);
272 : nsHtml5String crossOrigin =
273 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
274 : nsHtml5String integrity =
275 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY);
276 0 : mSpeculativeLoadQueue.AppendElement()->InitScript(
277 : url,
278 : nullptr,
279 : type,
280 : crossOrigin,
281 : integrity,
282 0 : mode == nsHtml5TreeBuilder::IN_HEAD);
283 : }
284 0 : } else if (nsGkAtoms::style == aName) {
285 0 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
286 0 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
287 0 : treeOp->Init(eTreeOpSetStyleLineNumber, content, tokenizer->getLineNumber());
288 :
289 : nsHtml5String url =
290 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF);
291 0 : if (url) {
292 : nsHtml5String crossOrigin =
293 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
294 : nsHtml5String integrity =
295 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY);
296 0 : mSpeculativeLoadQueue.AppendElement()->InitStyle(
297 0 : url, nullptr, crossOrigin, integrity);
298 : }
299 : }
300 0 : break;
301 : }
302 0 : } else if (aNamespace != kNameSpaceID_MathML) {
303 : // No speculative loader--just line numbers and defer/async check
304 0 : if (nsGkAtoms::style == aName) {
305 0 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
306 0 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
307 0 : treeOp->Init(eTreeOpSetStyleLineNumber, content, tokenizer->getLineNumber());
308 0 : } else if (nsGkAtoms::script == aName) {
309 0 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
310 0 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
311 0 : treeOp->Init(eTreeOpSetScriptLineNumberAndFreeze, content, tokenizer->getLineNumber());
312 0 : if (aNamespace == kNameSpaceID_XHTML) {
313 0 : mCurrentHtmlScriptIsAsyncOrDefer =
314 0 : aAttributes->contains(nsHtml5AttributeName::ATTR_SRC) &&
315 0 : (aAttributes->contains(nsHtml5AttributeName::ATTR_ASYNC) ||
316 0 : aAttributes->contains(nsHtml5AttributeName::ATTR_DEFER));
317 : }
318 0 : } else if (aNamespace == kNameSpaceID_XHTML) {
319 0 : if (nsGkAtoms::html == aName) {
320 : nsHtml5String url =
321 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_MANIFEST);
322 0 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
323 0 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
324 0 : if (url) {
325 : nsString
326 0 : urlString; // Not Auto, because using it to hold nsStringBuffer*
327 0 : url.ToString(urlString);
328 0 : treeOp->Init(eTreeOpProcessOfflineManifest, urlString);
329 : } else {
330 0 : treeOp->Init(eTreeOpProcessOfflineManifest, EmptyString());
331 : }
332 0 : } else if (nsGkAtoms::base == aName && mViewSource) {
333 : nsHtml5String url =
334 0 : aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
335 0 : if (url) {
336 0 : mViewSource->AddBase(url);
337 : }
338 : }
339 : }
340 : }
341 :
342 : // End wall of code for speculative loading
343 :
344 14 : return content;
345 : }
346 :
347 : nsIContentHandle*
348 0 : nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName,
349 : nsHtml5HtmlAttributes* aAttributes,
350 : nsIContentHandle* aFormElement,
351 : nsIContentHandle* aIntendedParent)
352 : {
353 : nsIContentHandle* content = createElement(aNamespace, aName, aAttributes,
354 0 : aIntendedParent);
355 0 : if (aFormElement) {
356 0 : if (mBuilder) {
357 : nsHtml5TreeOperation::SetFormElement(static_cast<nsIContent*>(content),
358 0 : static_cast<nsIContent*>(aFormElement));
359 : } else {
360 0 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
361 0 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
362 0 : treeOp->Init(eTreeOpSetFormElement, content, aFormElement);
363 : }
364 : }
365 0 : return content;
366 : }
367 :
368 : nsIContentHandle*
369 2 : nsHtml5TreeBuilder::createHtmlElementSetAsRoot(nsHtml5HtmlAttributes* aAttributes)
370 : {
371 : nsIContentHandle* content =
372 2 : createElement(kNameSpaceID_XHTML, nsGkAtoms::html, aAttributes, nullptr);
373 2 : if (mBuilder) {
374 : nsresult rv = nsHtml5TreeOperation::AppendToDocument(static_cast<nsIContent*>(content),
375 0 : mBuilder);
376 0 : if (NS_FAILED(rv)) {
377 0 : MarkAsBrokenAndRequestSuspension(rv);
378 : }
379 : } else {
380 2 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
381 2 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
382 2 : treeOp->Init(eTreeOpAppendToDocument, content);
383 : }
384 2 : return content;
385 : }
386 :
387 : nsIContentHandle*
388 0 : nsHtml5TreeBuilder::createAndInsertFosterParentedElement(int32_t aNamespace, nsIAtom* aName,
389 : nsHtml5HtmlAttributes* aAttributes,
390 : nsIContentHandle* aFormElement,
391 : nsIContentHandle* aTable,
392 : nsIContentHandle* aStackParent)
393 : {
394 0 : NS_PRECONDITION(aTable, "Null table");
395 0 : NS_PRECONDITION(aStackParent, "Null stack parent");
396 :
397 0 : if (mBuilder) {
398 : // Get the foster parent to use as the intended parent when creating
399 : // the child element.
400 : nsIContent* fosterParent = nsHtml5TreeOperation::GetFosterParent(
401 : static_cast<nsIContent*>(aTable),
402 0 : static_cast<nsIContent*>(aStackParent));
403 :
404 : nsIContentHandle* child = createElement(aNamespace, aName, aAttributes,
405 0 : aFormElement, fosterParent);
406 :
407 0 : insertFosterParentedChild(child, aTable, aStackParent);
408 :
409 0 : return child;
410 : }
411 :
412 : // Tree op to get the foster parent that we use as the intended parent
413 : // when creating the child element.
414 0 : nsHtml5TreeOperation* fosterParentTreeOp = mOpQueue.AppendElement();
415 0 : NS_ASSERTION(fosterParentTreeOp, "Tree op allocation failed.");
416 0 : nsIContentHandle* fosterParentHandle = AllocateContentHandle();
417 : fosterParentTreeOp->Init(eTreeOpGetFosterParent, aTable,
418 0 : aStackParent, fosterParentHandle);
419 :
420 : // Create the element with the correct intended parent.
421 : nsIContentHandle* child = createElement(aNamespace, aName, aAttributes,
422 0 : aFormElement, fosterParentHandle);
423 :
424 : // Insert the child into the foster parent.
425 0 : insertFosterParentedChild(child, aTable, aStackParent);
426 :
427 0 : return child;
428 : }
429 :
430 : void
431 0 : nsHtml5TreeBuilder::detachFromParent(nsIContentHandle* aElement)
432 : {
433 0 : NS_PRECONDITION(aElement, "Null element");
434 :
435 0 : if (mBuilder) {
436 : nsHtml5TreeOperation::Detach(static_cast<nsIContent*>(aElement),
437 0 : mBuilder);
438 0 : return;
439 : }
440 :
441 0 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
442 0 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
443 0 : treeOp->Init(eTreeOpDetach, aElement);
444 : }
445 :
446 : void
447 12 : nsHtml5TreeBuilder::appendElement(nsIContentHandle* aChild, nsIContentHandle* aParent)
448 : {
449 12 : NS_PRECONDITION(aChild, "Null child");
450 12 : NS_PRECONDITION(aParent, "Null parent");
451 12 : if (deepTreeSurrogateParent) {
452 0 : return;
453 : }
454 :
455 12 : if (mBuilder) {
456 : nsresult rv = nsHtml5TreeOperation::Append(static_cast<nsIContent*>(aChild),
457 : static_cast<nsIContent*>(aParent),
458 0 : mBuilder);
459 0 : if (NS_FAILED(rv)) {
460 0 : MarkAsBrokenAndRequestSuspension(rv);
461 : }
462 0 : return;
463 : }
464 :
465 12 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
466 12 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
467 12 : treeOp->Init(eTreeOpAppend, aChild, aParent);
468 : }
469 :
470 : void
471 0 : nsHtml5TreeBuilder::appendChildrenToNewParent(nsIContentHandle* aOldParent, nsIContentHandle* aNewParent)
472 : {
473 0 : NS_PRECONDITION(aOldParent, "Null old parent");
474 0 : NS_PRECONDITION(aNewParent, "Null new parent");
475 :
476 0 : if (mBuilder) {
477 : nsresult rv = nsHtml5TreeOperation::AppendChildrenToNewParent(
478 : static_cast<nsIContent*>(aOldParent),
479 : static_cast<nsIContent*>(aNewParent),
480 0 : mBuilder);
481 0 : if (NS_FAILED(rv)) {
482 0 : MarkAsBrokenAndRequestSuspension(rv);
483 : }
484 0 : return;
485 : }
486 :
487 0 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
488 0 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
489 0 : treeOp->Init(eTreeOpAppendChildrenToNewParent, aOldParent, aNewParent);
490 : }
491 :
492 : void
493 0 : nsHtml5TreeBuilder::insertFosterParentedCharacters(char16_t* aBuffer, int32_t aStart, int32_t aLength, nsIContentHandle* aTable, nsIContentHandle* aStackParent)
494 : {
495 0 : NS_PRECONDITION(aBuffer, "Null buffer");
496 0 : NS_PRECONDITION(aTable, "Null table");
497 0 : NS_PRECONDITION(aStackParent, "Null stack parent");
498 0 : MOZ_ASSERT(!aStart, "aStart must always be zero.");
499 :
500 0 : if (mBuilder) {
501 0 : nsresult rv = nsHtml5TreeOperation::FosterParentText(
502 : static_cast<nsIContent*>(aStackParent),
503 : aBuffer, // XXX aStart always ignored???
504 : aLength,
505 : static_cast<nsIContent*>(aTable),
506 0 : mBuilder);
507 0 : if (NS_FAILED(rv)) {
508 0 : MarkAsBrokenAndRequestSuspension(rv);
509 : }
510 0 : return;
511 : }
512 :
513 0 : char16_t* bufferCopy = new (mozilla::fallible) char16_t[aLength];
514 0 : if (!bufferCopy) {
515 : // Just assigning mBroken instead of generating tree op. The caller
516 : // of tokenizeBuffer() will call MarkAsBroken() as appropriate.
517 0 : mBroken = NS_ERROR_OUT_OF_MEMORY;
518 0 : requestSuspension();
519 0 : return;
520 : }
521 :
522 0 : memcpy(bufferCopy, aBuffer, aLength * sizeof(char16_t));
523 :
524 0 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
525 0 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
526 0 : treeOp->Init(eTreeOpFosterParentText, bufferCopy, aLength, aStackParent, aTable);
527 : }
528 :
529 : void
530 0 : nsHtml5TreeBuilder::insertFosterParentedChild(nsIContentHandle* aChild, nsIContentHandle* aTable, nsIContentHandle* aStackParent)
531 : {
532 0 : NS_PRECONDITION(aChild, "Null child");
533 0 : NS_PRECONDITION(aTable, "Null table");
534 0 : NS_PRECONDITION(aStackParent, "Null stack parent");
535 :
536 0 : if (mBuilder) {
537 : nsresult rv = nsHtml5TreeOperation::FosterParent(
538 : static_cast<nsIContent*>(aChild),
539 : static_cast<nsIContent*>(aStackParent),
540 : static_cast<nsIContent*>(aTable),
541 0 : mBuilder);
542 0 : if (NS_FAILED(rv)) {
543 0 : MarkAsBrokenAndRequestSuspension(rv);
544 : }
545 0 : return;
546 : }
547 :
548 0 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
549 0 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
550 0 : treeOp->Init(eTreeOpFosterParent, aChild, aStackParent, aTable);
551 : }
552 :
553 : void
554 12 : nsHtml5TreeBuilder::appendCharacters(nsIContentHandle* aParent, char16_t* aBuffer, int32_t aStart, int32_t aLength)
555 : {
556 12 : NS_PRECONDITION(aBuffer, "Null buffer");
557 12 : NS_PRECONDITION(aParent, "Null parent");
558 12 : MOZ_ASSERT(!aStart, "aStart must always be zero.");
559 :
560 12 : if (mBuilder) {
561 0 : nsresult rv = nsHtml5TreeOperation::AppendText(
562 : aBuffer, // XXX aStart always ignored???
563 : aLength,
564 0 : static_cast<nsIContent*>(deepTreeSurrogateParent ?
565 : deepTreeSurrogateParent : aParent),
566 0 : mBuilder);
567 0 : if (NS_FAILED(rv)) {
568 0 : MarkAsBrokenAndRequestSuspension(rv);
569 : }
570 0 : return;
571 : }
572 :
573 24 : char16_t* bufferCopy = new (mozilla::fallible) char16_t[aLength];
574 12 : if (!bufferCopy) {
575 : // Just assigning mBroken instead of generating tree op. The caller
576 : // of tokenizeBuffer() will call MarkAsBroken() as appropriate.
577 0 : mBroken = NS_ERROR_OUT_OF_MEMORY;
578 0 : requestSuspension();
579 0 : return;
580 : }
581 :
582 12 : memcpy(bufferCopy, aBuffer, aLength * sizeof(char16_t));
583 :
584 12 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
585 12 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
586 12 : treeOp->Init(eTreeOpAppendText, bufferCopy, aLength,
587 24 : deepTreeSurrogateParent ? deepTreeSurrogateParent : aParent);
588 : }
589 :
590 : void
591 0 : nsHtml5TreeBuilder::appendIsindexPrompt(nsIContentHandle* aParent)
592 : {
593 0 : NS_PRECONDITION(aParent, "Null parent");
594 :
595 0 : if (mBuilder) {
596 : nsresult rv = nsHtml5TreeOperation::AppendIsindexPrompt(
597 : static_cast<nsIContent*>(aParent),
598 0 : mBuilder);
599 0 : if (NS_FAILED(rv)) {
600 0 : MarkAsBrokenAndRequestSuspension(rv);
601 : }
602 0 : return;
603 : }
604 :
605 0 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
606 0 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
607 0 : treeOp->Init(eTreeOpAppendIsindexPrompt, aParent);
608 : }
609 :
610 : void
611 3 : nsHtml5TreeBuilder::appendComment(nsIContentHandle* aParent, char16_t* aBuffer, int32_t aStart, int32_t aLength)
612 : {
613 3 : NS_PRECONDITION(aBuffer, "Null buffer");
614 3 : NS_PRECONDITION(aParent, "Null parent");
615 3 : MOZ_ASSERT(!aStart, "aStart must always be zero.");
616 :
617 3 : if (deepTreeSurrogateParent) {
618 0 : return;
619 : }
620 :
621 3 : if (mBuilder) {
622 : nsresult rv = nsHtml5TreeOperation::AppendComment(
623 : static_cast<nsIContent*>(aParent),
624 : aBuffer, // XXX aStart always ignored???
625 : aLength,
626 0 : mBuilder);
627 0 : if (NS_FAILED(rv)) {
628 0 : MarkAsBrokenAndRequestSuspension(rv);
629 : }
630 0 : return;
631 : }
632 :
633 6 : char16_t* bufferCopy = new (mozilla::fallible) char16_t[aLength];
634 3 : if (!bufferCopy) {
635 : // Just assigning mBroken instead of generating tree op. The caller
636 : // of tokenizeBuffer() will call MarkAsBroken() as appropriate.
637 0 : mBroken = NS_ERROR_OUT_OF_MEMORY;
638 0 : requestSuspension();
639 0 : return;
640 : }
641 :
642 3 : memcpy(bufferCopy, aBuffer, aLength * sizeof(char16_t));
643 :
644 3 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
645 3 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
646 3 : treeOp->Init(eTreeOpAppendComment, bufferCopy, aLength, aParent);
647 : }
648 :
649 : void
650 2 : nsHtml5TreeBuilder::appendCommentToDocument(char16_t* aBuffer, int32_t aStart, int32_t aLength)
651 : {
652 2 : NS_PRECONDITION(aBuffer, "Null buffer");
653 2 : MOZ_ASSERT(!aStart, "aStart must always be zero.");
654 :
655 2 : if (mBuilder) {
656 : nsresult rv = nsHtml5TreeOperation::AppendCommentToDocument(
657 : aBuffer, // XXX aStart always ignored???
658 : aLength,
659 0 : mBuilder);
660 0 : if (NS_FAILED(rv)) {
661 0 : MarkAsBrokenAndRequestSuspension(rv);
662 : }
663 0 : return;
664 : }
665 :
666 4 : char16_t* bufferCopy = new (mozilla::fallible) char16_t[aLength];
667 2 : if (!bufferCopy) {
668 : // Just assigning mBroken instead of generating tree op. The caller
669 : // of tokenizeBuffer() will call MarkAsBroken() as appropriate.
670 0 : mBroken = NS_ERROR_OUT_OF_MEMORY;
671 0 : requestSuspension();
672 0 : return;
673 : }
674 :
675 2 : memcpy(bufferCopy, aBuffer, aLength * sizeof(char16_t));
676 :
677 2 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
678 2 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
679 2 : treeOp->Init(eTreeOpAppendCommentToDocument, bufferCopy, aLength);
680 : }
681 :
682 : void
683 0 : nsHtml5TreeBuilder::addAttributesToElement(nsIContentHandle* aElement, nsHtml5HtmlAttributes* aAttributes)
684 : {
685 0 : NS_PRECONDITION(aElement, "Null element");
686 0 : NS_PRECONDITION(aAttributes, "Null attributes");
687 :
688 0 : if (aAttributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
689 0 : return;
690 : }
691 :
692 0 : if (mBuilder) {
693 0 : MOZ_ASSERT(aAttributes == tokenizer->GetAttributes(),
694 : "Using attribute other than the tokenizer's to add to body or html.");
695 : nsresult rv = nsHtml5TreeOperation::AddAttributes(
696 : static_cast<nsIContent*>(aElement),
697 : aAttributes,
698 0 : mBuilder);
699 0 : if (NS_FAILED(rv)) {
700 0 : MarkAsBrokenAndRequestSuspension(rv);
701 : }
702 0 : return;
703 : }
704 :
705 0 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
706 0 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
707 0 : treeOp->Init(aElement, aAttributes);
708 : }
709 :
710 : void
711 4 : nsHtml5TreeBuilder::markMalformedIfScript(nsIContentHandle* aElement)
712 : {
713 4 : NS_PRECONDITION(aElement, "Null element");
714 :
715 4 : if (mBuilder) {
716 : nsHtml5TreeOperation::MarkMalformedIfScript(
717 0 : static_cast<nsIContent*>(aElement));
718 0 : return;
719 : }
720 :
721 4 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
722 4 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
723 4 : treeOp->Init(eTreeOpMarkMalformedIfScript, aElement);
724 : }
725 :
726 : void
727 4 : nsHtml5TreeBuilder::start(bool fragment)
728 : {
729 4 : mCurrentHtmlScriptIsAsyncOrDefer = false;
730 4 : deepTreeSurrogateParent = nullptr;
731 : #ifdef DEBUG
732 4 : mActive = true;
733 : #endif
734 4 : }
735 :
736 : void
737 1 : nsHtml5TreeBuilder::end()
738 : {
739 1 : mOpQueue.Clear();
740 : #ifdef DEBUG
741 1 : mActive = false;
742 : #endif
743 1 : }
744 :
745 : void
746 1 : nsHtml5TreeBuilder::appendDoctypeToDocument(nsIAtom* aName,
747 : nsHtml5String aPublicId,
748 : nsHtml5String aSystemId)
749 : {
750 1 : NS_PRECONDITION(aName, "Null name");
751 2 : nsString publicId; // Not Auto, because using it to hold nsStringBuffer*
752 2 : nsString systemId; // Not Auto, because using it to hold nsStringBuffer*
753 1 : aPublicId.ToString(publicId);
754 1 : aSystemId.ToString(systemId);
755 1 : if (mBuilder) {
756 0 : nsCOMPtr<nsIAtom> name = nsHtml5TreeOperation::Reget(aName);
757 0 : nsresult rv = nsHtml5TreeOperation::AppendDoctypeToDocument(
758 0 : name, publicId, systemId, mBuilder);
759 0 : if (NS_FAILED(rv)) {
760 0 : MarkAsBrokenAndRequestSuspension(rv);
761 : }
762 0 : return;
763 : }
764 :
765 1 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
766 1 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
767 1 : treeOp->Init(aName, publicId, systemId);
768 : // nsXMLContentSink can flush here, but what's the point?
769 : // It can also interrupt here, but we can't.
770 : }
771 :
772 : void
773 14 : nsHtml5TreeBuilder::elementPushed(int32_t aNamespace, nsIAtom* aName, nsIContentHandle* aElement)
774 : {
775 14 : NS_ASSERTION(aNamespace == kNameSpaceID_XHTML || aNamespace == kNameSpaceID_SVG || aNamespace == kNameSpaceID_MathML, "Element isn't HTML, SVG or MathML!");
776 14 : NS_ASSERTION(aName, "Element doesn't have local name!");
777 14 : NS_ASSERTION(aElement, "No element!");
778 : /*
779 : * The frame constructor uses recursive algorithms, so it can't deal with
780 : * arbitrarily deep trees. This is especially a problem on Windows where
781 : * the permitted depth of the runtime stack is rather small.
782 : *
783 : * The following is a protection against author incompetence--not against
784 : * malice. There are other ways to make the DOM deep anyway.
785 : *
786 : * The basic idea is that when the tree builder stack gets too deep,
787 : * append operations no longer append to the node that the HTML parsing
788 : * algorithm says they should but instead text nodes are append to the last
789 : * element that was seen before a magic tree builder stack threshold was
790 : * reached and element and comment nodes aren't appended to the DOM at all.
791 : *
792 : * However, for security reasons, non-child descendant text nodes inside an
793 : * SVG script or style element should not become children. Also, non-cell
794 : * table elements shouldn't be used as surrogate parents for user experience
795 : * reasons.
796 : */
797 14 : if (!deepTreeSurrogateParent && currentPtr >= MAX_REFLOW_DEPTH &&
798 0 : !(aName == nsGkAtoms::script || aName == nsGkAtoms::table ||
799 0 : aName == nsGkAtoms::thead || aName == nsGkAtoms::tfoot ||
800 0 : aName == nsGkAtoms::tbody || aName == nsGkAtoms::tr ||
801 0 : aName == nsGkAtoms::colgroup || aName == nsGkAtoms::style)) {
802 0 : deepTreeSurrogateParent = aElement;
803 : }
804 14 : if (aNamespace != kNameSpaceID_XHTML) {
805 0 : return;
806 : }
807 14 : if (aName == nsGkAtoms::body || aName == nsGkAtoms::frameset) {
808 2 : if (mBuilder) {
809 : // InnerHTML and DOMParser shouldn't start layout anyway
810 0 : return;
811 : }
812 2 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
813 2 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
814 2 : treeOp->Init(eTreeOpStartLayout);
815 2 : return;
816 : }
817 12 : if (aName == nsGkAtoms::input || aName == nsGkAtoms::button) {
818 0 : if (mBuilder) {
819 0 : nsHtml5TreeOperation::DoneCreatingElement(static_cast<nsIContent*>(aElement));
820 : } else {
821 0 : mOpQueue.AppendElement()->Init(eTreeOpDoneCreatingElement, aElement);
822 : }
823 0 : return;
824 : }
825 24 : if (aName == nsGkAtoms::audio || aName == nsGkAtoms::video ||
826 12 : aName == nsGkAtoms::menuitem) {
827 0 : if (mBuilder) {
828 0 : nsHtml5TreeOperation::DoneCreatingElement(static_cast<nsIContent*>(aElement));
829 : } else {
830 0 : mOpQueue.AppendElement()->Init(eTreeOpDoneCreatingElement, aElement);
831 : }
832 0 : return;
833 : }
834 12 : if (mSpeculativeLoadStage && aName == nsGkAtoms::picture) {
835 : // mSpeculativeLoadStage is non-null only in the off-the-main-thread
836 : // tree builder, which handles the network stream
837 : //
838 : // See comments in nsHtml5SpeculativeLoad.h about <picture> preloading
839 0 : mSpeculativeLoadQueue.AppendElement()->InitOpenPicture();
840 : }
841 : }
842 :
843 : void
844 14 : nsHtml5TreeBuilder::elementPopped(int32_t aNamespace, nsIAtom* aName, nsIContentHandle* aElement)
845 : {
846 14 : NS_ASSERTION(aNamespace == kNameSpaceID_XHTML || aNamespace == kNameSpaceID_SVG || aNamespace == kNameSpaceID_MathML, "Element isn't HTML, SVG or MathML!");
847 14 : NS_ASSERTION(aName, "Element doesn't have local name!");
848 14 : NS_ASSERTION(aElement, "No element!");
849 14 : if (deepTreeSurrogateParent && currentPtr <= MAX_REFLOW_DEPTH) {
850 0 : deepTreeSurrogateParent = nullptr;
851 : }
852 14 : if (aNamespace == kNameSpaceID_MathML) {
853 0 : return;
854 : }
855 : // we now have only SVG and HTML
856 14 : if (aName == nsGkAtoms::script) {
857 5 : if (mPreventScriptExecution) {
858 0 : if (mBuilder) {
859 0 : nsHtml5TreeOperation::PreventScriptExecution(static_cast<nsIContent*>(aElement));
860 0 : return;
861 : }
862 0 : mOpQueue.AppendElement()->Init(eTreeOpPreventScriptExecution, aElement);
863 0 : return;
864 : }
865 5 : if (mBuilder) {
866 0 : return;
867 : }
868 5 : if (mCurrentHtmlScriptIsAsyncOrDefer) {
869 0 : NS_ASSERTION(aNamespace == kNameSpaceID_XHTML,
870 : "Only HTML scripts may be async/defer.");
871 0 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
872 0 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
873 0 : treeOp->Init(eTreeOpRunScriptAsyncDefer, aElement);
874 0 : mCurrentHtmlScriptIsAsyncOrDefer = false;
875 0 : return;
876 : }
877 5 : requestSuspension();
878 5 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
879 5 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
880 5 : treeOp->InitScript(aElement);
881 5 : return;
882 : }
883 9 : if (aName == nsGkAtoms::title) {
884 1 : if (mBuilder) {
885 0 : nsHtml5TreeOperation::DoneAddingChildren(static_cast<nsIContent*>(aElement));
886 0 : return;
887 : }
888 1 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
889 1 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
890 1 : treeOp->Init(eTreeOpDoneAddingChildren, aElement);
891 1 : return;
892 : }
893 8 : if (aName == nsGkAtoms::style ||
894 8 : (aNamespace == kNameSpaceID_XHTML && aName == nsGkAtoms::link)) {
895 0 : if (mBuilder) {
896 0 : MOZ_ASSERT(!nsContentUtils::IsSafeToRunScript(),
897 : "Scripts must be blocked.");
898 0 : mBuilder->UpdateStyleSheet(static_cast<nsIContent*>(aElement));
899 0 : return;
900 : }
901 0 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
902 0 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
903 0 : treeOp->Init(eTreeOpUpdateStyleSheet, aElement);
904 0 : return;
905 : }
906 8 : if (aNamespace == kNameSpaceID_SVG) {
907 0 : if (aName == nsGkAtoms::svg) {
908 0 : if (mBuilder) {
909 0 : nsHtml5TreeOperation::SvgLoad(static_cast<nsIContent*>(aElement));
910 0 : return;
911 : }
912 0 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
913 0 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
914 0 : treeOp->Init(eTreeOpSvgLoad, aElement);
915 : }
916 0 : return;
917 : }
918 : // we now have only HTML
919 : // Some HTML nodes need DoneAddingChildren() called to initialize
920 : // properly (e.g. form state restoration).
921 : // XXX expose ElementName group here and do switch
922 16 : if (aName == nsGkAtoms::object || aName == nsGkAtoms::applet ||
923 24 : aName == nsGkAtoms::select || aName == nsGkAtoms::textarea ||
924 8 : aName == nsGkAtoms::output) {
925 0 : if (mBuilder) {
926 0 : nsHtml5TreeOperation::DoneAddingChildren(static_cast<nsIContent*>(aElement));
927 0 : return;
928 : }
929 0 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
930 0 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
931 0 : treeOp->Init(eTreeOpDoneAddingChildren, aElement);
932 0 : return;
933 : }
934 8 : if (aName == nsGkAtoms::meta && !fragment && !mBuilder) {
935 2 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
936 2 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
937 2 : treeOp->Init(eTreeOpProcessMeta, aElement);
938 2 : return;
939 : }
940 6 : if (mSpeculativeLoadStage && aName == nsGkAtoms::picture) {
941 : // mSpeculativeLoadStage is non-null only in the off-the-main-thread
942 : // tree builder, which handles the network stream
943 : //
944 : // See comments in nsHtml5SpeculativeLoad.h about <picture> preloading
945 0 : mSpeculativeLoadQueue.AppendElement()->InitEndPicture();
946 : }
947 6 : return;
948 : }
949 :
950 : void
951 20 : nsHtml5TreeBuilder::accumulateCharacters(const char16_t* aBuf, int32_t aStart, int32_t aLength)
952 : {
953 20 : MOZ_RELEASE_ASSERT(charBufferLen + aLength <= charBuffer.length,
954 : "About to memcpy past the end of the buffer!");
955 20 : memcpy(charBuffer + charBufferLen, aBuf + aStart, sizeof(char16_t) * aLength);
956 20 : charBufferLen += aLength;
957 20 : }
958 :
959 : // INT32_MAX is (2^31)-1. Therefore, the highest power-of-two that fits
960 : // is 2^30. Note that this is counting char16_t units. The underlying
961 : // bytes will be twice that, but they fit even in 32-bit size_t even
962 : // if a contiguous chunk of memory of that size is pretty unlikely to
963 : // be available on a 32-bit system.
964 : #define MAX_POWER_OF_TWO_IN_INT32 0x40000000
965 :
966 : bool
967 9 : nsHtml5TreeBuilder::EnsureBufferSpace(int32_t aLength)
968 : {
969 : // TODO: Unify nsHtml5Tokenizer::strBuf and nsHtml5TreeBuilder::charBuffer
970 : // so that this method becomes unnecessary.
971 9 : CheckedInt<int32_t> worstCase(charBufferLen);
972 9 : worstCase += aLength;
973 9 : if (!worstCase.isValid()) {
974 0 : return false;
975 : }
976 9 : if (worstCase.value() > MAX_POWER_OF_TWO_IN_INT32) {
977 0 : return false;
978 : }
979 9 : if (!charBuffer) {
980 2 : if (worstCase.value() < MAX_POWER_OF_TWO_IN_INT32) {
981 : // Add one to round to the next power of two to avoid immediate
982 : // reallocation once there are a few characters in the buffer.
983 2 : worstCase += 1;
984 : }
985 2 : charBuffer = jArray<char16_t,int32_t>::newFallibleJArray(mozilla::RoundUpPow2(worstCase.value()));
986 2 : if (!charBuffer) {
987 0 : return false;
988 : }
989 7 : } else if (worstCase.value() > charBuffer.length) {
990 0 : jArray<char16_t,int32_t> newBuf = jArray<char16_t,int32_t>::newFallibleJArray(mozilla::RoundUpPow2(worstCase.value()));
991 0 : if (!newBuf) {
992 0 : return false;
993 : }
994 0 : memcpy(newBuf, charBuffer, sizeof(char16_t) * size_t(charBufferLen));
995 0 : charBuffer = newBuf;
996 : }
997 9 : return true;
998 : }
999 :
1000 : nsIContentHandle*
1001 14 : nsHtml5TreeBuilder::AllocateContentHandle()
1002 : {
1003 14 : if (MOZ_UNLIKELY(mBuilder)) {
1004 0 : MOZ_ASSERT_UNREACHABLE("Must never allocate a handle with builder.");
1005 : return nullptr;
1006 : }
1007 14 : if (mHandlesUsed == NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH) {
1008 0 : mOldHandles.AppendElement(Move(mHandles));
1009 0 : mHandles = MakeUnique<nsIContent*[]>(NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH);
1010 0 : mHandlesUsed = 0;
1011 : }
1012 : #ifdef DEBUG
1013 14 : mHandles[mHandlesUsed] = reinterpret_cast<nsIContent*>(uintptr_t(0xC0DEDBAD));
1014 : #endif
1015 14 : return &mHandles[mHandlesUsed++];
1016 : }
1017 :
1018 : bool
1019 14 : nsHtml5TreeBuilder::HasScript()
1020 : {
1021 14 : uint32_t len = mOpQueue.Length();
1022 14 : if (!len) {
1023 0 : return false;
1024 : }
1025 14 : return mOpQueue.ElementAt(len - 1).IsRunScript();
1026 : }
1027 :
1028 : bool
1029 14 : nsHtml5TreeBuilder::Flush(bool aDiscretionary)
1030 : {
1031 14 : if (MOZ_UNLIKELY(mBuilder)) {
1032 0 : MOZ_ASSERT_UNREACHABLE("Must never flush with builder.");
1033 : return false;
1034 : }
1035 14 : if (NS_SUCCEEDED(mBroken)) {
1036 30 : if (!aDiscretionary ||
1037 2 : !(charBufferLen &&
1038 0 : currentPtr >= 0 &&
1039 0 : stack[currentPtr]->isFosterParenting())) {
1040 : // Don't flush text on discretionary flushes if the current element on
1041 : // the stack is a foster-parenting element and there's pending text,
1042 : // because flushing in that case would make the tree shape dependent on
1043 : // where the flush points fall.
1044 14 : flushCharacters();
1045 : }
1046 14 : FlushLoads();
1047 : }
1048 14 : if (mOpSink) {
1049 14 : bool hasOps = !mOpQueue.IsEmpty();
1050 14 : if (hasOps) {
1051 : // If the builder is broken and mOpQueue is not empty, there must be
1052 : // one op and it must be eTreeOpMarkAsBroken.
1053 8 : if (NS_FAILED(mBroken)) {
1054 0 : MOZ_ASSERT(mOpQueue.Length() == 1,
1055 : "Tree builder is broken with a non-empty op queue whose length isn't 1.");
1056 0 : MOZ_ASSERT(mOpQueue[0].IsMarkAsBroken(),
1057 : "Tree builder is broken but the op in queue is not marked as broken.");
1058 : }
1059 8 : mOpSink->MoveOpsFrom(mOpQueue);
1060 : }
1061 14 : return hasOps;
1062 : }
1063 : // no op sink: throw away ops
1064 0 : mOpQueue.Clear();
1065 0 : return false;
1066 : }
1067 :
1068 : void
1069 16 : nsHtml5TreeBuilder::FlushLoads()
1070 : {
1071 16 : if (MOZ_UNLIKELY(mBuilder)) {
1072 0 : MOZ_ASSERT_UNREACHABLE("Must never flush loads with builder.");
1073 : return;
1074 : }
1075 16 : if (!mSpeculativeLoadQueue.IsEmpty()) {
1076 5 : mSpeculativeLoadStage->MoveSpeculativeLoadsFrom(mSpeculativeLoadQueue);
1077 : }
1078 16 : }
1079 :
1080 : void
1081 2 : nsHtml5TreeBuilder::SetDocumentCharset(NotNull<const Encoding*> aEncoding,
1082 : int32_t aCharsetSource)
1083 : {
1084 2 : if (mBuilder) {
1085 0 : mBuilder->SetDocumentCharsetAndSource(aEncoding, aCharsetSource);
1086 2 : } else if (mSpeculativeLoadStage) {
1087 4 : nsAutoCString charset;
1088 2 : aEncoding->Name(charset);
1089 2 : mSpeculativeLoadQueue.AppendElement()->InitSetDocumentCharset(
1090 2 : charset, aCharsetSource);
1091 : } else {
1092 0 : mOpQueue.AppendElement()->Init(
1093 0 : eTreeOpSetDocumentCharset, aEncoding, aCharsetSource);
1094 : }
1095 2 : }
1096 :
1097 : void
1098 2 : nsHtml5TreeBuilder::StreamEnded()
1099 : {
1100 2 : MOZ_ASSERT(!mBuilder, "Must not call StreamEnded with builder.");
1101 2 : MOZ_ASSERT(!fragment, "Must not parse fragments off the main thread.");
1102 2 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
1103 2 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
1104 2 : treeOp->Init(eTreeOpStreamEnded);
1105 2 : }
1106 :
1107 : void
1108 0 : nsHtml5TreeBuilder::NeedsCharsetSwitchTo(NotNull<const Encoding*> aEncoding,
1109 : int32_t aCharsetSource,
1110 : int32_t aLineNumber)
1111 : {
1112 0 : if (MOZ_UNLIKELY(mBuilder)) {
1113 0 : MOZ_ASSERT_UNREACHABLE("Must never switch charset with builder.");
1114 : return;
1115 : }
1116 0 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
1117 0 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
1118 : treeOp->Init(eTreeOpNeedsCharsetSwitchTo,
1119 : aEncoding,
1120 : aCharsetSource,
1121 0 : aLineNumber);
1122 0 : }
1123 :
1124 : void
1125 0 : nsHtml5TreeBuilder::MaybeComplainAboutCharset(const char* aMsgId,
1126 : bool aError,
1127 : int32_t aLineNumber)
1128 : {
1129 0 : if (MOZ_UNLIKELY(mBuilder)) {
1130 0 : MOZ_ASSERT_UNREACHABLE("Must never complain about charset with builder.");
1131 : return;
1132 : }
1133 0 : mOpQueue.AppendElement()->Init(aMsgId, aError, aLineNumber);
1134 0 : }
1135 :
1136 : void
1137 5 : nsHtml5TreeBuilder::AddSnapshotToScript(nsAHtml5TreeBuilderState* aSnapshot, int32_t aLine)
1138 : {
1139 5 : if (MOZ_UNLIKELY(mBuilder)) {
1140 0 : MOZ_ASSERT_UNREACHABLE("Must never use snapshots with builder.");
1141 : return;
1142 : }
1143 5 : NS_PRECONDITION(HasScript(), "No script to add a snapshot to!");
1144 5 : NS_PRECONDITION(aSnapshot, "Got null snapshot.");
1145 5 : mOpQueue.ElementAt(mOpQueue.Length() - 1).SetSnapshot(aSnapshot, aLine);
1146 5 : }
1147 :
1148 : void
1149 0 : nsHtml5TreeBuilder::DropHandles()
1150 : {
1151 0 : MOZ_ASSERT(!mBuilder, "Must not drop handles with builder.");
1152 0 : mOldHandles.Clear();
1153 0 : mHandlesUsed = 0;
1154 0 : }
1155 :
1156 : void
1157 0 : nsHtml5TreeBuilder::MarkAsBroken(nsresult aRv)
1158 : {
1159 0 : if (MOZ_UNLIKELY(mBuilder)) {
1160 0 : MOZ_ASSERT_UNREACHABLE("Must not call this with builder.");
1161 : return;
1162 : }
1163 0 : mBroken = aRv;
1164 0 : mOpQueue.Clear(); // Previous ops don't matter anymore
1165 0 : mOpQueue.AppendElement()->Init(aRv);
1166 0 : }
1167 :
1168 : void
1169 0 : nsHtml5TreeBuilder::MarkAsBrokenFromPortability(nsresult aRv)
1170 : {
1171 0 : if (mBuilder) {
1172 0 : MarkAsBrokenAndRequestSuspension(aRv);
1173 0 : return;
1174 : }
1175 0 : mBroken = aRv;
1176 0 : requestSuspension();
1177 : }
1178 :
1179 : void
1180 0 : nsHtml5TreeBuilder::StartPlainTextViewSource(const nsAutoString& aTitle)
1181 : {
1182 0 : MOZ_ASSERT(!mBuilder, "Must not view source with builder.");
1183 : startTag(nsHtml5ElementName::ELT_TITLE,
1184 : nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES,
1185 0 : false);
1186 :
1187 : // XUL will add the "Source of: " prefix.
1188 0 : uint32_t length = aTitle.Length();
1189 0 : if (length > INT32_MAX) {
1190 0 : length = INT32_MAX;
1191 : }
1192 0 : characters(aTitle.get(), 0, (int32_t)length);
1193 0 : endTag(nsHtml5ElementName::ELT_TITLE);
1194 :
1195 0 : startTag(nsHtml5ElementName::ELT_LINK,
1196 : nsHtml5ViewSourceUtils::NewLinkAttributes(),
1197 0 : false);
1198 :
1199 0 : startTag(nsHtml5ElementName::ELT_BODY,
1200 : nsHtml5ViewSourceUtils::NewBodyAttributes(),
1201 0 : false);
1202 :
1203 0 : StartPlainTextBody();
1204 0 : }
1205 :
1206 : void
1207 0 : nsHtml5TreeBuilder::StartPlainText()
1208 : {
1209 0 : MOZ_ASSERT(!mBuilder, "Must not view source with builder.");
1210 0 : startTag(nsHtml5ElementName::ELT_LINK,
1211 : nsHtml5PlainTextUtils::NewLinkAttributes(),
1212 0 : false);
1213 :
1214 0 : StartPlainTextBody();
1215 0 : }
1216 :
1217 : void
1218 0 : nsHtml5TreeBuilder::StartPlainTextBody()
1219 : {
1220 0 : MOZ_ASSERT(!mBuilder, "Must not view source with builder.");
1221 : startTag(nsHtml5ElementName::ELT_PRE,
1222 : nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES,
1223 0 : false);
1224 0 : needToDropLF = false;
1225 0 : }
1226 :
1227 : // DocumentModeHandler
1228 : void
1229 2 : nsHtml5TreeBuilder::documentMode(nsHtml5DocumentMode m)
1230 : {
1231 2 : if (mBuilder) {
1232 0 : mBuilder->SetDocumentMode(m);
1233 0 : return;
1234 : }
1235 2 : if (mSpeculativeLoadStage) {
1236 2 : mSpeculativeLoadQueue.AppendElement()->InitSetDocumentMode(m);
1237 2 : return;
1238 : }
1239 0 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
1240 0 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
1241 0 : treeOp->Init(m);
1242 : }
1243 :
1244 : nsIContentHandle*
1245 0 : nsHtml5TreeBuilder::getDocumentFragmentForTemplate(nsIContentHandle* aTemplate)
1246 : {
1247 0 : if (mBuilder) {
1248 0 : return nsHtml5TreeOperation::GetDocumentFragmentForTemplate(static_cast<nsIContent*>(aTemplate));
1249 : }
1250 0 : nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
1251 0 : NS_ASSERTION(treeOp, "Tree op allocation failed.");
1252 0 : nsIContentHandle* fragHandle = AllocateContentHandle();
1253 0 : treeOp->Init(eTreeOpGetDocumentFragmentForTemplate, aTemplate, fragHandle);
1254 0 : return fragHandle;
1255 : }
1256 :
1257 : nsIContentHandle*
1258 0 : nsHtml5TreeBuilder::getFormPointerForContext(nsIContentHandle* aContext)
1259 : {
1260 0 : MOZ_ASSERT(mBuilder, "Must have builder.");
1261 0 : if (!aContext) {
1262 0 : return nullptr;
1263 : }
1264 :
1265 0 : MOZ_ASSERT(NS_IsMainThread());
1266 :
1267 : // aContext must always be an element that already exists
1268 : // in the document.
1269 0 : nsIContent* contextNode = static_cast<nsIContent*>(aContext);
1270 0 : nsIContent* currentAncestor = contextNode;
1271 :
1272 : // We traverse the ancestors of the context node to find the nearest
1273 : // form pointer. This traversal is why aContext must not be an emtpy handle.
1274 0 : nsIContent* nearestForm = nullptr;
1275 0 : while (currentAncestor) {
1276 0 : if (currentAncestor->IsHTMLElement(nsGkAtoms::form)) {
1277 0 : nearestForm = currentAncestor;
1278 0 : break;
1279 : }
1280 0 : currentAncestor = currentAncestor->GetParent();
1281 : }
1282 :
1283 0 : if (!nearestForm) {
1284 0 : return nullptr;
1285 : }
1286 :
1287 0 : return nearestForm;
1288 : }
1289 :
1290 : // Error reporting
1291 :
1292 : void
1293 0 : nsHtml5TreeBuilder::EnableViewSource(nsHtml5Highlighter* aHighlighter)
1294 : {
1295 0 : MOZ_ASSERT(!mBuilder, "Must not view source with builder.");
1296 0 : mViewSource = aHighlighter;
1297 0 : }
1298 :
1299 : void
1300 0 : nsHtml5TreeBuilder::errStrayStartTag(nsIAtom* aName)
1301 : {
1302 0 : if (MOZ_UNLIKELY(mViewSource)) {
1303 0 : mViewSource->AddErrorToCurrentRun("errStrayStartTag2", aName);
1304 : }
1305 0 : }
1306 :
1307 : void
1308 0 : nsHtml5TreeBuilder::errStrayEndTag(nsIAtom* aName)
1309 : {
1310 0 : if (MOZ_UNLIKELY(mViewSource)) {
1311 0 : mViewSource->AddErrorToCurrentRun("errStrayEndTag", aName);
1312 : }
1313 0 : }
1314 :
1315 : void
1316 0 : nsHtml5TreeBuilder::errUnclosedElements(int32_t aIndex, nsIAtom* aName)
1317 : {
1318 0 : if (MOZ_UNLIKELY(mViewSource)) {
1319 0 : mViewSource->AddErrorToCurrentRun("errUnclosedElements", aName);
1320 : }
1321 0 : }
1322 :
1323 : void
1324 0 : nsHtml5TreeBuilder::errUnclosedElementsImplied(int32_t aIndex, nsIAtom* aName)
1325 : {
1326 0 : if (MOZ_UNLIKELY(mViewSource)) {
1327 0 : mViewSource->AddErrorToCurrentRun("errUnclosedElementsImplied",
1328 0 : aName);
1329 : }
1330 0 : }
1331 :
1332 : void
1333 0 : nsHtml5TreeBuilder::errUnclosedElementsCell(int32_t aIndex)
1334 : {
1335 0 : if (MOZ_UNLIKELY(mViewSource)) {
1336 0 : mViewSource->AddErrorToCurrentRun("errUnclosedElementsCell");
1337 : }
1338 0 : }
1339 :
1340 : void
1341 0 : nsHtml5TreeBuilder::errStrayDoctype()
1342 : {
1343 0 : if (MOZ_UNLIKELY(mViewSource)) {
1344 0 : mViewSource->AddErrorToCurrentRun("errStrayDoctype");
1345 : }
1346 0 : }
1347 :
1348 : void
1349 0 : nsHtml5TreeBuilder::errAlmostStandardsDoctype()
1350 : {
1351 0 : if (MOZ_UNLIKELY(mViewSource) && !isSrcdocDocument) {
1352 0 : mViewSource->AddErrorToCurrentRun("errAlmostStandardsDoctype");
1353 : }
1354 0 : }
1355 :
1356 : void
1357 1 : nsHtml5TreeBuilder::errQuirkyDoctype()
1358 : {
1359 1 : if (MOZ_UNLIKELY(mViewSource) && !isSrcdocDocument) {
1360 0 : mViewSource->AddErrorToCurrentRun("errQuirkyDoctype");
1361 : }
1362 1 : }
1363 :
1364 : void
1365 0 : nsHtml5TreeBuilder::errNonSpaceInTrailer()
1366 : {
1367 0 : if (MOZ_UNLIKELY(mViewSource)) {
1368 0 : mViewSource->AddErrorToCurrentRun("errNonSpaceInTrailer");
1369 : }
1370 0 : }
1371 :
1372 : void
1373 0 : nsHtml5TreeBuilder::errNonSpaceAfterFrameset()
1374 : {
1375 0 : if (MOZ_UNLIKELY(mViewSource)) {
1376 0 : mViewSource->AddErrorToCurrentRun("errNonSpaceAfterFrameset");
1377 : }
1378 0 : }
1379 :
1380 : void
1381 0 : nsHtml5TreeBuilder::errNonSpaceInFrameset()
1382 : {
1383 0 : if (MOZ_UNLIKELY(mViewSource)) {
1384 0 : mViewSource->AddErrorToCurrentRun("errNonSpaceInFrameset");
1385 : }
1386 0 : }
1387 :
1388 : void
1389 0 : nsHtml5TreeBuilder::errNonSpaceAfterBody()
1390 : {
1391 0 : if (MOZ_UNLIKELY(mViewSource)) {
1392 0 : mViewSource->AddErrorToCurrentRun("errNonSpaceAfterBody");
1393 : }
1394 0 : }
1395 :
1396 : void
1397 0 : nsHtml5TreeBuilder::errNonSpaceInColgroupInFragment()
1398 : {
1399 0 : if (MOZ_UNLIKELY(mViewSource)) {
1400 0 : mViewSource->AddErrorToCurrentRun("errNonSpaceInColgroupInFragment");
1401 : }
1402 0 : }
1403 :
1404 : void
1405 0 : nsHtml5TreeBuilder::errNonSpaceInNoscriptInHead()
1406 : {
1407 0 : if (MOZ_UNLIKELY(mViewSource)) {
1408 0 : mViewSource->AddErrorToCurrentRun("errNonSpaceInNoscriptInHead");
1409 : }
1410 0 : }
1411 :
1412 : void
1413 0 : nsHtml5TreeBuilder::errFooBetweenHeadAndBody(nsIAtom* aName)
1414 : {
1415 0 : if (MOZ_UNLIKELY(mViewSource)) {
1416 0 : mViewSource->AddErrorToCurrentRun("errFooBetweenHeadAndBody", aName);
1417 : }
1418 0 : }
1419 :
1420 : void
1421 1 : nsHtml5TreeBuilder::errStartTagWithoutDoctype()
1422 : {
1423 1 : if (MOZ_UNLIKELY(mViewSource) && !isSrcdocDocument) {
1424 0 : mViewSource->AddErrorToCurrentRun("errStartTagWithoutDoctype");
1425 : }
1426 1 : }
1427 :
1428 : void
1429 0 : nsHtml5TreeBuilder::errNoSelectInTableScope()
1430 : {
1431 0 : if (MOZ_UNLIKELY(mViewSource)) {
1432 0 : mViewSource->AddErrorToCurrentRun("errNoSelectInTableScope");
1433 : }
1434 0 : }
1435 :
1436 : void
1437 0 : nsHtml5TreeBuilder::errStartSelectWhereEndSelectExpected()
1438 : {
1439 0 : if (MOZ_UNLIKELY(mViewSource)) {
1440 0 : mViewSource->AddErrorToCurrentRun(
1441 0 : "errStartSelectWhereEndSelectExpected");
1442 : }
1443 0 : }
1444 :
1445 : void
1446 0 : nsHtml5TreeBuilder::errStartTagWithSelectOpen(nsIAtom* aName)
1447 : {
1448 0 : if (MOZ_UNLIKELY(mViewSource)) {
1449 0 : mViewSource->AddErrorToCurrentRun("errStartTagWithSelectOpen", aName);
1450 : }
1451 0 : }
1452 :
1453 : void
1454 0 : nsHtml5TreeBuilder::errBadStartTagInHead(nsIAtom* aName)
1455 : {
1456 0 : if (MOZ_UNLIKELY(mViewSource)) {
1457 0 : mViewSource->AddErrorToCurrentRun("errBadStartTagInHead2", aName);
1458 : }
1459 0 : }
1460 :
1461 : void
1462 0 : nsHtml5TreeBuilder::errImage()
1463 : {
1464 0 : if (MOZ_UNLIKELY(mViewSource)) {
1465 0 : mViewSource->AddErrorToCurrentRun("errImage");
1466 : }
1467 0 : }
1468 :
1469 : void
1470 0 : nsHtml5TreeBuilder::errIsindex()
1471 : {
1472 0 : if (MOZ_UNLIKELY(mViewSource)) {
1473 0 : mViewSource->AddErrorToCurrentRun("errIsindex");
1474 : }
1475 0 : }
1476 :
1477 : void
1478 0 : nsHtml5TreeBuilder::errFooSeenWhenFooOpen(nsIAtom* aName)
1479 : {
1480 0 : if (MOZ_UNLIKELY(mViewSource)) {
1481 0 : mViewSource->AddErrorToCurrentRun("errFooSeenWhenFooOpen", aName);
1482 : }
1483 0 : }
1484 :
1485 : void
1486 0 : nsHtml5TreeBuilder::errHeadingWhenHeadingOpen()
1487 : {
1488 0 : if (MOZ_UNLIKELY(mViewSource)) {
1489 0 : mViewSource->AddErrorToCurrentRun("errHeadingWhenHeadingOpen");
1490 : }
1491 0 : }
1492 :
1493 : void
1494 0 : nsHtml5TreeBuilder::errFramesetStart()
1495 : {
1496 0 : if (MOZ_UNLIKELY(mViewSource)) {
1497 0 : mViewSource->AddErrorToCurrentRun("errFramesetStart");
1498 : }
1499 0 : }
1500 :
1501 : void
1502 0 : nsHtml5TreeBuilder::errNoCellToClose()
1503 : {
1504 0 : if (MOZ_UNLIKELY(mViewSource)) {
1505 0 : mViewSource->AddErrorToCurrentRun("errNoCellToClose");
1506 : }
1507 0 : }
1508 :
1509 : void
1510 0 : nsHtml5TreeBuilder::errStartTagInTable(nsIAtom* aName)
1511 : {
1512 0 : if (MOZ_UNLIKELY(mViewSource)) {
1513 0 : mViewSource->AddErrorToCurrentRun("errStartTagInTable", aName);
1514 : }
1515 0 : }
1516 :
1517 : void
1518 0 : nsHtml5TreeBuilder::errFormWhenFormOpen()
1519 : {
1520 0 : if (MOZ_UNLIKELY(mViewSource)) {
1521 0 : mViewSource->AddErrorToCurrentRun("errFormWhenFormOpen");
1522 : }
1523 0 : }
1524 :
1525 : void
1526 0 : nsHtml5TreeBuilder::errTableSeenWhileTableOpen()
1527 : {
1528 0 : if (MOZ_UNLIKELY(mViewSource)) {
1529 0 : mViewSource->AddErrorToCurrentRun("errTableSeenWhileTableOpen");
1530 : }
1531 0 : }
1532 :
1533 : void
1534 0 : nsHtml5TreeBuilder::errStartTagInTableBody(nsIAtom* aName)
1535 : {
1536 0 : if (MOZ_UNLIKELY(mViewSource)) {
1537 0 : mViewSource->AddErrorToCurrentRun("errStartTagInTableBody", aName);
1538 : }
1539 0 : }
1540 :
1541 : void
1542 0 : nsHtml5TreeBuilder::errEndTagSeenWithoutDoctype()
1543 : {
1544 0 : if (MOZ_UNLIKELY(mViewSource) && !isSrcdocDocument) {
1545 0 : mViewSource->AddErrorToCurrentRun("errEndTagSeenWithoutDoctype");
1546 : }
1547 0 : }
1548 :
1549 : void
1550 0 : nsHtml5TreeBuilder::errEndTagAfterBody()
1551 : {
1552 0 : if (MOZ_UNLIKELY(mViewSource)) {
1553 0 : mViewSource->AddErrorToCurrentRun("errEndTagAfterBody");
1554 : }
1555 0 : }
1556 :
1557 : void
1558 0 : nsHtml5TreeBuilder::errEndTagSeenWithSelectOpen(nsIAtom* aName)
1559 : {
1560 0 : if (MOZ_UNLIKELY(mViewSource)) {
1561 0 : mViewSource->AddErrorToCurrentRun("errEndTagSeenWithSelectOpen",
1562 0 : aName);
1563 : }
1564 0 : }
1565 :
1566 : void
1567 0 : nsHtml5TreeBuilder::errGarbageInColgroup()
1568 : {
1569 0 : if (MOZ_UNLIKELY(mViewSource)) {
1570 0 : mViewSource->AddErrorToCurrentRun("errGarbageInColgroup");
1571 : }
1572 0 : }
1573 :
1574 : void
1575 0 : nsHtml5TreeBuilder::errEndTagBr()
1576 : {
1577 0 : if (MOZ_UNLIKELY(mViewSource)) {
1578 0 : mViewSource->AddErrorToCurrentRun("errEndTagBr");
1579 : }
1580 0 : }
1581 :
1582 : void
1583 0 : nsHtml5TreeBuilder::errNoElementToCloseButEndTagSeen(nsIAtom* aName)
1584 : {
1585 0 : if (MOZ_UNLIKELY(mViewSource)) {
1586 0 : mViewSource->AddErrorToCurrentRun(
1587 0 : "errNoElementToCloseButEndTagSeen", aName);
1588 : }
1589 0 : }
1590 :
1591 : void
1592 0 : nsHtml5TreeBuilder::errHtmlStartTagInForeignContext(nsIAtom* aName)
1593 : {
1594 0 : if (MOZ_UNLIKELY(mViewSource)) {
1595 0 : mViewSource->AddErrorToCurrentRun("errHtmlStartTagInForeignContext",
1596 0 : aName);
1597 : }
1598 0 : }
1599 :
1600 : void
1601 0 : nsHtml5TreeBuilder::errTableClosedWhileCaptionOpen()
1602 : {
1603 0 : if (MOZ_UNLIKELY(mViewSource)) {
1604 0 : mViewSource->AddErrorToCurrentRun("errTableClosedWhileCaptionOpen");
1605 : }
1606 0 : }
1607 :
1608 : void
1609 0 : nsHtml5TreeBuilder::errNoTableRowToClose()
1610 : {
1611 0 : if (MOZ_UNLIKELY(mViewSource)) {
1612 0 : mViewSource->AddErrorToCurrentRun("errNoTableRowToClose");
1613 : }
1614 0 : }
1615 :
1616 : void
1617 0 : nsHtml5TreeBuilder::errNonSpaceInTable()
1618 : {
1619 0 : if (MOZ_UNLIKELY(mViewSource)) {
1620 0 : mViewSource->AddErrorToCurrentRun("errNonSpaceInTable");
1621 : }
1622 0 : }
1623 :
1624 : void
1625 0 : nsHtml5TreeBuilder::errUnclosedChildrenInRuby()
1626 : {
1627 0 : if (MOZ_UNLIKELY(mViewSource)) {
1628 0 : mViewSource->AddErrorToCurrentRun("errUnclosedChildrenInRuby");
1629 : }
1630 0 : }
1631 :
1632 : void
1633 0 : nsHtml5TreeBuilder::errStartTagSeenWithoutRuby(nsIAtom* aName)
1634 : {
1635 0 : if (MOZ_UNLIKELY(mViewSource)) {
1636 0 : mViewSource->AddErrorToCurrentRun("errStartTagSeenWithoutRuby",
1637 0 : aName);
1638 : }
1639 0 : }
1640 :
1641 : void
1642 0 : nsHtml5TreeBuilder::errSelfClosing()
1643 : {
1644 0 : if (MOZ_UNLIKELY(mViewSource)) {
1645 0 : mViewSource->AddErrorToCurrentSlash("errSelfClosing");
1646 : }
1647 0 : }
1648 :
1649 : void
1650 0 : nsHtml5TreeBuilder::errNoCheckUnclosedElementsOnStack()
1651 : {
1652 0 : if (MOZ_UNLIKELY(mViewSource)) {
1653 0 : mViewSource->AddErrorToCurrentRun(
1654 0 : "errNoCheckUnclosedElementsOnStack");
1655 : }
1656 0 : }
1657 :
1658 : void
1659 0 : nsHtml5TreeBuilder::errEndTagDidNotMatchCurrentOpenElement(nsIAtom* aName,
1660 : nsIAtom* aOther)
1661 : {
1662 0 : if (MOZ_UNLIKELY(mViewSource)) {
1663 0 : mViewSource->AddErrorToCurrentRun(
1664 0 : "errEndTagDidNotMatchCurrentOpenElement", aName, aOther);
1665 : }
1666 0 : }
1667 :
1668 : void
1669 0 : nsHtml5TreeBuilder::errEndTagViolatesNestingRules(nsIAtom* aName)
1670 : {
1671 0 : if (MOZ_UNLIKELY(mViewSource)) {
1672 0 : mViewSource->AddErrorToCurrentRun("errEndTagViolatesNestingRules", aName);
1673 : }
1674 0 : }
1675 :
1676 : void
1677 0 : nsHtml5TreeBuilder::errEndWithUnclosedElements(nsIAtom* aName)
1678 : {
1679 0 : if (MOZ_UNLIKELY(mViewSource)) {
1680 0 : mViewSource->AddErrorToCurrentRun("errEndWithUnclosedElements", aName);
1681 : }
1682 0 : }
|