Coverage Report

Created: 2018-09-25 14:53

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