parser/html/nsHtml5TreeBuilderCppSupplement.h

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

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

mercurial