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