PageRenderTime 69ms CodeModel.GetById 12ms app.highlight 50ms RepoModel.GetById 1ms app.codeStats 0ms

/parser/html/nsHtml5TreeBuilderCppSupplement.h

http://github.com/zpao/v8monkey
C Header | 1145 lines | 939 code | 115 blank | 91 comment | 196 complexity | a263e49fef2367206cafea2ba27527cb MD5 | raw file
   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/* ***** BEGIN LICENSE BLOCK *****
   4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
   5 *
   6 * The contents of this file are subject to the Mozilla Public License Version
   7 * 1.1 (the "License"); you may not use this file except in compliance with
   8 * the License. You may obtain a copy of the License at
   9 * http://www.mozilla.org/MPL/
  10 *
  11 * Software distributed under the License is distributed on an "AS IS" basis,
  12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  13 * for the specific language governing rights and limitations under the
  14 * License.
  15 *
  16 * The Original Code is Mozilla Communicator client code.
  17 *
  18 * The Initial Developer of the Original Code is
  19 * Netscape Communications Corporation.
  20 * Portions created by the Initial Developer are Copyright (C) 1998
  21 * the Initial Developer. All Rights Reserved.
  22 *
  23 * Contributor(s):
  24 *   Pierre Phaneuf <pp@ludusdesign.com>
  25 *   Henri Sivonen <hsivonen@iki.fi>
  26 *
  27 * Alternatively, the contents of this file may be used under the terms of
  28 * either of the GNU General Public License Version 2 or later (the "GPL"),
  29 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  30 * in which case the provisions of the GPL or the LGPL are applicable instead
  31 * of those above. If you wish to allow use of your version of this file only
  32 * under the terms of either the GPL or the LGPL, and not to allow others to
  33 * use your version of this file under the terms of the MPL, indicate your
  34 * decision by deleting the provisions above and replace them with the notice
  35 * and other provisions required by the GPL or the LGPL. If you do not delete
  36 * the provisions above, a recipient may use your version of this file under
  37 * the terms of any one of the MPL, the GPL or the LGPL.
  38 *
  39 * ***** END LICENSE BLOCK ***** */
  40
  41#include "nsContentErrors.h"
  42#include "nsIPresShell.h"
  43#include "nsEvent.h"
  44#include "nsGUIEvent.h"
  45#include "nsEventDispatcher.h"
  46#include "nsContentUtils.h"
  47#include "nsNodeUtils.h"
  48
  49#define NS_HTML5_TREE_DEPTH_LIMIT 200
  50
  51class nsPresContext;
  52
  53nsHtml5TreeBuilder::nsHtml5TreeBuilder(nsAHtml5TreeOpSink* aOpSink,
  54                                       nsHtml5TreeOpStage* aStage)
  55  : scriptingEnabled(false)
  56  , fragment(false)
  57  , contextNode(nsnull)
  58  , formPointer(nsnull)
  59  , headPointer(nsnull)
  60  , mViewSource(nsnull)
  61  , mOpSink(aOpSink)
  62  , mHandles(new nsIContent*[NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH])
  63  , mHandlesUsed(0)
  64  , mSpeculativeLoadStage(aStage)
  65  , mCurrentHtmlScriptIsAsyncOrDefer(false)
  66#ifdef DEBUG
  67  , mActive(false)
  68#endif
  69{
  70  MOZ_COUNT_CTOR(nsHtml5TreeBuilder);
  71}
  72
  73nsHtml5TreeBuilder::~nsHtml5TreeBuilder()
  74{
  75  MOZ_COUNT_DTOR(nsHtml5TreeBuilder);
  76  NS_ASSERTION(!mActive, "nsHtml5TreeBuilder deleted without ever calling end() on it!");
  77  mOpQueue.Clear();
  78}
  79
  80nsIContent**
  81nsHtml5TreeBuilder::createElement(PRInt32 aNamespace, nsIAtom* aName, nsHtml5HtmlAttributes* aAttributes)
  82{
  83  NS_PRECONDITION(aAttributes, "Got null attributes.");
  84  NS_PRECONDITION(aName, "Got null name.");
  85  NS_PRECONDITION(aNamespace == kNameSpaceID_XHTML || 
  86                  aNamespace == kNameSpaceID_SVG || 
  87                  aNamespace == kNameSpaceID_MathML,
  88                  "Bogus namespace.");
  89
  90  nsIContent** content = AllocateContentHandle();
  91  nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
  92  NS_ASSERTION(treeOp, "Tree op allocation failed.");
  93  treeOp->Init(aNamespace,
  94               aName,
  95               aAttributes,
  96               content,
  97               !!mSpeculativeLoadStage);
  98  // mSpeculativeLoadStage is non-null only in the off-the-main-thread
  99  // tree builder, which handles the network stream
 100  
 101  // Start wall of code for speculative loading and line numbers
 102  
 103  if (mSpeculativeLoadStage) {
 104    switch (aNamespace) {
 105      case kNameSpaceID_XHTML:
 106        if (nsHtml5Atoms::img == aName) {
 107          nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_SRC);
 108          if (url) {
 109            nsString* crossOrigin =
 110              aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
 111            if (crossOrigin) {
 112              mSpeculativeLoadQueue.AppendElement()->InitImage(*url, *crossOrigin);
 113            } else {
 114              mSpeculativeLoadQueue.AppendElement()->InitImage(*url, EmptyString());
 115            }
 116          }
 117        } else if (nsHtml5Atoms::script == aName) {
 118          nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 119          NS_ASSERTION(treeOp, "Tree op allocation failed.");
 120          treeOp->Init(eTreeOpSetScriptLineNumberAndFreeze, content, tokenizer->getLineNumber());
 121
 122          nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_SRC);
 123          if (url) {
 124            nsString* charset = aAttributes->getValue(nsHtml5AttributeName::ATTR_CHARSET);
 125            nsString* type = aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE);
 126            mSpeculativeLoadQueue.AppendElement()->InitScript(*url,
 127                                                   (charset) ? *charset : EmptyString(),
 128                                                   (type) ? *type : EmptyString());
 129            mCurrentHtmlScriptIsAsyncOrDefer = 
 130              aAttributes->contains(nsHtml5AttributeName::ATTR_ASYNC) ||
 131              aAttributes->contains(nsHtml5AttributeName::ATTR_DEFER);
 132          }
 133        } else if (nsHtml5Atoms::link == aName) {
 134          nsString* rel = aAttributes->getValue(nsHtml5AttributeName::ATTR_REL);
 135          // Not splitting on space here is bogus but the old parser didn't even
 136          // do a case-insensitive check.
 137          if (rel && rel->LowerCaseEqualsASCII("stylesheet")) {
 138            nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
 139            if (url) {
 140              nsString* charset = aAttributes->getValue(nsHtml5AttributeName::ATTR_CHARSET);
 141              mSpeculativeLoadQueue.AppendElement()->InitStyle(*url,
 142                                                    (charset) ? *charset : EmptyString());
 143            }
 144          }
 145        } else if (nsHtml5Atoms::video == aName) {
 146          nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_POSTER);
 147          if (url) {
 148            mSpeculativeLoadQueue.AppendElement()->InitImage(*url, EmptyString());
 149          }
 150        } else if (nsHtml5Atoms::style == aName) {
 151          nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 152          NS_ASSERTION(treeOp, "Tree op allocation failed.");
 153          treeOp->Init(eTreeOpSetStyleLineNumber, content, tokenizer->getLineNumber());
 154        } else if (nsHtml5Atoms::html == aName) {
 155          nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_MANIFEST);
 156          if (url) {
 157            mSpeculativeLoadQueue.AppendElement()->InitManifest(*url);
 158          } else {
 159            mSpeculativeLoadQueue.AppendElement()->InitManifest(EmptyString());
 160          }
 161        } else if (nsHtml5Atoms::base == aName) {
 162          nsString* url =
 163              aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
 164          if (url) {
 165            mSpeculativeLoadQueue.AppendElement()->InitBase(*url);
 166          }
 167        }
 168        break;
 169      case kNameSpaceID_SVG:
 170        if (nsHtml5Atoms::image == aName) {
 171          nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF);
 172          if (url) {
 173            mSpeculativeLoadQueue.AppendElement()->InitImage(*url, EmptyString());
 174          }
 175        } else if (nsHtml5Atoms::script == aName) {
 176          nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 177          NS_ASSERTION(treeOp, "Tree op allocation failed.");
 178          treeOp->Init(eTreeOpSetScriptLineNumberAndFreeze, content, tokenizer->getLineNumber());
 179
 180          nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF);
 181          if (url) {
 182            nsString* type = aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE);
 183            mSpeculativeLoadQueue.AppendElement()->InitScript(*url,
 184                                                   EmptyString(),
 185                                                   (type) ? *type : EmptyString());
 186          }
 187        } else if (nsHtml5Atoms::style == aName) {
 188          nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 189          NS_ASSERTION(treeOp, "Tree op allocation failed.");
 190          treeOp->Init(eTreeOpSetStyleLineNumber, content, tokenizer->getLineNumber());
 191
 192          nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF);
 193          if (url) {
 194            mSpeculativeLoadQueue.AppendElement()->InitStyle(*url, EmptyString());
 195          }
 196        }        
 197        break;
 198    }
 199  } else if (aNamespace != kNameSpaceID_MathML) {
 200    // No speculative loader--just line numbers and defer/async check
 201    if (nsHtml5Atoms::style == aName) {
 202      nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 203      NS_ASSERTION(treeOp, "Tree op allocation failed.");
 204      treeOp->Init(eTreeOpSetStyleLineNumber, content, tokenizer->getLineNumber());
 205    } else if (nsHtml5Atoms::script == aName) {
 206      nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 207      NS_ASSERTION(treeOp, "Tree op allocation failed.");
 208      treeOp->Init(eTreeOpSetScriptLineNumberAndFreeze, content, tokenizer->getLineNumber());
 209      if (aNamespace == kNameSpaceID_XHTML) {
 210        mCurrentHtmlScriptIsAsyncOrDefer = 
 211          aAttributes->contains(nsHtml5AttributeName::ATTR_SRC) &&
 212          (aAttributes->contains(nsHtml5AttributeName::ATTR_ASYNC) ||
 213           aAttributes->contains(nsHtml5AttributeName::ATTR_DEFER));
 214      }
 215    } else if (aNamespace == kNameSpaceID_XHTML && nsHtml5Atoms::html == aName) {
 216      nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_MANIFEST);
 217      nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 218      NS_ASSERTION(treeOp, "Tree op allocation failed.");
 219      if (url) {
 220        treeOp->Init(eTreeOpProcessOfflineManifest, *url);
 221      } else {
 222        treeOp->Init(eTreeOpProcessOfflineManifest, EmptyString());
 223      }
 224    }
 225  }
 226
 227  // End wall of code for speculative loading
 228  
 229  return content;
 230}
 231
 232nsIContent**
 233nsHtml5TreeBuilder::createElement(PRInt32 aNamespace, nsIAtom* aName, nsHtml5HtmlAttributes* aAttributes, nsIContent** aFormElement)
 234{
 235  nsIContent** content = createElement(aNamespace, aName, aAttributes);
 236  if (aFormElement) {
 237    nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 238    NS_ASSERTION(treeOp, "Tree op allocation failed.");
 239    treeOp->Init(eTreeOpSetFormElement, content, aFormElement);
 240  }
 241  return content;
 242}
 243
 244nsIContent**
 245nsHtml5TreeBuilder::createHtmlElementSetAsRoot(nsHtml5HtmlAttributes* aAttributes)
 246{
 247  nsIContent** content = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::html, aAttributes);
 248  nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 249  NS_ASSERTION(treeOp, "Tree op allocation failed.");
 250  treeOp->Init(eTreeOpAppendToDocument, content);
 251  return content;
 252}
 253
 254void
 255nsHtml5TreeBuilder::detachFromParent(nsIContent** aElement)
 256{
 257  NS_PRECONDITION(aElement, "Null element");
 258
 259  nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 260  NS_ASSERTION(treeOp, "Tree op allocation failed.");
 261  treeOp->Init(eTreeOpDetach, aElement);
 262}
 263
 264void
 265nsHtml5TreeBuilder::appendElement(nsIContent** aChild, nsIContent** aParent)
 266{
 267  NS_PRECONDITION(aChild, "Null child");
 268  NS_PRECONDITION(aParent, "Null parent");
 269  if (deepTreeSurrogateParent) {
 270    return;
 271  }
 272  nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 273  NS_ASSERTION(treeOp, "Tree op allocation failed.");
 274  treeOp->Init(eTreeOpAppend, aChild, aParent);
 275}
 276
 277void
 278nsHtml5TreeBuilder::appendChildrenToNewParent(nsIContent** aOldParent, nsIContent** aNewParent)
 279{
 280  NS_PRECONDITION(aOldParent, "Null old parent");
 281  NS_PRECONDITION(aNewParent, "Null new parent");
 282
 283  nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 284  NS_ASSERTION(treeOp, "Tree op allocation failed.");
 285  treeOp->Init(eTreeOpAppendChildrenToNewParent, aOldParent, aNewParent);
 286}
 287
 288void
 289nsHtml5TreeBuilder::insertFosterParentedCharacters(PRUnichar* aBuffer, PRInt32 aStart, PRInt32 aLength, nsIContent** aTable, nsIContent** aStackParent)
 290{
 291  NS_PRECONDITION(aBuffer, "Null buffer");
 292  NS_PRECONDITION(aTable, "Null table");
 293  NS_PRECONDITION(aStackParent, "Null stack parent");
 294
 295  PRUnichar* bufferCopy = new PRUnichar[aLength];
 296  memcpy(bufferCopy, aBuffer, aLength * sizeof(PRUnichar));
 297  
 298  nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 299  NS_ASSERTION(treeOp, "Tree op allocation failed.");
 300  treeOp->Init(eTreeOpFosterParentText, bufferCopy, aLength, aStackParent, aTable);
 301}
 302
 303void
 304nsHtml5TreeBuilder::insertFosterParentedChild(nsIContent** aChild, nsIContent** aTable, nsIContent** aStackParent)
 305{
 306  NS_PRECONDITION(aChild, "Null child");
 307  NS_PRECONDITION(aTable, "Null table");
 308  NS_PRECONDITION(aStackParent, "Null stack parent");
 309
 310  nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 311  NS_ASSERTION(treeOp, "Tree op allocation failed.");
 312  treeOp->Init(eTreeOpFosterParent, aChild, aStackParent, aTable);
 313}
 314
 315void
 316nsHtml5TreeBuilder::appendCharacters(nsIContent** aParent, PRUnichar* aBuffer, PRInt32 aStart, PRInt32 aLength)
 317{
 318  NS_PRECONDITION(aBuffer, "Null buffer");
 319  NS_PRECONDITION(aParent, "Null parent");
 320
 321  PRUnichar* bufferCopy = new PRUnichar[aLength];
 322  memcpy(bufferCopy, aBuffer, aLength * sizeof(PRUnichar));
 323  
 324  nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 325  NS_ASSERTION(treeOp, "Tree op allocation failed.");
 326  treeOp->Init(eTreeOpAppendText, bufferCopy, aLength,
 327      deepTreeSurrogateParent ? deepTreeSurrogateParent : aParent);
 328}
 329
 330void
 331nsHtml5TreeBuilder::appendIsindexPrompt(nsIContent** aParent)
 332{
 333  NS_PRECONDITION(aParent, "Null parent");
 334
 335  nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 336  NS_ASSERTION(treeOp, "Tree op allocation failed.");
 337  treeOp->Init(eTreeOpAppendIsindexPrompt, aParent);
 338}
 339
 340void
 341nsHtml5TreeBuilder::appendComment(nsIContent** aParent, PRUnichar* aBuffer, PRInt32 aStart, PRInt32 aLength)
 342{
 343  NS_PRECONDITION(aBuffer, "Null buffer");
 344  NS_PRECONDITION(aParent, "Null parent");
 345  if (deepTreeSurrogateParent) {
 346    return;
 347  }
 348
 349  PRUnichar* bufferCopy = new PRUnichar[aLength];
 350  memcpy(bufferCopy, aBuffer, aLength * sizeof(PRUnichar));
 351  
 352  nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 353  NS_ASSERTION(treeOp, "Tree op allocation failed.");
 354  treeOp->Init(eTreeOpAppendComment, bufferCopy, aLength, aParent);
 355}
 356
 357void
 358nsHtml5TreeBuilder::appendCommentToDocument(PRUnichar* aBuffer, PRInt32 aStart, PRInt32 aLength)
 359{
 360  NS_PRECONDITION(aBuffer, "Null buffer");
 361
 362  PRUnichar* bufferCopy = new PRUnichar[aLength];
 363  memcpy(bufferCopy, aBuffer, aLength * sizeof(PRUnichar));
 364  
 365  nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 366  NS_ASSERTION(treeOp, "Tree op allocation failed.");
 367  treeOp->Init(eTreeOpAppendCommentToDocument, bufferCopy, aLength);
 368}
 369
 370void
 371nsHtml5TreeBuilder::addAttributesToElement(nsIContent** aElement, nsHtml5HtmlAttributes* aAttributes)
 372{
 373  NS_PRECONDITION(aElement, "Null element");
 374  NS_PRECONDITION(aAttributes, "Null attributes");
 375
 376  if (aAttributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
 377    return;
 378  }
 379  nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 380  NS_ASSERTION(treeOp, "Tree op allocation failed.");
 381  treeOp->Init(aElement, aAttributes);
 382}
 383
 384void
 385nsHtml5TreeBuilder::markMalformedIfScript(nsIContent** aElement)
 386{
 387  NS_PRECONDITION(aElement, "Null element");
 388
 389  nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 390  NS_ASSERTION(treeOp, "Tree op allocation failed.");
 391  treeOp->Init(eTreeOpMarkMalformedIfScript, aElement);
 392}
 393
 394void
 395nsHtml5TreeBuilder::start(bool fragment)
 396{
 397  mCurrentHtmlScriptIsAsyncOrDefer = false;
 398  deepTreeSurrogateParent = nsnull;
 399#ifdef DEBUG
 400  mActive = true;
 401#endif
 402}
 403
 404void
 405nsHtml5TreeBuilder::end()
 406{
 407  mOpQueue.Clear();
 408#ifdef DEBUG
 409  mActive = false;
 410#endif
 411}
 412
 413void
 414nsHtml5TreeBuilder::appendDoctypeToDocument(nsIAtom* aName, nsString* aPublicId, nsString* aSystemId)
 415{
 416  NS_PRECONDITION(aName, "Null name");
 417
 418  nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 419  NS_ASSERTION(treeOp, "Tree op allocation failed.");
 420  treeOp->Init(aName, *aPublicId, *aSystemId);
 421  // nsXMLContentSink can flush here, but what's the point?
 422  // It can also interrupt here, but we can't.
 423}
 424
 425void
 426nsHtml5TreeBuilder::elementPushed(PRInt32 aNamespace, nsIAtom* aName, nsIContent** aElement)
 427{
 428  NS_ASSERTION(aNamespace == kNameSpaceID_XHTML || aNamespace == kNameSpaceID_SVG || aNamespace == kNameSpaceID_MathML, "Element isn't HTML, SVG or MathML!");
 429  NS_ASSERTION(aName, "Element doesn't have local name!");
 430  NS_ASSERTION(aElement, "No element!");
 431  /*
 432   * The frame constructor uses recursive algorithms, so it can't deal with
 433   * arbitrarily deep trees. This is especially a problem on Windows where
 434   * the permitted depth of the runtime stack is rather small.
 435   *
 436   * The following is a protection against author incompetence--not against
 437   * malice. There are other ways to make the DOM deep anyway.
 438   *
 439   * The basic idea is that when the tree builder stack gets too deep,
 440   * append operations no longer append to the node that the HTML parsing
 441   * algorithm says they should but instead text nodes are append to the last
 442   * element that was seen before a magic tree builder stack threshold was
 443   * reached and element and comment nodes aren't appended to the DOM at all.
 444   *
 445   * However, for security reasons, non-child descendant text nodes inside an
 446   * SVG script or style element should not become children. Also, non-cell
 447   * table elements shouldn't be used as surrogate parents for user experience
 448   * reasons.
 449   */
 450  if (!deepTreeSurrogateParent && currentPtr >= NS_HTML5_TREE_DEPTH_LIMIT &&
 451      !(aName == nsHtml5Atoms::script ||
 452        aName == nsHtml5Atoms::table ||
 453        aName == nsHtml5Atoms::thead ||
 454        aName == nsHtml5Atoms::tfoot ||
 455        aName == nsHtml5Atoms::tbody ||
 456        aName == nsHtml5Atoms::tr ||
 457        aName == nsHtml5Atoms::colgroup ||
 458        aName == nsHtml5Atoms::style)) {
 459    deepTreeSurrogateParent = aElement;
 460  }
 461  if (aNamespace != kNameSpaceID_XHTML) {
 462    return;
 463  }
 464  if (aName == nsHtml5Atoms::body || aName == nsHtml5Atoms::frameset) {
 465    nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 466    NS_ASSERTION(treeOp, "Tree op allocation failed.");
 467    treeOp->Init(eTreeOpStartLayout);
 468    return;
 469  }
 470}
 471
 472void
 473nsHtml5TreeBuilder::elementPopped(PRInt32 aNamespace, nsIAtom* aName, nsIContent** aElement)
 474{
 475  NS_ASSERTION(aNamespace == kNameSpaceID_XHTML || aNamespace == kNameSpaceID_SVG || aNamespace == kNameSpaceID_MathML, "Element isn't HTML, SVG or MathML!");
 476  NS_ASSERTION(aName, "Element doesn't have local name!");
 477  NS_ASSERTION(aElement, "No element!");
 478  if (deepTreeSurrogateParent && currentPtr <= NS_HTML5_TREE_DEPTH_LIMIT) {
 479    deepTreeSurrogateParent = nsnull;
 480  }
 481  if (aNamespace == kNameSpaceID_MathML) {
 482    return;
 483  }
 484  // we now have only SVG and HTML
 485  if (aName == nsHtml5Atoms::script) {
 486    if (mCurrentHtmlScriptIsAsyncOrDefer) {
 487      NS_ASSERTION(aNamespace == kNameSpaceID_XHTML, 
 488                   "Only HTML scripts may be async/defer.");
 489      nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 490      NS_ASSERTION(treeOp, "Tree op allocation failed.");
 491      treeOp->Init(eTreeOpRunScriptAsyncDefer, aElement);      
 492      mCurrentHtmlScriptIsAsyncOrDefer = false;
 493      return;
 494    }
 495    requestSuspension();
 496    nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 497    NS_ASSERTION(treeOp, "Tree op allocation failed.");
 498    treeOp->InitScript(aElement);
 499    return;
 500  }
 501  if (aName == nsHtml5Atoms::title) {
 502    nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 503    NS_ASSERTION(treeOp, "Tree op allocation failed.");
 504    treeOp->Init(eTreeOpDoneAddingChildren, aElement);
 505    return;
 506  }
 507  if (aName == nsHtml5Atoms::style || (aNamespace == kNameSpaceID_XHTML && aName == nsHtml5Atoms::link)) {
 508    nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 509    NS_ASSERTION(treeOp, "Tree op allocation failed.");
 510    treeOp->Init(eTreeOpUpdateStyleSheet, aElement);
 511    return;
 512  }
 513  if (aNamespace == kNameSpaceID_SVG) {
 514    if (aName == nsHtml5Atoms::svg) {
 515      nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 516      NS_ASSERTION(treeOp, "Tree op allocation failed.");
 517      treeOp->Init(eTreeOpSvgLoad, aElement);
 518    }
 519    return;
 520  }
 521  // we now have only HTML
 522  // Some HTML nodes need DoneAddingChildren() called to initialize
 523  // properly (e.g. form state restoration).
 524  // XXX expose ElementName group here and do switch
 525  if (aName == nsHtml5Atoms::object ||
 526      aName == nsHtml5Atoms::applet) {
 527    nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 528    NS_ASSERTION(treeOp, "Tree op allocation failed.");
 529    treeOp->Init(eTreeOpDoneAddingChildren, aElement);
 530    return;
 531  }
 532  if (aName == nsHtml5Atoms::select || 
 533      aName == nsHtml5Atoms::textarea) {
 534    if (!formPointer) {
 535      // If form inputs don't belong to a form, their state preservation
 536      // won't work right without an append notification flush at this 
 537      // point. See bug 497861 and bug 539895.
 538      nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 539      NS_ASSERTION(treeOp, "Tree op allocation failed.");
 540      treeOp->Init(eTreeOpFlushPendingAppendNotifications);
 541    }
 542    nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 543    NS_ASSERTION(treeOp, "Tree op allocation failed.");
 544    treeOp->Init(eTreeOpDoneAddingChildren, aElement);
 545    return;
 546  }
 547  if (aName == nsHtml5Atoms::input ||
 548      aName == nsHtml5Atoms::button ||
 549      aName == nsHtml5Atoms::menuitem) {
 550    if (!formPointer) {
 551      // If form inputs don't belong to a form, their state preservation
 552      // won't work right without an append notification flush at this 
 553      // point. See bug 497861.
 554      nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 555      NS_ASSERTION(treeOp, "Tree op allocation failed.");
 556      treeOp->Init(eTreeOpFlushPendingAppendNotifications);
 557    }
 558    nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 559    NS_ASSERTION(treeOp, "Tree op allocation failed.");
 560    treeOp->Init(eTreeOpDoneCreatingElement, aElement);
 561    return;
 562  }
 563  if (aName == nsHtml5Atoms::meta && !fragment) {
 564    nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 565    NS_ASSERTION(treeOp, "Tree op allocation failed.");
 566    treeOp->Init(eTreeOpProcessMeta, aElement);
 567    return;
 568  }
 569  if (aName == nsHtml5Atoms::audio || aName == nsHtml5Atoms::video) {
 570    nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 571    NS_ASSERTION(treeOp, "Tree op allocation failed.");
 572    treeOp->Init(eTreeOpDoneCreatingElement, aElement);
 573    return;
 574  }   
 575
 576  return;
 577}
 578
 579void
 580nsHtml5TreeBuilder::accumulateCharacters(const PRUnichar* aBuf, PRInt32 aStart, PRInt32 aLength)
 581{
 582  PRInt32 newFillLen = charBufferLen + aLength;
 583  if (newFillLen > charBuffer.length) {
 584    PRInt32 newAllocLength = newFillLen + (newFillLen >> 1);
 585    jArray<PRUnichar,PRInt32> newBuf = jArray<PRUnichar,PRInt32>::newJArray(newAllocLength);
 586    memcpy(newBuf, charBuffer, sizeof(PRUnichar) * charBufferLen);
 587    charBuffer = newBuf;
 588  }
 589  memcpy(charBuffer + charBufferLen, aBuf + aStart, sizeof(PRUnichar) * aLength);
 590  charBufferLen = newFillLen;
 591}
 592
 593nsIContent**
 594nsHtml5TreeBuilder::AllocateContentHandle()
 595{
 596  if (mHandlesUsed == NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH) {
 597    mOldHandles.AppendElement(mHandles.forget());
 598    mHandles = new nsIContent*[NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH];
 599    mHandlesUsed = 0;
 600  }
 601#ifdef DEBUG
 602  mHandles[mHandlesUsed] = (nsIContent*)0xC0DEDBAD;
 603#endif
 604  return &mHandles[mHandlesUsed++];
 605}
 606
 607bool
 608nsHtml5TreeBuilder::HasScript()
 609{
 610  PRUint32 len = mOpQueue.Length();
 611  if (!len) {
 612    return false;
 613  }
 614  return mOpQueue.ElementAt(len - 1).IsRunScript();
 615}
 616
 617bool
 618nsHtml5TreeBuilder::Flush(bool aDiscretionary)
 619{
 620  if (!aDiscretionary ||
 621      !(charBufferLen &&
 622        currentPtr >= 0 &&
 623        stack[currentPtr]->isFosterParenting())) {
 624    // Don't flush text on discretionary flushes if the current element on
 625    // the stack is a foster-parenting element and there's pending text,
 626    // because flushing in that case would make the tree shape dependent on
 627    // where the flush points fall.
 628    flushCharacters();
 629  }
 630  FlushLoads();
 631  if (mOpSink) {
 632    bool hasOps = !mOpQueue.IsEmpty();
 633    if (hasOps) {
 634      mOpSink->MoveOpsFrom(mOpQueue);
 635    }
 636    return hasOps;
 637  }
 638  // no op sink: throw away ops
 639  mOpQueue.Clear();
 640  return false;
 641}
 642
 643void
 644nsHtml5TreeBuilder::FlushLoads()
 645{
 646  if (!mSpeculativeLoadQueue.IsEmpty()) {
 647    mSpeculativeLoadStage->MoveSpeculativeLoadsFrom(mSpeculativeLoadQueue);
 648  }
 649}
 650
 651void
 652nsHtml5TreeBuilder::SetDocumentCharset(nsACString& aCharset, 
 653                                       PRInt32 aCharsetSource)
 654{
 655  if (mSpeculativeLoadStage) {
 656    mSpeculativeLoadQueue.AppendElement()->InitSetDocumentCharset(
 657      aCharset, aCharsetSource);
 658  } else {
 659    mOpQueue.AppendElement()->Init(
 660      eTreeOpSetDocumentCharset, aCharset, aCharsetSource);
 661  }
 662}
 663
 664void
 665nsHtml5TreeBuilder::StreamEnded()
 666{
 667  // The fragment mode calls DidBuildModel from nsHtml5Parser. 
 668  // Letting DidBuildModel be called from the executor in the fragment case
 669  // confuses the EndLoad logic of nsHTMLDocument, since nsHTMLDocument
 670  // thinks it is dealing with document.written content as opposed to 
 671  // innerHTML content.
 672  if (!fragment) {
 673    nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 674    NS_ASSERTION(treeOp, "Tree op allocation failed.");
 675    treeOp->Init(eTreeOpStreamEnded);
 676  }
 677}
 678
 679void
 680nsHtml5TreeBuilder::NeedsCharsetSwitchTo(const nsACString& aCharset,
 681                                         PRInt32 aCharsetSource)
 682{
 683  nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 684  NS_ASSERTION(treeOp, "Tree op allocation failed.");
 685  treeOp->Init(eTreeOpNeedsCharsetSwitchTo, aCharset, aCharsetSource);
 686}
 687
 688void
 689nsHtml5TreeBuilder::AddSnapshotToScript(nsAHtml5TreeBuilderState* aSnapshot, PRInt32 aLine)
 690{
 691  NS_PRECONDITION(HasScript(), "No script to add a snapshot to!");
 692  NS_PRECONDITION(aSnapshot, "Got null snapshot.");
 693  mOpQueue.ElementAt(mOpQueue.Length() - 1).SetSnapshot(aSnapshot, aLine);
 694}
 695
 696void
 697nsHtml5TreeBuilder::DropHandles()
 698{
 699  mOldHandles.Clear();
 700  mHandlesUsed = 0;
 701}
 702
 703void
 704nsHtml5TreeBuilder::MarkAsBroken()
 705{
 706  mOpQueue.Clear(); // Previous ops don't matter anymore
 707  mOpQueue.AppendElement()->Init(eTreeOpMarkAsBroken);
 708}
 709
 710void
 711nsHtml5TreeBuilder::StartPlainTextViewSource(const nsAutoString& aTitle)
 712{
 713  startTag(nsHtml5ElementName::ELT_TITLE,
 714           nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES,
 715           false);
 716
 717  // XUL will add the "Source of: " prefix.
 718  PRUint32 length = aTitle.Length();
 719  if (length > PR_INT32_MAX) {
 720    length = PR_INT32_MAX;
 721  }
 722  characters(aTitle.get(), 0, (PRInt32)length);
 723  endTag(nsHtml5ElementName::ELT_TITLE);
 724
 725  startTag(nsHtml5ElementName::ELT_LINK,
 726           nsHtml5ViewSourceUtils::NewLinkAttributes(),
 727           false);
 728
 729  startTag(nsHtml5ElementName::ELT_BODY,
 730           nsHtml5ViewSourceUtils::NewBodyAttributes(),
 731           false);
 732
 733  StartPlainText();
 734}
 735
 736void
 737nsHtml5TreeBuilder::StartPlainText()
 738{
 739  startTag(nsHtml5ElementName::ELT_PRE,
 740           nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES,
 741           false);
 742  needToDropLF = false;
 743}
 744
 745// DocumentModeHandler
 746void
 747nsHtml5TreeBuilder::documentMode(nsHtml5DocumentMode m)
 748{
 749  nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
 750  NS_ASSERTION(treeOp, "Tree op allocation failed.");
 751  treeOp->Init(m);
 752}
 753
 754// Error reporting
 755
 756void
 757nsHtml5TreeBuilder::EnableViewSource(nsHtml5Highlighter* aHighlighter)
 758{
 759  mViewSource = aHighlighter;
 760}
 761
 762void
 763nsHtml5TreeBuilder::errStrayStartTag(nsIAtom* aName)
 764{
 765  if (NS_UNLIKELY(mViewSource)) {
 766    mViewSource->AddErrorToCurrentRun("errStrayStartTag2", aName);
 767  }
 768}
 769
 770void
 771nsHtml5TreeBuilder::errStrayEndTag(nsIAtom* aName)
 772{
 773  if (NS_UNLIKELY(mViewSource)) {
 774    mViewSource->AddErrorToCurrentRun("errStrayEndTag", aName);
 775  }
 776}
 777
 778void
 779nsHtml5TreeBuilder::errUnclosedElements(PRInt32 aIndex, nsIAtom* aName)
 780{
 781  if (NS_UNLIKELY(mViewSource)) {
 782    mViewSource->AddErrorToCurrentRun("errUnclosedElements", aName);
 783  }
 784}
 785
 786void
 787nsHtml5TreeBuilder::errUnclosedElementsImplied(PRInt32 aIndex, nsIAtom* aName)
 788{
 789  if (NS_UNLIKELY(mViewSource)) {
 790    mViewSource->AddErrorToCurrentRun("errUnclosedElementsImplied",
 791        aName);
 792  }
 793}
 794
 795void
 796nsHtml5TreeBuilder::errUnclosedElementsCell(PRInt32 aIndex)
 797{
 798  if (NS_UNLIKELY(mViewSource)) {
 799    mViewSource->AddErrorToCurrentRun("errUnclosedElementsCell");
 800  }
 801}
 802
 803void
 804nsHtml5TreeBuilder::errStrayDoctype()
 805{
 806  if (NS_UNLIKELY(mViewSource)) {
 807    mViewSource->AddErrorToCurrentRun("errStrayDoctype");
 808  }
 809}
 810
 811void
 812nsHtml5TreeBuilder::errAlmostStandardsDoctype()
 813{
 814  if (NS_UNLIKELY(mViewSource)) {
 815    mViewSource->AddErrorToCurrentRun("errAlmostStandardsDoctype");
 816  }
 817}
 818
 819void
 820nsHtml5TreeBuilder::errQuirkyDoctype()
 821{
 822  if (NS_UNLIKELY(mViewSource)) {
 823    mViewSource->AddErrorToCurrentRun("errQuirkyDoctype");
 824  }
 825}
 826
 827void
 828nsHtml5TreeBuilder::errNonSpaceInTrailer()
 829{
 830  if (NS_UNLIKELY(mViewSource)) {
 831    mViewSource->AddErrorToCurrentRun("errNonSpaceInTrailer");
 832  }
 833}
 834
 835void
 836nsHtml5TreeBuilder::errNonSpaceAfterFrameset()
 837{
 838  if (NS_UNLIKELY(mViewSource)) {
 839    mViewSource->AddErrorToCurrentRun("errNonSpaceAfterFrameset");
 840  }
 841}
 842
 843void
 844nsHtml5TreeBuilder::errNonSpaceInFrameset()
 845{
 846  if (NS_UNLIKELY(mViewSource)) {
 847    mViewSource->AddErrorToCurrentRun("errNonSpaceInFrameset");
 848  }
 849}
 850
 851void
 852nsHtml5TreeBuilder::errNonSpaceAfterBody()
 853{
 854  if (NS_UNLIKELY(mViewSource)) {
 855    mViewSource->AddErrorToCurrentRun("errNonSpaceAfterBody");
 856  }
 857}
 858
 859void
 860nsHtml5TreeBuilder::errNonSpaceInColgroupInFragment()
 861{
 862  if (NS_UNLIKELY(mViewSource)) {
 863    mViewSource->AddErrorToCurrentRun("errNonSpaceInColgroupInFragment");
 864  }
 865}
 866
 867void
 868nsHtml5TreeBuilder::errNonSpaceInNoscriptInHead()
 869{
 870  if (NS_UNLIKELY(mViewSource)) {
 871    mViewSource->AddErrorToCurrentRun("errNonSpaceInNoscriptInHead");
 872  }
 873}
 874
 875void
 876nsHtml5TreeBuilder::errFooBetweenHeadAndBody(nsIAtom* aName)
 877{
 878  if (NS_UNLIKELY(mViewSource)) {
 879    mViewSource->AddErrorToCurrentRun("errFooBetweenHeadAndBody", aName);
 880  }
 881}
 882
 883void
 884nsHtml5TreeBuilder::errStartTagWithoutDoctype()
 885{
 886  if (NS_UNLIKELY(mViewSource)) {
 887    mViewSource->AddErrorToCurrentRun("errStartTagWithoutDoctype");
 888  }
 889}
 890
 891void
 892nsHtml5TreeBuilder::errNoSelectInTableScope()
 893{
 894  if (NS_UNLIKELY(mViewSource)) {
 895    mViewSource->AddErrorToCurrentRun("errNoSelectInTableScope");
 896  }
 897}
 898
 899void
 900nsHtml5TreeBuilder::errStartSelectWhereEndSelectExpected()
 901{
 902  if (NS_UNLIKELY(mViewSource)) {
 903    mViewSource->AddErrorToCurrentRun(
 904        "errStartSelectWhereEndSelectExpected");
 905  }
 906}
 907
 908void
 909nsHtml5TreeBuilder::errStartTagWithSelectOpen(nsIAtom* aName)
 910{
 911  if (NS_UNLIKELY(mViewSource)) {
 912    mViewSource->AddErrorToCurrentRun("errStartTagWithSelectOpen", aName);
 913  }
 914}
 915
 916void
 917nsHtml5TreeBuilder::errBadStartTagInHead(nsIAtom* aName)
 918{
 919  if (NS_UNLIKELY(mViewSource)) {
 920    mViewSource->AddErrorToCurrentRun("errBadStartTagInHead2", aName);
 921  }
 922}
 923
 924void
 925nsHtml5TreeBuilder::errImage()
 926{
 927  if (NS_UNLIKELY(mViewSource)) {
 928    mViewSource->AddErrorToCurrentRun("errImage");
 929  }
 930}
 931
 932void
 933nsHtml5TreeBuilder::errIsindex()
 934{
 935  if (NS_UNLIKELY(mViewSource)) {
 936    mViewSource->AddErrorToCurrentRun("errIsindex");
 937  }
 938}
 939
 940void
 941nsHtml5TreeBuilder::errFooSeenWhenFooOpen(nsIAtom* aName)
 942{
 943  if (NS_UNLIKELY(mViewSource)) {
 944    mViewSource->AddErrorToCurrentRun("errFooSeenWhenFooOpen", aName);
 945  }
 946}
 947
 948void
 949nsHtml5TreeBuilder::errHeadingWhenHeadingOpen()
 950{
 951  if (NS_UNLIKELY(mViewSource)) {
 952    mViewSource->AddErrorToCurrentRun("errHeadingWhenHeadingOpen");
 953  }
 954}
 955
 956void
 957nsHtml5TreeBuilder::errFramesetStart()
 958{
 959  if (NS_UNLIKELY(mViewSource)) {
 960    mViewSource->AddErrorToCurrentRun("errFramesetStart");
 961  }
 962}
 963
 964void
 965nsHtml5TreeBuilder::errNoCellToClose()
 966{
 967  if (NS_UNLIKELY(mViewSource)) {
 968    mViewSource->AddErrorToCurrentRun("errNoCellToClose");
 969  }
 970}
 971
 972void
 973nsHtml5TreeBuilder::errStartTagInTable(nsIAtom* aName)
 974{
 975  if (NS_UNLIKELY(mViewSource)) {
 976    mViewSource->AddErrorToCurrentRun("errStartTagInTable", aName);
 977  }
 978}
 979
 980void
 981nsHtml5TreeBuilder::errFormWhenFormOpen()
 982{
 983  if (NS_UNLIKELY(mViewSource)) {
 984    mViewSource->AddErrorToCurrentRun("errFormWhenFormOpen");
 985  }
 986}
 987
 988void
 989nsHtml5TreeBuilder::errTableSeenWhileTableOpen()
 990{
 991  if (NS_UNLIKELY(mViewSource)) {
 992    mViewSource->AddErrorToCurrentRun("errTableSeenWhileTableOpen");
 993  }
 994}
 995
 996void
 997nsHtml5TreeBuilder::errStartTagInTableBody(nsIAtom* aName)
 998{
 999  if (NS_UNLIKELY(mViewSource)) {
1000    mViewSource->AddErrorToCurrentRun("errStartTagInTableBody", aName);
1001  }
1002}
1003
1004void
1005nsHtml5TreeBuilder::errEndTagSeenWithoutDoctype()
1006{
1007  if (NS_UNLIKELY(mViewSource)) {
1008    mViewSource->AddErrorToCurrentRun("errEndTagSeenWithoutDoctype");
1009  }
1010}
1011
1012void
1013nsHtml5TreeBuilder::errEndTagAfterBody()
1014{
1015  if (NS_UNLIKELY(mViewSource)) {
1016    mViewSource->AddErrorToCurrentRun("errEndTagAfterBody");
1017  }
1018}
1019
1020void
1021nsHtml5TreeBuilder::errEndTagSeenWithSelectOpen(nsIAtom* aName)
1022{
1023  if (NS_UNLIKELY(mViewSource)) {
1024    mViewSource->AddErrorToCurrentRun("errEndTagSeenWithSelectOpen",
1025        aName);
1026  }
1027}
1028
1029void
1030nsHtml5TreeBuilder::errGarbageInColgroup()
1031{
1032  if (NS_UNLIKELY(mViewSource)) {
1033    mViewSource->AddErrorToCurrentRun("errGarbageInColgroup");
1034  }
1035}
1036
1037void
1038nsHtml5TreeBuilder::errEndTagBr()
1039{
1040  if (NS_UNLIKELY(mViewSource)) {
1041    mViewSource->AddErrorToCurrentRun("errEndTagBr");
1042  }
1043}
1044
1045void
1046nsHtml5TreeBuilder::errNoElementToCloseButEndTagSeen(nsIAtom* aName)
1047{
1048  if (NS_UNLIKELY(mViewSource)) {
1049    mViewSource->AddErrorToCurrentRun(
1050        "errNoElementToCloseButEndTagSeen", aName);
1051  }
1052}
1053
1054void
1055nsHtml5TreeBuilder::errHtmlStartTagInForeignContext(nsIAtom* aName)
1056{
1057  if (NS_UNLIKELY(mViewSource)) {
1058    mViewSource->AddErrorToCurrentRun("errHtmlStartTagInForeignContext",
1059        aName);
1060  }
1061}
1062
1063void
1064nsHtml5TreeBuilder::errTableClosedWhileCaptionOpen()
1065{
1066  if (NS_UNLIKELY(mViewSource)) {
1067    mViewSource->AddErrorToCurrentRun("errTableClosedWhileCaptionOpen");
1068  }
1069}
1070
1071void
1072nsHtml5TreeBuilder::errNoTableRowToClose()
1073{
1074  if (NS_UNLIKELY(mViewSource)) {
1075    mViewSource->AddErrorToCurrentRun("errNoTableRowToClose");
1076  }
1077}
1078
1079void
1080nsHtml5TreeBuilder::errNonSpaceInTable()
1081{
1082  if (NS_UNLIKELY(mViewSource)) {
1083    mViewSource->AddErrorToCurrentRun("errNonSpaceInTable");
1084  }
1085}
1086
1087void
1088nsHtml5TreeBuilder::errUnclosedChildrenInRuby()
1089{
1090  if (NS_UNLIKELY(mViewSource)) {
1091    mViewSource->AddErrorToCurrentRun("errUnclosedChildrenInRuby");
1092  }
1093}
1094
1095void
1096nsHtml5TreeBuilder::errStartTagSeenWithoutRuby(nsIAtom* aName)
1097{
1098  if (NS_UNLIKELY(mViewSource)) {
1099    mViewSource->AddErrorToCurrentRun("errStartTagSeenWithoutRuby",
1100        aName);
1101  }
1102}
1103
1104void
1105nsHtml5TreeBuilder::errSelfClosing()
1106{
1107  if (NS_UNLIKELY(mViewSource)) {
1108    mViewSource->AddErrorToCurrentSlash("errSelfClosing");
1109  }
1110}
1111
1112void
1113nsHtml5TreeBuilder::errNoCheckUnclosedElementsOnStack()
1114{
1115  if (NS_UNLIKELY(mViewSource)) {
1116    mViewSource->AddErrorToCurrentRun(
1117        "errNoCheckUnclosedElementsOnStack");
1118  }
1119}
1120
1121void
1122nsHtml5TreeBuilder::errEndTagDidNotMatchCurrentOpenElement(nsIAtom* aName,
1123                                                           nsIAtom* aOther)
1124{
1125  if (NS_UNLIKELY(mViewSource)) {
1126    mViewSource->AddErrorToCurrentRun(
1127        "errEndTagDidNotMatchCurrentOpenElement", aName, aOther);
1128  }
1129}
1130
1131void
1132nsHtml5TreeBuilder::errEndTagViolatesNestingRules(nsIAtom* aName)
1133{
1134  if (NS_UNLIKELY(mViewSource)) {
1135    mViewSource->AddErrorToCurrentRun("errEndTagViolatesNestingRules", aName);
1136  }
1137}
1138
1139void
1140nsHtml5TreeBuilder::errEndWithUnclosedElements(nsIAtom* aName)
1141{
1142  if (NS_UNLIKELY(mViewSource)) {
1143    mViewSource->AddErrorToCurrentRun("errEndWithUnclosedElements", aName);
1144  }
1145}