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"