tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsHtml5TreeBuilder.cpp (159603B)


      1 /*
      2 * Copyright (c) 2007 Henri Sivonen
      3 * Copyright (c) 2007-2017 Mozilla Foundation
      4 * Portions of comments Copyright 2004-2008 Apple Computer, Inc., Mozilla
      5 * Foundation, and Opera Software ASA.
      6 *
      7 * Permission is hereby granted, free of charge, to any person obtaining a
      8 * copy of this software and associated documentation files (the "Software"),
      9 * to deal in the Software without restriction, including without limitation
     10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     11 * and/or sell copies of the Software, and to permit persons to whom the
     12 * Software is furnished to do so, subject to the following conditions:
     13 *
     14 * The above copyright notice and this permission notice shall be included in
     15 * all copies or substantial portions of the Software.
     16 *
     17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     23 * DEALINGS IN THE SOFTWARE.
     24 */
     25 
     26 /*
     27 * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT.
     28 * Please edit TreeBuilder.java instead and regenerate.
     29 */
     30 
     31 #define nsHtml5TreeBuilder_cpp__
     32 
     33 #include "nsHtml5AttributeName.h"
     34 #include "nsHtml5ElementName.h"
     35 #include "nsHtml5Tokenizer.h"
     36 #include "nsHtml5StackNode.h"
     37 #include "nsHtml5UTF16Buffer.h"
     38 #include "nsHtml5StateSnapshot.h"
     39 #include "nsHtml5Portability.h"
     40 
     41 #include "nsHtml5TreeBuilder.h"
     42 
     43 char16_t nsHtml5TreeBuilder::REPLACEMENT_CHARACTER[] = {0xfffd};
     44 static const char* const QUIRKY_PUBLIC_IDS_DATA[] = {
     45    "+//silmaril//dtd html pro v0r11 19970101//",
     46    "-//advasoft ltd//dtd html 3.0 aswedit + extensions//",
     47    "-//as//dtd html 3.0 aswedit + extensions//",
     48    "-//ietf//dtd html 2.0 level 1//",
     49    "-//ietf//dtd html 2.0 level 2//",
     50    "-//ietf//dtd html 2.0 strict level 1//",
     51    "-//ietf//dtd html 2.0 strict level 2//",
     52    "-//ietf//dtd html 2.0 strict//",
     53    "-//ietf//dtd html 2.0//",
     54    "-//ietf//dtd html 2.1e//",
     55    "-//ietf//dtd html 3.0//",
     56    "-//ietf//dtd html 3.2 final//",
     57    "-//ietf//dtd html 3.2//",
     58    "-//ietf//dtd html 3//",
     59    "-//ietf//dtd html level 0//",
     60    "-//ietf//dtd html level 1//",
     61    "-//ietf//dtd html level 2//",
     62    "-//ietf//dtd html level 3//",
     63    "-//ietf//dtd html strict level 0//",
     64    "-//ietf//dtd html strict level 1//",
     65    "-//ietf//dtd html strict level 2//",
     66    "-//ietf//dtd html strict level 3//",
     67    "-//ietf//dtd html strict//",
     68    "-//ietf//dtd html//",
     69    "-//metrius//dtd metrius presentational//",
     70    "-//microsoft//dtd internet explorer 2.0 html strict//",
     71    "-//microsoft//dtd internet explorer 2.0 html//",
     72    "-//microsoft//dtd internet explorer 2.0 tables//",
     73    "-//microsoft//dtd internet explorer 3.0 html strict//",
     74    "-//microsoft//dtd internet explorer 3.0 html//",
     75    "-//microsoft//dtd internet explorer 3.0 tables//",
     76    "-//netscape comm. corp.//dtd html//",
     77    "-//netscape comm. corp.//dtd strict html//",
     78    "-//o'reilly and associates//dtd html 2.0//",
     79    "-//o'reilly and associates//dtd html extended 1.0//",
     80    "-//o'reilly and associates//dtd html extended relaxed 1.0//",
     81    "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html "
     82    "4.0//",
     83    "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//",
     84    "-//spyglass//dtd html 2.0 extended//",
     85    "-//sq//dtd html 2.0 hotmetal + extensions//",
     86    "-//sun microsystems corp.//dtd hotjava html//",
     87    "-//sun microsystems corp.//dtd hotjava strict html//",
     88    "-//w3c//dtd html 3 1995-03-24//",
     89    "-//w3c//dtd html 3.2 draft//",
     90    "-//w3c//dtd html 3.2 final//",
     91    "-//w3c//dtd html 3.2//",
     92    "-//w3c//dtd html 3.2s draft//",
     93    "-//w3c//dtd html 4.0 frameset//",
     94    "-//w3c//dtd html 4.0 transitional//",
     95    "-//w3c//dtd html experimental 19960712//",
     96    "-//w3c//dtd html experimental 970421//",
     97    "-//w3c//dtd w3 html//",
     98    "-//w3o//dtd w3 html 3.0//",
     99    "-//webtechs//dtd mozilla html 2.0//",
    100    "-//webtechs//dtd mozilla html//"};
    101 staticJArray<const char*, int32_t> nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS = {
    102    QUIRKY_PUBLIC_IDS_DATA, std::size(QUIRKY_PUBLIC_IDS_DATA)};
    103 void nsHtml5TreeBuilder::setKeepBuffer(bool keepBuffer) {
    104  this->keepBuffer = keepBuffer;
    105 }
    106 
    107 bool nsHtml5TreeBuilder::dropBufferIfLongerThan(int32_t length) {
    108  if (charBuffer.length > length) {
    109    charBuffer = nullptr;
    110    return true;
    111  }
    112  return false;
    113 }
    114 
    115 void nsHtml5TreeBuilder::startTokenization(nsHtml5Tokenizer* self) {
    116  tokenizer = self;
    117  stackNodes = jArray<nsHtml5StackNode*, int32_t>::newJArray(64);
    118  stack = jArray<nsHtml5StackNode*, int32_t>::newJArray(64);
    119  templateModeStack = jArray<int32_t, int32_t>::newJArray(64);
    120  listOfActiveFormattingElements =
    121      jArray<nsHtml5StackNode*, int32_t>::newJArray(64);
    122  needToDropLF = false;
    123  originalMode = INITIAL;
    124  templateModePtr = -1;
    125  stackNodesIdx = 0;
    126  numStackNodes = 0;
    127  currentPtr = -1;
    128  listPtr = -1;
    129  formPointer = nullptr;
    130  headPointer = nullptr;
    131  start(fragment);
    132  charBufferLen = 0;
    133  if (!keepBuffer) {
    134    charBuffer = nullptr;
    135  }
    136  framesetOk = true;
    137  if (fragment) {
    138    nsIContentHandle* elt;
    139    if (contextNode) {
    140      elt = contextNode;
    141    } else {
    142      elt = createHtmlElementSetAsRoot(tokenizer->emptyAttributes());
    143    }
    144    if (contextNamespace == kNameSpaceID_SVG) {
    145      nsHtml5ElementName* elementName = nsHtml5ElementName::ELT_SVG;
    146      if (nsGkAtoms::title == contextName || nsGkAtoms::desc == contextName ||
    147          nsGkAtoms::foreignObject == contextName) {
    148        elementName = nsHtml5ElementName::ELT_FOREIGNOBJECT;
    149      }
    150      nsHtml5StackNode* node =
    151          createStackNode(elementName, elementName->getCamelCaseName(), elt);
    152      currentPtr++;
    153      stack[currentPtr] = node;
    154      tokenizer->setState(nsHtml5Tokenizer::DATA);
    155      mode = FRAMESET_OK;
    156    } else if (contextNamespace == kNameSpaceID_MathML) {
    157      nsHtml5ElementName* elementName = nsHtml5ElementName::ELT_MATH;
    158      if (nsGkAtoms::mi == contextName || nsGkAtoms::mo == contextName ||
    159          nsGkAtoms::mn == contextName || nsGkAtoms::ms == contextName ||
    160          nsGkAtoms::mtext == contextName) {
    161        elementName = nsHtml5ElementName::ELT_MTEXT;
    162      } else if (nsGkAtoms::annotation_xml == contextName) {
    163        elementName = nsHtml5ElementName::ELT_ANNOTATION_XML;
    164      }
    165      nsHtml5StackNode* node =
    166          createStackNode(elementName, elt, elementName->getName(), false);
    167      currentPtr++;
    168      stack[currentPtr] = node;
    169      tokenizer->setState(nsHtml5Tokenizer::DATA);
    170      mode = FRAMESET_OK;
    171    } else {
    172      nsHtml5StackNode* node =
    173          createStackNode(nsHtml5ElementName::ELT_HTML, elt);
    174      currentPtr++;
    175      stack[currentPtr] = node;
    176      if (nsGkAtoms::_template == contextName) {
    177        pushTemplateMode(IN_TEMPLATE);
    178      }
    179      resetTheInsertionMode();
    180      formPointer = getFormPointerForContext(contextNode);
    181      if (nsGkAtoms::title == contextName ||
    182          nsGkAtoms::textarea == contextName) {
    183        tokenizer->setState(nsHtml5Tokenizer::RCDATA);
    184      } else if (nsGkAtoms::style == contextName ||
    185                 nsGkAtoms::xmp == contextName ||
    186                 nsGkAtoms::iframe == contextName ||
    187                 nsGkAtoms::noembed == contextName ||
    188                 nsGkAtoms::noframes == contextName ||
    189                 (scriptingEnabled && nsGkAtoms::noscript == contextName)) {
    190        tokenizer->setState(nsHtml5Tokenizer::RAWTEXT);
    191      } else if (nsGkAtoms::plaintext == contextName) {
    192        tokenizer->setState(nsHtml5Tokenizer::PLAINTEXT);
    193      } else if (nsGkAtoms::script == contextName) {
    194        tokenizer->setState(nsHtml5Tokenizer::SCRIPT_DATA);
    195      } else {
    196        tokenizer->setState(nsHtml5Tokenizer::DATA);
    197      }
    198    }
    199  } else {
    200    mode = INITIAL;
    201    if (tokenizer->isViewingXmlSource()) {
    202      nsIContentHandle* elt = createElement(
    203          kNameSpaceID_SVG, nsGkAtoms::svg, tokenizer->emptyAttributes(),
    204          nullptr, svgCreator(NS_NewSVGSVGElement));
    205      nsHtml5StackNode* node =
    206          createStackNode(nsHtml5ElementName::ELT_SVG, nsGkAtoms::svg, elt);
    207      currentPtr++;
    208      stack[currentPtr] = node;
    209    }
    210  }
    211 }
    212 
    213 void nsHtml5TreeBuilder::doctype(nsAtom* name, nsHtml5String publicIdentifier,
    214                                 nsHtml5String systemIdentifier,
    215                                 bool forceQuirks) {
    216  needToDropLF = false;
    217  if (!isInForeign() && mode == INITIAL) {
    218    nsHtml5String emptyString = nsHtml5Portability::newEmptyString();
    219    appendDoctypeToDocument(!name ? nsGkAtoms::_empty : name,
    220                            !publicIdentifier ? emptyString : publicIdentifier,
    221                            !systemIdentifier ? emptyString : systemIdentifier);
    222    emptyString.Release();
    223    if (isQuirky(name, publicIdentifier, systemIdentifier, forceQuirks)) {
    224      errQuirkyDoctype();
    225      documentModeInternal(QUIRKS_MODE, publicIdentifier, systemIdentifier);
    226    } else if (isAlmostStandards(publicIdentifier, systemIdentifier)) {
    227      errAlmostStandardsDoctype();
    228      documentModeInternal(ALMOST_STANDARDS_MODE, publicIdentifier,
    229                           systemIdentifier);
    230    } else {
    231      documentModeInternal(STANDARDS_MODE, publicIdentifier, systemIdentifier);
    232    }
    233    mode = BEFORE_HTML;
    234    return;
    235  }
    236  errStrayDoctype();
    237  return;
    238 }
    239 
    240 void nsHtml5TreeBuilder::comment(char16_t* buf, int32_t start, int32_t length) {
    241  needToDropLF = false;
    242  if (!isInForeign()) {
    243    switch (mode) {
    244      case INITIAL:
    245      case BEFORE_HTML:
    246      case AFTER_AFTER_BODY:
    247      case AFTER_AFTER_FRAMESET: {
    248        appendCommentToDocument(buf, start, length);
    249        return;
    250      }
    251      case AFTER_BODY: {
    252        flushCharacters();
    253        appendComment(stack[0]->node, buf, start, length);
    254        return;
    255      }
    256      default: {
    257        break;
    258      }
    259    }
    260  }
    261  flushCharacters();
    262  appendComment(stack[currentPtr]->node, buf, start, length);
    263  return;
    264 }
    265 
    266 void nsHtml5TreeBuilder::characters(const char16_t* buf, int32_t start,
    267                                    int32_t length) {
    268  if (tokenizer->isViewingXmlSource()) {
    269    return;
    270  }
    271  if (needToDropLF) {
    272    needToDropLF = false;
    273    if (buf[start] == '\n') {
    274      start++;
    275      length--;
    276      if (!length) {
    277        return;
    278      }
    279    }
    280  }
    281  switch (mode) {
    282    case IN_BODY:
    283    case IN_CELL:
    284    case IN_CAPTION: {
    285      if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
    286        reconstructTheActiveFormattingElements();
    287      }
    288      [[fallthrough]];
    289    }
    290    case TEXT: {
    291      accumulateCharacters(buf, start, length);
    292      return;
    293    }
    294    case IN_TABLE:
    295    case IN_TABLE_BODY:
    296    case IN_ROW: {
    297      accumulateCharactersForced(buf, start, length);
    298      return;
    299    }
    300    default: {
    301      int32_t end = start + length;
    302      for (int32_t i = start; i < end; i++) {
    303        switch (buf[i]) {
    304          case ' ':
    305          case '\t':
    306          case '\n':
    307          case '\r':
    308          case '\f': {
    309            switch (mode) {
    310              case INITIAL:
    311              case BEFORE_HTML:
    312              case BEFORE_HEAD: {
    313                start = i + 1;
    314                continue;
    315              }
    316              case IN_HEAD:
    317              case IN_HEAD_NOSCRIPT:
    318              case AFTER_HEAD:
    319              case IN_COLUMN_GROUP:
    320              case IN_FRAMESET:
    321              case AFTER_FRAMESET: {
    322                continue;
    323              }
    324              case FRAMESET_OK:
    325              case IN_TEMPLATE:
    326              case IN_BODY:
    327              case IN_CELL:
    328              case IN_CAPTION: {
    329                if (start < i) {
    330                  accumulateCharacters(buf, start, i - start);
    331                  start = i;
    332                }
    333                if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
    334                  flushCharacters();
    335                  reconstructTheActiveFormattingElements();
    336                }
    337                NS_HTML5_BREAK(charactersloop);
    338              }
    339              case IN_SELECT:
    340              case IN_SELECT_IN_TABLE: {
    341                NS_HTML5_BREAK(charactersloop);
    342              }
    343              case IN_TABLE:
    344              case IN_TABLE_BODY:
    345              case IN_ROW: {
    346                accumulateCharactersForced(buf, i, 1);
    347                start = i + 1;
    348                continue;
    349              }
    350              case AFTER_BODY:
    351              case AFTER_AFTER_BODY:
    352              case AFTER_AFTER_FRAMESET: {
    353                if (start < i) {
    354                  accumulateCharacters(buf, start, i - start);
    355                  start = i;
    356                }
    357                flushCharacters();
    358                reconstructTheActiveFormattingElements();
    359                continue;
    360              }
    361            }
    362            MOZ_FALLTHROUGH_ASSERT();
    363          }
    364          default: {
    365            switch (mode) {
    366              case INITIAL: {
    367                documentModeInternal(QUIRKS_MODE, nullptr, nullptr);
    368                mode = BEFORE_HTML;
    369                i--;
    370                continue;
    371              }
    372              case BEFORE_HTML: {
    373                appendHtmlElementToDocumentAndPush();
    374                mode = BEFORE_HEAD;
    375                i--;
    376                continue;
    377              }
    378              case BEFORE_HEAD: {
    379                if (start < i) {
    380                  accumulateCharacters(buf, start, i - start);
    381                  start = i;
    382                }
    383                flushCharacters();
    384                appendToCurrentNodeAndPushHeadElement(
    385                    nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
    386                mode = IN_HEAD;
    387                i--;
    388                continue;
    389              }
    390              case IN_HEAD: {
    391                if (start < i) {
    392                  accumulateCharacters(buf, start, i - start);
    393                  start = i;
    394                }
    395                flushCharacters();
    396                pop();
    397                mode = AFTER_HEAD;
    398                i--;
    399                continue;
    400              }
    401              case IN_HEAD_NOSCRIPT: {
    402                if (start < i) {
    403                  accumulateCharacters(buf, start, i - start);
    404                  start = i;
    405                }
    406                errNonSpaceInNoscriptInHead();
    407                flushCharacters();
    408                pop();
    409                mode = IN_HEAD;
    410                i--;
    411                continue;
    412              }
    413              case AFTER_HEAD: {
    414                if (start < i) {
    415                  accumulateCharacters(buf, start, i - start);
    416                  start = i;
    417                }
    418                flushCharacters();
    419                appendToCurrentNodeAndPushBodyElement();
    420                mode = FRAMESET_OK;
    421                i--;
    422                continue;
    423              }
    424              case FRAMESET_OK: {
    425                framesetOk = false;
    426                mode = IN_BODY;
    427                i--;
    428                continue;
    429              }
    430              case IN_TEMPLATE:
    431              case IN_BODY:
    432              case IN_CELL:
    433              case IN_CAPTION: {
    434                if (start < i) {
    435                  accumulateCharacters(buf, start, i - start);
    436                  start = i;
    437                }
    438                if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
    439                  flushCharacters();
    440                  reconstructTheActiveFormattingElements();
    441                }
    442                NS_HTML5_BREAK(charactersloop);
    443              }
    444              case IN_TABLE:
    445              case IN_TABLE_BODY:
    446              case IN_ROW: {
    447                accumulateCharactersForced(buf, i, 1);
    448                start = i + 1;
    449                continue;
    450              }
    451              case IN_COLUMN_GROUP: {
    452                if (start < i) {
    453                  accumulateCharacters(buf, start, i - start);
    454                  start = i;
    455                }
    456                if (!currentPtr || stack[currentPtr]->getGroup() ==
    457                                       nsHtml5TreeBuilder::TEMPLATE) {
    458                  errNonSpaceInColgroupInFragment();
    459                  start = i + 1;
    460                  continue;
    461                }
    462                flushCharacters();
    463                pop();
    464                mode = IN_TABLE;
    465                i--;
    466                continue;
    467              }
    468              case IN_SELECT:
    469              case IN_SELECT_IN_TABLE: {
    470                NS_HTML5_BREAK(charactersloop);
    471              }
    472              case AFTER_BODY: {
    473                errNonSpaceAfterBody();
    474 
    475                mode = framesetOk ? FRAMESET_OK : IN_BODY;
    476                i--;
    477                continue;
    478              }
    479              case IN_FRAMESET: {
    480                if (start < i) {
    481                  accumulateCharacters(buf, start, i - start);
    482                }
    483                errNonSpaceInFrameset();
    484                start = i + 1;
    485                continue;
    486              }
    487              case AFTER_FRAMESET: {
    488                if (start < i) {
    489                  accumulateCharacters(buf, start, i - start);
    490                }
    491                errNonSpaceAfterFrameset();
    492                start = i + 1;
    493                continue;
    494              }
    495              case AFTER_AFTER_BODY: {
    496                errNonSpaceInTrailer();
    497                mode = framesetOk ? FRAMESET_OK : IN_BODY;
    498                i--;
    499                continue;
    500              }
    501              case AFTER_AFTER_FRAMESET: {
    502                if (start < i) {
    503                  accumulateCharacters(buf, start, i - start);
    504                }
    505                errNonSpaceInTrailer();
    506                start = i + 1;
    507                continue;
    508              }
    509            }
    510          }
    511        }
    512      }
    513    charactersloop_end:;
    514      if (start < end) {
    515        accumulateCharacters(buf, start, end - start);
    516      }
    517    }
    518  }
    519 }
    520 
    521 void nsHtml5TreeBuilder::zeroOriginatingReplacementCharacter() {
    522  if (mode == TEXT) {
    523    accumulateCharacters(REPLACEMENT_CHARACTER, 0, 1);
    524    return;
    525  }
    526  if (currentPtr >= 0) {
    527    if (isSpecialParentInForeign(stack[currentPtr])) {
    528      return;
    529    }
    530    accumulateCharacters(REPLACEMENT_CHARACTER, 0, 1);
    531  }
    532 }
    533 
    534 void nsHtml5TreeBuilder::zeroOrReplacementCharacter() {
    535  zeroOriginatingReplacementCharacter();
    536 }
    537 
    538 void nsHtml5TreeBuilder::eof() {
    539  flushCharacters();
    540  for (;;) {
    541    switch (mode) {
    542      case INITIAL: {
    543        documentModeInternal(QUIRKS_MODE, nullptr, nullptr);
    544        mode = BEFORE_HTML;
    545        continue;
    546      }
    547      case BEFORE_HTML: {
    548        appendHtmlElementToDocumentAndPush();
    549        mode = BEFORE_HEAD;
    550        continue;
    551      }
    552      case BEFORE_HEAD: {
    553        appendToCurrentNodeAndPushHeadElement(
    554            nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
    555        mode = IN_HEAD;
    556        continue;
    557      }
    558      case IN_HEAD: {
    559        while (currentPtr > 0) {
    560          popOnEof();
    561        }
    562        mode = AFTER_HEAD;
    563        continue;
    564      }
    565      case IN_HEAD_NOSCRIPT: {
    566        while (currentPtr > 1) {
    567          popOnEof();
    568        }
    569        mode = IN_HEAD;
    570        continue;
    571      }
    572      case AFTER_HEAD: {
    573        appendToCurrentNodeAndPushBodyElement();
    574        mode = IN_BODY;
    575        continue;
    576      }
    577      case IN_TABLE_BODY:
    578      case IN_ROW:
    579      case IN_TABLE:
    580      case IN_SELECT_IN_TABLE:
    581      case IN_SELECT:
    582      case IN_COLUMN_GROUP:
    583      case FRAMESET_OK:
    584      case IN_CAPTION:
    585      case IN_CELL:
    586      case IN_BODY: {
    587        if (isTemplateModeStackEmpty()) {
    588          NS_HTML5_BREAK(eofloop);
    589        }
    590        [[fallthrough]];
    591      }
    592      case IN_TEMPLATE: {
    593        int32_t eltPos = findLast(nsGkAtoms::_template);
    594        if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
    595          MOZ_ASSERT(fragment);
    596          NS_HTML5_BREAK(eofloop);
    597        }
    598        if (MOZ_UNLIKELY(mViewSource)) {
    599          errListUnclosedStartTags(0);
    600        }
    601        while (currentPtr >= eltPos) {
    602          pop();
    603        }
    604        clearTheListOfActiveFormattingElementsUpToTheLastMarker();
    605        popTemplateMode();
    606        resetTheInsertionMode();
    607        continue;
    608      }
    609      case TEXT: {
    610        if (originalMode == AFTER_HEAD) {
    611          popOnEof();
    612        }
    613        popOnEof();
    614        mode = originalMode;
    615        continue;
    616      }
    617      case IN_FRAMESET: {
    618        NS_HTML5_BREAK(eofloop);
    619      }
    620      case AFTER_BODY:
    621      case AFTER_FRAMESET:
    622      case AFTER_AFTER_BODY:
    623      case AFTER_AFTER_FRAMESET:
    624      default: {
    625        NS_HTML5_BREAK(eofloop);
    626      }
    627    }
    628  }
    629 eofloop_end:;
    630  while (currentPtr > 0) {
    631    popOnEof();
    632  }
    633  if (!fragment) {
    634    popOnEof();
    635  }
    636 }
    637 
    638 void nsHtml5TreeBuilder::endTokenization() {
    639  formPointer = nullptr;
    640  headPointer = nullptr;
    641  contextName = nullptr;
    642  contextNode = nullptr;
    643  templateModeStack = nullptr;
    644  if (stack) {
    645    while (currentPtr > -1) {
    646      stack[currentPtr]->release(this);
    647      currentPtr--;
    648    }
    649    stack = nullptr;
    650  }
    651  if (listOfActiveFormattingElements) {
    652    while (listPtr > -1) {
    653      if (listOfActiveFormattingElements[listPtr]) {
    654        listOfActiveFormattingElements[listPtr]->release(this);
    655      }
    656      listPtr--;
    657    }
    658    listOfActiveFormattingElements = nullptr;
    659  }
    660  if (stackNodes) {
    661    for (int32_t i = 0; i < numStackNodes; i++) {
    662      MOZ_ASSERT(stackNodes[i]->isUnused());
    663      delete stackNodes[i];
    664    }
    665    numStackNodes = 0;
    666    stackNodesIdx = 0;
    667    stackNodes = nullptr;
    668  }
    669  if (!keepBuffer) {
    670    charBuffer = nullptr;
    671  }
    672  end();
    673 }
    674 
    675 void nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName,
    676                                  nsHtml5HtmlAttributes* attributes,
    677                                  bool selfClosing) {
    678  flushCharacters();
    679  int32_t eltPos;
    680  needToDropLF = false;
    681 starttagloop:
    682  for (;;) {
    683    int32_t group = elementName->getGroup();
    684    nsAtom* name = elementName->getName();
    685    if (isInForeign()) {
    686      nsHtml5StackNode* currentNode = stack[currentPtr];
    687      int32_t currNs = currentNode->ns;
    688      if (!(currentNode->isHtmlIntegrationPoint() ||
    689            (currNs == kNameSpaceID_MathML &&
    690             ((currentNode->getGroup() == MI_MO_MN_MS_MTEXT &&
    691               group != MGLYPH_OR_MALIGNMARK) ||
    692              (currentNode->getGroup() == ANNOTATION_XML && group == SVG))))) {
    693        switch (group) {
    694          case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
    695          case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
    696          case BODY:
    697          case BR:
    698          case RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR:
    699          case DD_OR_DT:
    700          case UL_OR_OL_OR_DL:
    701          case EMBED:
    702          case IMG:
    703          case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6:
    704          case HEAD:
    705          case HR:
    706          case LI:
    707          case META:
    708          case NOBR:
    709          case P:
    710          case PRE_OR_LISTING:
    711          case TABLE:
    712          case FONT: {
    713            if (!(group == FONT &&
    714                  !(attributes->contains(nsHtml5AttributeName::ATTR_COLOR) ||
    715                    attributes->contains(nsHtml5AttributeName::ATTR_FACE) ||
    716                    attributes->contains(nsHtml5AttributeName::ATTR_SIZE)))) {
    717              errHtmlStartTagInForeignContext(name);
    718              if (!fragment) {
    719                while (!isSpecialParentInForeign(stack[currentPtr])) {
    720                  popForeign(-1, -1);
    721                }
    722                NS_HTML5_CONTINUE(starttagloop);
    723              }
    724            }
    725            [[fallthrough]];
    726          }
    727          default: {
    728            if (kNameSpaceID_SVG == currNs) {
    729              attributes->adjustForSvg();
    730              if (selfClosing) {
    731                appendVoidElementToCurrentMayFosterSVG(elementName, attributes);
    732                selfClosing = false;
    733              } else {
    734                appendToCurrentNodeAndPushElementMayFosterSVG(elementName,
    735                                                              attributes);
    736              }
    737              attributes = nullptr;
    738              NS_HTML5_BREAK(starttagloop);
    739            } else {
    740              attributes->adjustForMath();
    741              if (selfClosing) {
    742                appendVoidElementToCurrentMayFosterMathML(elementName,
    743                                                          attributes);
    744                selfClosing = false;
    745              } else {
    746                appendToCurrentNodeAndPushElementMayFosterMathML(elementName,
    747                                                                 attributes);
    748              }
    749              attributes = nullptr;
    750              NS_HTML5_BREAK(starttagloop);
    751            }
    752          }
    753        }
    754      }
    755    }
    756    switch (mode) {
    757      case IN_TEMPLATE: {
    758        switch (group) {
    759          case COL: {
    760            popTemplateMode();
    761            pushTemplateMode(IN_COLUMN_GROUP);
    762            mode = IN_COLUMN_GROUP;
    763            continue;
    764          }
    765          case CAPTION:
    766          case COLGROUP:
    767          case TBODY_OR_THEAD_OR_TFOOT: {
    768            popTemplateMode();
    769            pushTemplateMode(IN_TABLE);
    770            mode = IN_TABLE;
    771            continue;
    772          }
    773          case TR: {
    774            popTemplateMode();
    775            pushTemplateMode(IN_TABLE_BODY);
    776            mode = IN_TABLE_BODY;
    777            continue;
    778          }
    779          case TD_OR_TH: {
    780            popTemplateMode();
    781            pushTemplateMode(IN_ROW);
    782            mode = IN_ROW;
    783            continue;
    784          }
    785          case META: {
    786            checkMetaCharset(attributes);
    787            appendVoidElementToCurrentMayFoster(elementName, attributes);
    788            selfClosing = false;
    789            attributes = nullptr;
    790            NS_HTML5_BREAK(starttagloop);
    791          }
    792          case TITLE: {
    793            startTagTitleInHead(elementName, attributes);
    794            attributes = nullptr;
    795            NS_HTML5_BREAK(starttagloop);
    796          }
    797          case BASE:
    798          case LINK_OR_BASEFONT_OR_BGSOUND: {
    799            appendVoidElementToCurrentMayFoster(elementName, attributes);
    800            selfClosing = false;
    801            attributes = nullptr;
    802            NS_HTML5_BREAK(starttagloop);
    803          }
    804          case SCRIPT: {
    805            startTagScriptInHead(elementName, attributes);
    806            attributes = nullptr;
    807            NS_HTML5_BREAK(starttagloop);
    808          }
    809          case NOFRAMES:
    810          case STYLE: {
    811            startTagGenericRawText(elementName, attributes);
    812            attributes = nullptr;
    813            NS_HTML5_BREAK(starttagloop);
    814          }
    815          case TEMPLATE: {
    816            startTagTemplateInHead(elementName, attributes);
    817            attributes = nullptr;
    818            NS_HTML5_BREAK(starttagloop);
    819          }
    820          default: {
    821            popTemplateMode();
    822            pushTemplateMode(IN_BODY);
    823            mode = IN_BODY;
    824            continue;
    825          }
    826        }
    827      }
    828      case IN_ROW: {
    829        switch (group) {
    830          case TD_OR_TH: {
    831            clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TR));
    832            appendToCurrentNodeAndPushElement(elementName, attributes);
    833            mode = IN_CELL;
    834            insertMarker();
    835            attributes = nullptr;
    836            NS_HTML5_BREAK(starttagloop);
    837          }
    838          case CAPTION:
    839          case COL:
    840          case COLGROUP:
    841          case TBODY_OR_THEAD_OR_TFOOT:
    842          case TR: {
    843            eltPos = findLastOrRoot(nsHtml5TreeBuilder::TR);
    844            if (!eltPos) {
    845              MOZ_ASSERT(fragment || isTemplateContents());
    846              errNoTableRowToClose();
    847              NS_HTML5_BREAK(starttagloop);
    848            }
    849            clearStackBackTo(eltPos);
    850            pop();
    851            mode = IN_TABLE_BODY;
    852            continue;
    853          }
    854          default:;  // fall through
    855        }
    856        [[fallthrough]];
    857      }
    858      case IN_TABLE_BODY: {
    859        switch (group) {
    860          case TR: {
    861            clearStackBackTo(
    862                findLastInTableScopeOrRootTemplateTbodyTheadTfoot());
    863            appendToCurrentNodeAndPushElement(elementName, attributes);
    864            mode = IN_ROW;
    865            attributes = nullptr;
    866            NS_HTML5_BREAK(starttagloop);
    867          }
    868          case TD_OR_TH: {
    869            errStartTagInTableBody(name);
    870            clearStackBackTo(
    871                findLastInTableScopeOrRootTemplateTbodyTheadTfoot());
    872            appendToCurrentNodeAndPushElement(
    873                nsHtml5ElementName::ELT_TR,
    874                nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
    875            mode = IN_ROW;
    876            continue;
    877          }
    878          case CAPTION:
    879          case COL:
    880          case COLGROUP:
    881          case TBODY_OR_THEAD_OR_TFOOT: {
    882            eltPos = findLastInTableScopeOrRootTemplateTbodyTheadTfoot();
    883            if (!eltPos || stack[eltPos]->getGroup() == TEMPLATE) {
    884              MOZ_ASSERT(fragment || isTemplateContents());
    885              errStrayStartTag(name);
    886              NS_HTML5_BREAK(starttagloop);
    887            } else {
    888              clearStackBackTo(eltPos);
    889              pop();
    890              mode = IN_TABLE;
    891              continue;
    892            }
    893          }
    894          default:;  // fall through
    895        }
    896        [[fallthrough]];
    897      }
    898      case IN_TABLE: {
    899        for (;;) {
    900          switch (group) {
    901            case CAPTION: {
    902              clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE));
    903              insertMarker();
    904              appendToCurrentNodeAndPushElement(elementName, attributes);
    905              mode = IN_CAPTION;
    906              attributes = nullptr;
    907              NS_HTML5_BREAK(starttagloop);
    908            }
    909            case COLGROUP: {
    910              clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE));
    911              appendToCurrentNodeAndPushElement(elementName, attributes);
    912              mode = IN_COLUMN_GROUP;
    913              attributes = nullptr;
    914              NS_HTML5_BREAK(starttagloop);
    915            }
    916            case COL: {
    917              clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE));
    918              appendToCurrentNodeAndPushElement(
    919                  nsHtml5ElementName::ELT_COLGROUP,
    920                  nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
    921              mode = IN_COLUMN_GROUP;
    922              NS_HTML5_CONTINUE(starttagloop);
    923            }
    924            case TBODY_OR_THEAD_OR_TFOOT: {
    925              clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE));
    926              appendToCurrentNodeAndPushElement(elementName, attributes);
    927              mode = IN_TABLE_BODY;
    928              attributes = nullptr;
    929              NS_HTML5_BREAK(starttagloop);
    930            }
    931            case TR:
    932            case TD_OR_TH: {
    933              clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE));
    934              appendToCurrentNodeAndPushElement(
    935                  nsHtml5ElementName::ELT_TBODY,
    936                  nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
    937              mode = IN_TABLE_BODY;
    938              NS_HTML5_CONTINUE(starttagloop);
    939            }
    940            case TEMPLATE: {
    941              NS_HTML5_BREAK(intableloop);
    942            }
    943            case TABLE: {
    944              errTableSeenWhileTableOpen();
    945              eltPos = findLastInTableScope(name);
    946              if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
    947                MOZ_ASSERT(fragment || isTemplateContents());
    948                NS_HTML5_BREAK(starttagloop);
    949              }
    950              generateImpliedEndTags();
    951              if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(nsGkAtoms::table)) {
    952                errNoCheckUnclosedElementsOnStack();
    953              }
    954              while (currentPtr >= eltPos) {
    955                pop();
    956              }
    957              resetTheInsertionMode();
    958              NS_HTML5_CONTINUE(starttagloop);
    959            }
    960            case SCRIPT: {
    961              appendToCurrentNodeAndPushElement(elementName, attributes);
    962              originalMode = mode;
    963              mode = TEXT;
    964              tokenizer->setStateAndEndTagExpectation(
    965                  nsHtml5Tokenizer::SCRIPT_DATA, elementName);
    966              attributes = nullptr;
    967              NS_HTML5_BREAK(starttagloop);
    968            }
    969            case STYLE: {
    970              appendToCurrentNodeAndPushElement(elementName, attributes);
    971              originalMode = mode;
    972              mode = TEXT;
    973              tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
    974                                                      elementName);
    975              attributes = nullptr;
    976              NS_HTML5_BREAK(starttagloop);
    977            }
    978            case INPUT: {
    979              errStartTagInTable(name);
    980              if (!nsHtml5Portability::
    981                      lowerCaseLiteralEqualsIgnoreAsciiCaseString(
    982                          "hidden", attributes->getValue(
    983                                        nsHtml5AttributeName::ATTR_TYPE))) {
    984                NS_HTML5_BREAK(intableloop);
    985              }
    986              appendVoidInputToCurrent(attributes, formPointer);
    987              selfClosing = false;
    988              attributes = nullptr;
    989              NS_HTML5_BREAK(starttagloop);
    990            }
    991            case FORM: {
    992              if (!!formPointer || isTemplateContents()) {
    993                errFormWhenFormOpen();
    994                NS_HTML5_BREAK(starttagloop);
    995              } else {
    996                errStartTagInTable(name);
    997                appendVoidFormToCurrent(attributes);
    998                attributes = nullptr;
    999                NS_HTML5_BREAK(starttagloop);
   1000              }
   1001            }
   1002            default: {
   1003              errStartTagInTable(name);
   1004              NS_HTML5_BREAK(intableloop);
   1005            }
   1006          }
   1007        }
   1008      intableloop_end:;
   1009        [[fallthrough]];
   1010      }
   1011      case IN_CAPTION: {
   1012        switch (group) {
   1013          case CAPTION:
   1014          case COL:
   1015          case COLGROUP:
   1016          case TBODY_OR_THEAD_OR_TFOOT:
   1017          case TR:
   1018          case TD_OR_TH: {
   1019            eltPos = findLastInTableScope(nsGkAtoms::caption);
   1020            if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
   1021              MOZ_ASSERT(fragment || isTemplateContents());
   1022              errStrayStartTag(name);
   1023              NS_HTML5_BREAK(starttagloop);
   1024            }
   1025            generateImpliedEndTags();
   1026            if (!!MOZ_UNLIKELY(mViewSource) && currentPtr != eltPos) {
   1027              errNoCheckUnclosedElementsOnStack();
   1028            }
   1029            while (currentPtr >= eltPos) {
   1030              pop();
   1031            }
   1032            clearTheListOfActiveFormattingElementsUpToTheLastMarker();
   1033            mode = IN_TABLE;
   1034            continue;
   1035          }
   1036          default:;  // fall through
   1037        }
   1038        [[fallthrough]];
   1039      }
   1040      case IN_CELL: {
   1041        switch (group) {
   1042          case CAPTION:
   1043          case COL:
   1044          case COLGROUP:
   1045          case TBODY_OR_THEAD_OR_TFOOT:
   1046          case TR:
   1047          case TD_OR_TH: {
   1048            eltPos = findLastInTableScopeTdTh();
   1049            if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
   1050              errNoCellToClose();
   1051              NS_HTML5_BREAK(starttagloop);
   1052            } else {
   1053              closeTheCell(eltPos);
   1054              continue;
   1055            }
   1056          }
   1057          default:;  // fall through
   1058        }
   1059        [[fallthrough]];
   1060      }
   1061      case FRAMESET_OK: {
   1062        switch (group) {
   1063          case FRAMESET: {
   1064            if (mode == FRAMESET_OK) {
   1065              if (!currentPtr || stack[1]->getGroup() != BODY) {
   1066                MOZ_ASSERT(fragment || isTemplateContents());
   1067                errStrayStartTag(name);
   1068                NS_HTML5_BREAK(starttagloop);
   1069              } else {
   1070                errFramesetStart();
   1071                detachFromParent(stack[1]->node);
   1072                while (currentPtr > 0) {
   1073                  pop();
   1074                }
   1075                appendToCurrentNodeAndPushElement(elementName, attributes);
   1076                mode = IN_FRAMESET;
   1077                attributes = nullptr;
   1078                NS_HTML5_BREAK(starttagloop);
   1079              }
   1080            } else {
   1081              errStrayStartTag(name);
   1082              NS_HTML5_BREAK(starttagloop);
   1083            }
   1084          }
   1085          case PRE_OR_LISTING:
   1086          case LI:
   1087          case DD_OR_DT:
   1088          case BUTTON:
   1089          case MARQUEE_OR_APPLET:
   1090          case OBJECT:
   1091          case TABLE:
   1092          case AREA_OR_WBR:
   1093          case KEYGEN:
   1094          case BR:
   1095          case EMBED:
   1096          case IMG:
   1097          case INPUT:
   1098          case HR:
   1099          case TEXTAREA:
   1100          case XMP:
   1101          case IFRAME:
   1102          case SELECT: {
   1103            if (mode == FRAMESET_OK &&
   1104                !(group == INPUT &&
   1105                  nsHtml5Portability::
   1106                      lowerCaseLiteralEqualsIgnoreAsciiCaseString(
   1107                          "hidden", attributes->getValue(
   1108                                        nsHtml5AttributeName::ATTR_TYPE)))) {
   1109              framesetOk = false;
   1110              mode = IN_BODY;
   1111            }
   1112            [[fallthrough]];
   1113          }
   1114          default:;  // fall through
   1115        }
   1116        [[fallthrough]];
   1117      }
   1118      case IN_BODY: {
   1119        for (;;) {
   1120          switch (group) {
   1121            case HTML: {
   1122              errStrayStartTag(name);
   1123              if (!fragment && !isTemplateContents()) {
   1124                addAttributesToHtml(attributes);
   1125                attributes = nullptr;
   1126              }
   1127              NS_HTML5_BREAK(starttagloop);
   1128            }
   1129            case BASE:
   1130            case LINK_OR_BASEFONT_OR_BGSOUND:
   1131            case META:
   1132            case STYLE:
   1133            case SCRIPT:
   1134            case TITLE:
   1135            case TEMPLATE: {
   1136              NS_HTML5_BREAK(inbodyloop);
   1137            }
   1138            case BODY: {
   1139              if (!currentPtr || stack[1]->getGroup() != BODY ||
   1140                  isTemplateContents()) {
   1141                MOZ_ASSERT(fragment || isTemplateContents());
   1142                errStrayStartTag(name);
   1143                NS_HTML5_BREAK(starttagloop);
   1144              }
   1145              errFooSeenWhenFooOpen(name);
   1146              framesetOk = false;
   1147              if (mode == FRAMESET_OK) {
   1148                mode = IN_BODY;
   1149              }
   1150              if (addAttributesToBody(attributes)) {
   1151                attributes = nullptr;
   1152              }
   1153              NS_HTML5_BREAK(starttagloop);
   1154            }
   1155            case P:
   1156            case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
   1157            case UL_OR_OL_OR_DL:
   1158            case ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SEARCH_OR_SECTION_OR_SUMMARY: {
   1159              implicitlyCloseP();
   1160              appendToCurrentNodeAndPushElementMayFoster(elementName,
   1161                                                         attributes);
   1162              attributes = nullptr;
   1163              NS_HTML5_BREAK(starttagloop);
   1164            }
   1165            case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6: {
   1166              implicitlyCloseP();
   1167              if (stack[currentPtr]->getGroup() ==
   1168                  H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6) {
   1169                errHeadingWhenHeadingOpen();
   1170                pop();
   1171              }
   1172              appendToCurrentNodeAndPushElementMayFoster(elementName,
   1173                                                         attributes);
   1174              attributes = nullptr;
   1175              NS_HTML5_BREAK(starttagloop);
   1176            }
   1177            case FIELDSET: {
   1178              implicitlyCloseP();
   1179              appendToCurrentNodeAndPushElementMayFoster(
   1180                  elementName, attributes, formPointer);
   1181              attributes = nullptr;
   1182              NS_HTML5_BREAK(starttagloop);
   1183            }
   1184            case PRE_OR_LISTING: {
   1185              implicitlyCloseP();
   1186              appendToCurrentNodeAndPushElementMayFoster(elementName,
   1187                                                         attributes);
   1188              needToDropLF = true;
   1189              attributes = nullptr;
   1190              NS_HTML5_BREAK(starttagloop);
   1191            }
   1192            case FORM: {
   1193              if (!!formPointer && !isTemplateContents()) {
   1194                errFormWhenFormOpen();
   1195                NS_HTML5_BREAK(starttagloop);
   1196              } else {
   1197                implicitlyCloseP();
   1198                appendToCurrentNodeAndPushFormElementMayFoster(attributes);
   1199                attributes = nullptr;
   1200                NS_HTML5_BREAK(starttagloop);
   1201              }
   1202            }
   1203            case LI:
   1204            case DD_OR_DT: {
   1205              eltPos = currentPtr;
   1206              for (;;) {
   1207                nsHtml5StackNode* node = stack[eltPos];
   1208                if (node->getGroup() == group) {
   1209                  generateImpliedEndTagsExceptFor(node->name);
   1210                  if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
   1211                    errUnclosedElementsImplied(eltPos, name);
   1212                  }
   1213                  while (currentPtr >= eltPos) {
   1214                    pop();
   1215                  }
   1216                  break;
   1217                } else if (!eltPos || (node->isSpecial() &&
   1218                                       (node->ns != kNameSpaceID_XHTML ||
   1219                                        (node->name != nsGkAtoms::p &&
   1220                                         node->name != nsGkAtoms::address &&
   1221                                         node->name != nsGkAtoms::div)))) {
   1222                  break;
   1223                }
   1224                eltPos--;
   1225              }
   1226              implicitlyCloseP();
   1227              appendToCurrentNodeAndPushElementMayFoster(elementName,
   1228                                                         attributes);
   1229              attributes = nullptr;
   1230              NS_HTML5_BREAK(starttagloop);
   1231            }
   1232            case PLAINTEXT: {
   1233              implicitlyCloseP();
   1234              appendToCurrentNodeAndPushElementMayFoster(elementName,
   1235                                                         attributes);
   1236              tokenizer->setStateAndEndTagExpectation(
   1237                  nsHtml5Tokenizer::PLAINTEXT, elementName);
   1238              attributes = nullptr;
   1239              NS_HTML5_BREAK(starttagloop);
   1240            }
   1241            case A: {
   1242              int32_t activeAPos =
   1243                  findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker(
   1244                      nsGkAtoms::a);
   1245              if (activeAPos != -1) {
   1246                errFooSeenWhenFooOpen(name);
   1247                nsHtml5StackNode* activeA =
   1248                    listOfActiveFormattingElements[activeAPos];
   1249                activeA->retain();
   1250                adoptionAgencyEndTag(nsGkAtoms::a);
   1251                removeFromStack(activeA);
   1252                activeAPos = findInListOfActiveFormattingElements(activeA);
   1253                if (activeAPos != -1) {
   1254                  removeFromListOfActiveFormattingElements(activeAPos);
   1255                }
   1256                activeA->release(this);
   1257              }
   1258              reconstructTheActiveFormattingElements();
   1259              appendToCurrentNodeAndPushFormattingElementMayFoster(elementName,
   1260                                                                   attributes);
   1261              attributes = nullptr;
   1262              NS_HTML5_BREAK(starttagloop);
   1263            }
   1264            case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
   1265            case FONT: {
   1266              reconstructTheActiveFormattingElements();
   1267              maybeForgetEarlierDuplicateFormattingElement(
   1268                  elementName->getName(), attributes);
   1269              appendToCurrentNodeAndPushFormattingElementMayFoster(elementName,
   1270                                                                   attributes);
   1271              attributes = nullptr;
   1272              NS_HTML5_BREAK(starttagloop);
   1273            }
   1274            case NOBR: {
   1275              reconstructTheActiveFormattingElements();
   1276              if (nsHtml5TreeBuilder::NOT_FOUND_ON_STACK !=
   1277                  findLastInScope(nsGkAtoms::nobr)) {
   1278                errFooSeenWhenFooOpen(name);
   1279                adoptionAgencyEndTag(nsGkAtoms::nobr);
   1280                reconstructTheActiveFormattingElements();
   1281              }
   1282              appendToCurrentNodeAndPushFormattingElementMayFoster(elementName,
   1283                                                                   attributes);
   1284              attributes = nullptr;
   1285              NS_HTML5_BREAK(starttagloop);
   1286            }
   1287            case BUTTON: {
   1288              eltPos = findLastInScope(name);
   1289              if (eltPos != nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
   1290                errFooSeenWhenFooOpen(name);
   1291                generateImpliedEndTags();
   1292                if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
   1293                  errUnclosedElementsImplied(eltPos, name);
   1294                }
   1295                while (currentPtr >= eltPos) {
   1296                  pop();
   1297                }
   1298                NS_HTML5_CONTINUE(starttagloop);
   1299              } else {
   1300                reconstructTheActiveFormattingElements();
   1301                appendToCurrentNodeAndPushElementMayFoster(
   1302                    elementName, attributes, formPointer);
   1303                attributes = nullptr;
   1304                NS_HTML5_BREAK(starttagloop);
   1305              }
   1306            }
   1307            case OBJECT: {
   1308              reconstructTheActiveFormattingElements();
   1309              appendToCurrentNodeAndPushElementMayFoster(
   1310                  elementName, attributes, formPointer);
   1311              insertMarker();
   1312              attributes = nullptr;
   1313              NS_HTML5_BREAK(starttagloop);
   1314            }
   1315            case MARQUEE_OR_APPLET: {
   1316              reconstructTheActiveFormattingElements();
   1317              appendToCurrentNodeAndPushElementMayFoster(elementName,
   1318                                                         attributes);
   1319              insertMarker();
   1320              attributes = nullptr;
   1321              NS_HTML5_BREAK(starttagloop);
   1322            }
   1323            case TABLE: {
   1324              if (!quirks) {
   1325                implicitlyCloseP();
   1326              }
   1327              appendToCurrentNodeAndPushElementMayFoster(elementName,
   1328                                                         attributes);
   1329              mode = IN_TABLE;
   1330              attributes = nullptr;
   1331              NS_HTML5_BREAK(starttagloop);
   1332            }
   1333            case BR:
   1334            case EMBED:
   1335            case AREA_OR_WBR:
   1336            case KEYGEN: {
   1337              reconstructTheActiveFormattingElements();
   1338              [[fallthrough]];
   1339            }
   1340            case PARAM_OR_SOURCE_OR_TRACK: {
   1341              appendVoidElementToCurrentMayFoster(elementName, attributes);
   1342              selfClosing = false;
   1343              attributes = nullptr;
   1344              NS_HTML5_BREAK(starttagloop);
   1345            }
   1346            case HR: {
   1347              implicitlyCloseP();
   1348              appendVoidElementToCurrentMayFoster(elementName, attributes);
   1349              selfClosing = false;
   1350              attributes = nullptr;
   1351              NS_HTML5_BREAK(starttagloop);
   1352            }
   1353            case IMAGE: {
   1354              errImage();
   1355              elementName = nsHtml5ElementName::ELT_IMG;
   1356              NS_HTML5_CONTINUE(starttagloop);
   1357            }
   1358            case IMG:
   1359            case INPUT: {
   1360              reconstructTheActiveFormattingElements();
   1361              appendVoidElementToCurrentMayFoster(elementName, attributes,
   1362                                                  formPointer);
   1363              selfClosing = false;
   1364              attributes = nullptr;
   1365              NS_HTML5_BREAK(starttagloop);
   1366            }
   1367            case TEXTAREA: {
   1368              appendToCurrentNodeAndPushElementMayFoster(
   1369                  elementName, attributes, formPointer);
   1370              tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA,
   1371                                                      elementName);
   1372              originalMode = mode;
   1373              mode = TEXT;
   1374              needToDropLF = true;
   1375              attributes = nullptr;
   1376              NS_HTML5_BREAK(starttagloop);
   1377            }
   1378            case XMP: {
   1379              implicitlyCloseP();
   1380              reconstructTheActiveFormattingElements();
   1381              appendToCurrentNodeAndPushElementMayFoster(elementName,
   1382                                                         attributes);
   1383              originalMode = mode;
   1384              mode = TEXT;
   1385              tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
   1386                                                      elementName);
   1387              attributes = nullptr;
   1388              NS_HTML5_BREAK(starttagloop);
   1389            }
   1390            case NOSCRIPT: {
   1391              if (!scriptingEnabled) {
   1392                reconstructTheActiveFormattingElements();
   1393                appendToCurrentNodeAndPushElementMayFoster(elementName,
   1394                                                           attributes);
   1395                attributes = nullptr;
   1396                NS_HTML5_BREAK(starttagloop);
   1397              }
   1398              [[fallthrough]];
   1399            }
   1400            case NOFRAMES:
   1401            case IFRAME:
   1402            case NOEMBED: {
   1403              startTagGenericRawText(elementName, attributes);
   1404              attributes = nullptr;
   1405              NS_HTML5_BREAK(starttagloop);
   1406            }
   1407            case SELECT: {
   1408              reconstructTheActiveFormattingElements();
   1409              appendToCurrentNodeAndPushElementMayFoster(
   1410                  elementName, attributes, formPointer);
   1411              switch (mode) {
   1412                case IN_TABLE:
   1413                case IN_CAPTION:
   1414                case IN_COLUMN_GROUP:
   1415                case IN_TABLE_BODY:
   1416                case IN_ROW:
   1417                case IN_CELL: {
   1418                  mode = IN_SELECT_IN_TABLE;
   1419                  break;
   1420                }
   1421                default: {
   1422                  mode = IN_SELECT;
   1423                  break;
   1424                }
   1425              }
   1426              attributes = nullptr;
   1427              NS_HTML5_BREAK(starttagloop);
   1428            }
   1429            case OPTGROUP:
   1430            case OPTION: {
   1431              if (isCurrent(nsGkAtoms::option)) {
   1432                pop();
   1433              }
   1434              reconstructTheActiveFormattingElements();
   1435              appendToCurrentNodeAndPushElementMayFoster(elementName,
   1436                                                         attributes);
   1437              attributes = nullptr;
   1438              NS_HTML5_BREAK(starttagloop);
   1439            }
   1440            case RB_OR_RTC: {
   1441              eltPos = findLastInScope(nsGkAtoms::ruby);
   1442              if (eltPos != NOT_FOUND_ON_STACK) {
   1443                generateImpliedEndTags();
   1444              }
   1445              if (eltPos != currentPtr) {
   1446                if (eltPos == NOT_FOUND_ON_STACK) {
   1447                  errStartTagSeenWithoutRuby(name);
   1448                } else {
   1449                  errUnclosedChildrenInRuby();
   1450                }
   1451              }
   1452              appendToCurrentNodeAndPushElementMayFoster(elementName,
   1453                                                         attributes);
   1454              attributes = nullptr;
   1455              NS_HTML5_BREAK(starttagloop);
   1456            }
   1457            case RT_OR_RP: {
   1458              eltPos = findLastInScope(nsGkAtoms::ruby);
   1459              if (eltPos != NOT_FOUND_ON_STACK) {
   1460                generateImpliedEndTagsExceptFor(nsGkAtoms::rtc);
   1461              }
   1462              if (eltPos != currentPtr) {
   1463                if (!isCurrent(nsGkAtoms::rtc)) {
   1464                  if (eltPos == NOT_FOUND_ON_STACK) {
   1465                    errStartTagSeenWithoutRuby(name);
   1466                  } else {
   1467                    errUnclosedChildrenInRuby();
   1468                  }
   1469                }
   1470              }
   1471              appendToCurrentNodeAndPushElementMayFoster(elementName,
   1472                                                         attributes);
   1473              attributes = nullptr;
   1474              NS_HTML5_BREAK(starttagloop);
   1475            }
   1476            case MATH: {
   1477              reconstructTheActiveFormattingElements();
   1478              attributes->adjustForMath();
   1479              if (selfClosing) {
   1480                appendVoidElementToCurrentMayFosterMathML(elementName,
   1481                                                          attributes);
   1482                selfClosing = false;
   1483              } else {
   1484                appendToCurrentNodeAndPushElementMayFosterMathML(elementName,
   1485                                                                 attributes);
   1486              }
   1487              attributes = nullptr;
   1488              NS_HTML5_BREAK(starttagloop);
   1489            }
   1490            case SVG: {
   1491              reconstructTheActiveFormattingElements();
   1492              attributes->adjustForSvg();
   1493              if (selfClosing) {
   1494                appendVoidElementToCurrentMayFosterSVG(elementName, attributes);
   1495                selfClosing = false;
   1496              } else {
   1497                appendToCurrentNodeAndPushElementMayFosterSVG(elementName,
   1498                                                              attributes);
   1499              }
   1500              attributes = nullptr;
   1501              NS_HTML5_BREAK(starttagloop);
   1502            }
   1503            case CAPTION:
   1504            case COL:
   1505            case COLGROUP:
   1506            case TBODY_OR_THEAD_OR_TFOOT:
   1507            case TR:
   1508            case TD_OR_TH:
   1509            case FRAME:
   1510            case FRAMESET:
   1511            case HEAD: {
   1512              errStrayStartTag(name);
   1513              NS_HTML5_BREAK(starttagloop);
   1514            }
   1515            case OUTPUT: {
   1516              reconstructTheActiveFormattingElements();
   1517              appendToCurrentNodeAndPushElementMayFoster(
   1518                  elementName, attributes, formPointer);
   1519              attributes = nullptr;
   1520              NS_HTML5_BREAK(starttagloop);
   1521            }
   1522            default: {
   1523              reconstructTheActiveFormattingElements();
   1524              appendToCurrentNodeAndPushElementMayFoster(elementName,
   1525                                                         attributes);
   1526              attributes = nullptr;
   1527              NS_HTML5_BREAK(starttagloop);
   1528            }
   1529          }
   1530        }
   1531      inbodyloop_end:;
   1532        [[fallthrough]];
   1533      }
   1534      case IN_HEAD: {
   1535        for (;;) {
   1536          switch (group) {
   1537            case HTML: {
   1538              errStrayStartTag(name);
   1539              if (!fragment && !isTemplateContents()) {
   1540                addAttributesToHtml(attributes);
   1541                attributes = nullptr;
   1542              }
   1543              NS_HTML5_BREAK(starttagloop);
   1544            }
   1545            case BASE:
   1546            case LINK_OR_BASEFONT_OR_BGSOUND: {
   1547              appendVoidElementToCurrentMayFoster(elementName, attributes);
   1548              selfClosing = false;
   1549              attributes = nullptr;
   1550              NS_HTML5_BREAK(starttagloop);
   1551            }
   1552            case META: {
   1553              NS_HTML5_BREAK(inheadloop);
   1554            }
   1555            case TITLE: {
   1556              startTagTitleInHead(elementName, attributes);
   1557              attributes = nullptr;
   1558              NS_HTML5_BREAK(starttagloop);
   1559            }
   1560            case NOSCRIPT: {
   1561              if (scriptingEnabled) {
   1562                appendToCurrentNodeAndPushElement(elementName, attributes);
   1563                originalMode = mode;
   1564                mode = TEXT;
   1565                tokenizer->setStateAndEndTagExpectation(
   1566                    nsHtml5Tokenizer::RAWTEXT, elementName);
   1567              } else {
   1568                appendToCurrentNodeAndPushElementMayFoster(elementName,
   1569                                                           attributes);
   1570                mode = IN_HEAD_NOSCRIPT;
   1571              }
   1572              attributes = nullptr;
   1573              NS_HTML5_BREAK(starttagloop);
   1574            }
   1575            case SCRIPT: {
   1576              startTagScriptInHead(elementName, attributes);
   1577              attributes = nullptr;
   1578              NS_HTML5_BREAK(starttagloop);
   1579            }
   1580            case STYLE:
   1581            case NOFRAMES: {
   1582              startTagGenericRawText(elementName, attributes);
   1583              attributes = nullptr;
   1584              NS_HTML5_BREAK(starttagloop);
   1585            }
   1586            case HEAD: {
   1587              errFooSeenWhenFooOpen(name);
   1588              NS_HTML5_BREAK(starttagloop);
   1589            }
   1590            case TEMPLATE: {
   1591              startTagTemplateInHead(elementName, attributes);
   1592              attributes = nullptr;
   1593              NS_HTML5_BREAK(starttagloop);
   1594            }
   1595            default: {
   1596              pop();
   1597              mode = AFTER_HEAD;
   1598              NS_HTML5_CONTINUE(starttagloop);
   1599            }
   1600          }
   1601        }
   1602      inheadloop_end:;
   1603        [[fallthrough]];
   1604      }
   1605      case IN_HEAD_NOSCRIPT: {
   1606        switch (group) {
   1607          case HTML: {
   1608            errStrayStartTag(name);
   1609            if (!fragment && !isTemplateContents()) {
   1610              addAttributesToHtml(attributes);
   1611              attributes = nullptr;
   1612            }
   1613            NS_HTML5_BREAK(starttagloop);
   1614          }
   1615          case LINK_OR_BASEFONT_OR_BGSOUND: {
   1616            appendVoidElementToCurrentMayFoster(elementName, attributes);
   1617            selfClosing = false;
   1618            attributes = nullptr;
   1619            NS_HTML5_BREAK(starttagloop);
   1620          }
   1621          case META: {
   1622            checkMetaCharset(attributes);
   1623            appendVoidElementToCurrentMayFoster(elementName, attributes);
   1624            selfClosing = false;
   1625            attributes = nullptr;
   1626            NS_HTML5_BREAK(starttagloop);
   1627          }
   1628          case STYLE:
   1629          case NOFRAMES: {
   1630            appendToCurrentNodeAndPushElement(elementName, attributes);
   1631            originalMode = mode;
   1632            mode = TEXT;
   1633            tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
   1634                                                    elementName);
   1635            attributes = nullptr;
   1636            NS_HTML5_BREAK(starttagloop);
   1637          }
   1638          case HEAD: {
   1639            errFooSeenWhenFooOpen(name);
   1640            NS_HTML5_BREAK(starttagloop);
   1641          }
   1642          case NOSCRIPT: {
   1643            errFooSeenWhenFooOpen(name);
   1644            NS_HTML5_BREAK(starttagloop);
   1645          }
   1646          default: {
   1647            errBadStartTagInNoscriptInHead(name);
   1648            pop();
   1649            mode = IN_HEAD;
   1650            continue;
   1651          }
   1652        }
   1653      }
   1654      case IN_COLUMN_GROUP: {
   1655        switch (group) {
   1656          case HTML: {
   1657            errStrayStartTag(name);
   1658            if (!fragment && !isTemplateContents()) {
   1659              addAttributesToHtml(attributes);
   1660              attributes = nullptr;
   1661            }
   1662            NS_HTML5_BREAK(starttagloop);
   1663          }
   1664          case COL: {
   1665            appendVoidElementToCurrentMayFoster(elementName, attributes);
   1666            selfClosing = false;
   1667            attributes = nullptr;
   1668            NS_HTML5_BREAK(starttagloop);
   1669          }
   1670          case TEMPLATE: {
   1671            startTagTemplateInHead(elementName, attributes);
   1672            attributes = nullptr;
   1673            NS_HTML5_BREAK(starttagloop);
   1674          }
   1675          default: {
   1676            if (!currentPtr || stack[currentPtr]->getGroup() == TEMPLATE) {
   1677              MOZ_ASSERT(fragment || isTemplateContents());
   1678              errGarbageInColgroup();
   1679              NS_HTML5_BREAK(starttagloop);
   1680            }
   1681            pop();
   1682            mode = IN_TABLE;
   1683            continue;
   1684          }
   1685        }
   1686      }
   1687      case IN_SELECT_IN_TABLE: {
   1688        switch (group) {
   1689          case CAPTION:
   1690          case TBODY_OR_THEAD_OR_TFOOT:
   1691          case TR:
   1692          case TD_OR_TH:
   1693          case TABLE: {
   1694            errStartTagWithSelectOpen(name);
   1695            eltPos = findLastInTableScope(nsGkAtoms::select);
   1696            if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
   1697              MOZ_ASSERT(fragment);
   1698              NS_HTML5_BREAK(starttagloop);
   1699            }
   1700            while (currentPtr >= eltPos) {
   1701              pop();
   1702            }
   1703            resetTheInsertionMode();
   1704            continue;
   1705          }
   1706          default:;  // fall through
   1707        }
   1708        [[fallthrough]];
   1709      }
   1710      case IN_SELECT: {
   1711        switch (group) {
   1712          case HTML: {
   1713            errStrayStartTag(name);
   1714            if (!fragment) {
   1715              addAttributesToHtml(attributes);
   1716              attributes = nullptr;
   1717            }
   1718            NS_HTML5_BREAK(starttagloop);
   1719          }
   1720          case OPTION: {
   1721            if (isCurrent(nsGkAtoms::option)) {
   1722              pop();
   1723            }
   1724            appendToCurrentNodeAndPushElement(elementName, attributes);
   1725            attributes = nullptr;
   1726            NS_HTML5_BREAK(starttagloop);
   1727          }
   1728          case OPTGROUP: {
   1729            if (isCurrent(nsGkAtoms::option)) {
   1730              pop();
   1731            }
   1732            if (isCurrent(nsGkAtoms::optgroup)) {
   1733              pop();
   1734            }
   1735            appendToCurrentNodeAndPushElement(elementName, attributes);
   1736            attributes = nullptr;
   1737            NS_HTML5_BREAK(starttagloop);
   1738          }
   1739          case SELECT: {
   1740            errStartSelectWhereEndSelectExpected();
   1741            eltPos = findLastInTableScope(name);
   1742            if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
   1743              MOZ_ASSERT(fragment);
   1744              errNoSelectInTableScope();
   1745              NS_HTML5_BREAK(starttagloop);
   1746            } else {
   1747              while (currentPtr >= eltPos) {
   1748                pop();
   1749              }
   1750              resetTheInsertionMode();
   1751              NS_HTML5_BREAK(starttagloop);
   1752            }
   1753          }
   1754          case INPUT:
   1755          case TEXTAREA: {
   1756            errStartTagWithSelectOpen(name);
   1757            eltPos = findLastInTableScope(nsGkAtoms::select);
   1758            if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
   1759              MOZ_ASSERT(fragment);
   1760              NS_HTML5_BREAK(starttagloop);
   1761            }
   1762            while (currentPtr >= eltPos) {
   1763              pop();
   1764            }
   1765            resetTheInsertionMode();
   1766            continue;
   1767          }
   1768          case SCRIPT: {
   1769            startTagScriptInHead(elementName, attributes);
   1770            attributes = nullptr;
   1771            NS_HTML5_BREAK(starttagloop);
   1772          }
   1773          case TEMPLATE: {
   1774            startTagTemplateInHead(elementName, attributes);
   1775            attributes = nullptr;
   1776            NS_HTML5_BREAK(starttagloop);
   1777          }
   1778          case HR: {
   1779            if (isCurrent(nsGkAtoms::option)) {
   1780              pop();
   1781            }
   1782            if (isCurrent(nsGkAtoms::optgroup)) {
   1783              pop();
   1784            }
   1785            appendVoidElementToCurrent(elementName, attributes);
   1786            selfClosing = false;
   1787            attributes = nullptr;
   1788            NS_HTML5_BREAK(starttagloop);
   1789          }
   1790          default: {
   1791            errStrayStartTag(name);
   1792            NS_HTML5_BREAK(starttagloop);
   1793          }
   1794        }
   1795      }
   1796      case AFTER_BODY: {
   1797        switch (group) {
   1798          case HTML: {
   1799            errStrayStartTag(name);
   1800            if (!fragment && !isTemplateContents()) {
   1801              addAttributesToHtml(attributes);
   1802              attributes = nullptr;
   1803            }
   1804            NS_HTML5_BREAK(starttagloop);
   1805          }
   1806          default: {
   1807            errStrayStartTag(name);
   1808            mode = framesetOk ? FRAMESET_OK : IN_BODY;
   1809            continue;
   1810          }
   1811        }
   1812      }
   1813      case IN_FRAMESET: {
   1814        switch (group) {
   1815          case FRAMESET: {
   1816            appendToCurrentNodeAndPushElement(elementName, attributes);
   1817            attributes = nullptr;
   1818            NS_HTML5_BREAK(starttagloop);
   1819          }
   1820          case FRAME: {
   1821            appendVoidElementToCurrentMayFoster(elementName, attributes);
   1822            selfClosing = false;
   1823            attributes = nullptr;
   1824            NS_HTML5_BREAK(starttagloop);
   1825          }
   1826          default:;  // fall through
   1827        }
   1828        [[fallthrough]];
   1829      }
   1830      case AFTER_FRAMESET: {
   1831        switch (group) {
   1832          case HTML: {
   1833            errStrayStartTag(name);
   1834            if (!fragment && !isTemplateContents()) {
   1835              addAttributesToHtml(attributes);
   1836              attributes = nullptr;
   1837            }
   1838            NS_HTML5_BREAK(starttagloop);
   1839          }
   1840          case NOFRAMES: {
   1841            appendToCurrentNodeAndPushElement(elementName, attributes);
   1842            originalMode = mode;
   1843            mode = TEXT;
   1844            tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
   1845                                                    elementName);
   1846            attributes = nullptr;
   1847            NS_HTML5_BREAK(starttagloop);
   1848          }
   1849          default: {
   1850            errStrayStartTag(name);
   1851            NS_HTML5_BREAK(starttagloop);
   1852          }
   1853        }
   1854      }
   1855      case INITIAL: {
   1856        errStartTagWithoutDoctype();
   1857        documentModeInternal(QUIRKS_MODE, nullptr, nullptr);
   1858        mode = BEFORE_HTML;
   1859        continue;
   1860      }
   1861      case BEFORE_HTML: {
   1862        switch (group) {
   1863          case HTML: {
   1864            if (attributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
   1865              appendHtmlElementToDocumentAndPush();
   1866            } else {
   1867              appendHtmlElementToDocumentAndPush(attributes);
   1868            }
   1869            mode = BEFORE_HEAD;
   1870            attributes = nullptr;
   1871            NS_HTML5_BREAK(starttagloop);
   1872          }
   1873          default: {
   1874            appendHtmlElementToDocumentAndPush();
   1875            mode = BEFORE_HEAD;
   1876            continue;
   1877          }
   1878        }
   1879      }
   1880      case BEFORE_HEAD: {
   1881        switch (group) {
   1882          case HTML: {
   1883            errStrayStartTag(name);
   1884            if (!fragment && !isTemplateContents()) {
   1885              addAttributesToHtml(attributes);
   1886              attributes = nullptr;
   1887            }
   1888            NS_HTML5_BREAK(starttagloop);
   1889          }
   1890          case HEAD: {
   1891            appendToCurrentNodeAndPushHeadElement(attributes);
   1892            mode = IN_HEAD;
   1893            attributes = nullptr;
   1894            NS_HTML5_BREAK(starttagloop);
   1895          }
   1896          default: {
   1897            appendToCurrentNodeAndPushHeadElement(
   1898                nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
   1899            mode = IN_HEAD;
   1900            continue;
   1901          }
   1902        }
   1903      }
   1904      case AFTER_HEAD: {
   1905        switch (group) {
   1906          case HTML: {
   1907            errStrayStartTag(name);
   1908            if (!fragment && !isTemplateContents()) {
   1909              addAttributesToHtml(attributes);
   1910              attributes = nullptr;
   1911            }
   1912            NS_HTML5_BREAK(starttagloop);
   1913          }
   1914          case BODY: {
   1915            if (!attributes->getLength()) {
   1916              appendToCurrentNodeAndPushBodyElement();
   1917            } else {
   1918              appendToCurrentNodeAndPushBodyElement(attributes);
   1919            }
   1920            framesetOk = false;
   1921            mode = IN_BODY;
   1922            attributes = nullptr;
   1923            NS_HTML5_BREAK(starttagloop);
   1924          }
   1925          case FRAMESET: {
   1926            appendToCurrentNodeAndPushElement(elementName, attributes);
   1927            mode = IN_FRAMESET;
   1928            attributes = nullptr;
   1929            NS_HTML5_BREAK(starttagloop);
   1930          }
   1931          case TEMPLATE: {
   1932            errFooBetweenHeadAndBody(name);
   1933            pushHeadPointerOntoStack();
   1934            nsHtml5StackNode* headOnStack = stack[currentPtr];
   1935            startTagTemplateInHead(elementName, attributes);
   1936            removeFromStack(headOnStack);
   1937            attributes = nullptr;
   1938            NS_HTML5_BREAK(starttagloop);
   1939          }
   1940          case BASE:
   1941          case LINK_OR_BASEFONT_OR_BGSOUND: {
   1942            errFooBetweenHeadAndBody(name);
   1943            pushHeadPointerOntoStack();
   1944            appendVoidElementToCurrentMayFoster(elementName, attributes);
   1945            selfClosing = false;
   1946            pop();
   1947            attributes = nullptr;
   1948            NS_HTML5_BREAK(starttagloop);
   1949          }
   1950          case META: {
   1951            errFooBetweenHeadAndBody(name);
   1952            checkMetaCharset(attributes);
   1953            pushHeadPointerOntoStack();
   1954            appendVoidElementToCurrentMayFoster(elementName, attributes);
   1955            selfClosing = false;
   1956            pop();
   1957            attributes = nullptr;
   1958            NS_HTML5_BREAK(starttagloop);
   1959          }
   1960          case SCRIPT: {
   1961            errFooBetweenHeadAndBody(name);
   1962            pushHeadPointerOntoStack();
   1963            appendToCurrentNodeAndPushElement(elementName, attributes);
   1964            originalMode = mode;
   1965            mode = TEXT;
   1966            tokenizer->setStateAndEndTagExpectation(
   1967                nsHtml5Tokenizer::SCRIPT_DATA, elementName);
   1968            attributes = nullptr;
   1969            NS_HTML5_BREAK(starttagloop);
   1970          }
   1971          case STYLE:
   1972          case NOFRAMES: {
   1973            errFooBetweenHeadAndBody(name);
   1974            pushHeadPointerOntoStack();
   1975            appendToCurrentNodeAndPushElement(elementName, attributes);
   1976            originalMode = mode;
   1977            mode = TEXT;
   1978            tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
   1979                                                    elementName);
   1980            attributes = nullptr;
   1981            NS_HTML5_BREAK(starttagloop);
   1982          }
   1983          case TITLE: {
   1984            errFooBetweenHeadAndBody(name);
   1985            pushHeadPointerOntoStack();
   1986            appendToCurrentNodeAndPushElement(elementName, attributes);
   1987            originalMode = mode;
   1988            mode = TEXT;
   1989            tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA,
   1990                                                    elementName);
   1991            attributes = nullptr;
   1992            NS_HTML5_BREAK(starttagloop);
   1993          }
   1994          case HEAD: {
   1995            errStrayStartTag(name);
   1996            NS_HTML5_BREAK(starttagloop);
   1997          }
   1998          default: {
   1999            appendToCurrentNodeAndPushBodyElement();
   2000            mode = FRAMESET_OK;
   2001            continue;
   2002          }
   2003        }
   2004      }
   2005      case AFTER_AFTER_BODY: {
   2006        switch (group) {
   2007          case HTML: {
   2008            errStrayStartTag(name);
   2009            if (!fragment && !isTemplateContents()) {
   2010              addAttributesToHtml(attributes);
   2011              attributes = nullptr;
   2012            }
   2013            NS_HTML5_BREAK(starttagloop);
   2014          }
   2015          default: {
   2016            errStrayStartTag(name);
   2017 
   2018            mode = framesetOk ? FRAMESET_OK : IN_BODY;
   2019            continue;
   2020          }
   2021        }
   2022      }
   2023      case AFTER_AFTER_FRAMESET: {
   2024        switch (group) {
   2025          case HTML: {
   2026            errStrayStartTag(name);
   2027            if (!fragment && !isTemplateContents()) {
   2028              addAttributesToHtml(attributes);
   2029              attributes = nullptr;
   2030            }
   2031            NS_HTML5_BREAK(starttagloop);
   2032          }
   2033          case NOFRAMES: {
   2034            startTagGenericRawText(elementName, attributes);
   2035            attributes = nullptr;
   2036            NS_HTML5_BREAK(starttagloop);
   2037          }
   2038          default: {
   2039            errStrayStartTag(name);
   2040            NS_HTML5_BREAK(starttagloop);
   2041          }
   2042        }
   2043      }
   2044      case TEXT: {
   2045        MOZ_ASSERT(false);
   2046        NS_HTML5_BREAK(starttagloop);
   2047      }
   2048    }
   2049  }
   2050 starttagloop_end:;
   2051  if (selfClosing) {
   2052    errSelfClosing();
   2053  }
   2054  if (!mBuilder && attributes != nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
   2055    delete attributes;
   2056  }
   2057 }
   2058 
   2059 void nsHtml5TreeBuilder::startTagTitleInHead(
   2060    nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
   2061  appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
   2062  originalMode = mode;
   2063  mode = TEXT;
   2064  tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA,
   2065                                          elementName);
   2066 }
   2067 
   2068 void nsHtml5TreeBuilder::startTagGenericRawText(
   2069    nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
   2070  appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
   2071  originalMode = mode;
   2072  mode = TEXT;
   2073  tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
   2074                                          elementName);
   2075 }
   2076 
   2077 void nsHtml5TreeBuilder::startTagScriptInHead(
   2078    nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
   2079  appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
   2080  originalMode = mode;
   2081  mode = TEXT;
   2082  tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::SCRIPT_DATA,
   2083                                          elementName);
   2084 }
   2085 
   2086 void nsHtml5TreeBuilder::startTagTemplateInHead(
   2087    nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
   2088  appendToCurrentNodeAndPushElement(elementName, attributes);
   2089  insertMarker();
   2090  framesetOk = false;
   2091  originalMode = mode;
   2092  mode = IN_TEMPLATE;
   2093  pushTemplateMode(IN_TEMPLATE);
   2094 }
   2095 
   2096 bool nsHtml5TreeBuilder::isTemplateContents() {
   2097  return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK !=
   2098         findLast(nsGkAtoms::_template);
   2099 }
   2100 
   2101 bool nsHtml5TreeBuilder::isTemplateModeStackEmpty() {
   2102  return templateModePtr == -1;
   2103 }
   2104 
   2105 bool nsHtml5TreeBuilder::isSpecialParentInForeign(nsHtml5StackNode* stackNode) {
   2106  int32_t ns = stackNode->ns;
   2107  return (kNameSpaceID_XHTML == ns) || (stackNode->isHtmlIntegrationPoint()) ||
   2108         ((kNameSpaceID_MathML == ns) &&
   2109          (stackNode->getGroup() == MI_MO_MN_MS_MTEXT));
   2110 }
   2111 
   2112 nsIContentHandle* nsHtml5TreeBuilder::getDeclarativeShadowRoot(
   2113    nsIContentHandle* currentNode, nsIContentHandle* templateNode,
   2114    nsHtml5HtmlAttributes* attributes) {
   2115  if (!isAllowDeclarativeShadowRoots()) {
   2116    return nullptr;
   2117  }
   2118  nsHtml5String shadowRootMode =
   2119      attributes->getValue(nsHtml5AttributeName::ATTR_SHADOWROOTMODE);
   2120  if (!shadowRootMode) {
   2121    return nullptr;
   2122  }
   2123  bool shadowRootIsClonable =
   2124      attributes->contains(nsHtml5AttributeName::ATTR_SHADOWROOTCLONABLE);
   2125  bool shadowRootIsSerializable =
   2126      attributes->contains(nsHtml5AttributeName::ATTR_SHADOWROOTSERIALIZABLE);
   2127  bool shadowRootDelegatesFocus =
   2128      attributes->contains(nsHtml5AttributeName::ATTR_SHADOWROOTDELEGATESFOCUS);
   2129  nsHtml5String shadowRootReferenceTarget = attributes->getValue(
   2130      nsHtml5AttributeName::ATTR_SHADOWROOTREFERENCETARGET);
   2131  return getShadowRootFromHost(currentNode, templateNode, shadowRootMode,
   2132                               shadowRootIsClonable, shadowRootIsSerializable,
   2133                               shadowRootDelegatesFocus,
   2134                               shadowRootReferenceTarget);
   2135 }
   2136 
   2137 nsHtml5String nsHtml5TreeBuilder::extractCharsetFromContent(
   2138    nsHtml5String attributeValue, nsHtml5TreeBuilder* tb) {
   2139  int32_t charsetState = CHARSET_INITIAL;
   2140  int32_t start = -1;
   2141  int32_t end = -1;
   2142  autoJArray<char16_t, int32_t> buffer =
   2143      nsHtml5Portability::newCharArrayFromString(attributeValue);
   2144  for (int32_t i = 0; i < buffer.length; i++) {
   2145    char16_t c = buffer[i];
   2146    switch (charsetState) {
   2147      case CHARSET_INITIAL: {
   2148        switch (c) {
   2149          case 'c':
   2150          case 'C': {
   2151            charsetState = CHARSET_C;
   2152            continue;
   2153          }
   2154          default: {
   2155            continue;
   2156          }
   2157        }
   2158      }
   2159      case CHARSET_C: {
   2160        switch (c) {
   2161          case 'h':
   2162          case 'H': {
   2163            charsetState = CHARSET_H;
   2164            continue;
   2165          }
   2166          default: {
   2167            charsetState = CHARSET_INITIAL;
   2168            continue;
   2169          }
   2170        }
   2171      }
   2172      case CHARSET_H: {
   2173        switch (c) {
   2174          case 'a':
   2175          case 'A': {
   2176            charsetState = CHARSET_A;
   2177            continue;
   2178          }
   2179          default: {
   2180            charsetState = CHARSET_INITIAL;
   2181            continue;
   2182          }
   2183        }
   2184      }
   2185      case CHARSET_A: {
   2186        switch (c) {
   2187          case 'r':
   2188          case 'R': {
   2189            charsetState = CHARSET_R;
   2190            continue;
   2191          }
   2192          default: {
   2193            charsetState = CHARSET_INITIAL;
   2194            continue;
   2195          }
   2196        }
   2197      }
   2198      case CHARSET_R: {
   2199        switch (c) {
   2200          case 's':
   2201          case 'S': {
   2202            charsetState = CHARSET_S;
   2203            continue;
   2204          }
   2205          default: {
   2206            charsetState = CHARSET_INITIAL;
   2207            continue;
   2208          }
   2209        }
   2210      }
   2211      case CHARSET_S: {
   2212        switch (c) {
   2213          case 'e':
   2214          case 'E': {
   2215            charsetState = CHARSET_E;
   2216            continue;
   2217          }
   2218          default: {
   2219            charsetState = CHARSET_INITIAL;
   2220            continue;
   2221          }
   2222        }
   2223      }
   2224      case CHARSET_E: {
   2225        switch (c) {
   2226          case 't':
   2227          case 'T': {
   2228            charsetState = CHARSET_T;
   2229            continue;
   2230          }
   2231          default: {
   2232            charsetState = CHARSET_INITIAL;
   2233            continue;
   2234          }
   2235        }
   2236      }
   2237      case CHARSET_T: {
   2238        switch (c) {
   2239          case '\t':
   2240          case '\n':
   2241          case '\f':
   2242          case '\r':
   2243          case ' ': {
   2244            continue;
   2245          }
   2246          case '=': {
   2247            charsetState = CHARSET_EQUALS;
   2248            continue;
   2249          }
   2250          default: {
   2251            return nullptr;
   2252          }
   2253        }
   2254      }
   2255      case CHARSET_EQUALS: {
   2256        switch (c) {
   2257          case '\t':
   2258          case '\n':
   2259          case '\f':
   2260          case '\r':
   2261          case ' ': {
   2262            continue;
   2263          }
   2264          case '\'': {
   2265            start = i + 1;
   2266            charsetState = CHARSET_SINGLE_QUOTED;
   2267            continue;
   2268          }
   2269          case '\"': {
   2270            start = i + 1;
   2271            charsetState = CHARSET_DOUBLE_QUOTED;
   2272            continue;
   2273          }
   2274          default: {
   2275            start = i;
   2276            charsetState = CHARSET_UNQUOTED;
   2277            continue;
   2278          }
   2279        }
   2280      }
   2281      case CHARSET_SINGLE_QUOTED: {
   2282        switch (c) {
   2283          case '\'': {
   2284            end = i;
   2285            NS_HTML5_BREAK(charsetloop);
   2286          }
   2287          default: {
   2288            continue;
   2289          }
   2290        }
   2291      }
   2292      case CHARSET_DOUBLE_QUOTED: {
   2293        switch (c) {
   2294          case '\"': {
   2295            end = i;
   2296            NS_HTML5_BREAK(charsetloop);
   2297          }
   2298          default: {
   2299            continue;
   2300          }
   2301        }
   2302      }
   2303      case CHARSET_UNQUOTED: {
   2304        switch (c) {
   2305          case '\t':
   2306          case '\n':
   2307          case '\f':
   2308          case '\r':
   2309          case ' ':
   2310          case ';': {
   2311            end = i;
   2312            NS_HTML5_BREAK(charsetloop);
   2313          }
   2314          default: {
   2315            continue;
   2316          }
   2317        }
   2318      }
   2319    }
   2320  }
   2321 charsetloop_end:;
   2322  if (start != -1) {
   2323    if (end == -1) {
   2324      if (charsetState == CHARSET_UNQUOTED) {
   2325        end = buffer.length;
   2326      } else {
   2327        return nullptr;
   2328      }
   2329    }
   2330    return nsHtml5Portability::newStringFromBuffer(buffer, start, end - start,
   2331                                                   tb, false);
   2332  }
   2333  return nullptr;
   2334 }
   2335 
   2336 void nsHtml5TreeBuilder::checkMetaCharset(nsHtml5HtmlAttributes* attributes) {
   2337  nsHtml5String charset =
   2338      attributes->getValue(nsHtml5AttributeName::ATTR_CHARSET);
   2339  if (charset) {
   2340    if (tokenizer->internalEncodingDeclaration(charset)) {
   2341      requestSuspension();
   2342      return;
   2343    }
   2344    return;
   2345  }
   2346  if (!nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
   2347          "content-type",
   2348          attributes->getValue(nsHtml5AttributeName::ATTR_HTTP_EQUIV))) {
   2349    return;
   2350  }
   2351  nsHtml5String content =
   2352      attributes->getValue(nsHtml5AttributeName::ATTR_CONTENT);
   2353  if (content) {
   2354    nsHtml5String extract =
   2355        nsHtml5TreeBuilder::extractCharsetFromContent(content, this);
   2356    if (extract) {
   2357      if (tokenizer->internalEncodingDeclaration(extract)) {
   2358        requestSuspension();
   2359      }
   2360    }
   2361    extract.Release();
   2362  }
   2363 }
   2364 
   2365 void nsHtml5TreeBuilder::endTag(nsHtml5ElementName* elementName) {
   2366  flushCharacters();
   2367  needToDropLF = false;
   2368  int32_t eltPos;
   2369  int32_t group = elementName->getGroup();
   2370  nsAtom* name = elementName->getName();
   2371  for (;;) {
   2372    if (isInForeign()) {
   2373      if (stack[currentPtr]->name != name) {
   2374        if (!currentPtr) {
   2375          errStrayEndTag(name);
   2376        } else {
   2377          errEndTagDidNotMatchCurrentOpenElement(name,
   2378                                                 stack[currentPtr]->popName);
   2379        }
   2380      }
   2381      eltPos = currentPtr;
   2382      int32_t origPos = currentPtr;
   2383      for (;;) {
   2384        if (!eltPos) {
   2385          MOZ_ASSERT(fragment,
   2386                     "We can get this close to the root of the stack in "
   2387                     "foreign content only in the fragment case.");
   2388          NS_HTML5_BREAK(endtagloop);
   2389        }
   2390        if (stack[eltPos]->name == name) {
   2391          while (currentPtr >= eltPos) {
   2392            popForeign(origPos, eltPos);
   2393          }
   2394          NS_HTML5_BREAK(endtagloop);
   2395        }
   2396        if (stack[--eltPos]->ns == kNameSpaceID_XHTML) {
   2397          break;
   2398        }
   2399      }
   2400    }
   2401    switch (mode) {
   2402      case IN_TEMPLATE: {
   2403        switch (group) {
   2404          case TEMPLATE: {
   2405            break;
   2406          }
   2407          default: {
   2408            errStrayEndTag(name);
   2409            NS_HTML5_BREAK(endtagloop);
   2410          }
   2411        }
   2412        [[fallthrough]];
   2413      }
   2414      case IN_ROW: {
   2415        switch (group) {
   2416          case TR: {
   2417            eltPos = findLastOrRoot(nsHtml5TreeBuilder::TR);
   2418            if (!eltPos) {
   2419              MOZ_ASSERT(fragment || isTemplateContents());
   2420              errNoTableRowToClose();
   2421              NS_HTML5_BREAK(endtagloop);
   2422            }
   2423            clearStackBackTo(eltPos);
   2424            pop();
   2425            mode = IN_TABLE_BODY;
   2426            NS_HTML5_BREAK(endtagloop);
   2427          }
   2428          case TABLE: {
   2429            eltPos = findLastOrRoot(nsHtml5TreeBuilder::TR);
   2430            if (!eltPos) {
   2431              MOZ_ASSERT(fragment || isTemplateContents());
   2432              errNoTableRowToClose();
   2433              NS_HTML5_BREAK(endtagloop);
   2434            }
   2435            clearStackBackTo(eltPos);
   2436            pop();
   2437            mode = IN_TABLE_BODY;
   2438            continue;
   2439          }
   2440          case TBODY_OR_THEAD_OR_TFOOT: {
   2441            if (findLastInTableScope(name) ==
   2442                nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
   2443              errStrayEndTag(name);
   2444              NS_HTML5_BREAK(endtagloop);
   2445            }
   2446            eltPos = findLastOrRoot(nsHtml5TreeBuilder::TR);
   2447            if (!eltPos) {
   2448              MOZ_ASSERT(fragment || isTemplateContents());
   2449              errNoTableRowToClose();
   2450              NS_HTML5_BREAK(endtagloop);
   2451            }
   2452            clearStackBackTo(eltPos);
   2453            pop();
   2454            mode = IN_TABLE_BODY;
   2455            continue;
   2456          }
   2457          case BODY:
   2458          case CAPTION:
   2459          case COL:
   2460          case COLGROUP:
   2461          case HTML:
   2462          case TD_OR_TH: {
   2463            errStrayEndTag(name);
   2464            NS_HTML5_BREAK(endtagloop);
   2465          }
   2466          default:;  // fall through
   2467        }
   2468        [[fallthrough]];
   2469      }
   2470      case IN_TABLE_BODY: {
   2471        switch (group) {
   2472          case TBODY_OR_THEAD_OR_TFOOT: {
   2473            eltPos = findLastOrRoot(name);
   2474            if (!eltPos) {
   2475              errStrayEndTag(name);
   2476              NS_HTML5_BREAK(endtagloop);
   2477            }
   2478            clearStackBackTo(eltPos);
   2479            pop();
   2480            mode = IN_TABLE;
   2481            NS_HTML5_BREAK(endtagloop);
   2482          }
   2483          case TABLE: {
   2484            eltPos = findLastInTableScopeOrRootTemplateTbodyTheadTfoot();
   2485            if (!eltPos || stack[eltPos]->getGroup() == TEMPLATE) {
   2486              MOZ_ASSERT(fragment || isTemplateContents());
   2487              errStrayEndTag(name);
   2488              NS_HTML5_BREAK(endtagloop);
   2489            }
   2490            clearStackBackTo(eltPos);
   2491            pop();
   2492            mode = IN_TABLE;
   2493            continue;
   2494          }
   2495          case BODY:
   2496          case CAPTION:
   2497          case COL:
   2498          case COLGROUP:
   2499          case HTML:
   2500          case TD_OR_TH:
   2501          case TR: {
   2502            errStrayEndTag(name);
   2503            NS_HTML5_BREAK(endtagloop);
   2504          }
   2505          default:;  // fall through
   2506        }
   2507        [[fallthrough]];
   2508      }
   2509      case IN_TABLE: {
   2510        switch (group) {
   2511          case TABLE: {
   2512            eltPos = findLast(nsGkAtoms::table);
   2513            if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
   2514              MOZ_ASSERT(fragment || isTemplateContents());
   2515              errStrayEndTag(name);
   2516              NS_HTML5_BREAK(endtagloop);
   2517            }
   2518            while (currentPtr >= eltPos) {
   2519              pop();
   2520            }
   2521            resetTheInsertionMode();
   2522            NS_HTML5_BREAK(endtagloop);
   2523          }
   2524          case BODY:
   2525          case CAPTION:
   2526          case COL:
   2527          case COLGROUP:
   2528          case HTML:
   2529          case TBODY_OR_THEAD_OR_TFOOT:
   2530          case TD_OR_TH:
   2531          case TR: {
   2532            errStrayEndTag(name);
   2533            NS_HTML5_BREAK(endtagloop);
   2534          }
   2535          case TEMPLATE: {
   2536            break;
   2537          }
   2538          default: {
   2539            errStrayEndTag(name);
   2540          }
   2541        }
   2542        [[fallthrough]];
   2543      }
   2544      case IN_CAPTION: {
   2545        switch (group) {
   2546          case CAPTION: {
   2547            eltPos = findLastInTableScope(nsGkAtoms::caption);
   2548            if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
   2549              NS_HTML5_BREAK(endtagloop);
   2550            }
   2551            generateImpliedEndTags();
   2552            if (!!MOZ_UNLIKELY(mViewSource) && currentPtr != eltPos) {
   2553              errUnclosedElements(eltPos, name);
   2554            }
   2555            while (currentPtr >= eltPos) {
   2556              pop();
   2557            }
   2558            clearTheListOfActiveFormattingElementsUpToTheLastMarker();
   2559            mode = IN_TABLE;
   2560            NS_HTML5_BREAK(endtagloop);
   2561          }
   2562          case TABLE: {
   2563            eltPos = findLastInTableScope(nsGkAtoms::caption);
   2564            if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
   2565              MOZ_ASSERT(fragment || isTemplateContents());
   2566              errStrayEndTag(name);
   2567              NS_HTML5_BREAK(endtagloop);
   2568            }
   2569            generateImpliedEndTags();
   2570            if (!!MOZ_UNLIKELY(mViewSource) && currentPtr != eltPos) {
   2571              errUnclosedElements(eltPos, name);
   2572            }
   2573            while (currentPtr >= eltPos) {
   2574              pop();
   2575            }
   2576            clearTheListOfActiveFormattingElementsUpToTheLastMarker();
   2577            mode = IN_TABLE;
   2578            continue;
   2579          }
   2580          case BODY:
   2581          case COL:
   2582          case COLGROUP:
   2583          case HTML:
   2584          case TBODY_OR_THEAD_OR_TFOOT:
   2585          case TD_OR_TH:
   2586          case TR: {
   2587            errStrayEndTag(name);
   2588            NS_HTML5_BREAK(endtagloop);
   2589          }
   2590          default:;  // fall through
   2591        }
   2592        [[fallthrough]];
   2593      }
   2594      case IN_CELL: {
   2595        switch (group) {
   2596          case TD_OR_TH: {
   2597            eltPos = findLastInTableScope(name);
   2598            if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
   2599              errStrayEndTag(name);
   2600              NS_HTML5_BREAK(endtagloop);
   2601            }
   2602            generateImpliedEndTags();
   2603            if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
   2604              errUnclosedElements(eltPos, name);
   2605            }
   2606            while (currentPtr >= eltPos) {
   2607              pop();
   2608            }
   2609            clearTheListOfActiveFormattingElementsUpToTheLastMarker();
   2610            mode = IN_ROW;
   2611            NS_HTML5_BREAK(endtagloop);
   2612          }
   2613          case TABLE:
   2614          case TBODY_OR_THEAD_OR_TFOOT:
   2615          case TR: {
   2616            if (findLastInTableScope(name) ==
   2617                nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
   2618              MOZ_ASSERT(name == nsGkAtoms::tbody || name == nsGkAtoms::tfoot ||
   2619                         name == nsGkAtoms::thead || fragment ||
   2620                         isTemplateContents());
   2621              errStrayEndTag(name);
   2622              NS_HTML5_BREAK(endtagloop);
   2623            }
   2624            closeTheCell(findLastInTableScopeTdTh());
   2625            continue;
   2626          }
   2627          case BODY:
   2628          case CAPTION:
   2629          case COL:
   2630          case COLGROUP:
   2631          case HTML: {
   2632            errStrayEndTag(name);
   2633            NS_HTML5_BREAK(endtagloop);
   2634          }
   2635          default:;  // fall through
   2636        }
   2637        [[fallthrough]];
   2638      }
   2639      case FRAMESET_OK:
   2640      case IN_BODY: {
   2641        switch (group) {
   2642          case BODY: {
   2643            if (!isSecondOnStackBody()) {
   2644              MOZ_ASSERT(fragment || isTemplateContents());
   2645              errStrayEndTag(name);
   2646              NS_HTML5_BREAK(endtagloop);
   2647            }
   2648            MOZ_ASSERT(currentPtr >= 1);
   2649            if (MOZ_UNLIKELY(mViewSource)) {
   2650              for (int32_t i = 2; i <= currentPtr; i++) {
   2651                switch (stack[i]->getGroup()) {
   2652                  case DD_OR_DT:
   2653                  case LI:
   2654                  case OPTGROUP:
   2655                  case OPTION:
   2656                  case P:
   2657                  case RB_OR_RTC:
   2658                  case RT_OR_RP:
   2659                  case TD_OR_TH:
   2660                  case TBODY_OR_THEAD_OR_TFOOT: {
   2661                    break;
   2662                  }
   2663                  default: {
   2664                    errEndWithUnclosedElements(name);
   2665                    NS_HTML5_BREAK(uncloseloop1);
   2666                  }
   2667                }
   2668              }
   2669            uncloseloop1_end:;
   2670            }
   2671            mode = AFTER_BODY;
   2672            NS_HTML5_BREAK(endtagloop);
   2673          }
   2674          case HTML: {
   2675            if (!isSecondOnStackBody()) {
   2676              MOZ_ASSERT(fragment || isTemplateContents());
   2677              errStrayEndTag(name);
   2678              NS_HTML5_BREAK(endtagloop);
   2679            }
   2680            if (MOZ_UNLIKELY(mViewSource)) {
   2681              for (int32_t i = 0; i <= currentPtr; i++) {
   2682                switch (stack[i]->getGroup()) {
   2683                  case DD_OR_DT:
   2684                  case LI:
   2685                  case P:
   2686                  case RB_OR_RTC:
   2687                  case RT_OR_RP:
   2688                  case TBODY_OR_THEAD_OR_TFOOT:
   2689                  case TD_OR_TH:
   2690                  case BODY:
   2691                  case HTML: {
   2692                    break;
   2693                  }
   2694                  default: {
   2695                    errEndWithUnclosedElements(name);
   2696                    NS_HTML5_BREAK(uncloseloop2);
   2697                  }
   2698                }
   2699              }
   2700            uncloseloop2_end:;
   2701            }
   2702            mode = AFTER_BODY;
   2703            continue;
   2704          }
   2705          case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
   2706          case UL_OR_OL_OR_DL:
   2707          case PRE_OR_LISTING:
   2708          case FIELDSET:
   2709          case BUTTON:
   2710          case ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SEARCH_OR_SECTION_OR_SUMMARY: {
   2711            eltPos = findLastInScope(name);
   2712            if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
   2713              errStrayEndTag(name);
   2714            } else {
   2715              generateImpliedEndTags();
   2716              if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
   2717                errUnclosedElements(eltPos, name);
   2718              }
   2719              while (currentPtr >= eltPos) {
   2720                pop();
   2721              }
   2722            }
   2723            NS_HTML5_BREAK(endtagloop);
   2724          }
   2725          case FORM: {
   2726            if (!isTemplateContents()) {
   2727              if (!formPointer) {
   2728                errStrayEndTag(name);
   2729                NS_HTML5_BREAK(endtagloop);
   2730              }
   2731              formPointer = nullptr;
   2732              eltPos = findLastInScope(name);
   2733              if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
   2734                errStrayEndTag(name);
   2735                NS_HTML5_BREAK(endtagloop);
   2736              }
   2737              generateImpliedEndTags();
   2738              if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
   2739                errUnclosedElements(eltPos, name);
   2740              }
   2741              removeFromStack(eltPos);
   2742              NS_HTML5_BREAK(endtagloop);
   2743            } else {
   2744              eltPos = findLastInScope(name);
   2745              if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
   2746                errStrayEndTag(name);
   2747                NS_HTML5_BREAK(endtagloop);
   2748              }
   2749              generateImpliedEndTags();
   2750              if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
   2751                errUnclosedElements(eltPos, name);
   2752              }
   2753              while (currentPtr >= eltPos) {
   2754                pop();
   2755              }
   2756              NS_HTML5_BREAK(endtagloop);
   2757            }
   2758          }
   2759          case P: {
   2760            eltPos = findLastInButtonScope(nsGkAtoms::p);
   2761            if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
   2762              errNoElementToCloseButEndTagSeen(nsGkAtoms::p);
   2763              if (isInForeign()) {
   2764                errHtmlStartTagInForeignContext(name);
   2765                while (currentPtr >= 0 &&
   2766                       stack[currentPtr]->ns != kNameSpaceID_XHTML) {
   2767                  pop();
   2768                }
   2769              }
   2770              appendVoidElementToCurrentMayFoster(
   2771                  elementName, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
   2772              NS_HTML5_BREAK(endtagloop);
   2773            }
   2774            generateImpliedEndTagsExceptFor(nsGkAtoms::p);
   2775            MOZ_ASSERT(eltPos != nsHtml5TreeBuilder::NOT_FOUND_ON_STACK);
   2776            if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
   2777              errUnclosedElements(eltPos, name);
   2778            }
   2779            while (currentPtr >= eltPos) {
   2780              pop();
   2781            }
   2782            NS_HTML5_BREAK(endtagloop);
   2783          }
   2784          case LI: {
   2785            eltPos = findLastInListScope(name);
   2786            if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
   2787              errNoElementToCloseButEndTagSeen(name);
   2788            } else {
   2789              generateImpliedEndTagsExceptFor(name);
   2790              if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
   2791                errUnclosedElements(eltPos, name);
   2792              }
   2793              while (currentPtr >= eltPos) {
   2794                pop();
   2795              }
   2796            }
   2797            NS_HTML5_BREAK(endtagloop);
   2798          }
   2799          case DD_OR_DT: {
   2800            eltPos = findLastInScope(name);
   2801            if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
   2802              errNoElementToCloseButEndTagSeen(name);
   2803            } else {
   2804              generateImpliedEndTagsExceptFor(name);
   2805              if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
   2806                errUnclosedElements(eltPos, name);
   2807              }
   2808              while (currentPtr >= eltPos) {
   2809                pop();
   2810              }
   2811            }
   2812            NS_HTML5_BREAK(endtagloop);
   2813          }
   2814          case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6: {
   2815            eltPos = findLastInScopeHn();
   2816            if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
   2817              errStrayEndTag(name);
   2818            } else {
   2819              generateImpliedEndTags();
   2820              if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
   2821                errUnclosedElements(eltPos, name);
   2822              }
   2823              while (currentPtr >= eltPos) {
   2824                pop();
   2825              }
   2826            }
   2827            NS_HTML5_BREAK(endtagloop);
   2828          }
   2829          case OBJECT:
   2830          case MARQUEE_OR_APPLET: {
   2831            eltPos = findLastInScope(name);
   2832            if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
   2833              errStrayEndTag(name);
   2834            } else {
   2835              generateImpliedEndTags();
   2836              if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
   2837                errUnclosedElements(eltPos, name);
   2838              }
   2839              while (currentPtr >= eltPos) {
   2840                pop();
   2841              }
   2842              clearTheListOfActiveFormattingElementsUpToTheLastMarker();
   2843            }
   2844            NS_HTML5_BREAK(endtagloop);
   2845          }
   2846          case BR: {
   2847            errEndTagBr();
   2848            if (isInForeign()) {
   2849              errHtmlStartTagInForeignContext(name);
   2850              while (currentPtr >= 0 &&
   2851                     stack[currentPtr]->ns != kNameSpaceID_XHTML) {
   2852                pop();
   2853              }
   2854            }
   2855            reconstructTheActiveFormattingElements();
   2856            appendVoidElementToCurrentMayFoster(
   2857                elementName, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
   2858            NS_HTML5_BREAK(endtagloop);
   2859          }
   2860          case TEMPLATE: {
   2861            break;
   2862          }
   2863          case AREA_OR_WBR:
   2864          case KEYGEN:
   2865          case PARAM_OR_SOURCE_OR_TRACK:
   2866          case EMBED:
   2867          case IMG:
   2868          case IMAGE:
   2869          case INPUT:
   2870          case HR:
   2871          case IFRAME:
   2872          case NOEMBED:
   2873          case NOFRAMES:
   2874          case SELECT:
   2875          case TABLE:
   2876          case TEXTAREA: {
   2877            errStrayEndTag(name);
   2878            NS_HTML5_BREAK(endtagloop);
   2879          }
   2880          case NOSCRIPT: {
   2881            if (scriptingEnabled) {
   2882              errStrayEndTag(name);
   2883              NS_HTML5_BREAK(endtagloop);
   2884            }
   2885            [[fallthrough]];
   2886          }
   2887          case A:
   2888          case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
   2889          case FONT:
   2890          case NOBR: {
   2891            if (adoptionAgencyEndTag(name)) {
   2892              NS_HTML5_BREAK(endtagloop);
   2893            }
   2894            [[fallthrough]];
   2895          }
   2896          default: {
   2897            if (isCurrent(name)) {
   2898              pop();
   2899              NS_HTML5_BREAK(endtagloop);
   2900            }
   2901            eltPos = currentPtr;
   2902            for (;;) {
   2903              nsHtml5StackNode* node = stack[eltPos];
   2904              if (node->ns == kNameSpaceID_XHTML && node->name == name) {
   2905                generateImpliedEndTags();
   2906                if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
   2907                  errUnclosedElements(eltPos, name);
   2908                }
   2909                while (currentPtr >= eltPos) {
   2910                  pop();
   2911                }
   2912                NS_HTML5_BREAK(endtagloop);
   2913              } else if (!eltPos || node->isSpecial()) {
   2914                errStrayEndTag(name);
   2915                NS_HTML5_BREAK(endtagloop);
   2916              }
   2917              eltPos--;
   2918            }
   2919          }
   2920        }
   2921        [[fallthrough]];
   2922      }
   2923      case IN_HEAD: {
   2924        switch (group) {
   2925          case HEAD: {
   2926            pop();
   2927            mode = AFTER_HEAD;
   2928            NS_HTML5_BREAK(endtagloop);
   2929          }
   2930          case BR:
   2931          case HTML:
   2932          case BODY: {
   2933            pop();
   2934            mode = AFTER_HEAD;
   2935            continue;
   2936          }
   2937          case TEMPLATE: {
   2938            endTagTemplateInHead();
   2939            NS_HTML5_BREAK(endtagloop);
   2940          }
   2941          default: {
   2942            errStrayEndTag(name);
   2943            NS_HTML5_BREAK(endtagloop);
   2944          }
   2945        }
   2946      }
   2947      case IN_HEAD_NOSCRIPT: {
   2948        switch (group) {
   2949          case NOSCRIPT: {
   2950            pop();
   2951            mode = IN_HEAD;
   2952            NS_HTML5_BREAK(endtagloop);
   2953          }
   2954          case BR: {
   2955            errStrayEndTag(name);
   2956            pop();
   2957            mode = IN_HEAD;
   2958            continue;
   2959          }
   2960          default: {
   2961            errStrayEndTag(name);
   2962            NS_HTML5_BREAK(endtagloop);
   2963          }
   2964        }
   2965      }
   2966      case IN_COLUMN_GROUP: {
   2967        switch (group) {
   2968          case COLGROUP: {
   2969            if (!currentPtr ||
   2970                stack[currentPtr]->getGroup() == nsHtml5TreeBuilder::TEMPLATE) {
   2971              MOZ_ASSERT(fragment || isTemplateContents());
   2972              errGarbageInColgroup();
   2973              NS_HTML5_BREAK(endtagloop);
   2974            }
   2975            pop();
   2976            mode = IN_TABLE;
   2977            NS_HTML5_BREAK(endtagloop);
   2978          }
   2979          case COL: {
   2980            errStrayEndTag(name);
   2981            NS_HTML5_BREAK(endtagloop);
   2982          }
   2983          case TEMPLATE: {
   2984            endTagTemplateInHead();
   2985            NS_HTML5_BREAK(endtagloop);
   2986          }
   2987          default: {
   2988            if (!currentPtr ||
   2989                stack[currentPtr]->getGroup() == nsHtml5TreeBuilder::TEMPLATE) {
   2990              MOZ_ASSERT(fragment || isTemplateContents());
   2991              errGarbageInColgroup();
   2992              NS_HTML5_BREAK(endtagloop);
   2993            }
   2994            pop();
   2995            mode = IN_TABLE;
   2996            continue;
   2997          }
   2998        }
   2999      }
   3000      case IN_SELECT_IN_TABLE: {
   3001        switch (group) {
   3002          case CAPTION:
   3003          case TABLE:
   3004          case TBODY_OR_THEAD_OR_TFOOT:
   3005          case TR:
   3006          case TD_OR_TH: {
   3007            errEndTagSeenWithSelectOpen(name);
   3008            if (findLastInTableScope(name) !=
   3009                nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
   3010              eltPos = findLastInTableScope(nsGkAtoms::select);
   3011              if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
   3012                MOZ_ASSERT(fragment);
   3013                NS_HTML5_BREAK(endtagloop);
   3014              }
   3015              while (currentPtr >= eltPos) {
   3016                pop();
   3017              }
   3018              resetTheInsertionMode();
   3019              continue;
   3020            } else {
   3021              NS_HTML5_BREAK(endtagloop);
   3022            }
   3023          }
   3024          default:;  // fall through
   3025        }
   3026        [[fallthrough]];
   3027      }
   3028      case IN_SELECT: {
   3029        switch (group) {
   3030          case OPTION: {
   3031            if (isCurrent(nsGkAtoms::option)) {
   3032              pop();
   3033              NS_HTML5_BREAK(endtagloop);
   3034            } else {
   3035              errStrayEndTag(name);
   3036              NS_HTML5_BREAK(endtagloop);
   3037            }
   3038          }
   3039          case OPTGROUP: {
   3040            if (isCurrent(nsGkAtoms::option) &&
   3041                nsGkAtoms::optgroup == stack[currentPtr - 1]->name) {
   3042              pop();
   3043            }
   3044            if (isCurrent(nsGkAtoms::optgroup)) {
   3045              pop();
   3046            } else {
   3047              errStrayEndTag(name);
   3048            }
   3049            NS_HTML5_BREAK(endtagloop);
   3050          }
   3051          case SELECT: {
   3052            eltPos = findLastInTableScope(nsGkAtoms::select);
   3053            if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
   3054              MOZ_ASSERT(fragment);
   3055              errStrayEndTag(name);
   3056              NS_HTML5_BREAK(endtagloop);
   3057            }
   3058            while (currentPtr >= eltPos) {
   3059              pop();
   3060            }
   3061            resetTheInsertionMode();
   3062            NS_HTML5_BREAK(endtagloop);
   3063          }
   3064          case TEMPLATE: {
   3065            endTagTemplateInHead();
   3066            NS_HTML5_BREAK(endtagloop);
   3067          }
   3068          default: {
   3069            errStrayEndTag(name);
   3070            NS_HTML5_BREAK(endtagloop);
   3071          }
   3072        }
   3073      }
   3074      case AFTER_BODY: {
   3075        switch (group) {
   3076          case HTML: {
   3077            if (fragment) {
   3078              errStrayEndTag(name);
   3079              NS_HTML5_BREAK(endtagloop);
   3080            } else {
   3081              mode = AFTER_AFTER_BODY;
   3082              NS_HTML5_BREAK(endtagloop);
   3083            }
   3084          }
   3085          default: {
   3086            errEndTagAfterBody();
   3087            mode = framesetOk ? FRAMESET_OK : IN_BODY;
   3088            continue;
   3089          }
   3090        }
   3091      }
   3092      case IN_FRAMESET: {
   3093        switch (group) {
   3094          case FRAMESET: {
   3095            if (!currentPtr) {
   3096              MOZ_ASSERT(fragment);
   3097              errStrayEndTag(name);
   3098              NS_HTML5_BREAK(endtagloop);
   3099            }
   3100            pop();
   3101            if ((!fragment) && !isCurrent(nsGkAtoms::frameset)) {
   3102              mode = AFTER_FRAMESET;
   3103            }
   3104            NS_HTML5_BREAK(endtagloop);
   3105          }
   3106          default: {
   3107            errStrayEndTag(name);
   3108            NS_HTML5_BREAK(endtagloop);
   3109          }
   3110        }
   3111      }
   3112      case AFTER_FRAMESET: {
   3113        switch (group) {
   3114          case HTML: {
   3115            mode = AFTER_AFTER_FRAMESET;
   3116            NS_HTML5_BREAK(endtagloop);
   3117          }
   3118          default: {
   3119            errStrayEndTag(name);
   3120            NS_HTML5_BREAK(endtagloop);
   3121          }
   3122        }
   3123      }
   3124      case INITIAL: {
   3125        errEndTagSeenWithoutDoctype();
   3126        documentModeInternal(QUIRKS_MODE, nullptr, nullptr);
   3127        mode = BEFORE_HTML;
   3128        continue;
   3129      }
   3130      case BEFORE_HTML: {
   3131        switch (group) {
   3132          case HEAD:
   3133          case BR:
   3134          case HTML:
   3135          case BODY: {
   3136            appendHtmlElementToDocumentAndPush();
   3137            mode = BEFORE_HEAD;
   3138            continue;
   3139          }
   3140          default: {
   3141            errStrayEndTag(name);
   3142            NS_HTML5_BREAK(endtagloop);
   3143          }
   3144        }
   3145      }
   3146      case BEFORE_HEAD: {
   3147        switch (group) {
   3148          case HEAD:
   3149          case BR:
   3150          case HTML:
   3151          case BODY: {
   3152            appendToCurrentNodeAndPushHeadElement(
   3153                nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
   3154            mode = IN_HEAD;
   3155            continue;
   3156          }
   3157          default: {
   3158            errStrayEndTag(name);
   3159            NS_HTML5_BREAK(endtagloop);
   3160          }
   3161        }
   3162      }
   3163      case AFTER_HEAD: {
   3164        switch (group) {
   3165          case TEMPLATE: {
   3166            endTagTemplateInHead();
   3167            NS_HTML5_BREAK(endtagloop);
   3168          }
   3169          case HTML:
   3170          case BODY:
   3171          case BR: {
   3172            appendToCurrentNodeAndPushBodyElement();
   3173            mode = FRAMESET_OK;
   3174            continue;
   3175          }
   3176          default: {
   3177            errStrayEndTag(name);
   3178            NS_HTML5_BREAK(endtagloop);
   3179          }
   3180        }
   3181      }
   3182      case AFTER_AFTER_BODY: {
   3183        errStrayEndTag(name);
   3184        mode = framesetOk ? FRAMESET_OK : IN_BODY;
   3185        continue;
   3186      }
   3187      case AFTER_AFTER_FRAMESET: {
   3188        errStrayEndTag(name);
   3189        NS_HTML5_BREAK(endtagloop);
   3190      }
   3191      case TEXT: {
   3192        pop();
   3193        if (originalMode == AFTER_HEAD) {
   3194          silentPop();
   3195        }
   3196        mode = originalMode;
   3197        NS_HTML5_BREAK(endtagloop);
   3198      }
   3199    }
   3200  }
   3201 endtagloop_end:;
   3202 }
   3203 
   3204 void nsHtml5TreeBuilder::endTagTemplateInHead() {
   3205  int32_t eltPos = findLast(nsGkAtoms::_template);
   3206  if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
   3207    errStrayEndTag(nsGkAtoms::_template);
   3208    return;
   3209  }
   3210  generateImpliedEndTagsThoroughly();
   3211  if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(nsGkAtoms::_template)) {
   3212    errUnclosedElements(eltPos, nsGkAtoms::_template);
   3213  }
   3214  while (currentPtr >= eltPos) {
   3215    pop();
   3216  }
   3217  clearTheListOfActiveFormattingElementsUpToTheLastMarker();
   3218  popTemplateMode();
   3219  resetTheInsertionMode();
   3220 }
   3221 
   3222 int32_t
   3223 nsHtml5TreeBuilder::findLastInTableScopeOrRootTemplateTbodyTheadTfoot() {
   3224  for (int32_t i = currentPtr; i > 0; i--) {
   3225    if (stack[i]->ns == kNameSpaceID_XHTML &&
   3226        (stack[i]->getGroup() == nsHtml5TreeBuilder::TBODY_OR_THEAD_OR_TFOOT ||
   3227         stack[i]->getGroup() == nsHtml5TreeBuilder::TEMPLATE)) {
   3228      return i;
   3229    }
   3230  }
   3231  return 0;
   3232 }
   3233 
   3234 int32_t nsHtml5TreeBuilder::findLast(nsAtom* name) {
   3235  for (int32_t i = currentPtr; i > 0; i--) {
   3236    if (stack[i]->ns == kNameSpaceID_XHTML && stack[i]->name == name) {
   3237      return i;
   3238    }
   3239  }
   3240  return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
   3241 }
   3242 
   3243 int32_t nsHtml5TreeBuilder::findLastInTableScope(nsAtom* name) {
   3244  for (int32_t i = currentPtr; i > 0; i--) {
   3245    if (stack[i]->ns == kNameSpaceID_XHTML) {
   3246      if (stack[i]->name == name) {
   3247        return i;
   3248      } else if (stack[i]->name == nsGkAtoms::table ||
   3249                 stack[i]->name == nsGkAtoms::_template) {
   3250        return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
   3251      }
   3252    }
   3253  }
   3254  return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
   3255 }
   3256 
   3257 int32_t nsHtml5TreeBuilder::findLastInButtonScope(nsAtom* name) {
   3258  for (int32_t i = currentPtr; i > 0; i--) {
   3259    if (stack[i]->ns == kNameSpaceID_XHTML) {
   3260      if (stack[i]->name == name) {
   3261        return i;
   3262      } else if (stack[i]->name == nsGkAtoms::button) {
   3263        return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
   3264      }
   3265    }
   3266    if (stack[i]->isScoping()) {
   3267      return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
   3268    }
   3269  }
   3270  return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
   3271 }
   3272 
   3273 int32_t nsHtml5TreeBuilder::findLastInScope(nsAtom* name) {
   3274  for (int32_t i = currentPtr; i > 0; i--) {
   3275    if (stack[i]->ns == kNameSpaceID_XHTML && stack[i]->name == name) {
   3276      return i;
   3277    } else if (stack[i]->isScoping()) {
   3278      return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
   3279    }
   3280  }
   3281  return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
   3282 }
   3283 
   3284 int32_t nsHtml5TreeBuilder::findLastInListScope(nsAtom* name) {
   3285  for (int32_t i = currentPtr; i > 0; i--) {
   3286    if (stack[i]->ns == kNameSpaceID_XHTML) {
   3287      if (stack[i]->name == name) {
   3288        return i;
   3289      } else if (stack[i]->name == nsGkAtoms::ul ||
   3290                 stack[i]->name == nsGkAtoms::ol) {
   3291        return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
   3292      }
   3293    }
   3294    if (stack[i]->isScoping()) {
   3295      return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
   3296    }
   3297  }
   3298  return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
   3299 }
   3300 
   3301 int32_t nsHtml5TreeBuilder::findLastInScopeHn() {
   3302  for (int32_t i = currentPtr; i > 0; i--) {
   3303    if (stack[i]->getGroup() ==
   3304        nsHtml5TreeBuilder::H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6) {
   3305      return i;
   3306    } else if (stack[i]->isScoping()) {
   3307      return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
   3308    }
   3309  }
   3310  return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
   3311 }
   3312 
   3313 void nsHtml5TreeBuilder::generateImpliedEndTagsExceptFor(nsAtom* name) {
   3314  for (;;) {
   3315    nsHtml5StackNode* node = stack[currentPtr];
   3316    switch (node->getGroup()) {
   3317      case P:
   3318      case LI:
   3319      case DD_OR_DT:
   3320      case OPTION:
   3321      case OPTGROUP:
   3322      case RB_OR_RTC:
   3323      case RT_OR_RP: {
   3324        if (node->ns == kNameSpaceID_XHTML && node->name == name) {
   3325          return;
   3326        }
   3327        pop();
   3328        continue;
   3329      }
   3330      default: {
   3331        return;
   3332      }
   3333    }
   3334  }
   3335 }
   3336 
   3337 void nsHtml5TreeBuilder::generateImpliedEndTags() {
   3338  for (;;) {
   3339    switch (stack[currentPtr]->getGroup()) {
   3340      case P:
   3341      case LI:
   3342      case DD_OR_DT:
   3343      case OPTION:
   3344      case OPTGROUP:
   3345      case RB_OR_RTC:
   3346      case RT_OR_RP: {
   3347        pop();
   3348        continue;
   3349      }
   3350      default: {
   3351        return;
   3352      }
   3353    }
   3354  }
   3355 }
   3356 
   3357 void nsHtml5TreeBuilder::generateImpliedEndTagsThoroughly() {
   3358  for (;;) {
   3359    switch (stack[currentPtr]->getGroup()) {
   3360      case CAPTION:
   3361      case COLGROUP:
   3362      case DD_OR_DT:
   3363      case LI:
   3364      case OPTGROUP:
   3365      case OPTION:
   3366      case P:
   3367      case RB_OR_RTC:
   3368      case RT_OR_RP:
   3369      case TBODY_OR_THEAD_OR_TFOOT:
   3370      case TD_OR_TH:
   3371      case TR: {
   3372        pop();
   3373        continue;
   3374      }
   3375      default: {
   3376        return;
   3377      }
   3378    }
   3379  }
   3380 }
   3381 
   3382 bool nsHtml5TreeBuilder::isSecondOnStackBody() {
   3383  return currentPtr >= 1 && stack[1]->getGroup() == nsHtml5TreeBuilder::BODY;
   3384 }
   3385 
   3386 void nsHtml5TreeBuilder::documentModeInternal(nsHtml5DocumentMode m,
   3387                                              nsHtml5String publicIdentifier,
   3388                                              nsHtml5String systemIdentifier) {
   3389  if (forceNoQuirks) {
   3390    quirks = false;
   3391    this->documentMode(STANDARDS_MODE);
   3392    return;
   3393  }
   3394  quirks = (m == QUIRKS_MODE);
   3395  this->documentMode(m);
   3396 }
   3397 
   3398 bool nsHtml5TreeBuilder::isAlmostStandards(nsHtml5String publicIdentifier,
   3399                                           nsHtml5String systemIdentifier) {
   3400  if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
   3401          "-//w3c//dtd xhtml 1.0 transitional//", publicIdentifier)) {
   3402    return true;
   3403  }
   3404  if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
   3405          "-//w3c//dtd xhtml 1.0 frameset//", publicIdentifier)) {
   3406    return true;
   3407  }
   3408  if (systemIdentifier) {
   3409    if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
   3410            "-//w3c//dtd html 4.01 transitional//", publicIdentifier)) {
   3411      return true;
   3412    }
   3413    if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
   3414            "-//w3c//dtd html 4.01 frameset//", publicIdentifier)) {
   3415      return true;
   3416    }
   3417  }
   3418  return false;
   3419 }
   3420 
   3421 bool nsHtml5TreeBuilder::isQuirky(nsAtom* name, nsHtml5String publicIdentifier,
   3422                                  nsHtml5String systemIdentifier,
   3423                                  bool forceQuirks) {
   3424  if (forceQuirks) {
   3425    return true;
   3426  }
   3427  if (name != nsGkAtoms::html) {
   3428    return true;
   3429  }
   3430  if (publicIdentifier) {
   3431    for (int32_t i = 0; i < nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS.length; i++) {
   3432      if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
   3433              nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS[i], publicIdentifier)) {
   3434        return true;
   3435      }
   3436    }
   3437    if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
   3438            "-//w3o//dtd w3 html strict 3.0//en//", publicIdentifier) ||
   3439        nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
   3440            "-/w3c/dtd html 4.0 transitional/en", publicIdentifier) ||
   3441        nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
   3442            "html", publicIdentifier)) {
   3443      return true;
   3444    }
   3445  }
   3446  if (!systemIdentifier) {
   3447    if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
   3448            "-//w3c//dtd html 4.01 transitional//", publicIdentifier)) {
   3449      return true;
   3450    } else if (nsHtml5Portability::
   3451                   lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
   3452                       "-//w3c//dtd html 4.01 frameset//", publicIdentifier)) {
   3453      return true;
   3454    }
   3455  } else if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
   3456                 "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd",
   3457                 systemIdentifier)) {
   3458    return true;
   3459  }
   3460  return false;
   3461 }
   3462 
   3463 void nsHtml5TreeBuilder::closeTheCell(int32_t eltPos) {
   3464  generateImpliedEndTags();
   3465  if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
   3466    errUnclosedElementsCell(eltPos);
   3467  }
   3468  while (currentPtr >= eltPos) {
   3469    pop();
   3470  }
   3471  clearTheListOfActiveFormattingElementsUpToTheLastMarker();
   3472  mode = IN_ROW;
   3473  return;
   3474 }
   3475 
   3476 int32_t nsHtml5TreeBuilder::findLastInTableScopeTdTh() {
   3477  for (int32_t i = currentPtr; i > 0; i--) {
   3478    nsAtom* name = stack[i]->name;
   3479    if (stack[i]->ns == kNameSpaceID_XHTML) {
   3480      if (nsGkAtoms::td == name || nsGkAtoms::th == name) {
   3481        return i;
   3482      } else if (name == nsGkAtoms::table || name == nsGkAtoms::_template) {
   3483        return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
   3484      }
   3485    }
   3486  }
   3487  return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
   3488 }
   3489 
   3490 void nsHtml5TreeBuilder::clearStackBackTo(int32_t eltPos) {
   3491  int32_t eltGroup = stack[eltPos]->getGroup();
   3492  while (currentPtr > eltPos) {
   3493    if (stack[currentPtr]->ns == kNameSpaceID_XHTML &&
   3494        stack[currentPtr]->getGroup() == TEMPLATE &&
   3495        (eltGroup == TABLE || eltGroup == TBODY_OR_THEAD_OR_TFOOT ||
   3496         eltGroup == TR || !eltPos)) {
   3497      return;
   3498    }
   3499    pop();
   3500  }
   3501 }
   3502 
   3503 void nsHtml5TreeBuilder::resetTheInsertionMode() {
   3504  nsHtml5StackNode* node;
   3505  nsAtom* name;
   3506  int32_t ns;
   3507  for (int32_t i = currentPtr; i >= 0; i--) {
   3508    node = stack[i];
   3509    name = node->name;
   3510    ns = node->ns;
   3511    if (!i) {
   3512      if (!(contextNamespace == kNameSpaceID_XHTML &&
   3513            (contextName == nsGkAtoms::td || contextName == nsGkAtoms::th))) {
   3514        if (fragment) {
   3515          name = contextName;
   3516          ns = contextNamespace;
   3517        }
   3518      } else {
   3519        mode = framesetOk ? FRAMESET_OK : IN_BODY;
   3520        return;
   3521      }
   3522    }
   3523    if (nsGkAtoms::select == name) {
   3524      int32_t ancestorIndex = i;
   3525      while (ancestorIndex > 0) {
   3526        nsHtml5StackNode* ancestor = stack[ancestorIndex--];
   3527        if (kNameSpaceID_XHTML == ancestor->ns) {
   3528          if (nsGkAtoms::_template == ancestor->name) {
   3529            break;
   3530          }
   3531          if (nsGkAtoms::table == ancestor->name) {
   3532            mode = IN_SELECT_IN_TABLE;
   3533            return;
   3534          }
   3535        }
   3536      }
   3537      mode = IN_SELECT;
   3538      return;
   3539    } else if (nsGkAtoms::td == name || nsGkAtoms::th == name) {
   3540      mode = IN_CELL;
   3541      return;
   3542    } else if (nsGkAtoms::tr == name) {
   3543      mode = IN_ROW;
   3544      return;
   3545    } else if (nsGkAtoms::tbody == name || nsGkAtoms::thead == name ||
   3546               nsGkAtoms::tfoot == name) {
   3547      mode = IN_TABLE_BODY;
   3548      return;
   3549    } else if (nsGkAtoms::caption == name) {
   3550      mode = IN_CAPTION;
   3551      return;
   3552    } else if (nsGkAtoms::colgroup == name) {
   3553      mode = IN_COLUMN_GROUP;
   3554      return;
   3555    } else if (nsGkAtoms::table == name) {
   3556      mode = IN_TABLE;
   3557      return;
   3558    } else if (kNameSpaceID_XHTML != ns) {
   3559      mode = framesetOk ? FRAMESET_OK : IN_BODY;
   3560      return;
   3561    } else if (nsGkAtoms::_template == name) {
   3562      MOZ_ASSERT(templateModePtr >= 0);
   3563      mode = templateModeStack[templateModePtr];
   3564      return;
   3565    } else if (nsGkAtoms::head == name) {
   3566      if (name == contextName) {
   3567        mode = framesetOk ? FRAMESET_OK : IN_BODY;
   3568      } else {
   3569        mode = IN_HEAD;
   3570      }
   3571      return;
   3572    } else if (nsGkAtoms::body == name) {
   3573      mode = framesetOk ? FRAMESET_OK : IN_BODY;
   3574      return;
   3575    } else if (nsGkAtoms::frameset == name) {
   3576      mode = IN_FRAMESET;
   3577      return;
   3578    } else if (nsGkAtoms::html == name) {
   3579      if (!headPointer) {
   3580        mode = BEFORE_HEAD;
   3581      } else {
   3582        mode = AFTER_HEAD;
   3583      }
   3584      return;
   3585    } else if (!i) {
   3586      mode = framesetOk ? FRAMESET_OK : IN_BODY;
   3587      return;
   3588    }
   3589  }
   3590 }
   3591 
   3592 void nsHtml5TreeBuilder::implicitlyCloseP() {
   3593  int32_t eltPos = findLastInButtonScope(nsGkAtoms::p);
   3594  if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
   3595    return;
   3596  }
   3597  generateImpliedEndTagsExceptFor(nsGkAtoms::p);
   3598  if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
   3599    errUnclosedElementsImplied(eltPos, nsGkAtoms::p);
   3600  }
   3601  while (currentPtr >= eltPos) {
   3602    pop();
   3603  }
   3604 }
   3605 
   3606 bool nsHtml5TreeBuilder::debugOnlyClearLastStackSlot() {
   3607  stack[currentPtr] = nullptr;
   3608  return true;
   3609 }
   3610 
   3611 bool nsHtml5TreeBuilder::debugOnlyClearLastListSlot() {
   3612  listOfActiveFormattingElements[listPtr] = nullptr;
   3613  return true;
   3614 }
   3615 
   3616 void nsHtml5TreeBuilder::pushTemplateMode(int32_t mode) {
   3617  templateModePtr++;
   3618  if (templateModePtr == templateModeStack.length) {
   3619    jArray<int32_t, int32_t> newStack =
   3620        jArray<int32_t, int32_t>::newJArray(templateModeStack.length + 64);
   3621    nsHtml5ArrayCopy::arraycopy(templateModeStack, newStack,
   3622                                templateModeStack.length);
   3623    templateModeStack = newStack;
   3624  }
   3625  templateModeStack[templateModePtr] = mode;
   3626 }
   3627 
   3628 void nsHtml5TreeBuilder::push(nsHtml5StackNode* node) {
   3629  currentPtr++;
   3630  if (currentPtr == stack.length) {
   3631    jArray<nsHtml5StackNode*, int32_t> newStack =
   3632        jArray<nsHtml5StackNode*, int32_t>::newJArray(stack.length + 64);
   3633    nsHtml5ArrayCopy::arraycopy(stack, newStack, stack.length);
   3634    stack = newStack;
   3635  }
   3636  stack[currentPtr] = node;
   3637  elementPushed(node->ns, node->popName, node->node);
   3638 }
   3639 
   3640 void nsHtml5TreeBuilder::silentPush(nsHtml5StackNode* node) {
   3641  currentPtr++;
   3642  if (currentPtr == stack.length) {
   3643    jArray<nsHtml5StackNode*, int32_t> newStack =
   3644        jArray<nsHtml5StackNode*, int32_t>::newJArray(stack.length + 64);
   3645    nsHtml5ArrayCopy::arraycopy(stack, newStack, stack.length);
   3646    stack = newStack;
   3647  }
   3648  stack[currentPtr] = node;
   3649 }
   3650 
   3651 void nsHtml5TreeBuilder::append(nsHtml5StackNode* node) {
   3652  listPtr++;
   3653  if (listPtr == listOfActiveFormattingElements.length) {
   3654    jArray<nsHtml5StackNode*, int32_t> newList =
   3655        jArray<nsHtml5StackNode*, int32_t>::newJArray(
   3656            listOfActiveFormattingElements.length + 64);
   3657    nsHtml5ArrayCopy::arraycopy(listOfActiveFormattingElements, newList,
   3658                                listOfActiveFormattingElements.length);
   3659    listOfActiveFormattingElements = newList;
   3660  }
   3661  listOfActiveFormattingElements[listPtr] = node;
   3662 }
   3663 
   3664 void nsHtml5TreeBuilder::
   3665    clearTheListOfActiveFormattingElementsUpToTheLastMarker() {
   3666  while (listPtr > -1) {
   3667    if (!listOfActiveFormattingElements[listPtr]) {
   3668      --listPtr;
   3669      return;
   3670    }
   3671    listOfActiveFormattingElements[listPtr]->release(this);
   3672    --listPtr;
   3673  }
   3674 }
   3675 
   3676 void nsHtml5TreeBuilder::removeFromStack(int32_t pos) {
   3677  if (currentPtr == pos) {
   3678    pop();
   3679  } else {
   3680    stack[pos]->release(this);
   3681    nsHtml5ArrayCopy::arraycopy(stack, pos + 1, pos, currentPtr - pos);
   3682    MOZ_ASSERT(debugOnlyClearLastStackSlot());
   3683    currentPtr--;
   3684  }
   3685 }
   3686 
   3687 void nsHtml5TreeBuilder::removeFromStack(nsHtml5StackNode* node) {
   3688  if (stack[currentPtr] == node) {
   3689    pop();
   3690  } else {
   3691    int32_t pos = currentPtr - 1;
   3692    while (pos >= 0 && stack[pos] != node) {
   3693      pos--;
   3694    }
   3695    if (pos == -1) {
   3696      return;
   3697    }
   3698 
   3699    node->release(this);
   3700    nsHtml5ArrayCopy::arraycopy(stack, pos + 1, pos, currentPtr - pos);
   3701    currentPtr--;
   3702  }
   3703 }
   3704 
   3705 void nsHtml5TreeBuilder::removeFromListOfActiveFormattingElements(int32_t pos) {
   3706  MOZ_ASSERT(!!listOfActiveFormattingElements[pos]);
   3707  listOfActiveFormattingElements[pos]->release(this);
   3708  if (pos == listPtr) {
   3709    MOZ_ASSERT(debugOnlyClearLastListSlot());
   3710    listPtr--;
   3711    return;
   3712  }
   3713  MOZ_ASSERT(pos < listPtr);
   3714  nsHtml5ArrayCopy::arraycopy(listOfActiveFormattingElements, pos + 1, pos,
   3715                              listPtr - pos);
   3716  MOZ_ASSERT(debugOnlyClearLastListSlot());
   3717  listPtr--;
   3718 }
   3719 
   3720 bool nsHtml5TreeBuilder::adoptionAgencyEndTag(nsAtom* name) {
   3721  if (stack[currentPtr]->ns == kNameSpaceID_XHTML &&
   3722      stack[currentPtr]->name == name &&
   3723      findInListOfActiveFormattingElements(stack[currentPtr]) == -1) {
   3724    pop();
   3725    return true;
   3726  }
   3727  for (int32_t i = 0; i < 8; ++i) {
   3728    int32_t formattingEltListPos = listPtr;
   3729    while (formattingEltListPos > -1) {
   3730      nsHtml5StackNode* listNode =
   3731          listOfActiveFormattingElements[formattingEltListPos];
   3732      if (!listNode) {
   3733        formattingEltListPos = -1;
   3734        break;
   3735      } else if (listNode->name == name) {
   3736        break;
   3737      }
   3738      formattingEltListPos--;
   3739    }
   3740    if (formattingEltListPos == -1) {
   3741      return false;
   3742    }
   3743    nsHtml5StackNode* formattingElt =
   3744        listOfActiveFormattingElements[formattingEltListPos];
   3745    int32_t formattingEltStackPos = currentPtr;
   3746    bool inScope = true;
   3747    while (formattingEltStackPos > -1) {
   3748      nsHtml5StackNode* node = stack[formattingEltStackPos];
   3749      if (node == formattingElt) {
   3750        break;
   3751      } else if (node->isScoping()) {
   3752        inScope = false;
   3753      }
   3754      formattingEltStackPos--;
   3755    }
   3756    if (formattingEltStackPos == -1) {
   3757      errNoElementToCloseButEndTagSeen(name);
   3758      removeFromListOfActiveFormattingElements(formattingEltListPos);
   3759      return true;
   3760    }
   3761    if (!inScope) {
   3762      errNoElementToCloseButEndTagSeen(name);
   3763      return true;
   3764    }
   3765    if (formattingEltStackPos != currentPtr) {
   3766      errEndTagViolatesNestingRules(name);
   3767    }
   3768    int32_t furthestBlockPos = formattingEltStackPos + 1;
   3769    while (furthestBlockPos <= currentPtr) {
   3770      nsHtml5StackNode* node = stack[furthestBlockPos];
   3771      MOZ_ASSERT(furthestBlockPos > 0,
   3772                 "How is formattingEltStackPos + 1 not > 0?");
   3773      if (node->isSpecial()) {
   3774        break;
   3775      }
   3776      furthestBlockPos++;
   3777    }
   3778    if (furthestBlockPos > currentPtr) {
   3779      while (currentPtr >= formattingEltStackPos) {
   3780        pop();
   3781      }
   3782      removeFromListOfActiveFormattingElements(formattingEltListPos);
   3783      return true;
   3784    }
   3785    nsHtml5StackNode* commonAncestor = stack[formattingEltStackPos - 1];
   3786    nsIContentHandle* insertionCommonAncestor =
   3787        nodeFromStackWithBlinkCompat(formattingEltStackPos - 1);
   3788    nsHtml5StackNode* furthestBlock = stack[furthestBlockPos];
   3789    int32_t bookmark = formattingEltListPos;
   3790    int32_t nodePos = furthestBlockPos;
   3791    nsHtml5StackNode* lastNode = furthestBlock;
   3792    int32_t j = 0;
   3793    for (;;) {
   3794      ++j;
   3795      nodePos--;
   3796      if (nodePos == formattingEltStackPos) {
   3797        break;
   3798      }
   3799      nsHtml5StackNode* node = stack[nodePos];
   3800      int32_t nodeListPos = findInListOfActiveFormattingElements(node);
   3801      if (j > 3 && nodeListPos != -1) {
   3802        removeFromListOfActiveFormattingElements(nodeListPos);
   3803        if (nodeListPos <= formattingEltListPos) {
   3804          formattingEltListPos--;
   3805        }
   3806        if (nodeListPos <= bookmark) {
   3807          bookmark--;
   3808        }
   3809        nodeListPos = -1;
   3810      }
   3811      if (nodeListPos == -1) {
   3812        MOZ_ASSERT(formattingEltStackPos < nodePos);
   3813        MOZ_ASSERT(bookmark < nodePos);
   3814        MOZ_ASSERT(furthestBlockPos > nodePos);
   3815        removeFromStack(nodePos);
   3816        furthestBlockPos--;
   3817        continue;
   3818      }
   3819      if (nodePos == furthestBlockPos) {
   3820        bookmark = nodeListPos + 1;
   3821      }
   3822      MOZ_ASSERT(node == listOfActiveFormattingElements[nodeListPos]);
   3823      MOZ_ASSERT(node == stack[nodePos]);
   3824      nsIContentHandle* clone = createElement(
   3825          kNameSpaceID_XHTML, node->name, node->attributes->cloneAttributes(),
   3826          insertionCommonAncestor, htmlCreator(node->getHtmlCreator()));
   3827      nsHtml5StackNode* newNode = createStackNode(
   3828          node->getFlags(), node->ns, node->name, clone, node->popName,
   3829          node->attributes, node->getHtmlCreator());
   3830      node->dropAttributes();
   3831      stack[nodePos] = newNode;
   3832      newNode->retain();
   3833      listOfActiveFormattingElements[nodeListPos] = newNode;
   3834      node->release(this);
   3835      node->release(this);
   3836      node = newNode;
   3837      detachFromParent(lastNode->node);
   3838      appendElement(lastNode->node, nodeFromStackWithBlinkCompat(nodePos));
   3839      lastNode = node;
   3840    }
   3841    if (commonAncestor->isFosterParenting()) {
   3842      detachFromParent(lastNode->node);
   3843      insertIntoFosterParent(lastNode->node);
   3844    } else {
   3845      detachFromParent(lastNode->node);
   3846      appendElement(lastNode->node, insertionCommonAncestor);
   3847    }
   3848    nsIContentHandle* clone = createElement(
   3849        kNameSpaceID_XHTML, formattingElt->name,
   3850        formattingElt->attributes->cloneAttributes(), furthestBlock->node,
   3851        htmlCreator(formattingElt->getHtmlCreator()));
   3852    nsHtml5StackNode* formattingClone = createStackNode(
   3853        formattingElt->getFlags(), formattingElt->ns, formattingElt->name,
   3854        clone, formattingElt->popName, formattingElt->attributes,
   3855        formattingElt->getHtmlCreator());
   3856    formattingElt->dropAttributes();
   3857    appendChildrenToNewParent(furthestBlock->node, clone);
   3858    appendElement(clone, furthestBlock->node);
   3859    removeFromListOfActiveFormattingElements(formattingEltListPos);
   3860    insertIntoListOfActiveFormattingElements(formattingClone, bookmark);
   3861    MOZ_ASSERT(formattingEltStackPos < furthestBlockPos);
   3862    removeFromStack(formattingEltStackPos);
   3863    insertIntoStack(formattingClone, furthestBlockPos);
   3864  }
   3865  return true;
   3866 }
   3867 
   3868 void nsHtml5TreeBuilder::insertIntoStack(nsHtml5StackNode* node,
   3869                                         int32_t position) {
   3870  MOZ_ASSERT(currentPtr + 1 < stack.length);
   3871  MOZ_ASSERT(position <= currentPtr + 1);
   3872  if (position == currentPtr + 1) {
   3873    push(node);
   3874  } else {
   3875    nsHtml5ArrayCopy::arraycopy(stack, position, position + 1,
   3876                                (currentPtr - position) + 1);
   3877    currentPtr++;
   3878    stack[position] = node;
   3879  }
   3880 }
   3881 
   3882 void nsHtml5TreeBuilder::insertIntoListOfActiveFormattingElements(
   3883    nsHtml5StackNode* formattingClone, int32_t bookmark) {
   3884  formattingClone->retain();
   3885  MOZ_ASSERT(listPtr + 1 < listOfActiveFormattingElements.length);
   3886  if (bookmark <= listPtr) {
   3887    nsHtml5ArrayCopy::arraycopy(listOfActiveFormattingElements, bookmark,
   3888                                bookmark + 1, (listPtr - bookmark) + 1);
   3889  }
   3890  listPtr++;
   3891  listOfActiveFormattingElements[bookmark] = formattingClone;
   3892 }
   3893 
   3894 int32_t nsHtml5TreeBuilder::findInListOfActiveFormattingElements(
   3895    nsHtml5StackNode* node) {
   3896  for (int32_t i = listPtr; i >= 0; i--) {
   3897    if (node == listOfActiveFormattingElements[i]) {
   3898      return i;
   3899    }
   3900  }
   3901  return -1;
   3902 }
   3903 
   3904 int32_t nsHtml5TreeBuilder::
   3905    findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker(
   3906        nsAtom* name) {
   3907  for (int32_t i = listPtr; i >= 0; i--) {
   3908    nsHtml5StackNode* node = listOfActiveFormattingElements[i];
   3909    if (!node) {
   3910      return -1;
   3911    } else if (node->name == name) {
   3912      return i;
   3913    }
   3914  }
   3915  return -1;
   3916 }
   3917 
   3918 void nsHtml5TreeBuilder::maybeForgetEarlierDuplicateFormattingElement(
   3919    nsAtom* name, nsHtml5HtmlAttributes* attributes) {
   3920  int32_t candidate = -1;
   3921  int32_t count = 0;
   3922  for (int32_t i = listPtr; i >= 0; i--) {
   3923    nsHtml5StackNode* node = listOfActiveFormattingElements[i];
   3924    if (!node) {
   3925      break;
   3926    }
   3927    if (node->name == name && node->attributes->equalsAnother(attributes)) {
   3928      candidate = i;
   3929      ++count;
   3930    }
   3931  }
   3932  if (count >= 3) {
   3933    removeFromListOfActiveFormattingElements(candidate);
   3934  }
   3935 }
   3936 
   3937 int32_t nsHtml5TreeBuilder::findLastOrRoot(nsAtom* name) {
   3938  for (int32_t i = currentPtr; i > 0; i--) {
   3939    if (stack[i]->ns == kNameSpaceID_XHTML && stack[i]->name == name) {
   3940      return i;
   3941    }
   3942  }
   3943  return 0;
   3944 }
   3945 
   3946 int32_t nsHtml5TreeBuilder::findLastOrRoot(int32_t group) {
   3947  for (int32_t i = currentPtr; i > 0; i--) {
   3948    if (stack[i]->ns == kNameSpaceID_XHTML && stack[i]->getGroup() == group) {
   3949      return i;
   3950    }
   3951  }
   3952  return 0;
   3953 }
   3954 
   3955 bool nsHtml5TreeBuilder::addAttributesToBody(
   3956    nsHtml5HtmlAttributes* attributes) {
   3957  if (currentPtr >= 1) {
   3958    nsHtml5StackNode* body = stack[1];
   3959    if (body->getGroup() == nsHtml5TreeBuilder::BODY) {
   3960      addAttributesToElement(body->node, attributes);
   3961      return true;
   3962    }
   3963  }
   3964  return false;
   3965 }
   3966 
   3967 void nsHtml5TreeBuilder::addAttributesToHtml(
   3968    nsHtml5HtmlAttributes* attributes) {
   3969  addAttributesToElement(stack[0]->node, attributes);
   3970 }
   3971 
   3972 void nsHtml5TreeBuilder::pushHeadPointerOntoStack() {
   3973  MOZ_ASSERT(!!headPointer);
   3974  MOZ_ASSERT(mode == AFTER_HEAD);
   3975 
   3976  silentPush(createStackNode(nsHtml5ElementName::ELT_HEAD, headPointer));
   3977 }
   3978 
   3979 void nsHtml5TreeBuilder::reconstructTheActiveFormattingElements() {
   3980  if (listPtr == -1) {
   3981    return;
   3982  }
   3983  nsHtml5StackNode* mostRecent = listOfActiveFormattingElements[listPtr];
   3984  if (!mostRecent || isInStack(mostRecent)) {
   3985    return;
   3986  }
   3987  int32_t entryPos = listPtr;
   3988  for (;;) {
   3989    entryPos--;
   3990    if (entryPos == -1) {
   3991      break;
   3992    }
   3993    if (!listOfActiveFormattingElements[entryPos]) {
   3994      break;
   3995    }
   3996    if (isInStack(listOfActiveFormattingElements[entryPos])) {
   3997      break;
   3998    }
   3999  }
   4000  while (entryPos < listPtr) {
   4001    entryPos++;
   4002    nsHtml5StackNode* entry = listOfActiveFormattingElements[entryPos];
   4003    nsHtml5StackNode* current = stack[currentPtr];
   4004    nsIContentHandle* clone;
   4005    if (current->isFosterParenting()) {
   4006      clone = createAndInsertFosterParentedElement(
   4007          kNameSpaceID_XHTML, entry->name, entry->attributes->cloneAttributes(),
   4008          htmlCreator(entry->getHtmlCreator()));
   4009    } else {
   4010      nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
   4011      clone = createElement(kNameSpaceID_XHTML, entry->name,
   4012                            entry->attributes->cloneAttributes(), currentNode,
   4013                            htmlCreator(entry->getHtmlCreator()));
   4014      appendElement(clone, currentNode);
   4015    }
   4016    nsHtml5StackNode* entryClone = createStackNode(
   4017        entry->getFlags(), entry->ns, entry->name, clone, entry->popName,
   4018        entry->attributes, entry->getHtmlCreator());
   4019    entry->dropAttributes();
   4020    push(entryClone);
   4021    listOfActiveFormattingElements[entryPos] = entryClone;
   4022    entry->release(this);
   4023    entryClone->retain();
   4024  }
   4025 }
   4026 
   4027 void nsHtml5TreeBuilder::notifyUnusedStackNode(int32_t idxInStackNodes) {
   4028  if (idxInStackNodes < stackNodesIdx) {
   4029    stackNodesIdx = idxInStackNodes;
   4030  }
   4031 }
   4032 
   4033 nsHtml5StackNode* nsHtml5TreeBuilder::getUnusedStackNode() {
   4034  while (stackNodesIdx < numStackNodes) {
   4035    if (stackNodes[stackNodesIdx]->isUnused()) {
   4036      return stackNodes[stackNodesIdx++];
   4037    }
   4038    stackNodesIdx++;
   4039  }
   4040  if (stackNodesIdx < stackNodes.length) {
   4041    stackNodes[stackNodesIdx] = new nsHtml5StackNode(stackNodesIdx);
   4042    numStackNodes++;
   4043    return stackNodes[stackNodesIdx++];
   4044  }
   4045  jArray<nsHtml5StackNode*, int32_t> newStack =
   4046      jArray<nsHtml5StackNode*, int32_t>::newJArray(stackNodes.length + 64);
   4047  nsHtml5ArrayCopy::arraycopy(stackNodes, newStack, stackNodes.length);
   4048  stackNodes = newStack;
   4049  stackNodes[stackNodesIdx] = new nsHtml5StackNode(stackNodesIdx);
   4050  numStackNodes++;
   4051  return stackNodes[stackNodesIdx++];
   4052 }
   4053 
   4054 nsHtml5StackNode* nsHtml5TreeBuilder::createStackNode(
   4055    int32_t flags, int32_t ns, nsAtom* name, nsIContentHandle* node,
   4056    nsAtom* popName, nsHtml5HtmlAttributes* attributes,
   4057    mozilla::dom::HTMLContentCreatorFunction htmlCreator) {
   4058  nsHtml5StackNode* instance = getUnusedStackNode();
   4059  instance->setValues(flags, ns, name, node, popName, attributes, htmlCreator);
   4060  return instance;
   4061 }
   4062 
   4063 nsHtml5StackNode* nsHtml5TreeBuilder::createStackNode(
   4064    nsHtml5ElementName* elementName, nsIContentHandle* node) {
   4065  nsHtml5StackNode* instance = getUnusedStackNode();
   4066  instance->setValues(elementName, node);
   4067  return instance;
   4068 }
   4069 
   4070 nsHtml5StackNode* nsHtml5TreeBuilder::createStackNode(
   4071    nsHtml5ElementName* elementName, nsIContentHandle* node,
   4072    nsHtml5HtmlAttributes* attributes) {
   4073  nsHtml5StackNode* instance = getUnusedStackNode();
   4074  instance->setValues(elementName, node, attributes);
   4075  return instance;
   4076 }
   4077 
   4078 nsHtml5StackNode* nsHtml5TreeBuilder::createStackNode(
   4079    nsHtml5ElementName* elementName, nsIContentHandle* node, nsAtom* popName) {
   4080  nsHtml5StackNode* instance = getUnusedStackNode();
   4081  instance->setValues(elementName, node, popName);
   4082  return instance;
   4083 }
   4084 
   4085 nsHtml5StackNode* nsHtml5TreeBuilder::createStackNode(
   4086    nsHtml5ElementName* elementName, nsAtom* popName, nsIContentHandle* node) {
   4087  nsHtml5StackNode* instance = getUnusedStackNode();
   4088  instance->setValues(elementName, popName, node);
   4089  return instance;
   4090 }
   4091 
   4092 nsHtml5StackNode* nsHtml5TreeBuilder::createStackNode(
   4093    nsHtml5ElementName* elementName, nsIContentHandle* node, nsAtom* popName,
   4094    bool markAsIntegrationPoint) {
   4095  nsHtml5StackNode* instance = getUnusedStackNode();
   4096  instance->setValues(elementName, node, popName, markAsIntegrationPoint);
   4097  return instance;
   4098 }
   4099 
   4100 void nsHtml5TreeBuilder::insertIntoFosterParent(nsIContentHandle* child) {
   4101  int32_t tablePos = findLastOrRoot(nsHtml5TreeBuilder::TABLE);
   4102  int32_t templatePos = findLastOrRoot(nsHtml5TreeBuilder::TEMPLATE);
   4103  if (templatePos >= tablePos) {
   4104    appendElement(child, stack[templatePos]->node);
   4105    return;
   4106  }
   4107  nsHtml5StackNode* node = stack[tablePos];
   4108  insertFosterParentedChild(child, node->node, stack[tablePos - 1]->node);
   4109 }
   4110 
   4111 nsIContentHandle* nsHtml5TreeBuilder::createAndInsertFosterParentedElement(
   4112    int32_t ns, nsAtom* name, nsHtml5HtmlAttributes* attributes,
   4113    nsHtml5ContentCreatorFunction creator) {
   4114  return createAndInsertFosterParentedElement(ns, name, attributes, nullptr,
   4115                                              creator);
   4116 }
   4117 
   4118 nsIContentHandle* nsHtml5TreeBuilder::createAndInsertFosterParentedElement(
   4119    int32_t ns, nsAtom* name, nsHtml5HtmlAttributes* attributes,
   4120    nsIContentHandle* form, nsHtml5ContentCreatorFunction creator) {
   4121  int32_t tablePos = findLastOrRoot(nsHtml5TreeBuilder::TABLE);
   4122  int32_t templatePos = findLastOrRoot(nsHtml5TreeBuilder::TEMPLATE);
   4123  if (templatePos >= tablePos) {
   4124    nsIContentHandle* child = createElement(ns, name, attributes, form,
   4125                                            stack[templatePos]->node, creator);
   4126    appendElement(child, stack[templatePos]->node);
   4127    return child;
   4128  }
   4129  nsHtml5StackNode* node = stack[tablePos];
   4130  return createAndInsertFosterParentedElement(
   4131      ns, name, attributes, form, node->node, stack[tablePos - 1]->node,
   4132      creator);
   4133 }
   4134 
   4135 bool nsHtml5TreeBuilder::isInStack(nsHtml5StackNode* node) {
   4136  for (int32_t i = currentPtr; i >= 0; i--) {
   4137    if (stack[i] == node) {
   4138      return true;
   4139    }
   4140  }
   4141  return false;
   4142 }
   4143 
   4144 void nsHtml5TreeBuilder::popTemplateMode() { templateModePtr--; }
   4145 
   4146 void nsHtml5TreeBuilder::pop() {
   4147  nsHtml5StackNode* node = stack[currentPtr];
   4148  MOZ_ASSERT(debugOnlyClearLastStackSlot());
   4149  currentPtr--;
   4150  elementPopped(node->ns, node->popName, node->node);
   4151  node->release(this);
   4152 }
   4153 
   4154 void nsHtml5TreeBuilder::popForeign(int32_t origPos, int32_t eltPos) {
   4155  nsHtml5StackNode* node = stack[currentPtr];
   4156  if (origPos != currentPtr || eltPos != currentPtr) {
   4157    markMalformedIfScript(node->node);
   4158  }
   4159  MOZ_ASSERT(debugOnlyClearLastStackSlot());
   4160  currentPtr--;
   4161  elementPopped(node->ns, node->popName, node->node);
   4162  node->release(this);
   4163 }
   4164 
   4165 void nsHtml5TreeBuilder::silentPop() {
   4166  nsHtml5StackNode* node = stack[currentPtr];
   4167  MOZ_ASSERT(debugOnlyClearLastStackSlot());
   4168  currentPtr--;
   4169  node->release(this);
   4170 }
   4171 
   4172 void nsHtml5TreeBuilder::popOnEof() {
   4173  nsHtml5StackNode* node = stack[currentPtr];
   4174  MOZ_ASSERT(debugOnlyClearLastStackSlot());
   4175  currentPtr--;
   4176  markMalformedIfScript(node->node);
   4177  elementPopped(node->ns, node->popName, node->node);
   4178  node->release(this);
   4179 }
   4180 
   4181 void nsHtml5TreeBuilder::appendHtmlElementToDocumentAndPush(
   4182    nsHtml5HtmlAttributes* attributes) {
   4183  nsIContentHandle* elt = createHtmlElementSetAsRoot(attributes);
   4184  nsHtml5StackNode* node = createStackNode(nsHtml5ElementName::ELT_HTML, elt);
   4185  push(node);
   4186 }
   4187 
   4188 void nsHtml5TreeBuilder::appendHtmlElementToDocumentAndPush() {
   4189  appendHtmlElementToDocumentAndPush(tokenizer->emptyAttributes());
   4190 }
   4191 
   4192 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushHeadElement(
   4193    nsHtml5HtmlAttributes* attributes) {
   4194  nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
   4195  nsIContentHandle* elt =
   4196      createElement(kNameSpaceID_XHTML, nsGkAtoms::head, attributes,
   4197                    currentNode, htmlCreator(NS_NewHTMLSharedElement));
   4198  appendElement(elt, currentNode);
   4199  headPointer = elt;
   4200  nsHtml5StackNode* node = createStackNode(nsHtml5ElementName::ELT_HEAD, elt);
   4201  push(node);
   4202 }
   4203 
   4204 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushBodyElement(
   4205    nsHtml5HtmlAttributes* attributes) {
   4206  appendToCurrentNodeAndPushElement(nsHtml5ElementName::ELT_BODY, attributes);
   4207 }
   4208 
   4209 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushBodyElement() {
   4210  appendToCurrentNodeAndPushBodyElement(tokenizer->emptyAttributes());
   4211 }
   4212 
   4213 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormElementMayFoster(
   4214    nsHtml5HtmlAttributes* attributes) {
   4215  nsIContentHandle* elt;
   4216  nsHtml5StackNode* current = stack[currentPtr];
   4217  if (current->isFosterParenting()) {
   4218    elt = createAndInsertFosterParentedElement(
   4219        kNameSpaceID_XHTML, nsGkAtoms::form, attributes,
   4220        htmlCreator(NS_NewHTMLFormElement));
   4221  } else {
   4222    nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
   4223    elt = createElement(kNameSpaceID_XHTML, nsGkAtoms::form, attributes,
   4224                        currentNode, htmlCreator(NS_NewHTMLFormElement));
   4225    appendElement(elt, currentNode);
   4226  }
   4227  if (!isTemplateContents()) {
   4228    formPointer = elt;
   4229  }
   4230  nsHtml5StackNode* node = createStackNode(nsHtml5ElementName::ELT_FORM, elt);
   4231  push(node);
   4232 }
   4233 
   4234 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormattingElementMayFoster(
   4235    nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
   4236  nsHtml5HtmlAttributes* clone = attributes->cloneAttributes();
   4237  nsIContentHandle* elt;
   4238  nsHtml5StackNode* current = stack[currentPtr];
   4239  if (current->isFosterParenting()) {
   4240    elt = createAndInsertFosterParentedElement(
   4241        kNameSpaceID_XHTML, elementName->getName(), attributes,
   4242        htmlCreator(elementName->getHtmlCreator()));
   4243  } else {
   4244    nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
   4245    elt =
   4246        createElement(kNameSpaceID_XHTML, elementName->getName(), attributes,
   4247                      currentNode, htmlCreator(elementName->getHtmlCreator()));
   4248    appendElement(elt, currentNode);
   4249  }
   4250  nsHtml5StackNode* node = createStackNode(elementName, elt, clone);
   4251  push(node);
   4252  append(node);
   4253  node->retain();
   4254 }
   4255 
   4256 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElement(
   4257    nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
   4258  nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
   4259  nsIContentHandle* elt =
   4260      createElement(kNameSpaceID_XHTML, elementName->getName(), attributes,
   4261                    currentNode, htmlCreator(elementName->getHtmlCreator()));
   4262  if (nsHtml5ElementName::ELT_TEMPLATE == elementName) {
   4263    nsIContentHandle* root =
   4264        getDeclarativeShadowRoot(currentNode, elt, attributes);
   4265    if (root) {
   4266      setDocumentFragmentForTemplate(elt, root);
   4267      elt = root;
   4268    } else {
   4269      appendElement(elt, currentNode);
   4270      elt = getDocumentFragmentForTemplate(elt);
   4271    }
   4272  } else {
   4273    appendElement(elt, currentNode);
   4274  }
   4275  nsHtml5StackNode* node = createStackNode(elementName, elt);
   4276  push(node);
   4277 }
   4278 
   4279 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(
   4280    nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
   4281  nsAtom* popName = elementName->getName();
   4282  nsIContentHandle* elt;
   4283  nsHtml5StackNode* current = stack[currentPtr];
   4284  if (current->isFosterParenting()) {
   4285    elt = createAndInsertFosterParentedElement(
   4286        kNameSpaceID_XHTML, popName, attributes,
   4287        htmlCreator(elementName->getHtmlCreator()));
   4288  } else {
   4289    nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
   4290    elt = createElement(kNameSpaceID_XHTML, popName, attributes, currentNode,
   4291                        htmlCreator(elementName->getHtmlCreator()));
   4292    appendElement(elt, currentNode);
   4293  }
   4294  nsHtml5StackNode* node = createStackNode(elementName, elt, popName);
   4295  push(node);
   4296 }
   4297 
   4298 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterMathML(
   4299    nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
   4300  nsAtom* popName = elementName->getName();
   4301  bool markAsHtmlIntegrationPoint = false;
   4302  if (nsHtml5ElementName::ELT_ANNOTATION_XML == elementName &&
   4303      annotationXmlEncodingPermitsHtml(attributes)) {
   4304    markAsHtmlIntegrationPoint = true;
   4305  }
   4306  nsIContentHandle* elt;
   4307  nsHtml5StackNode* current = stack[currentPtr];
   4308  if (current->isFosterParenting()) {
   4309    elt = createAndInsertFosterParentedElement(
   4310        kNameSpaceID_MathML, popName, attributes, htmlCreator(nullptr));
   4311  } else {
   4312    nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
   4313    elt = createElement(kNameSpaceID_MathML, popName, attributes, currentNode,
   4314                        htmlCreator(nullptr));
   4315    appendElement(elt, currentNode);
   4316  }
   4317  nsHtml5StackNode* node =
   4318      createStackNode(elementName, elt, popName, markAsHtmlIntegrationPoint);
   4319  push(node);
   4320 }
   4321 
   4322 bool nsHtml5TreeBuilder::annotationXmlEncodingPermitsHtml(
   4323    nsHtml5HtmlAttributes* attributes) {
   4324  nsHtml5String encoding =
   4325      attributes->getValue(nsHtml5AttributeName::ATTR_ENCODING);
   4326  if (!encoding) {
   4327    return false;
   4328  }
   4329  return nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
   4330             "application/xhtml+xml", encoding) ||
   4331         nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
   4332             "text/html", encoding);
   4333 }
   4334 
   4335 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterSVG(
   4336    nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
   4337  nsAtom* popName = elementName->getCamelCaseName();
   4338  nsIContentHandle* elt;
   4339  nsHtml5StackNode* current = stack[currentPtr];
   4340  if (current->isFosterParenting()) {
   4341    elt = createAndInsertFosterParentedElement(
   4342        kNameSpaceID_SVG, popName, attributes,
   4343        svgCreator(elementName->getSvgCreator()));
   4344  } else {
   4345    nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
   4346    elt = createElement(kNameSpaceID_SVG, popName, attributes, currentNode,
   4347                        svgCreator(elementName->getSvgCreator()));
   4348    appendElement(elt, currentNode);
   4349  }
   4350  nsHtml5StackNode* node = createStackNode(elementName, popName, elt);
   4351  push(node);
   4352 }
   4353 
   4354 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(
   4355    nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes,
   4356    nsIContentHandle* form) {
   4357  nsIContentHandle* elt;
   4358  nsIContentHandle* formOwner =
   4359      !form || fragment || isTemplateContents() ? nullptr : form;
   4360  nsHtml5StackNode* current = stack[currentPtr];
   4361  if (current->isFosterParenting()) {
   4362    elt = createAndInsertFosterParentedElement(
   4363        kNameSpaceID_XHTML, elementName->getName(), attributes, formOwner,
   4364        htmlCreator(elementName->getHtmlCreator()));
   4365  } else {
   4366    nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
   4367    elt = createElement(kNameSpaceID_XHTML, elementName->getName(), attributes,
   4368                        formOwner, currentNode,
   4369                        htmlCreator(elementName->getHtmlCreator()));
   4370    appendElement(elt, currentNode);
   4371  }
   4372  nsHtml5StackNode* node = createStackNode(elementName, elt);
   4373  push(node);
   4374 }
   4375 
   4376 void nsHtml5TreeBuilder::appendVoidElementToCurrent(
   4377    nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
   4378  nsAtom* popName = elementName->getName();
   4379  nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
   4380  nsIContentHandle* elt =
   4381      createElement(kNameSpaceID_XHTML, popName, attributes, currentNode,
   4382                    htmlCreator(elementName->getHtmlCreator()));
   4383  appendElement(elt, currentNode);
   4384  elementPushed(kNameSpaceID_XHTML, popName, elt);
   4385  elementPopped(kNameSpaceID_XHTML, popName, elt);
   4386 }
   4387 
   4388 void nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(
   4389    nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes,
   4390    nsIContentHandle* form) {
   4391  nsAtom* name = elementName->getName();
   4392  nsIContentHandle* elt;
   4393  nsIContentHandle* formOwner =
   4394      !form || fragment || isTemplateContents() ? nullptr : form;
   4395  nsHtml5StackNode* current = stack[currentPtr];
   4396  if (current->isFosterParenting()) {
   4397    elt = createAndInsertFosterParentedElement(
   4398        kNameSpaceID_XHTML, name, attributes, formOwner,
   4399        htmlCreator(elementName->getHtmlCreator()));
   4400  } else {
   4401    nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
   4402    elt =
   4403        createElement(kNameSpaceID_XHTML, name, attributes, formOwner,
   4404                      currentNode, htmlCreator(elementName->getHtmlCreator()));
   4405    appendElement(elt, currentNode);
   4406  }
   4407  elementPushed(kNameSpaceID_XHTML, name, elt);
   4408  elementPopped(kNameSpaceID_XHTML, name, elt);
   4409 }
   4410 
   4411 void nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(
   4412    nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
   4413  nsAtom* popName = elementName->getName();
   4414  nsIContentHandle* elt;
   4415  nsHtml5StackNode* current = stack[currentPtr];
   4416  if (current->isFosterParenting()) {
   4417    elt = createAndInsertFosterParentedElement(
   4418        kNameSpaceID_XHTML, popName, attributes,
   4419        htmlCreator(elementName->getHtmlCreator()));
   4420  } else {
   4421    nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
   4422    elt = createElement(kNameSpaceID_XHTML, popName, attributes, currentNode,
   4423                        htmlCreator(elementName->getHtmlCreator()));
   4424    appendElement(elt, currentNode);
   4425  }
   4426  elementPushed(kNameSpaceID_XHTML, popName, elt);
   4427  elementPopped(kNameSpaceID_XHTML, popName, elt);
   4428 }
   4429 
   4430 void nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterSVG(
   4431    nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
   4432  nsAtom* popName = elementName->getCamelCaseName();
   4433  nsIContentHandle* elt;
   4434  nsHtml5StackNode* current = stack[currentPtr];
   4435  if (current->isFosterParenting()) {
   4436    elt = createAndInsertFosterParentedElement(
   4437        kNameSpaceID_SVG, popName, attributes,
   4438        svgCreator(elementName->getSvgCreator()));
   4439  } else {
   4440    nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
   4441    elt = createElement(kNameSpaceID_SVG, popName, attributes, currentNode,
   4442                        svgCreator(elementName->getSvgCreator()));
   4443    appendElement(elt, currentNode);
   4444  }
   4445  elementPushed(kNameSpaceID_SVG, popName, elt);
   4446  elementPopped(kNameSpaceID_SVG, popName, elt);
   4447 }
   4448 
   4449 void nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterMathML(
   4450    nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
   4451  nsAtom* popName = elementName->getName();
   4452  nsIContentHandle* elt;
   4453  nsHtml5StackNode* current = stack[currentPtr];
   4454  if (current->isFosterParenting()) {
   4455    elt = createAndInsertFosterParentedElement(
   4456        kNameSpaceID_MathML, popName, attributes, htmlCreator(nullptr));
   4457  } else {
   4458    nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
   4459    elt = createElement(kNameSpaceID_MathML, popName, attributes, currentNode,
   4460                        htmlCreator(nullptr));
   4461    appendElement(elt, currentNode);
   4462  }
   4463  elementPushed(kNameSpaceID_MathML, popName, elt);
   4464  elementPopped(kNameSpaceID_MathML, popName, elt);
   4465 }
   4466 
   4467 void nsHtml5TreeBuilder::appendVoidInputToCurrent(
   4468    nsHtml5HtmlAttributes* attributes, nsIContentHandle* form) {
   4469  nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
   4470  nsIContentHandle* elt =
   4471      createElement(kNameSpaceID_XHTML, nsGkAtoms::input, attributes,
   4472                    !form || fragment || isTemplateContents() ? nullptr : form,
   4473                    currentNode, htmlCreator(NS_NewHTMLInputElement));
   4474  appendElement(elt, currentNode);
   4475  elementPushed(kNameSpaceID_XHTML, nsGkAtoms::input, elt);
   4476  elementPopped(kNameSpaceID_XHTML, nsGkAtoms::input, elt);
   4477 }
   4478 
   4479 void nsHtml5TreeBuilder::appendVoidFormToCurrent(
   4480    nsHtml5HtmlAttributes* attributes) {
   4481  nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
   4482  nsIContentHandle* elt =
   4483      createElement(kNameSpaceID_XHTML, nsGkAtoms::form, attributes,
   4484                    currentNode, htmlCreator(NS_NewHTMLFormElement));
   4485  formPointer = elt;
   4486  appendElement(elt, currentNode);
   4487  elementPushed(kNameSpaceID_XHTML, nsGkAtoms::form, elt);
   4488  elementPopped(kNameSpaceID_XHTML, nsGkAtoms::form, elt);
   4489 }
   4490 
   4491 void nsHtml5TreeBuilder::requestSuspension() {
   4492  tokenizer->requestSuspension();
   4493 }
   4494 
   4495 ;
   4496 bool nsHtml5TreeBuilder::isInForeign() {
   4497  return currentPtr >= 0 && stack[currentPtr]->ns != kNameSpaceID_XHTML;
   4498 }
   4499 
   4500 bool nsHtml5TreeBuilder::isInForeignButNotHtmlOrMathTextIntegrationPoint() {
   4501  if (currentPtr < 0) {
   4502    return false;
   4503  }
   4504  return !isSpecialParentInForeign(stack[currentPtr]);
   4505 }
   4506 
   4507 void nsHtml5TreeBuilder::setFragmentContext(nsAtom* context, int32_t ns,
   4508                                            nsIContentHandle* node,
   4509                                            bool quirks) {
   4510  this->contextName = context;
   4511  this->contextNamespace = ns;
   4512  this->contextNode = node;
   4513  this->fragment = (!!contextName);
   4514  this->quirks = quirks;
   4515 }
   4516 
   4517 nsIContentHandle* nsHtml5TreeBuilder::currentNode() {
   4518  return stack[currentPtr]->node;
   4519 }
   4520 
   4521 bool nsHtml5TreeBuilder::isScriptingEnabled() { return scriptingEnabled; }
   4522 
   4523 void nsHtml5TreeBuilder::setScriptingEnabled(bool scriptingEnabled) {
   4524  this->scriptingEnabled = scriptingEnabled;
   4525 }
   4526 
   4527 void nsHtml5TreeBuilder::setForceNoQuirks(bool forceNoQuirks) {
   4528  this->forceNoQuirks = forceNoQuirks;
   4529 }
   4530 
   4531 void nsHtml5TreeBuilder::setIsSrcdocDocument(bool isSrcdocDocument) {
   4532  this->setForceNoQuirks(isSrcdocDocument);
   4533 }
   4534 
   4535 bool nsHtml5TreeBuilder::isAllowDeclarativeShadowRoots() {
   4536  return allowDeclarativeShadowRoots;
   4537 }
   4538 
   4539 void nsHtml5TreeBuilder::setAllowDeclarativeShadowRoots(bool allow) {
   4540  allowDeclarativeShadowRoots = allow;
   4541 }
   4542 
   4543 void nsHtml5TreeBuilder::flushCharacters() {
   4544  if (charBufferLen > 0) {
   4545    if ((mode == IN_TABLE || mode == IN_TABLE_BODY || mode == IN_ROW) &&
   4546        charBufferContainsNonWhitespace()) {
   4547      errNonSpaceInTable();
   4548      reconstructTheActiveFormattingElements();
   4549      if (!stack[currentPtr]->isFosterParenting()) {
   4550        appendCharacters(currentNode(), charBuffer, 0, charBufferLen);
   4551        charBufferLen = 0;
   4552        return;
   4553      }
   4554      int32_t tablePos = findLastOrRoot(nsHtml5TreeBuilder::TABLE);
   4555      int32_t templatePos = findLastOrRoot(nsHtml5TreeBuilder::TEMPLATE);
   4556      if (templatePos >= tablePos) {
   4557        appendCharacters(stack[templatePos]->node, charBuffer, 0,
   4558                         charBufferLen);
   4559        charBufferLen = 0;
   4560        return;
   4561      }
   4562      nsHtml5StackNode* tableElt = stack[tablePos];
   4563      insertFosterParentedCharacters(charBuffer, 0, charBufferLen,
   4564                                     tableElt->node, stack[tablePos - 1]->node);
   4565      charBufferLen = 0;
   4566      return;
   4567    }
   4568    appendCharacters(currentNode(), charBuffer, 0, charBufferLen);
   4569    charBufferLen = 0;
   4570  }
   4571 }
   4572 
   4573 bool nsHtml5TreeBuilder::charBufferContainsNonWhitespace() {
   4574  for (int32_t i = 0; i < charBufferLen; i++) {
   4575    switch (charBuffer[i]) {
   4576      case ' ':
   4577      case '\t':
   4578      case '\n':
   4579      case '\r':
   4580      case '\f': {
   4581        continue;
   4582      }
   4583      default: {
   4584        return true;
   4585      }
   4586    }
   4587  }
   4588  return false;
   4589 }
   4590 
   4591 nsAHtml5TreeBuilderState* nsHtml5TreeBuilder::newSnapshot() {
   4592  jArray<nsHtml5StackNode*, int32_t> listCopy =
   4593      jArray<nsHtml5StackNode*, int32_t>::newJArray(listPtr + 1);
   4594  for (int32_t i = 0; i < listCopy.length; i++) {
   4595    nsHtml5StackNode* node = listOfActiveFormattingElements[i];
   4596    if (node) {
   4597      nsHtml5StackNode* newNode = new nsHtml5StackNode(-1);
   4598      newNode->setValues(node->getFlags(), node->ns, node->name, node->node,
   4599                         node->popName, node->attributes->cloneAttributes(),
   4600                         node->getHtmlCreator());
   4601      listCopy[i] = newNode;
   4602    } else {
   4603      listCopy[i] = nullptr;
   4604    }
   4605  }
   4606  jArray<nsHtml5StackNode*, int32_t> stackCopy =
   4607      jArray<nsHtml5StackNode*, int32_t>::newJArray(currentPtr + 1);
   4608  for (int32_t i = 0; i < stackCopy.length; i++) {
   4609    nsHtml5StackNode* node = stack[i];
   4610    int32_t listIndex = findInListOfActiveFormattingElements(node);
   4611    if (listIndex == -1) {
   4612      nsHtml5StackNode* newNode = new nsHtml5StackNode(-1);
   4613      newNode->setValues(node->getFlags(), node->ns, node->name, node->node,
   4614                         node->popName, nullptr, node->getHtmlCreator());
   4615      stackCopy[i] = newNode;
   4616    } else {
   4617      stackCopy[i] = listCopy[listIndex];
   4618      stackCopy[i]->retain();
   4619    }
   4620  }
   4621  jArray<int32_t, int32_t> templateModeStackCopy =
   4622      jArray<int32_t, int32_t>::newJArray(templateModePtr + 1);
   4623  nsHtml5ArrayCopy::arraycopy(templateModeStack, templateModeStackCopy,
   4624                              templateModeStackCopy.length);
   4625  return new nsHtml5StateSnapshot(stackCopy, listCopy, templateModeStackCopy,
   4626                                  formPointer, headPointer, mode, originalMode,
   4627                                  framesetOk, needToDropLF, quirks);
   4628 }
   4629 
   4630 bool nsHtml5TreeBuilder::snapshotMatches(nsAHtml5TreeBuilderState* snapshot) {
   4631  jArray<nsHtml5StackNode*, int32_t> stackCopy = snapshot->getStack();
   4632  int32_t stackLen = snapshot->getStackLength();
   4633  jArray<nsHtml5StackNode*, int32_t> listCopy =
   4634      snapshot->getListOfActiveFormattingElements();
   4635  int32_t listLen = snapshot->getListOfActiveFormattingElementsLength();
   4636  jArray<int32_t, int32_t> templateModeStackCopy =
   4637      snapshot->getTemplateModeStack();
   4638  int32_t templateModeStackLen = snapshot->getTemplateModeStackLength();
   4639  if (stackLen != currentPtr + 1 || listLen != listPtr + 1 ||
   4640      templateModeStackLen != templateModePtr + 1 ||
   4641      formPointer != snapshot->getFormPointer() ||
   4642      headPointer != snapshot->getHeadPointer() ||
   4643      mode != snapshot->getMode() ||
   4644      originalMode != snapshot->getOriginalMode() ||
   4645      framesetOk != snapshot->isFramesetOk() ||
   4646      needToDropLF != snapshot->isNeedToDropLF() ||
   4647      quirks != snapshot->isQuirks()) {
   4648    return false;
   4649  }
   4650  for (int32_t i = listLen - 1; i >= 0; i--) {
   4651    if (!listCopy[i] && !listOfActiveFormattingElements[i]) {
   4652      continue;
   4653    } else if (!listCopy[i] || !listOfActiveFormattingElements[i]) {
   4654      return false;
   4655    }
   4656    if (listCopy[i]->node != listOfActiveFormattingElements[i]->node) {
   4657      return false;
   4658    }
   4659  }
   4660  for (int32_t i = stackLen - 1; i >= 0; i--) {
   4661    if (stackCopy[i]->node != stack[i]->node) {
   4662      return false;
   4663    }
   4664  }
   4665  for (int32_t i = templateModeStackLen - 1; i >= 0; i--) {
   4666    if (templateModeStackCopy[i] != templateModeStack[i]) {
   4667      return false;
   4668    }
   4669  }
   4670  return true;
   4671 }
   4672 
   4673 void nsHtml5TreeBuilder::loadState(nsAHtml5TreeBuilderState* snapshot) {
   4674  mCurrentHtmlScriptCannotDocumentWriteOrBlock = false;
   4675  jArray<nsHtml5StackNode*, int32_t> stackCopy = snapshot->getStack();
   4676  int32_t stackLen = snapshot->getStackLength();
   4677  jArray<nsHtml5StackNode*, int32_t> listCopy =
   4678      snapshot->getListOfActiveFormattingElements();
   4679  int32_t listLen = snapshot->getListOfActiveFormattingElementsLength();
   4680  jArray<int32_t, int32_t> templateModeStackCopy =
   4681      snapshot->getTemplateModeStack();
   4682  int32_t templateModeStackLen = snapshot->getTemplateModeStackLength();
   4683  for (int32_t i = 0; i <= listPtr; i++) {
   4684    if (listOfActiveFormattingElements[i]) {
   4685      listOfActiveFormattingElements[i]->release(this);
   4686    }
   4687  }
   4688  if (listOfActiveFormattingElements.length < listLen) {
   4689    listOfActiveFormattingElements =
   4690        jArray<nsHtml5StackNode*, int32_t>::newJArray(listLen);
   4691  }
   4692  listPtr = listLen - 1;
   4693  for (int32_t i = 0; i <= currentPtr; i++) {
   4694    stack[i]->release(this);
   4695  }
   4696  if (stack.length < stackLen) {
   4697    stack = jArray<nsHtml5StackNode*, int32_t>::newJArray(stackLen);
   4698  }
   4699  currentPtr = stackLen - 1;
   4700  if (templateModeStack.length < templateModeStackLen) {
   4701    templateModeStack =
   4702        jArray<int32_t, int32_t>::newJArray(templateModeStackLen);
   4703  }
   4704  templateModePtr = templateModeStackLen - 1;
   4705  for (int32_t i = 0; i < listLen; i++) {
   4706    nsHtml5StackNode* node = listCopy[i];
   4707    if (node) {
   4708      nsHtml5StackNode* newNode = createStackNode(
   4709          node->getFlags(), node->ns, node->name, node->node, node->popName,
   4710          node->attributes->cloneAttributes(), node->getHtmlCreator());
   4711      listOfActiveFormattingElements[i] = newNode;
   4712    } else {
   4713      listOfActiveFormattingElements[i] = nullptr;
   4714    }
   4715  }
   4716  for (int32_t i = 0; i < stackLen; i++) {
   4717    nsHtml5StackNode* node = stackCopy[i];
   4718    int32_t listIndex = findInArray(node, listCopy);
   4719    if (listIndex == -1) {
   4720      nsHtml5StackNode* newNode =
   4721          createStackNode(node->getFlags(), node->ns, node->name, node->node,
   4722                          node->popName, nullptr, node->getHtmlCreator());
   4723      stack[i] = newNode;
   4724    } else {
   4725      stack[i] = listOfActiveFormattingElements[listIndex];
   4726      stack[i]->retain();
   4727    }
   4728  }
   4729  nsHtml5ArrayCopy::arraycopy(templateModeStackCopy, templateModeStack,
   4730                              templateModeStackLen);
   4731  formPointer = snapshot->getFormPointer();
   4732  headPointer = snapshot->getHeadPointer();
   4733  mode = snapshot->getMode();
   4734  originalMode = snapshot->getOriginalMode();
   4735  framesetOk = snapshot->isFramesetOk();
   4736  needToDropLF = snapshot->isNeedToDropLF();
   4737  quirks = snapshot->isQuirks();
   4738 }
   4739 
   4740 int32_t nsHtml5TreeBuilder::findInArray(
   4741    nsHtml5StackNode* node, jArray<nsHtml5StackNode*, int32_t> arr) {
   4742  for (int32_t i = listPtr; i >= 0; i--) {
   4743    if (node == arr[i]) {
   4744      return i;
   4745    }
   4746  }
   4747  return -1;
   4748 }
   4749 
   4750 nsIContentHandle* nsHtml5TreeBuilder::nodeFromStackWithBlinkCompat(
   4751    int32_t stackPos) {
   4752  if (stackPos > 511) {
   4753    errDeepTree();
   4754    return stack[511]->node;
   4755  }
   4756  return stack[stackPos]->node;
   4757 }
   4758 
   4759 nsIContentHandle* nsHtml5TreeBuilder::getFormPointer() { return formPointer; }
   4760 
   4761 nsIContentHandle* nsHtml5TreeBuilder::getHeadPointer() { return headPointer; }
   4762 
   4763 jArray<nsHtml5StackNode*, int32_t>
   4764 nsHtml5TreeBuilder::getListOfActiveFormattingElements() {
   4765  return listOfActiveFormattingElements;
   4766 }
   4767 
   4768 jArray<nsHtml5StackNode*, int32_t> nsHtml5TreeBuilder::getStack() {
   4769  return stack;
   4770 }
   4771 
   4772 jArray<int32_t, int32_t> nsHtml5TreeBuilder::getTemplateModeStack() {
   4773  return templateModeStack;
   4774 }
   4775 
   4776 int32_t nsHtml5TreeBuilder::getMode() { return mode; }
   4777 
   4778 int32_t nsHtml5TreeBuilder::getOriginalMode() { return originalMode; }
   4779 
   4780 bool nsHtml5TreeBuilder::isFramesetOk() { return framesetOk; }
   4781 
   4782 bool nsHtml5TreeBuilder::isNeedToDropLF() { return needToDropLF; }
   4783 
   4784 bool nsHtml5TreeBuilder::isQuirks() { return quirks; }
   4785 
   4786 int32_t nsHtml5TreeBuilder::getListOfActiveFormattingElementsLength() {
   4787  return listPtr + 1;
   4788 }
   4789 
   4790 int32_t nsHtml5TreeBuilder::getStackLength() { return currentPtr + 1; }
   4791 
   4792 int32_t nsHtml5TreeBuilder::getTemplateModeStackLength() {
   4793  return templateModePtr + 1;
   4794 }
   4795 
   4796 void nsHtml5TreeBuilder::initializeStatics() {}
   4797 
   4798 void nsHtml5TreeBuilder::releaseStatics() {}
   4799 
   4800 #include "nsHtml5TreeBuilderCppSupplement.h"