1 /*
2 * Copyright (c) 2005-2007 Henri Sivonen
3 * Copyright (c) 2007-2015 Mozilla Foundation
4 * Portions of comments Copyright 2004-2010 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 Tokenizer.java instead and regenerate.
29 */
30
31 #define nsHtml5Tokenizer_cpp__
32
33 #include "nsAtom.h"
34 #include "nsHtml5AtomTable.h"
35 #include "nsHtml5String.h"
36 #include "nsIContent.h"
37 #include "nsTraceRefcnt.h"
38 #include "jArray.h"
39 #include "nsHtml5DocumentMode.h"
40 #include "nsHtml5ArrayCopy.h"
41 #include "nsHtml5NamedCharacters.h"
42 #include "nsHtml5NamedCharactersAccel.h"
43 #include "nsGkAtoms.h"
44 #include "nsAHtml5TreeBuilderState.h"
45 #include "nsHtml5Macros.h"
46 #include "nsHtml5Highlighter.h"
47 #include "nsHtml5TokenizerLoopPolicies.h"
48
49 #include "nsHtml5AttributeName.h"
50 #include "nsHtml5ElementName.h"
51 #include "nsHtml5TreeBuilder.h"
52 #include "nsHtml5MetaScanner.h"
53 #include "nsHtml5StackNode.h"
54 #include "nsHtml5UTF16Buffer.h"
55 #include "nsHtml5StateSnapshot.h"
56 #include "nsHtml5Portability.h"
57
58 #include "nsHtml5Tokenizer.h"
59
60 char16_t nsHtml5Tokenizer::LT_GT[] = {'<', '>'};
61 char16_t nsHtml5Tokenizer::LT_SOLIDUS[] = {'<', '/'};
62 char16_t nsHtml5Tokenizer::RSQB_RSQB[] = {']', ']'};
63 char16_t nsHtml5Tokenizer::REPLACEMENT_CHARACTER[] = {0xfffd};
64 char16_t nsHtml5Tokenizer::LF[] = {'\n'};
65 char16_t nsHtml5Tokenizer::CDATA_LSQB[] = {'C', 'D', 'A', 'T', 'A', '['};
66 char16_t nsHtml5Tokenizer::OCTYPE[] = {'o', 'c', 't', 'y', 'p', 'e'};
67 char16_t nsHtml5Tokenizer::UBLIC[] = {'u', 'b', 'l', 'i', 'c'};
68 char16_t nsHtml5Tokenizer::YSTEM[] = {'y', 's', 't', 'e', 'm'};
69 static char16_t const TITLE_ARR_DATA[] = {'t', 'i', 't', 'l', 'e'};
70 staticJArray<char16_t, int32_t> nsHtml5Tokenizer::TITLE_ARR = {
71 TITLE_ARR_DATA, MOZ_ARRAY_LENGTH(TITLE_ARR_DATA)};
72 static char16_t const SCRIPT_ARR_DATA[] = {'s', 'c', 'r', 'i', 'p', 't'};
73 staticJArray<char16_t, int32_t> nsHtml5Tokenizer::SCRIPT_ARR = {
74 SCRIPT_ARR_DATA, MOZ_ARRAY_LENGTH(SCRIPT_ARR_DATA)};
75 static char16_t const STYLE_ARR_DATA[] = {'s', 't', 'y', 'l', 'e'};
76 staticJArray<char16_t, int32_t> nsHtml5Tokenizer::STYLE_ARR = {
77 STYLE_ARR_DATA, MOZ_ARRAY_LENGTH(STYLE_ARR_DATA)};
78 static char16_t const PLAINTEXT_ARR_DATA[] = {'p', 'l', 'a', 'i', 'n',
79 't', 'e', 'x', 't'};
80 staticJArray<char16_t, int32_t> nsHtml5Tokenizer::PLAINTEXT_ARR = {
81 PLAINTEXT_ARR_DATA, MOZ_ARRAY_LENGTH(PLAINTEXT_ARR_DATA)};
82 static char16_t const XMP_ARR_DATA[] = {'x', 'm', 'p'};
83 staticJArray<char16_t, int32_t> nsHtml5Tokenizer::XMP_ARR = {
84 XMP_ARR_DATA, MOZ_ARRAY_LENGTH(XMP_ARR_DATA)};
85 static char16_t const TEXTAREA_ARR_DATA[] = {'t', 'e', 'x', 't',
86 'a', 'r', 'e', 'a'};
87 staticJArray<char16_t, int32_t> nsHtml5Tokenizer::TEXTAREA_ARR = {
88 TEXTAREA_ARR_DATA, MOZ_ARRAY_LENGTH(TEXTAREA_ARR_DATA)};
89 static char16_t const IFRAME_ARR_DATA[] = {'i', 'f', 'r', 'a', 'm', 'e'};
90 staticJArray<char16_t, int32_t> nsHtml5Tokenizer::IFRAME_ARR = {
91 IFRAME_ARR_DATA, MOZ_ARRAY_LENGTH(IFRAME_ARR_DATA)};
92 static char16_t const NOEMBED_ARR_DATA[] = {'n', 'o', 'e', 'm', 'b', 'e', 'd'};
93 staticJArray<char16_t, int32_t> nsHtml5Tokenizer::NOEMBED_ARR = {
94 NOEMBED_ARR_DATA, MOZ_ARRAY_LENGTH(NOEMBED_ARR_DATA)};
95 static char16_t const NOSCRIPT_ARR_DATA[] = {'n', 'o', 's', 'c',
96 'r', 'i', 'p', 't'};
97 staticJArray<char16_t, int32_t> nsHtml5Tokenizer::NOSCRIPT_ARR = {
98 NOSCRIPT_ARR_DATA, MOZ_ARRAY_LENGTH(NOSCRIPT_ARR_DATA)};
99 static char16_t const NOFRAMES_ARR_DATA[] = {'n', 'o', 'f', 'r',
100 'a', 'm', 'e', 's'};
101 staticJArray<char16_t, int32_t> nsHtml5Tokenizer::NOFRAMES_ARR = {
102 NOFRAMES_ARR_DATA, MOZ_ARRAY_LENGTH(NOFRAMES_ARR_DATA)};
103
nsHtml5Tokenizer(nsHtml5TreeBuilder * tokenHandler,bool viewingXmlSource)104 nsHtml5Tokenizer::nsHtml5Tokenizer(nsHtml5TreeBuilder* tokenHandler,
105 bool viewingXmlSource)
106 : tokenHandler(tokenHandler),
107 encodingDeclarationHandler(nullptr),
108 lastCR(false),
109 stateSave(0),
110 returnStateSave(0),
111 index(0),
112 forceQuirks(false),
113 additional('\0'),
114 entCol(0),
115 firstCharKey(0),
116 lo(0),
117 hi(0),
118 candidate(0),
119 charRefBufMark(0),
120 value(0),
121 seenDigits(false),
122 cstart(0),
123 strBufLen(0),
124 charRefBuf(jArray<char16_t, int32_t>::newJArray(32)),
125 charRefBufLen(0),
126 bmpChar(jArray<char16_t, int32_t>::newJArray(1)),
127 astralChar(jArray<char16_t, int32_t>::newJArray(2)),
128 endTagExpectation(nullptr),
129 endTagExpectationAsArray(nullptr),
130 endTag(false),
131 containsHyphen(false),
132 tagName(nullptr),
133 nonInternedTagName(new nsHtml5ElementName()),
134 attributeName(nullptr),
135 nonInternedAttributeName(new nsHtml5AttributeName()),
136 doctypeName(nullptr),
137 publicIdentifier(nullptr),
138 systemIdentifier(nullptr),
139 attributes(tokenHandler->HasBuilder() ? new nsHtml5HtmlAttributes(0)
140 : nullptr),
141 newAttributesEachTime(!tokenHandler->HasBuilder()),
142 shouldSuspend(false),
143 confident(false),
144 line(0),
145 attributeLine(0),
146 interner(nullptr),
147 viewingXmlSource(viewingXmlSource) {
148 MOZ_COUNT_CTOR(nsHtml5Tokenizer);
149 }
150
setInterner(nsHtml5AtomTable * interner)151 void nsHtml5Tokenizer::setInterner(nsHtml5AtomTable* interner) {
152 this->interner = interner;
153 }
154
initLocation(nsHtml5String newPublicId,nsHtml5String newSystemId)155 void nsHtml5Tokenizer::initLocation(nsHtml5String newPublicId,
156 nsHtml5String newSystemId) {
157 this->systemId = newSystemId;
158 this->publicId = newPublicId;
159 }
160
isViewingXmlSource()161 bool nsHtml5Tokenizer::isViewingXmlSource() { return viewingXmlSource; }
162
setState(int32_t specialTokenizerState)163 void nsHtml5Tokenizer::setState(int32_t specialTokenizerState) {
164 this->stateSave = specialTokenizerState;
165 this->endTagExpectation = nullptr;
166 this->endTagExpectationAsArray = nullptr;
167 }
168
setStateAndEndTagExpectation(int32_t specialTokenizerState,nsHtml5ElementName * endTagExpectation)169 void nsHtml5Tokenizer::setStateAndEndTagExpectation(
170 int32_t specialTokenizerState, nsHtml5ElementName* endTagExpectation) {
171 this->stateSave = specialTokenizerState;
172 this->endTagExpectation = endTagExpectation;
173 endTagExpectationToArray();
174 }
175
endTagExpectationToArray()176 void nsHtml5Tokenizer::endTagExpectationToArray() {
177 switch (endTagExpectation->getGroup()) {
178 case nsHtml5TreeBuilder::TITLE: {
179 endTagExpectationAsArray = TITLE_ARR;
180 return;
181 }
182 case nsHtml5TreeBuilder::SCRIPT: {
183 endTagExpectationAsArray = SCRIPT_ARR;
184 return;
185 }
186 case nsHtml5TreeBuilder::STYLE: {
187 endTagExpectationAsArray = STYLE_ARR;
188 return;
189 }
190 case nsHtml5TreeBuilder::PLAINTEXT: {
191 endTagExpectationAsArray = PLAINTEXT_ARR;
192 return;
193 }
194 case nsHtml5TreeBuilder::XMP: {
195 endTagExpectationAsArray = XMP_ARR;
196 return;
197 }
198 case nsHtml5TreeBuilder::TEXTAREA: {
199 endTagExpectationAsArray = TEXTAREA_ARR;
200 return;
201 }
202 case nsHtml5TreeBuilder::IFRAME: {
203 endTagExpectationAsArray = IFRAME_ARR;
204 return;
205 }
206 case nsHtml5TreeBuilder::NOEMBED: {
207 endTagExpectationAsArray = NOEMBED_ARR;
208 return;
209 }
210 case nsHtml5TreeBuilder::NOSCRIPT: {
211 endTagExpectationAsArray = NOSCRIPT_ARR;
212 return;
213 }
214 case nsHtml5TreeBuilder::NOFRAMES: {
215 endTagExpectationAsArray = NOFRAMES_ARR;
216 return;
217 }
218 default: {
219 MOZ_ASSERT(false, "Bad end tag expectation.");
220 return;
221 }
222 }
223 }
224
setLineNumber(int32_t line)225 void nsHtml5Tokenizer::setLineNumber(int32_t line) {
226 this->attributeLine = line;
227 this->line = line;
228 }
229
emptyAttributes()230 nsHtml5HtmlAttributes* nsHtml5Tokenizer::emptyAttributes() {
231 return nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES;
232 }
233
emitOrAppendCharRefBuf(int32_t returnState)234 void nsHtml5Tokenizer::emitOrAppendCharRefBuf(int32_t returnState) {
235 if ((returnState & DATA_AND_RCDATA_MASK)) {
236 appendCharRefBufToStrBuf();
237 } else {
238 if (charRefBufLen > 0) {
239 tokenHandler->characters(charRefBuf, 0, charRefBufLen);
240 charRefBufLen = 0;
241 }
242 }
243 }
244
strBufToString()245 nsHtml5String nsHtml5Tokenizer::strBufToString() {
246 nsHtml5String str = nsHtml5Portability::newStringFromBuffer(
247 strBuf, 0, strBufLen, tokenHandler,
248 !newAttributesEachTime &&
249 attributeName == nsHtml5AttributeName::ATTR_CLASS);
250 clearStrBufAfterUse();
251 return str;
252 }
253
strBufToDoctypeName()254 void nsHtml5Tokenizer::strBufToDoctypeName() {
255 doctypeName =
256 nsHtml5Portability::newLocalNameFromBuffer(strBuf, strBufLen, interner);
257 clearStrBufAfterUse();
258 }
259
emitStrBuf()260 void nsHtml5Tokenizer::emitStrBuf() {
261 if (strBufLen > 0) {
262 tokenHandler->characters(strBuf, 0, strBufLen);
263 clearStrBufAfterUse();
264 }
265 }
266
appendStrBuf(char16_t * buffer,int32_t offset,int32_t length)267 void nsHtml5Tokenizer::appendStrBuf(char16_t* buffer, int32_t offset,
268 int32_t length) {
269 int32_t newLen = nsHtml5Portability::checkedAdd(strBufLen, length);
270 MOZ_ASSERT(newLen <= strBuf.length, "Previous buffer length insufficient.");
271 if (MOZ_UNLIKELY(strBuf.length < newLen)) {
272 if (MOZ_UNLIKELY(!EnsureBufferSpace(length))) {
273 MOZ_CRASH("Unable to recover from buffer reallocation failure");
274 }
275 }
276 nsHtml5ArrayCopy::arraycopy(buffer, offset, strBuf, strBufLen, length);
277 strBufLen = newLen;
278 }
279
emitComment(int32_t provisionalHyphens,int32_t pos)280 void nsHtml5Tokenizer::emitComment(int32_t provisionalHyphens, int32_t pos) {
281 tokenHandler->comment(strBuf, 0, strBufLen - provisionalHyphens);
282 clearStrBufAfterUse();
283 cstart = pos + 1;
284 }
285
flushChars(char16_t * buf,int32_t pos)286 void nsHtml5Tokenizer::flushChars(char16_t* buf, int32_t pos) {
287 if (pos > cstart) {
288 tokenHandler->characters(buf, cstart, pos - cstart);
289 }
290 cstart = INT32_MAX;
291 }
292
strBufToElementNameString()293 void nsHtml5Tokenizer::strBufToElementNameString() {
294 if (containsHyphen) {
295 nsAtom* annotationName = nsHtml5ElementName::ELT_ANNOTATION_XML->getName();
296 if (nsHtml5Portability::localEqualsBuffer(annotationName, strBuf,
297 strBufLen)) {
298 tagName = nsHtml5ElementName::ELT_ANNOTATION_XML;
299 } else {
300 nonInternedTagName->setNameForNonInterned(
301 nsHtml5Portability::newLocalNameFromBuffer(strBuf, strBufLen,
302 interner),
303 true);
304 tagName = nonInternedTagName;
305 }
306 } else {
307 tagName =
308 nsHtml5ElementName::elementNameByBuffer(strBuf, strBufLen, interner);
309 if (!tagName) {
310 nonInternedTagName->setNameForNonInterned(
311 nsHtml5Portability::newLocalNameFromBuffer(strBuf, strBufLen,
312 interner),
313 false);
314 tagName = nonInternedTagName;
315 }
316 }
317 containsHyphen = false;
318 clearStrBufAfterUse();
319 }
320
emitCurrentTagToken(bool selfClosing,int32_t pos)321 int32_t nsHtml5Tokenizer::emitCurrentTagToken(bool selfClosing, int32_t pos) {
322 cstart = pos + 1;
323 maybeErrSlashInEndTag(selfClosing);
324 stateSave = nsHtml5Tokenizer::DATA;
325 nsHtml5HtmlAttributes* attrs =
326 (!attributes ? nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES : attributes);
327 if (endTag) {
328 maybeErrAttributesOnEndTag(attrs);
329 if (!viewingXmlSource) {
330 tokenHandler->endTag(tagName);
331 }
332 if (newAttributesEachTime) {
333 delete attributes;
334 attributes = nullptr;
335 }
336 } else {
337 if (viewingXmlSource) {
338 MOZ_ASSERT(newAttributesEachTime);
339 delete attributes;
340 attributes = nullptr;
341 } else {
342 tokenHandler->startTag(tagName, attrs, selfClosing);
343 }
344 }
345 tagName = nullptr;
346 if (newAttributesEachTime) {
347 attributes = nullptr;
348 } else {
349 attributes->clear(0);
350 }
351 return stateSave;
352 }
353
attributeNameComplete()354 void nsHtml5Tokenizer::attributeNameComplete() {
355 attributeName =
356 nsHtml5AttributeName::nameByBuffer(strBuf, strBufLen, interner);
357 if (!attributeName) {
358 nonInternedAttributeName->setNameForNonInterned(
359 nsHtml5Portability::newLocalNameFromBuffer(strBuf, strBufLen,
360 interner));
361 attributeName = nonInternedAttributeName;
362 }
363 clearStrBufAfterUse();
364 if (!attributes) {
365 attributes = new nsHtml5HtmlAttributes(0);
366 }
367 if (attributes->contains(attributeName)) {
368 errDuplicateAttribute();
369 attributeName = nullptr;
370 }
371 }
372
addAttributeWithoutValue()373 void nsHtml5Tokenizer::addAttributeWithoutValue() {
374 if (attributeName) {
375 attributes->addAttribute(
376 attributeName, nsHtml5Portability::newEmptyString(), attributeLine);
377 attributeName = nullptr;
378 } else {
379 clearStrBufAfterUse();
380 }
381 }
382
addAttributeWithValue()383 void nsHtml5Tokenizer::addAttributeWithValue() {
384 if (attributeName) {
385 nsHtml5String val = strBufToString();
386 if (mViewSource) {
387 mViewSource->MaybeLinkifyAttributeValue(attributeName, val);
388 }
389 attributes->addAttribute(attributeName, val, attributeLine);
390 attributeName = nullptr;
391 } else {
392 clearStrBufAfterUse();
393 }
394 }
395
start()396 void nsHtml5Tokenizer::start() {
397 initializeWithoutStarting();
398 tokenHandler->startTokenization(this);
399 }
400
tokenizeBuffer(nsHtml5UTF16Buffer * buffer)401 bool nsHtml5Tokenizer::tokenizeBuffer(nsHtml5UTF16Buffer* buffer) {
402 int32_t state = stateSave;
403 int32_t returnState = returnStateSave;
404 char16_t c = '\0';
405 shouldSuspend = false;
406 lastCR = false;
407 int32_t start = buffer->getStart();
408 int32_t end = buffer->getEnd();
409 int32_t pos = start - 1;
410 switch (state) {
411 case DATA:
412 case RCDATA:
413 case SCRIPT_DATA:
414 case PLAINTEXT:
415 case RAWTEXT:
416 case CDATA_SECTION:
417 case SCRIPT_DATA_ESCAPED:
418 case SCRIPT_DATA_ESCAPE_START:
419 case SCRIPT_DATA_ESCAPE_START_DASH:
420 case SCRIPT_DATA_ESCAPED_DASH:
421 case SCRIPT_DATA_ESCAPED_DASH_DASH:
422 case SCRIPT_DATA_DOUBLE_ESCAPE_START:
423 case SCRIPT_DATA_DOUBLE_ESCAPED:
424 case SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN:
425 case SCRIPT_DATA_DOUBLE_ESCAPED_DASH:
426 case SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH:
427 case SCRIPT_DATA_DOUBLE_ESCAPE_END: {
428 cstart = start;
429 break;
430 }
431 default: {
432 cstart = INT32_MAX;
433 break;
434 }
435 }
436 if (mViewSource) {
437 mViewSource->SetBuffer(buffer);
438 pos = stateLoop<nsHtml5ViewSourcePolicy>(state, c, pos, buffer->getBuffer(),
439 false, returnState,
440 buffer->getEnd());
441 mViewSource->DropBuffer((pos == buffer->getEnd()) ? pos : pos + 1);
442 } else {
443 pos = stateLoop<nsHtml5SilentPolicy>(state, c, pos, buffer->getBuffer(),
444 false, returnState, buffer->getEnd());
445 }
446 if (pos == end) {
447 buffer->setStart(pos);
448 } else {
449 buffer->setStart(pos + 1);
450 }
451 return lastCR;
452 }
453
454 template <class P>
stateLoop(int32_t state,char16_t c,int32_t pos,char16_t * buf,bool reconsume,int32_t returnState,int32_t endPos)455 int32_t nsHtml5Tokenizer::stateLoop(int32_t state, char16_t c, int32_t pos,
456 char16_t* buf, bool reconsume,
457 int32_t returnState, int32_t endPos) {
458 stateloop:
459 for (;;) {
460 switch (state) {
461 case DATA: {
462 for (;;) {
463 if (reconsume) {
464 reconsume = false;
465 } else {
466 if (++pos == endPos) {
467 NS_HTML5_BREAK(stateloop);
468 }
469 c = checkChar(buf, pos);
470 }
471 switch (c) {
472 case '&': {
473 flushChars(buf, pos);
474 MOZ_ASSERT(!charRefBufLen,
475 "charRefBufLen not reset after previous use!");
476 appendCharRefBuf(c);
477 setAdditionalAndRememberAmpersandLocation('\0');
478 returnState = state;
479 state =
480 P::transition(mViewSource.get(),
481 nsHtml5Tokenizer::CONSUME_CHARACTER_REFERENCE,
482 reconsume, pos);
483 NS_HTML5_CONTINUE(stateloop);
484 }
485 case '<': {
486 flushChars(buf, pos);
487 state = P::transition(mViewSource.get(),
488 nsHtml5Tokenizer::TAG_OPEN, reconsume, pos);
489 NS_HTML5_BREAK(dataloop);
490 }
491 case '\0': {
492 emitReplacementCharacter(buf, pos);
493 continue;
494 }
495 case '\r': {
496 emitCarriageReturn(buf, pos);
497 NS_HTML5_BREAK(stateloop);
498 }
499 case '\n': {
500 silentLineFeed();
501 [[fallthrough]];
502 }
503 default: {
504 continue;
505 }
506 }
507 }
508 dataloop_end:;
509 [[fallthrough]];
510 }
511 case TAG_OPEN: {
512 for (;;) {
513 if (++pos == endPos) {
514 NS_HTML5_BREAK(stateloop);
515 }
516 c = checkChar(buf, pos);
517 if (c >= 'A' && c <= 'Z') {
518 endTag = false;
519 clearStrBufBeforeUse();
520 appendStrBuf((char16_t)(c + 0x20));
521 containsHyphen = false;
522 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::TAG_NAME,
523 reconsume, pos);
524 NS_HTML5_BREAK(tagopenloop);
525 } else if (c >= 'a' && c <= 'z') {
526 endTag = false;
527 clearStrBufBeforeUse();
528 appendStrBuf(c);
529 containsHyphen = false;
530 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::TAG_NAME,
531 reconsume, pos);
532 NS_HTML5_BREAK(tagopenloop);
533 }
534 switch (c) {
535 case '!': {
536 state = P::transition(mViewSource.get(),
537 nsHtml5Tokenizer::MARKUP_DECLARATION_OPEN,
538 reconsume, pos);
539 NS_HTML5_CONTINUE(stateloop);
540 }
541 case '/': {
542 state = P::transition(mViewSource.get(),
543 nsHtml5Tokenizer::CLOSE_TAG_OPEN, reconsume,
544 pos);
545 NS_HTML5_CONTINUE(stateloop);
546 }
547 case '\?': {
548 if (viewingXmlSource) {
549 state = P::transition(mViewSource.get(),
550 nsHtml5Tokenizer::PROCESSING_INSTRUCTION,
551 reconsume, pos);
552 NS_HTML5_CONTINUE(stateloop);
553 }
554 if (P::reportErrors) {
555 errProcessingInstruction();
556 }
557 clearStrBufBeforeUse();
558 appendStrBuf(c);
559 state = P::transition(mViewSource.get(),
560 nsHtml5Tokenizer::BOGUS_COMMENT, reconsume,
561 pos);
562 NS_HTML5_CONTINUE(stateloop);
563 }
564 case '>': {
565 if (P::reportErrors) {
566 errLtGt();
567 }
568 tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 2);
569 cstart = pos + 1;
570 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
571 reconsume, pos);
572 NS_HTML5_CONTINUE(stateloop);
573 }
574 default: {
575 if (P::reportErrors) {
576 errBadCharAfterLt(c);
577 }
578 tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1);
579 cstart = pos;
580 reconsume = true;
581 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
582 reconsume, pos);
583 NS_HTML5_CONTINUE(stateloop);
584 }
585 }
586 }
587 tagopenloop_end:;
588 [[fallthrough]];
589 }
590 case TAG_NAME: {
591 for (;;) {
592 if (++pos == endPos) {
593 NS_HTML5_BREAK(stateloop);
594 }
595 c = checkChar(buf, pos);
596 switch (c) {
597 case '\r': {
598 silentCarriageReturn();
599 strBufToElementNameString();
600 state = P::transition(mViewSource.get(),
601 nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME,
602 reconsume, pos);
603 NS_HTML5_BREAK(stateloop);
604 }
605 case '\n': {
606 silentLineFeed();
607 [[fallthrough]];
608 }
609 case ' ':
610 case '\t':
611 case '\f': {
612 strBufToElementNameString();
613 state = P::transition(mViewSource.get(),
614 nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME,
615 reconsume, pos);
616 NS_HTML5_BREAK(tagnameloop);
617 }
618 case '/': {
619 strBufToElementNameString();
620 state = P::transition(mViewSource.get(),
621 nsHtml5Tokenizer::SELF_CLOSING_START_TAG,
622 reconsume, pos);
623 NS_HTML5_CONTINUE(stateloop);
624 }
625 case '>': {
626 strBufToElementNameString();
627 state = P::transition(mViewSource.get(),
628 emitCurrentTagToken(false, pos), reconsume,
629 pos);
630 if (shouldSuspend) {
631 NS_HTML5_BREAK(stateloop);
632 }
633 NS_HTML5_CONTINUE(stateloop);
634 }
635 case '\0': {
636 c = 0xfffd;
637 [[fallthrough]];
638 }
639 default: {
640 if (c >= 'A' && c <= 'Z') {
641 c += 0x20;
642 } else if (c == '-') {
643 containsHyphen = true;
644 }
645 appendStrBuf(c);
646 continue;
647 }
648 }
649 }
650 tagnameloop_end:;
651 [[fallthrough]];
652 }
653 case BEFORE_ATTRIBUTE_NAME: {
654 for (;;) {
655 if (reconsume) {
656 reconsume = false;
657 } else {
658 if (++pos == endPos) {
659 NS_HTML5_BREAK(stateloop);
660 }
661 c = checkChar(buf, pos);
662 }
663 switch (c) {
664 case '\r': {
665 silentCarriageReturn();
666 NS_HTML5_BREAK(stateloop);
667 }
668 case '\n': {
669 silentLineFeed();
670 [[fallthrough]];
671 }
672 case ' ':
673 case '\t':
674 case '\f': {
675 continue;
676 }
677 case '/': {
678 state = P::transition(mViewSource.get(),
679 nsHtml5Tokenizer::SELF_CLOSING_START_TAG,
680 reconsume, pos);
681 NS_HTML5_CONTINUE(stateloop);
682 }
683 case '>': {
684 state = P::transition(mViewSource.get(),
685 emitCurrentTagToken(false, pos), reconsume,
686 pos);
687 if (shouldSuspend) {
688 NS_HTML5_BREAK(stateloop);
689 }
690 NS_HTML5_CONTINUE(stateloop);
691 }
692 case '\0': {
693 c = 0xfffd;
694 [[fallthrough]];
695 }
696 case '\"':
697 case '\'':
698 case '<':
699 case '=': {
700 if (P::reportErrors) {
701 errBadCharBeforeAttributeNameOrNull(c);
702 }
703 [[fallthrough]];
704 }
705 default: {
706 if (c >= 'A' && c <= 'Z') {
707 c += 0x20;
708 }
709 attributeLine = line;
710 clearStrBufBeforeUse();
711 appendStrBuf(c);
712 state = P::transition(mViewSource.get(),
713 nsHtml5Tokenizer::ATTRIBUTE_NAME, reconsume,
714 pos);
715 NS_HTML5_BREAK(beforeattributenameloop);
716 }
717 }
718 }
719 beforeattributenameloop_end:;
720 [[fallthrough]];
721 }
722 case ATTRIBUTE_NAME: {
723 for (;;) {
724 if (++pos == endPos) {
725 NS_HTML5_BREAK(stateloop);
726 }
727 c = checkChar(buf, pos);
728 switch (c) {
729 case '\r': {
730 silentCarriageReturn();
731 attributeNameComplete();
732 state = P::transition(mViewSource.get(),
733 nsHtml5Tokenizer::AFTER_ATTRIBUTE_NAME,
734 reconsume, pos);
735 NS_HTML5_BREAK(stateloop);
736 }
737 case '\n': {
738 silentLineFeed();
739 [[fallthrough]];
740 }
741 case ' ':
742 case '\t':
743 case '\f': {
744 attributeNameComplete();
745 state = P::transition(mViewSource.get(),
746 nsHtml5Tokenizer::AFTER_ATTRIBUTE_NAME,
747 reconsume, pos);
748 NS_HTML5_CONTINUE(stateloop);
749 }
750 case '/': {
751 attributeNameComplete();
752 addAttributeWithoutValue();
753 state = P::transition(mViewSource.get(),
754 nsHtml5Tokenizer::SELF_CLOSING_START_TAG,
755 reconsume, pos);
756 NS_HTML5_CONTINUE(stateloop);
757 }
758 case '=': {
759 attributeNameComplete();
760 state = P::transition(mViewSource.get(),
761 nsHtml5Tokenizer::BEFORE_ATTRIBUTE_VALUE,
762 reconsume, pos);
763 NS_HTML5_BREAK(attributenameloop);
764 }
765 case '>': {
766 attributeNameComplete();
767 addAttributeWithoutValue();
768 state = P::transition(mViewSource.get(),
769 emitCurrentTagToken(false, pos), reconsume,
770 pos);
771 if (shouldSuspend) {
772 NS_HTML5_BREAK(stateloop);
773 }
774 NS_HTML5_CONTINUE(stateloop);
775 }
776 case '\0': {
777 c = 0xfffd;
778 [[fallthrough]];
779 }
780 case '\"':
781 case '\'':
782 case '<': {
783 if (P::reportErrors) {
784 errQuoteOrLtInAttributeNameOrNull(c);
785 }
786 [[fallthrough]];
787 }
788 default: {
789 if (c >= 'A' && c <= 'Z') {
790 c += 0x20;
791 }
792 appendStrBuf(c);
793 continue;
794 }
795 }
796 }
797 attributenameloop_end:;
798 [[fallthrough]];
799 }
800 case BEFORE_ATTRIBUTE_VALUE: {
801 for (;;) {
802 if (++pos == endPos) {
803 NS_HTML5_BREAK(stateloop);
804 }
805 c = checkChar(buf, pos);
806 switch (c) {
807 case '\r': {
808 silentCarriageReturn();
809 NS_HTML5_BREAK(stateloop);
810 }
811 case '\n': {
812 silentLineFeed();
813 [[fallthrough]];
814 }
815 case ' ':
816 case '\t':
817 case '\f': {
818 continue;
819 }
820 case '\"': {
821 attributeLine = line;
822 clearStrBufBeforeUse();
823 state =
824 P::transition(mViewSource.get(),
825 nsHtml5Tokenizer::ATTRIBUTE_VALUE_DOUBLE_QUOTED,
826 reconsume, pos);
827 NS_HTML5_BREAK(beforeattributevalueloop);
828 }
829 case '&': {
830 attributeLine = line;
831 clearStrBufBeforeUse();
832 reconsume = true;
833 state = P::transition(mViewSource.get(),
834 nsHtml5Tokenizer::ATTRIBUTE_VALUE_UNQUOTED,
835 reconsume, pos);
836
837 NS_HTML5_CONTINUE(stateloop);
838 }
839 case '\'': {
840 attributeLine = line;
841 clearStrBufBeforeUse();
842 state =
843 P::transition(mViewSource.get(),
844 nsHtml5Tokenizer::ATTRIBUTE_VALUE_SINGLE_QUOTED,
845 reconsume, pos);
846 NS_HTML5_CONTINUE(stateloop);
847 }
848 case '>': {
849 if (P::reportErrors) {
850 errAttributeValueMissing();
851 }
852 addAttributeWithoutValue();
853 state = P::transition(mViewSource.get(),
854 emitCurrentTagToken(false, pos), reconsume,
855 pos);
856 if (shouldSuspend) {
857 NS_HTML5_BREAK(stateloop);
858 }
859 NS_HTML5_CONTINUE(stateloop);
860 }
861 case '\0': {
862 c = 0xfffd;
863 [[fallthrough]];
864 }
865 case '<':
866 case '=':
867 case '`': {
868 if (P::reportErrors) {
869 errLtOrEqualsOrGraveInUnquotedAttributeOrNull(c);
870 }
871 [[fallthrough]];
872 }
873 default: {
874 attributeLine = line;
875 clearStrBufBeforeUse();
876 appendStrBuf(c);
877 state = P::transition(mViewSource.get(),
878 nsHtml5Tokenizer::ATTRIBUTE_VALUE_UNQUOTED,
879 reconsume, pos);
880
881 NS_HTML5_CONTINUE(stateloop);
882 }
883 }
884 }
885 beforeattributevalueloop_end:;
886 [[fallthrough]];
887 }
888 case ATTRIBUTE_VALUE_DOUBLE_QUOTED: {
889 for (;;) {
890 if (reconsume) {
891 reconsume = false;
892 } else {
893 if (++pos == endPos) {
894 NS_HTML5_BREAK(stateloop);
895 }
896 c = checkChar(buf, pos);
897 }
898 switch (c) {
899 case '\"': {
900 addAttributeWithValue();
901 state =
902 P::transition(mViewSource.get(),
903 nsHtml5Tokenizer::AFTER_ATTRIBUTE_VALUE_QUOTED,
904 reconsume, pos);
905 NS_HTML5_BREAK(attributevaluedoublequotedloop);
906 }
907 case '&': {
908 MOZ_ASSERT(!charRefBufLen,
909 "charRefBufLen not reset after previous use!");
910 appendCharRefBuf(c);
911 setAdditionalAndRememberAmpersandLocation('\"');
912 returnState = state;
913 state =
914 P::transition(mViewSource.get(),
915 nsHtml5Tokenizer::CONSUME_CHARACTER_REFERENCE,
916 reconsume, pos);
917 NS_HTML5_CONTINUE(stateloop);
918 }
919 case '\r': {
920 appendStrBufCarriageReturn();
921 NS_HTML5_BREAK(stateloop);
922 }
923 case '\n': {
924 appendStrBufLineFeed();
925 continue;
926 }
927 case '\0': {
928 c = 0xfffd;
929 [[fallthrough]];
930 }
931 default: {
932 appendStrBuf(c);
933 continue;
934 }
935 }
936 }
937 attributevaluedoublequotedloop_end:;
938 [[fallthrough]];
939 }
940 case AFTER_ATTRIBUTE_VALUE_QUOTED: {
941 for (;;) {
942 if (++pos == endPos) {
943 NS_HTML5_BREAK(stateloop);
944 }
945 c = checkChar(buf, pos);
946 switch (c) {
947 case '\r': {
948 silentCarriageReturn();
949 state = P::transition(mViewSource.get(),
950 nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME,
951 reconsume, pos);
952 NS_HTML5_BREAK(stateloop);
953 }
954 case '\n': {
955 silentLineFeed();
956 [[fallthrough]];
957 }
958 case ' ':
959 case '\t':
960 case '\f': {
961 state = P::transition(mViewSource.get(),
962 nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME,
963 reconsume, pos);
964 NS_HTML5_CONTINUE(stateloop);
965 }
966 case '/': {
967 state = P::transition(mViewSource.get(),
968 nsHtml5Tokenizer::SELF_CLOSING_START_TAG,
969 reconsume, pos);
970 NS_HTML5_BREAK(afterattributevaluequotedloop);
971 }
972 case '>': {
973 state = P::transition(mViewSource.get(),
974 emitCurrentTagToken(false, pos), reconsume,
975 pos);
976 if (shouldSuspend) {
977 NS_HTML5_BREAK(stateloop);
978 }
979 NS_HTML5_CONTINUE(stateloop);
980 }
981 default: {
982 if (P::reportErrors) {
983 errNoSpaceBetweenAttributes();
984 }
985 reconsume = true;
986 state = P::transition(mViewSource.get(),
987 nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME,
988 reconsume, pos);
989 NS_HTML5_CONTINUE(stateloop);
990 }
991 }
992 }
993 afterattributevaluequotedloop_end:;
994 [[fallthrough]];
995 }
996 case SELF_CLOSING_START_TAG: {
997 if (++pos == endPos) {
998 NS_HTML5_BREAK(stateloop);
999 }
1000 c = checkChar(buf, pos);
1001 switch (c) {
1002 case '>': {
1003 state =
1004 P::transition(mViewSource.get(), emitCurrentTagToken(true, pos),
1005 reconsume, pos);
1006 if (shouldSuspend) {
1007 NS_HTML5_BREAK(stateloop);
1008 }
1009 NS_HTML5_CONTINUE(stateloop);
1010 }
1011 default: {
1012 if (P::reportErrors) {
1013 errSlashNotFollowedByGt();
1014 }
1015 reconsume = true;
1016 state = P::transition(mViewSource.get(),
1017 nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME,
1018 reconsume, pos);
1019 NS_HTML5_CONTINUE(stateloop);
1020 }
1021 }
1022 }
1023 case ATTRIBUTE_VALUE_UNQUOTED: {
1024 for (;;) {
1025 if (reconsume) {
1026 reconsume = false;
1027 } else {
1028 if (++pos == endPos) {
1029 NS_HTML5_BREAK(stateloop);
1030 }
1031 c = checkChar(buf, pos);
1032 }
1033 switch (c) {
1034 case '\r': {
1035 silentCarriageReturn();
1036 addAttributeWithValue();
1037 state = P::transition(mViewSource.get(),
1038 nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME,
1039 reconsume, pos);
1040 NS_HTML5_BREAK(stateloop);
1041 }
1042 case '\n': {
1043 silentLineFeed();
1044 [[fallthrough]];
1045 }
1046 case ' ':
1047 case '\t':
1048 case '\f': {
1049 addAttributeWithValue();
1050 state = P::transition(mViewSource.get(),
1051 nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME,
1052 reconsume, pos);
1053 NS_HTML5_CONTINUE(stateloop);
1054 }
1055 case '&': {
1056 MOZ_ASSERT(!charRefBufLen,
1057 "charRefBufLen not reset after previous use!");
1058 appendCharRefBuf(c);
1059 setAdditionalAndRememberAmpersandLocation('>');
1060 returnState = state;
1061 state =
1062 P::transition(mViewSource.get(),
1063 nsHtml5Tokenizer::CONSUME_CHARACTER_REFERENCE,
1064 reconsume, pos);
1065 NS_HTML5_CONTINUE(stateloop);
1066 }
1067 case '>': {
1068 addAttributeWithValue();
1069 state = P::transition(mViewSource.get(),
1070 emitCurrentTagToken(false, pos), reconsume,
1071 pos);
1072 if (shouldSuspend) {
1073 NS_HTML5_BREAK(stateloop);
1074 }
1075 NS_HTML5_CONTINUE(stateloop);
1076 }
1077 case '\0': {
1078 c = 0xfffd;
1079 [[fallthrough]];
1080 }
1081 case '<':
1082 case '\"':
1083 case '\'':
1084 case '=':
1085 case '`': {
1086 if (P::reportErrors) {
1087 errUnquotedAttributeValOrNull(c);
1088 }
1089 [[fallthrough]];
1090 }
1091 default: {
1092 appendStrBuf(c);
1093 continue;
1094 }
1095 }
1096 }
1097 }
1098 case AFTER_ATTRIBUTE_NAME: {
1099 for (;;) {
1100 if (++pos == endPos) {
1101 NS_HTML5_BREAK(stateloop);
1102 }
1103 c = checkChar(buf, pos);
1104 switch (c) {
1105 case '\r': {
1106 silentCarriageReturn();
1107 NS_HTML5_BREAK(stateloop);
1108 }
1109 case '\n': {
1110 silentLineFeed();
1111 [[fallthrough]];
1112 }
1113 case ' ':
1114 case '\t':
1115 case '\f': {
1116 continue;
1117 }
1118 case '/': {
1119 addAttributeWithoutValue();
1120 state = P::transition(mViewSource.get(),
1121 nsHtml5Tokenizer::SELF_CLOSING_START_TAG,
1122 reconsume, pos);
1123 NS_HTML5_CONTINUE(stateloop);
1124 }
1125 case '=': {
1126 state = P::transition(mViewSource.get(),
1127 nsHtml5Tokenizer::BEFORE_ATTRIBUTE_VALUE,
1128 reconsume, pos);
1129 NS_HTML5_CONTINUE(stateloop);
1130 }
1131 case '>': {
1132 addAttributeWithoutValue();
1133 state = P::transition(mViewSource.get(),
1134 emitCurrentTagToken(false, pos), reconsume,
1135 pos);
1136 if (shouldSuspend) {
1137 NS_HTML5_BREAK(stateloop);
1138 }
1139 NS_HTML5_CONTINUE(stateloop);
1140 }
1141 case '\0': {
1142 c = 0xfffd;
1143 [[fallthrough]];
1144 }
1145 case '\"':
1146 case '\'':
1147 case '<': {
1148 if (P::reportErrors) {
1149 errQuoteOrLtInAttributeNameOrNull(c);
1150 }
1151 [[fallthrough]];
1152 }
1153 default: {
1154 addAttributeWithoutValue();
1155 if (c >= 'A' && c <= 'Z') {
1156 c += 0x20;
1157 }
1158 clearStrBufBeforeUse();
1159 appendStrBuf(c);
1160 state = P::transition(mViewSource.get(),
1161 nsHtml5Tokenizer::ATTRIBUTE_NAME, reconsume,
1162 pos);
1163 NS_HTML5_CONTINUE(stateloop);
1164 }
1165 }
1166 }
1167 }
1168 case MARKUP_DECLARATION_OPEN: {
1169 for (;;) {
1170 if (++pos == endPos) {
1171 NS_HTML5_BREAK(stateloop);
1172 }
1173 c = checkChar(buf, pos);
1174 switch (c) {
1175 case '-': {
1176 clearStrBufBeforeUse();
1177 appendStrBuf(c);
1178 state = P::transition(mViewSource.get(),
1179 nsHtml5Tokenizer::MARKUP_DECLARATION_HYPHEN,
1180 reconsume, pos);
1181 NS_HTML5_BREAK(markupdeclarationopenloop);
1182 }
1183 case 'd':
1184 case 'D': {
1185 clearStrBufBeforeUse();
1186 appendStrBuf(c);
1187 index = 0;
1188 state = P::transition(mViewSource.get(),
1189 nsHtml5Tokenizer::MARKUP_DECLARATION_OCTYPE,
1190 reconsume, pos);
1191 NS_HTML5_CONTINUE(stateloop);
1192 }
1193 case '[': {
1194 if (tokenHandler->cdataSectionAllowed()) {
1195 clearStrBufBeforeUse();
1196 appendStrBuf(c);
1197 index = 0;
1198 state = P::transition(mViewSource.get(),
1199 nsHtml5Tokenizer::CDATA_START, reconsume,
1200 pos);
1201 NS_HTML5_CONTINUE(stateloop);
1202 }
1203 [[fallthrough]];
1204 }
1205 default: {
1206 if (P::reportErrors) {
1207 errBogusComment();
1208 }
1209 clearStrBufBeforeUse();
1210 reconsume = true;
1211 state = P::transition(mViewSource.get(),
1212 nsHtml5Tokenizer::BOGUS_COMMENT, reconsume,
1213 pos);
1214 NS_HTML5_CONTINUE(stateloop);
1215 }
1216 }
1217 }
1218 markupdeclarationopenloop_end:;
1219 [[fallthrough]];
1220 }
1221 case MARKUP_DECLARATION_HYPHEN: {
1222 for (;;) {
1223 if (++pos == endPos) {
1224 NS_HTML5_BREAK(stateloop);
1225 }
1226 c = checkChar(buf, pos);
1227 switch (c) {
1228 case '-': {
1229 clearStrBufAfterOneHyphen();
1230 state = P::transition(mViewSource.get(),
1231 nsHtml5Tokenizer::COMMENT_START, reconsume,
1232 pos);
1233 NS_HTML5_BREAK(markupdeclarationhyphenloop);
1234 }
1235 default: {
1236 if (P::reportErrors) {
1237 errBogusComment();
1238 }
1239 reconsume = true;
1240 state = P::transition(mViewSource.get(),
1241 nsHtml5Tokenizer::BOGUS_COMMENT, reconsume,
1242 pos);
1243 NS_HTML5_CONTINUE(stateloop);
1244 }
1245 }
1246 }
1247 markupdeclarationhyphenloop_end:;
1248 [[fallthrough]];
1249 }
1250 case COMMENT_START: {
1251 for (;;) {
1252 if (++pos == endPos) {
1253 NS_HTML5_BREAK(stateloop);
1254 }
1255 c = checkChar(buf, pos);
1256 switch (c) {
1257 case '-': {
1258 appendStrBuf(c);
1259 state = P::transition(mViewSource.get(),
1260 nsHtml5Tokenizer::COMMENT_START_DASH,
1261 reconsume, pos);
1262 NS_HTML5_CONTINUE(stateloop);
1263 }
1264 case '>': {
1265 if (P::reportErrors) {
1266 errPrematureEndOfComment();
1267 }
1268 emitComment(0, pos);
1269 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
1270 reconsume, pos);
1271 NS_HTML5_CONTINUE(stateloop);
1272 }
1273 case '\r': {
1274 appendStrBufCarriageReturn();
1275 state = P::transition(mViewSource.get(),
1276 nsHtml5Tokenizer::COMMENT, reconsume, pos);
1277 NS_HTML5_BREAK(stateloop);
1278 }
1279 case '\n': {
1280 appendStrBufLineFeed();
1281 state = P::transition(mViewSource.get(),
1282 nsHtml5Tokenizer::COMMENT, reconsume, pos);
1283 NS_HTML5_BREAK(commentstartloop);
1284 }
1285 case '\0': {
1286 c = 0xfffd;
1287 [[fallthrough]];
1288 }
1289 default: {
1290 appendStrBuf(c);
1291 state = P::transition(mViewSource.get(),
1292 nsHtml5Tokenizer::COMMENT, reconsume, pos);
1293 NS_HTML5_BREAK(commentstartloop);
1294 }
1295 }
1296 }
1297 commentstartloop_end:;
1298 [[fallthrough]];
1299 }
1300 case COMMENT: {
1301 for (;;) {
1302 if (++pos == endPos) {
1303 NS_HTML5_BREAK(stateloop);
1304 }
1305 c = checkChar(buf, pos);
1306 switch (c) {
1307 case '-': {
1308 appendStrBuf(c);
1309 state = P::transition(mViewSource.get(),
1310 nsHtml5Tokenizer::COMMENT_END_DASH,
1311 reconsume, pos);
1312 NS_HTML5_BREAK(commentloop);
1313 }
1314 case '\r': {
1315 appendStrBufCarriageReturn();
1316 NS_HTML5_BREAK(stateloop);
1317 }
1318 case '\n': {
1319 appendStrBufLineFeed();
1320 continue;
1321 }
1322 case '\0': {
1323 c = 0xfffd;
1324 [[fallthrough]];
1325 }
1326 default: {
1327 appendStrBuf(c);
1328 continue;
1329 }
1330 }
1331 }
1332 commentloop_end:;
1333 [[fallthrough]];
1334 }
1335 case COMMENT_END_DASH: {
1336 for (;;) {
1337 if (++pos == endPos) {
1338 NS_HTML5_BREAK(stateloop);
1339 }
1340 c = checkChar(buf, pos);
1341 switch (c) {
1342 case '-': {
1343 appendStrBuf(c);
1344 state =
1345 P::transition(mViewSource.get(),
1346 nsHtml5Tokenizer::COMMENT_END, reconsume, pos);
1347 NS_HTML5_BREAK(commentenddashloop);
1348 }
1349 case '\r': {
1350 appendStrBufCarriageReturn();
1351 state = P::transition(mViewSource.get(),
1352 nsHtml5Tokenizer::COMMENT, reconsume, pos);
1353 NS_HTML5_BREAK(stateloop);
1354 }
1355 case '\n': {
1356 appendStrBufLineFeed();
1357 state = P::transition(mViewSource.get(),
1358 nsHtml5Tokenizer::COMMENT, reconsume, pos);
1359 NS_HTML5_CONTINUE(stateloop);
1360 }
1361 case '\0': {
1362 c = 0xfffd;
1363 [[fallthrough]];
1364 }
1365 default: {
1366 appendStrBuf(c);
1367 state = P::transition(mViewSource.get(),
1368 nsHtml5Tokenizer::COMMENT, reconsume, pos);
1369 NS_HTML5_CONTINUE(stateloop);
1370 }
1371 }
1372 }
1373 commentenddashloop_end:;
1374 [[fallthrough]];
1375 }
1376 case COMMENT_END: {
1377 for (;;) {
1378 if (++pos == endPos) {
1379 NS_HTML5_BREAK(stateloop);
1380 }
1381 c = checkChar(buf, pos);
1382 switch (c) {
1383 case '>': {
1384 emitComment(2, pos);
1385 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
1386 reconsume, pos);
1387 NS_HTML5_CONTINUE(stateloop);
1388 }
1389 case '-': {
1390 adjustDoubleHyphenAndAppendToStrBufAndErr(c);
1391 continue;
1392 }
1393 case '\r': {
1394 adjustDoubleHyphenAndAppendToStrBufCarriageReturn();
1395 state = P::transition(mViewSource.get(),
1396 nsHtml5Tokenizer::COMMENT, reconsume, pos);
1397 NS_HTML5_BREAK(stateloop);
1398 }
1399 case '\n': {
1400 adjustDoubleHyphenAndAppendToStrBufLineFeed();
1401 state = P::transition(mViewSource.get(),
1402 nsHtml5Tokenizer::COMMENT, reconsume, pos);
1403 NS_HTML5_CONTINUE(stateloop);
1404 }
1405 case '!': {
1406 if (P::reportErrors) {
1407 errHyphenHyphenBang();
1408 }
1409 appendStrBuf(c);
1410 state = P::transition(mViewSource.get(),
1411 nsHtml5Tokenizer::COMMENT_END_BANG,
1412 reconsume, pos);
1413 NS_HTML5_CONTINUE(stateloop);
1414 }
1415 case '\0': {
1416 c = 0xfffd;
1417 [[fallthrough]];
1418 }
1419 default: {
1420 adjustDoubleHyphenAndAppendToStrBufAndErr(c);
1421 state = P::transition(mViewSource.get(),
1422 nsHtml5Tokenizer::COMMENT, reconsume, pos);
1423 NS_HTML5_CONTINUE(stateloop);
1424 }
1425 }
1426 }
1427 }
1428 case COMMENT_END_BANG: {
1429 for (;;) {
1430 if (++pos == endPos) {
1431 NS_HTML5_BREAK(stateloop);
1432 }
1433 c = checkChar(buf, pos);
1434 switch (c) {
1435 case '>': {
1436 emitComment(3, pos);
1437 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
1438 reconsume, pos);
1439 NS_HTML5_CONTINUE(stateloop);
1440 }
1441 case '-': {
1442 appendStrBuf(c);
1443 state = P::transition(mViewSource.get(),
1444 nsHtml5Tokenizer::COMMENT_END_DASH,
1445 reconsume, pos);
1446 NS_HTML5_CONTINUE(stateloop);
1447 }
1448 case '\r': {
1449 appendStrBufCarriageReturn();
1450 state = P::transition(mViewSource.get(),
1451 nsHtml5Tokenizer::COMMENT, reconsume, pos);
1452 NS_HTML5_BREAK(stateloop);
1453 }
1454 case '\n': {
1455 appendStrBufLineFeed();
1456 state = P::transition(mViewSource.get(),
1457 nsHtml5Tokenizer::COMMENT, reconsume, pos);
1458 NS_HTML5_CONTINUE(stateloop);
1459 }
1460 case '\0': {
1461 c = 0xfffd;
1462 [[fallthrough]];
1463 }
1464 default: {
1465 appendStrBuf(c);
1466 state = P::transition(mViewSource.get(),
1467 nsHtml5Tokenizer::COMMENT, reconsume, pos);
1468 NS_HTML5_CONTINUE(stateloop);
1469 }
1470 }
1471 }
1472 }
1473 case COMMENT_START_DASH: {
1474 if (++pos == endPos) {
1475 NS_HTML5_BREAK(stateloop);
1476 }
1477 c = checkChar(buf, pos);
1478 switch (c) {
1479 case '-': {
1480 appendStrBuf(c);
1481 state =
1482 P::transition(mViewSource.get(), nsHtml5Tokenizer::COMMENT_END,
1483 reconsume, pos);
1484 NS_HTML5_CONTINUE(stateloop);
1485 }
1486 case '>': {
1487 if (P::reportErrors) {
1488 errPrematureEndOfComment();
1489 }
1490 emitComment(1, pos);
1491 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
1492 reconsume, pos);
1493 NS_HTML5_CONTINUE(stateloop);
1494 }
1495 case '\r': {
1496 appendStrBufCarriageReturn();
1497 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::COMMENT,
1498 reconsume, pos);
1499 NS_HTML5_BREAK(stateloop);
1500 }
1501 case '\n': {
1502 appendStrBufLineFeed();
1503 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::COMMENT,
1504 reconsume, pos);
1505 NS_HTML5_CONTINUE(stateloop);
1506 }
1507 case '\0': {
1508 c = 0xfffd;
1509 [[fallthrough]];
1510 }
1511 default: {
1512 appendStrBuf(c);
1513 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::COMMENT,
1514 reconsume, pos);
1515 NS_HTML5_CONTINUE(stateloop);
1516 }
1517 }
1518 }
1519 case CDATA_START: {
1520 for (;;) {
1521 if (++pos == endPos) {
1522 NS_HTML5_BREAK(stateloop);
1523 }
1524 c = checkChar(buf, pos);
1525 if (index < 6) {
1526 if (c == nsHtml5Tokenizer::CDATA_LSQB[index]) {
1527 appendStrBuf(c);
1528 } else {
1529 if (P::reportErrors) {
1530 errBogusComment();
1531 }
1532 reconsume = true;
1533 state = P::transition(mViewSource.get(),
1534 nsHtml5Tokenizer::BOGUS_COMMENT, reconsume,
1535 pos);
1536 NS_HTML5_CONTINUE(stateloop);
1537 }
1538 index++;
1539 continue;
1540 } else {
1541 clearStrBufAfterUse();
1542 cstart = pos;
1543 reconsume = true;
1544 state =
1545 P::transition(mViewSource.get(),
1546 nsHtml5Tokenizer::CDATA_SECTION, reconsume, pos);
1547 break;
1548 }
1549 }
1550 [[fallthrough]];
1551 }
1552 case CDATA_SECTION: {
1553 for (;;) {
1554 if (reconsume) {
1555 reconsume = false;
1556 } else {
1557 if (++pos == endPos) {
1558 NS_HTML5_BREAK(stateloop);
1559 }
1560 c = checkChar(buf, pos);
1561 }
1562 switch (c) {
1563 case ']': {
1564 flushChars(buf, pos);
1565 state =
1566 P::transition(mViewSource.get(), nsHtml5Tokenizer::CDATA_RSQB,
1567 reconsume, pos);
1568 NS_HTML5_BREAK(cdatasectionloop);
1569 }
1570 case '\0': {
1571 emitReplacementCharacter(buf, pos);
1572 continue;
1573 }
1574 case '\r': {
1575 emitCarriageReturn(buf, pos);
1576 NS_HTML5_BREAK(stateloop);
1577 }
1578 case '\n': {
1579 silentLineFeed();
1580 [[fallthrough]];
1581 }
1582 default: {
1583 continue;
1584 }
1585 }
1586 }
1587 cdatasectionloop_end:;
1588 [[fallthrough]];
1589 }
1590 case CDATA_RSQB: {
1591 for (;;) {
1592 if (++pos == endPos) {
1593 NS_HTML5_BREAK(stateloop);
1594 }
1595 c = checkChar(buf, pos);
1596 switch (c) {
1597 case ']': {
1598 state = P::transition(mViewSource.get(),
1599 nsHtml5Tokenizer::CDATA_RSQB_RSQB,
1600 reconsume, pos);
1601 NS_HTML5_BREAK(cdatarsqb);
1602 }
1603 default: {
1604 tokenHandler->characters(nsHtml5Tokenizer::RSQB_RSQB, 0, 1);
1605 cstart = pos;
1606 reconsume = true;
1607 state = P::transition(mViewSource.get(),
1608 nsHtml5Tokenizer::CDATA_SECTION, reconsume,
1609 pos);
1610 NS_HTML5_CONTINUE(stateloop);
1611 }
1612 }
1613 }
1614 cdatarsqb_end:;
1615 [[fallthrough]];
1616 }
1617 case CDATA_RSQB_RSQB: {
1618 for (;;) {
1619 if (++pos == endPos) {
1620 NS_HTML5_BREAK(stateloop);
1621 }
1622 c = checkChar(buf, pos);
1623 switch (c) {
1624 case ']': {
1625 tokenHandler->characters(nsHtml5Tokenizer::RSQB_RSQB, 0, 1);
1626 continue;
1627 }
1628 case '>': {
1629 cstart = pos + 1;
1630 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
1631 reconsume, pos);
1632 NS_HTML5_CONTINUE(stateloop);
1633 }
1634 default: {
1635 tokenHandler->characters(nsHtml5Tokenizer::RSQB_RSQB, 0, 2);
1636 cstart = pos;
1637 reconsume = true;
1638 state = P::transition(mViewSource.get(),
1639 nsHtml5Tokenizer::CDATA_SECTION, reconsume,
1640 pos);
1641 NS_HTML5_CONTINUE(stateloop);
1642 }
1643 }
1644 }
1645 }
1646 case ATTRIBUTE_VALUE_SINGLE_QUOTED: {
1647 for (;;) {
1648 if (reconsume) {
1649 reconsume = false;
1650 } else {
1651 if (++pos == endPos) {
1652 NS_HTML5_BREAK(stateloop);
1653 }
1654 c = checkChar(buf, pos);
1655 }
1656 switch (c) {
1657 case '\'': {
1658 addAttributeWithValue();
1659 state =
1660 P::transition(mViewSource.get(),
1661 nsHtml5Tokenizer::AFTER_ATTRIBUTE_VALUE_QUOTED,
1662 reconsume, pos);
1663 NS_HTML5_CONTINUE(stateloop);
1664 }
1665 case '&': {
1666 MOZ_ASSERT(!charRefBufLen,
1667 "charRefBufLen not reset after previous use!");
1668 appendCharRefBuf(c);
1669 setAdditionalAndRememberAmpersandLocation('\'');
1670 returnState = state;
1671 state =
1672 P::transition(mViewSource.get(),
1673 nsHtml5Tokenizer::CONSUME_CHARACTER_REFERENCE,
1674 reconsume, pos);
1675 NS_HTML5_BREAK(attributevaluesinglequotedloop);
1676 }
1677 case '\r': {
1678 appendStrBufCarriageReturn();
1679 NS_HTML5_BREAK(stateloop);
1680 }
1681 case '\n': {
1682 appendStrBufLineFeed();
1683 continue;
1684 }
1685 case '\0': {
1686 c = 0xfffd;
1687 [[fallthrough]];
1688 }
1689 default: {
1690 appendStrBuf(c);
1691 continue;
1692 }
1693 }
1694 }
1695 attributevaluesinglequotedloop_end:;
1696 [[fallthrough]];
1697 }
1698 case CONSUME_CHARACTER_REFERENCE: {
1699 if (++pos == endPos) {
1700 NS_HTML5_BREAK(stateloop);
1701 }
1702 c = checkChar(buf, pos);
1703 switch (c) {
1704 case ' ':
1705 case '\t':
1706 case '\n':
1707 case '\r':
1708 case '\f':
1709 case '<':
1710 case '&':
1711 case '\0': {
1712 emitOrAppendCharRefBuf(returnState);
1713 if (!(returnState & DATA_AND_RCDATA_MASK)) {
1714 cstart = pos;
1715 }
1716 reconsume = true;
1717 state =
1718 P::transition(mViewSource.get(), returnState, reconsume, pos);
1719 NS_HTML5_CONTINUE(stateloop);
1720 }
1721 case '#': {
1722 appendCharRefBuf('#');
1723 state =
1724 P::transition(mViewSource.get(), nsHtml5Tokenizer::CONSUME_NCR,
1725 reconsume, pos);
1726 NS_HTML5_CONTINUE(stateloop);
1727 }
1728 default: {
1729 if (c == additional) {
1730 emitOrAppendCharRefBuf(returnState);
1731 reconsume = true;
1732 state =
1733 P::transition(mViewSource.get(), returnState, reconsume, pos);
1734 NS_HTML5_CONTINUE(stateloop);
1735 }
1736 if (c >= 'a' && c <= 'z') {
1737 firstCharKey = c - 'a' + 26;
1738 } else if (c >= 'A' && c <= 'Z') {
1739 firstCharKey = c - 'A';
1740 } else {
1741 if (P::reportErrors) {
1742 errNoNamedCharacterMatch();
1743 }
1744 emitOrAppendCharRefBuf(returnState);
1745 if (!(returnState & DATA_AND_RCDATA_MASK)) {
1746 cstart = pos;
1747 }
1748 reconsume = true;
1749 state =
1750 P::transition(mViewSource.get(), returnState, reconsume, pos);
1751 NS_HTML5_CONTINUE(stateloop);
1752 }
1753 appendCharRefBuf(c);
1754 state =
1755 P::transition(mViewSource.get(),
1756 nsHtml5Tokenizer::CHARACTER_REFERENCE_HILO_LOOKUP,
1757 reconsume, pos);
1758 }
1759 }
1760 [[fallthrough]];
1761 }
1762 case CHARACTER_REFERENCE_HILO_LOOKUP: {
1763 {
1764 if (++pos == endPos) {
1765 NS_HTML5_BREAK(stateloop);
1766 }
1767 c = checkChar(buf, pos);
1768 int32_t hilo = 0;
1769 if (c <= 'z') {
1770 const int32_t* row = nsHtml5NamedCharactersAccel::HILO_ACCEL[c];
1771 if (row) {
1772 hilo = row[firstCharKey];
1773 }
1774 }
1775 if (!hilo) {
1776 if (P::reportErrors) {
1777 errNoNamedCharacterMatch();
1778 }
1779 emitOrAppendCharRefBuf(returnState);
1780 if (!(returnState & DATA_AND_RCDATA_MASK)) {
1781 cstart = pos;
1782 }
1783 reconsume = true;
1784 state =
1785 P::transition(mViewSource.get(), returnState, reconsume, pos);
1786 NS_HTML5_CONTINUE(stateloop);
1787 }
1788 appendCharRefBuf(c);
1789 lo = hilo & 0xFFFF;
1790 hi = hilo >> 16;
1791 entCol = -1;
1792 candidate = -1;
1793 charRefBufMark = 0;
1794 state = P::transition(mViewSource.get(),
1795 nsHtml5Tokenizer::CHARACTER_REFERENCE_TAIL,
1796 reconsume, pos);
1797 }
1798 [[fallthrough]];
1799 }
1800 case CHARACTER_REFERENCE_TAIL: {
1801 for (;;) {
1802 if (++pos == endPos) {
1803 NS_HTML5_BREAK(stateloop);
1804 }
1805 c = checkChar(buf, pos);
1806 entCol++;
1807 for (;;) {
1808 if (hi < lo) {
1809 NS_HTML5_BREAK(outer);
1810 }
1811 if (entCol == nsHtml5NamedCharacters::NAMES[lo].length()) {
1812 candidate = lo;
1813 charRefBufMark = charRefBufLen;
1814 lo++;
1815 } else if (entCol > nsHtml5NamedCharacters::NAMES[lo].length()) {
1816 NS_HTML5_BREAK(outer);
1817 } else if (c > nsHtml5NamedCharacters::NAMES[lo].charAt(entCol)) {
1818 lo++;
1819 } else {
1820 NS_HTML5_BREAK(loloop);
1821 }
1822 }
1823 loloop_end:;
1824 for (;;) {
1825 if (hi < lo) {
1826 NS_HTML5_BREAK(outer);
1827 }
1828 if (entCol == nsHtml5NamedCharacters::NAMES[hi].length()) {
1829 NS_HTML5_BREAK(hiloop);
1830 }
1831 if (entCol > nsHtml5NamedCharacters::NAMES[hi].length()) {
1832 NS_HTML5_BREAK(outer);
1833 } else if (c < nsHtml5NamedCharacters::NAMES[hi].charAt(entCol)) {
1834 hi--;
1835 } else {
1836 NS_HTML5_BREAK(hiloop);
1837 }
1838 }
1839 hiloop_end:;
1840 if (c == ';') {
1841 if (entCol + 1 == nsHtml5NamedCharacters::NAMES[lo].length()) {
1842 candidate = lo;
1843 charRefBufMark = charRefBufLen;
1844 }
1845 NS_HTML5_BREAK(outer);
1846 }
1847 if (hi < lo) {
1848 NS_HTML5_BREAK(outer);
1849 }
1850 appendCharRefBuf(c);
1851 continue;
1852 }
1853 outer_end:;
1854 if (candidate == -1) {
1855 if (P::reportErrors) {
1856 errNoNamedCharacterMatch();
1857 }
1858 emitOrAppendCharRefBuf(returnState);
1859 if (!(returnState & DATA_AND_RCDATA_MASK)) {
1860 cstart = pos;
1861 }
1862 reconsume = true;
1863 state = P::transition(mViewSource.get(), returnState, reconsume, pos);
1864 NS_HTML5_CONTINUE(stateloop);
1865 } else {
1866 const nsHtml5CharacterName& candidateName =
1867 nsHtml5NamedCharacters::NAMES[candidate];
1868 if (!candidateName.length() ||
1869 candidateName.charAt(candidateName.length() - 1) != ';') {
1870 if ((returnState & DATA_AND_RCDATA_MASK)) {
1871 char16_t ch;
1872 if (charRefBufMark == charRefBufLen) {
1873 ch = c;
1874 } else {
1875 ch = charRefBuf[charRefBufMark];
1876 }
1877 if (ch == '=' || (ch >= '0' && ch <= '9') ||
1878 (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {
1879 if (P::reportErrors) {
1880 errNoNamedCharacterMatch();
1881 }
1882 appendCharRefBufToStrBuf();
1883 reconsume = true;
1884 state = P::transition(mViewSource.get(), returnState, reconsume,
1885 pos);
1886 NS_HTML5_CONTINUE(stateloop);
1887 }
1888 }
1889 if ((returnState & DATA_AND_RCDATA_MASK)) {
1890 if (P::reportErrors) {
1891 errUnescapedAmpersandInterpretedAsCharacterReference();
1892 }
1893 } else {
1894 if (P::reportErrors) {
1895 errNotSemicolonTerminated();
1896 }
1897 }
1898 }
1899 P::completedNamedCharacterReference(mViewSource.get());
1900 const char16_t* val = nsHtml5NamedCharacters::VALUES[candidate];
1901 if (!val[1]) {
1902 emitOrAppendOne(val, returnState);
1903 } else {
1904 emitOrAppendTwo(val, returnState);
1905 }
1906 if (charRefBufMark < charRefBufLen) {
1907 if ((returnState & DATA_AND_RCDATA_MASK)) {
1908 appendStrBuf(charRefBuf, charRefBufMark,
1909 charRefBufLen - charRefBufMark);
1910 } else {
1911 tokenHandler->characters(charRefBuf, charRefBufMark,
1912 charRefBufLen - charRefBufMark);
1913 }
1914 }
1915 bool earlyBreak = (c == ';' && charRefBufMark == charRefBufLen);
1916 charRefBufLen = 0;
1917 if (!(returnState & DATA_AND_RCDATA_MASK)) {
1918 cstart = earlyBreak ? pos + 1 : pos;
1919 }
1920 reconsume = !earlyBreak;
1921 state = P::transition(mViewSource.get(), returnState, reconsume, pos);
1922 NS_HTML5_CONTINUE(stateloop);
1923 }
1924 }
1925 case CONSUME_NCR: {
1926 if (++pos == endPos) {
1927 NS_HTML5_BREAK(stateloop);
1928 }
1929 c = checkChar(buf, pos);
1930 value = 0;
1931 seenDigits = false;
1932 switch (c) {
1933 case 'x':
1934 case 'X': {
1935 appendCharRefBuf(c);
1936 state =
1937 P::transition(mViewSource.get(), nsHtml5Tokenizer::HEX_NCR_LOOP,
1938 reconsume, pos);
1939 NS_HTML5_CONTINUE(stateloop);
1940 }
1941 default: {
1942 reconsume = true;
1943 state = P::transition(mViewSource.get(),
1944 nsHtml5Tokenizer::DECIMAL_NRC_LOOP, reconsume,
1945 pos);
1946 }
1947 }
1948 [[fallthrough]];
1949 }
1950 case DECIMAL_NRC_LOOP: {
1951 for (;;) {
1952 if (reconsume) {
1953 reconsume = false;
1954 } else {
1955 if (++pos == endPos) {
1956 NS_HTML5_BREAK(stateloop);
1957 }
1958 c = checkChar(buf, pos);
1959 }
1960 MOZ_ASSERT(value >= 0, "value must not become negative.");
1961 if (c >= '0' && c <= '9') {
1962 seenDigits = true;
1963 if (value <= 0x10FFFF) {
1964 value *= 10;
1965 value += c - '0';
1966 }
1967 continue;
1968 } else if (c == ';') {
1969 if (seenDigits) {
1970 if (!(returnState & DATA_AND_RCDATA_MASK)) {
1971 cstart = pos + 1;
1972 }
1973 state = P::transition(mViewSource.get(),
1974 nsHtml5Tokenizer::HANDLE_NCR_VALUE,
1975 reconsume, pos);
1976 NS_HTML5_BREAK(decimalloop);
1977 } else {
1978 if (P::reportErrors) {
1979 errNoDigitsInNCR();
1980 }
1981 appendCharRefBuf(';');
1982 emitOrAppendCharRefBuf(returnState);
1983 if (!(returnState & DATA_AND_RCDATA_MASK)) {
1984 cstart = pos + 1;
1985 }
1986 state =
1987 P::transition(mViewSource.get(), returnState, reconsume, pos);
1988 NS_HTML5_CONTINUE(stateloop);
1989 }
1990 } else {
1991 if (!seenDigits) {
1992 if (P::reportErrors) {
1993 errNoDigitsInNCR();
1994 }
1995 emitOrAppendCharRefBuf(returnState);
1996 if (!(returnState & DATA_AND_RCDATA_MASK)) {
1997 cstart = pos;
1998 }
1999 reconsume = true;
2000 state =
2001 P::transition(mViewSource.get(), returnState, reconsume, pos);
2002 NS_HTML5_CONTINUE(stateloop);
2003 } else {
2004 if (P::reportErrors) {
2005 errCharRefLacksSemicolon();
2006 }
2007 if (!(returnState & DATA_AND_RCDATA_MASK)) {
2008 cstart = pos;
2009 }
2010 reconsume = true;
2011 state = P::transition(mViewSource.get(),
2012 nsHtml5Tokenizer::HANDLE_NCR_VALUE,
2013 reconsume, pos);
2014 NS_HTML5_BREAK(decimalloop);
2015 }
2016 }
2017 }
2018 decimalloop_end:;
2019 [[fallthrough]];
2020 }
2021 case HANDLE_NCR_VALUE: {
2022 charRefBufLen = 0;
2023 handleNcrValue(returnState);
2024 state = P::transition(mViewSource.get(), returnState, reconsume, pos);
2025 NS_HTML5_CONTINUE(stateloop);
2026 }
2027 case HEX_NCR_LOOP: {
2028 for (;;) {
2029 if (++pos == endPos) {
2030 NS_HTML5_BREAK(stateloop);
2031 }
2032 c = checkChar(buf, pos);
2033 MOZ_ASSERT(value >= 0, "value must not become negative.");
2034 if (c >= '0' && c <= '9') {
2035 seenDigits = true;
2036 if (value <= 0x10FFFF) {
2037 value *= 16;
2038 value += c - '0';
2039 }
2040 continue;
2041 } else if (c >= 'A' && c <= 'F') {
2042 seenDigits = true;
2043 if (value <= 0x10FFFF) {
2044 value *= 16;
2045 value += c - 'A' + 10;
2046 }
2047 continue;
2048 } else if (c >= 'a' && c <= 'f') {
2049 seenDigits = true;
2050 if (value <= 0x10FFFF) {
2051 value *= 16;
2052 value += c - 'a' + 10;
2053 }
2054 continue;
2055 } else if (c == ';') {
2056 if (seenDigits) {
2057 if (!(returnState & DATA_AND_RCDATA_MASK)) {
2058 cstart = pos + 1;
2059 }
2060 state = P::transition(mViewSource.get(),
2061 nsHtml5Tokenizer::HANDLE_NCR_VALUE,
2062 reconsume, pos);
2063 NS_HTML5_CONTINUE(stateloop);
2064 } else {
2065 if (P::reportErrors) {
2066 errNoDigitsInNCR();
2067 }
2068 appendCharRefBuf(';');
2069 emitOrAppendCharRefBuf(returnState);
2070 if (!(returnState & DATA_AND_RCDATA_MASK)) {
2071 cstart = pos + 1;
2072 }
2073 state =
2074 P::transition(mViewSource.get(), returnState, reconsume, pos);
2075 NS_HTML5_CONTINUE(stateloop);
2076 }
2077 } else {
2078 if (!seenDigits) {
2079 if (P::reportErrors) {
2080 errNoDigitsInNCR();
2081 }
2082 emitOrAppendCharRefBuf(returnState);
2083 if (!(returnState & DATA_AND_RCDATA_MASK)) {
2084 cstart = pos;
2085 }
2086 reconsume = true;
2087 state =
2088 P::transition(mViewSource.get(), returnState, reconsume, pos);
2089 NS_HTML5_CONTINUE(stateloop);
2090 } else {
2091 if (P::reportErrors) {
2092 errCharRefLacksSemicolon();
2093 }
2094 if (!(returnState & DATA_AND_RCDATA_MASK)) {
2095 cstart = pos;
2096 }
2097 reconsume = true;
2098 state = P::transition(mViewSource.get(),
2099 nsHtml5Tokenizer::HANDLE_NCR_VALUE,
2100 reconsume, pos);
2101 NS_HTML5_CONTINUE(stateloop);
2102 }
2103 }
2104 }
2105 }
2106 case PLAINTEXT: {
2107 for (;;) {
2108 if (reconsume) {
2109 reconsume = false;
2110 } else {
2111 if (++pos == endPos) {
2112 NS_HTML5_BREAK(stateloop);
2113 }
2114 c = checkChar(buf, pos);
2115 }
2116 switch (c) {
2117 case '\0': {
2118 emitPlaintextReplacementCharacter(buf, pos);
2119 continue;
2120 }
2121 case '\r': {
2122 emitCarriageReturn(buf, pos);
2123 NS_HTML5_BREAK(stateloop);
2124 }
2125 case '\n': {
2126 silentLineFeed();
2127 [[fallthrough]];
2128 }
2129 default: {
2130 continue;
2131 }
2132 }
2133 }
2134 }
2135 case CLOSE_TAG_OPEN: {
2136 if (++pos == endPos) {
2137 NS_HTML5_BREAK(stateloop);
2138 }
2139 c = checkChar(buf, pos);
2140 switch (c) {
2141 case '>': {
2142 if (P::reportErrors) {
2143 errLtSlashGt();
2144 }
2145 cstart = pos + 1;
2146 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
2147 reconsume, pos);
2148 NS_HTML5_CONTINUE(stateloop);
2149 }
2150 case '\r': {
2151 silentCarriageReturn();
2152 if (P::reportErrors) {
2153 errGarbageAfterLtSlash();
2154 }
2155 clearStrBufBeforeUse();
2156 appendStrBuf('\n');
2157 state =
2158 P::transition(mViewSource.get(),
2159 nsHtml5Tokenizer::BOGUS_COMMENT, reconsume, pos);
2160 NS_HTML5_BREAK(stateloop);
2161 }
2162 case '\n': {
2163 silentLineFeed();
2164 if (P::reportErrors) {
2165 errGarbageAfterLtSlash();
2166 }
2167 clearStrBufBeforeUse();
2168 appendStrBuf(c);
2169 state =
2170 P::transition(mViewSource.get(),
2171 nsHtml5Tokenizer::BOGUS_COMMENT, reconsume, pos);
2172 NS_HTML5_CONTINUE(stateloop);
2173 }
2174 case '\0': {
2175 c = 0xfffd;
2176 [[fallthrough]];
2177 }
2178 default: {
2179 if (c >= 'A' && c <= 'Z') {
2180 c += 0x20;
2181 }
2182 if (c >= 'a' && c <= 'z') {
2183 endTag = true;
2184 clearStrBufBeforeUse();
2185 appendStrBuf(c);
2186 containsHyphen = false;
2187 state = P::transition(mViewSource.get(),
2188 nsHtml5Tokenizer::TAG_NAME, reconsume, pos);
2189 NS_HTML5_CONTINUE(stateloop);
2190 } else {
2191 if (P::reportErrors) {
2192 errGarbageAfterLtSlash();
2193 }
2194 clearStrBufBeforeUse();
2195 appendStrBuf(c);
2196 state = P::transition(mViewSource.get(),
2197 nsHtml5Tokenizer::BOGUS_COMMENT, reconsume,
2198 pos);
2199 NS_HTML5_CONTINUE(stateloop);
2200 }
2201 }
2202 }
2203 }
2204 case RCDATA: {
2205 for (;;) {
2206 if (reconsume) {
2207 reconsume = false;
2208 } else {
2209 if (++pos == endPos) {
2210 NS_HTML5_BREAK(stateloop);
2211 }
2212 c = checkChar(buf, pos);
2213 }
2214 switch (c) {
2215 case '&': {
2216 flushChars(buf, pos);
2217 MOZ_ASSERT(!charRefBufLen,
2218 "charRefBufLen not reset after previous use!");
2219 appendCharRefBuf(c);
2220 setAdditionalAndRememberAmpersandLocation('\0');
2221 returnState = state;
2222 state =
2223 P::transition(mViewSource.get(),
2224 nsHtml5Tokenizer::CONSUME_CHARACTER_REFERENCE,
2225 reconsume, pos);
2226 NS_HTML5_CONTINUE(stateloop);
2227 }
2228 case '<': {
2229 flushChars(buf, pos);
2230 returnState = state;
2231 state =
2232 P::transition(mViewSource.get(),
2233 nsHtml5Tokenizer::RAWTEXT_RCDATA_LESS_THAN_SIGN,
2234 reconsume, pos);
2235 NS_HTML5_CONTINUE(stateloop);
2236 }
2237 case '\0': {
2238 emitReplacementCharacter(buf, pos);
2239 continue;
2240 }
2241 case '\r': {
2242 emitCarriageReturn(buf, pos);
2243 NS_HTML5_BREAK(stateloop);
2244 }
2245 case '\n': {
2246 silentLineFeed();
2247 [[fallthrough]];
2248 }
2249 default: {
2250 continue;
2251 }
2252 }
2253 }
2254 }
2255 case RAWTEXT: {
2256 for (;;) {
2257 if (reconsume) {
2258 reconsume = false;
2259 } else {
2260 if (++pos == endPos) {
2261 NS_HTML5_BREAK(stateloop);
2262 }
2263 c = checkChar(buf, pos);
2264 }
2265 switch (c) {
2266 case '<': {
2267 flushChars(buf, pos);
2268 returnState = state;
2269 state =
2270 P::transition(mViewSource.get(),
2271 nsHtml5Tokenizer::RAWTEXT_RCDATA_LESS_THAN_SIGN,
2272 reconsume, pos);
2273 NS_HTML5_BREAK(rawtextloop);
2274 }
2275 case '\0': {
2276 emitReplacementCharacter(buf, pos);
2277 continue;
2278 }
2279 case '\r': {
2280 emitCarriageReturn(buf, pos);
2281 NS_HTML5_BREAK(stateloop);
2282 }
2283 case '\n': {
2284 silentLineFeed();
2285 [[fallthrough]];
2286 }
2287 default: {
2288 continue;
2289 }
2290 }
2291 }
2292 rawtextloop_end:;
2293 [[fallthrough]];
2294 }
2295 case RAWTEXT_RCDATA_LESS_THAN_SIGN: {
2296 for (;;) {
2297 if (++pos == endPos) {
2298 NS_HTML5_BREAK(stateloop);
2299 }
2300 c = checkChar(buf, pos);
2301 switch (c) {
2302 case '/': {
2303 index = 0;
2304 clearStrBufBeforeUse();
2305 state = P::transition(mViewSource.get(),
2306 nsHtml5Tokenizer::NON_DATA_END_TAG_NAME,
2307 reconsume, pos);
2308 NS_HTML5_BREAK(rawtextrcdatalessthansignloop);
2309 }
2310 default: {
2311 tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1);
2312 cstart = pos;
2313 reconsume = true;
2314 state =
2315 P::transition(mViewSource.get(), returnState, reconsume, pos);
2316 NS_HTML5_CONTINUE(stateloop);
2317 }
2318 }
2319 }
2320 rawtextrcdatalessthansignloop_end:;
2321 [[fallthrough]];
2322 }
2323 case NON_DATA_END_TAG_NAME: {
2324 for (;;) {
2325 if (++pos == endPos) {
2326 NS_HTML5_BREAK(stateloop);
2327 }
2328 c = checkChar(buf, pos);
2329 if (!endTagExpectationAsArray) {
2330 tokenHandler->characters(nsHtml5Tokenizer::LT_SOLIDUS, 0, 2);
2331 cstart = pos;
2332 reconsume = true;
2333 state =
2334 P::transition(mViewSource.get(), returnState, reconsume, pos);
2335 NS_HTML5_CONTINUE(stateloop);
2336 } else if (index < endTagExpectationAsArray.length) {
2337 char16_t e = endTagExpectationAsArray[index];
2338 char16_t folded = c;
2339 if (c >= 'A' && c <= 'Z') {
2340 folded += 0x20;
2341 }
2342 if (folded != e) {
2343 tokenHandler->characters(nsHtml5Tokenizer::LT_SOLIDUS, 0, 2);
2344 emitStrBuf();
2345 cstart = pos;
2346 reconsume = true;
2347 state =
2348 P::transition(mViewSource.get(), returnState, reconsume, pos);
2349 NS_HTML5_CONTINUE(stateloop);
2350 }
2351 appendStrBuf(c);
2352 index++;
2353 continue;
2354 } else {
2355 endTag = true;
2356 tagName = endTagExpectation;
2357 switch (c) {
2358 case '\r': {
2359 silentCarriageReturn();
2360 clearStrBufAfterUse();
2361 state = P::transition(mViewSource.get(),
2362 nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME,
2363 reconsume, pos);
2364 NS_HTML5_BREAK(stateloop);
2365 }
2366 case '\n': {
2367 silentLineFeed();
2368 [[fallthrough]];
2369 }
2370 case ' ':
2371 case '\t':
2372 case '\f': {
2373 clearStrBufAfterUse();
2374 state = P::transition(mViewSource.get(),
2375 nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME,
2376 reconsume, pos);
2377 NS_HTML5_CONTINUE(stateloop);
2378 }
2379 case '/': {
2380 clearStrBufAfterUse();
2381 state = P::transition(mViewSource.get(),
2382 nsHtml5Tokenizer::SELF_CLOSING_START_TAG,
2383 reconsume, pos);
2384 NS_HTML5_CONTINUE(stateloop);
2385 }
2386 case '>': {
2387 clearStrBufAfterUse();
2388 state = P::transition(mViewSource.get(),
2389 emitCurrentTagToken(false, pos),
2390 reconsume, pos);
2391 if (shouldSuspend) {
2392 NS_HTML5_BREAK(stateloop);
2393 }
2394 NS_HTML5_CONTINUE(stateloop);
2395 }
2396 default: {
2397 tokenHandler->characters(nsHtml5Tokenizer::LT_SOLIDUS, 0, 2);
2398 emitStrBuf();
2399 cstart = pos;
2400 reconsume = true;
2401 state = P::transition(mViewSource.get(), returnState, reconsume,
2402 pos);
2403 NS_HTML5_CONTINUE(stateloop);
2404 }
2405 }
2406 }
2407 }
2408 }
2409 case BOGUS_COMMENT: {
2410 for (;;) {
2411 if (reconsume) {
2412 reconsume = false;
2413 } else {
2414 if (++pos == endPos) {
2415 NS_HTML5_BREAK(stateloop);
2416 }
2417 c = checkChar(buf, pos);
2418 }
2419 switch (c) {
2420 case '>': {
2421 emitComment(0, pos);
2422 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
2423 reconsume, pos);
2424 NS_HTML5_CONTINUE(stateloop);
2425 }
2426 case '-': {
2427 appendStrBuf(c);
2428 state = P::transition(mViewSource.get(),
2429 nsHtml5Tokenizer::BOGUS_COMMENT_HYPHEN,
2430 reconsume, pos);
2431 NS_HTML5_BREAK(boguscommentloop);
2432 }
2433 case '\r': {
2434 appendStrBufCarriageReturn();
2435 NS_HTML5_BREAK(stateloop);
2436 }
2437 case '\n': {
2438 appendStrBufLineFeed();
2439 continue;
2440 }
2441 case '\0': {
2442 c = 0xfffd;
2443 [[fallthrough]];
2444 }
2445 default: {
2446 appendStrBuf(c);
2447 continue;
2448 }
2449 }
2450 }
2451 boguscommentloop_end:;
2452 [[fallthrough]];
2453 }
2454 case BOGUS_COMMENT_HYPHEN: {
2455 boguscommenthyphenloop:
2456 for (;;) {
2457 if (++pos == endPos) {
2458 NS_HTML5_BREAK(stateloop);
2459 }
2460 c = checkChar(buf, pos);
2461 switch (c) {
2462 case '>': {
2463 emitComment(0, pos);
2464 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
2465 reconsume, pos);
2466 NS_HTML5_CONTINUE(stateloop);
2467 }
2468 case '-': {
2469 appendSecondHyphenToBogusComment();
2470 NS_HTML5_CONTINUE(boguscommenthyphenloop);
2471 }
2472 case '\r': {
2473 appendStrBufCarriageReturn();
2474 state = P::transition(mViewSource.get(),
2475 nsHtml5Tokenizer::BOGUS_COMMENT, reconsume,
2476 pos);
2477 NS_HTML5_BREAK(stateloop);
2478 }
2479 case '\n': {
2480 appendStrBufLineFeed();
2481 state = P::transition(mViewSource.get(),
2482 nsHtml5Tokenizer::BOGUS_COMMENT, reconsume,
2483 pos);
2484 NS_HTML5_CONTINUE(stateloop);
2485 }
2486 case '\0': {
2487 c = 0xfffd;
2488 [[fallthrough]];
2489 }
2490 default: {
2491 appendStrBuf(c);
2492 state = P::transition(mViewSource.get(),
2493 nsHtml5Tokenizer::BOGUS_COMMENT, reconsume,
2494 pos);
2495 NS_HTML5_CONTINUE(stateloop);
2496 }
2497 }
2498 }
2499 }
2500 case SCRIPT_DATA: {
2501 for (;;) {
2502 if (reconsume) {
2503 reconsume = false;
2504 } else {
2505 if (++pos == endPos) {
2506 NS_HTML5_BREAK(stateloop);
2507 }
2508 c = checkChar(buf, pos);
2509 }
2510 switch (c) {
2511 case '<': {
2512 flushChars(buf, pos);
2513 returnState = state;
2514 state = P::transition(
2515 mViewSource.get(),
2516 nsHtml5Tokenizer::SCRIPT_DATA_LESS_THAN_SIGN, reconsume, pos);
2517 NS_HTML5_BREAK(scriptdataloop);
2518 }
2519 case '\0': {
2520 emitReplacementCharacter(buf, pos);
2521 continue;
2522 }
2523 case '\r': {
2524 emitCarriageReturn(buf, pos);
2525 NS_HTML5_BREAK(stateloop);
2526 }
2527 case '\n': {
2528 silentLineFeed();
2529 [[fallthrough]];
2530 }
2531 default: {
2532 continue;
2533 }
2534 }
2535 }
2536 scriptdataloop_end:;
2537 [[fallthrough]];
2538 }
2539 case SCRIPT_DATA_LESS_THAN_SIGN: {
2540 for (;;) {
2541 if (++pos == endPos) {
2542 NS_HTML5_BREAK(stateloop);
2543 }
2544 c = checkChar(buf, pos);
2545 switch (c) {
2546 case '/': {
2547 index = 0;
2548 clearStrBufBeforeUse();
2549 state = P::transition(mViewSource.get(),
2550 nsHtml5Tokenizer::NON_DATA_END_TAG_NAME,
2551 reconsume, pos);
2552 NS_HTML5_CONTINUE(stateloop);
2553 }
2554 case '!': {
2555 tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1);
2556 cstart = pos;
2557 state = P::transition(mViewSource.get(),
2558 nsHtml5Tokenizer::SCRIPT_DATA_ESCAPE_START,
2559 reconsume, pos);
2560 NS_HTML5_BREAK(scriptdatalessthansignloop);
2561 }
2562 default: {
2563 tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1);
2564 cstart = pos;
2565 reconsume = true;
2566 state =
2567 P::transition(mViewSource.get(),
2568 nsHtml5Tokenizer::SCRIPT_DATA, reconsume, pos);
2569 NS_HTML5_CONTINUE(stateloop);
2570 }
2571 }
2572 }
2573 scriptdatalessthansignloop_end:;
2574 [[fallthrough]];
2575 }
2576 case SCRIPT_DATA_ESCAPE_START: {
2577 for (;;) {
2578 if (++pos == endPos) {
2579 NS_HTML5_BREAK(stateloop);
2580 }
2581 c = checkChar(buf, pos);
2582 switch (c) {
2583 case '-': {
2584 state =
2585 P::transition(mViewSource.get(),
2586 nsHtml5Tokenizer::SCRIPT_DATA_ESCAPE_START_DASH,
2587 reconsume, pos);
2588 NS_HTML5_BREAK(scriptdataescapestartloop);
2589 }
2590 default: {
2591 reconsume = true;
2592 state =
2593 P::transition(mViewSource.get(),
2594 nsHtml5Tokenizer::SCRIPT_DATA, reconsume, pos);
2595 NS_HTML5_CONTINUE(stateloop);
2596 }
2597 }
2598 }
2599 scriptdataescapestartloop_end:;
2600 [[fallthrough]];
2601 }
2602 case SCRIPT_DATA_ESCAPE_START_DASH: {
2603 for (;;) {
2604 if (++pos == endPos) {
2605 NS_HTML5_BREAK(stateloop);
2606 }
2607 c = checkChar(buf, pos);
2608 switch (c) {
2609 case '-': {
2610 state =
2611 P::transition(mViewSource.get(),
2612 nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED_DASH_DASH,
2613 reconsume, pos);
2614 NS_HTML5_BREAK(scriptdataescapestartdashloop);
2615 }
2616 default: {
2617 reconsume = true;
2618 state =
2619 P::transition(mViewSource.get(),
2620 nsHtml5Tokenizer::SCRIPT_DATA, reconsume, pos);
2621 NS_HTML5_CONTINUE(stateloop);
2622 }
2623 }
2624 }
2625 scriptdataescapestartdashloop_end:;
2626 [[fallthrough]];
2627 }
2628 case SCRIPT_DATA_ESCAPED_DASH_DASH: {
2629 for (;;) {
2630 if (++pos == endPos) {
2631 NS_HTML5_BREAK(stateloop);
2632 }
2633 c = checkChar(buf, pos);
2634 switch (c) {
2635 case '-': {
2636 continue;
2637 }
2638 case '<': {
2639 flushChars(buf, pos);
2640 state = P::transition(
2641 mViewSource.get(),
2642 nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN,
2643 reconsume, pos);
2644 NS_HTML5_CONTINUE(stateloop);
2645 }
2646 case '>': {
2647 state =
2648 P::transition(mViewSource.get(),
2649 nsHtml5Tokenizer::SCRIPT_DATA, reconsume, pos);
2650 NS_HTML5_CONTINUE(stateloop);
2651 }
2652 case '\0': {
2653 emitReplacementCharacter(buf, pos);
2654 state = P::transition(mViewSource.get(),
2655 nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED,
2656 reconsume, pos);
2657 NS_HTML5_BREAK(scriptdataescapeddashdashloop);
2658 }
2659 case '\r': {
2660 emitCarriageReturn(buf, pos);
2661 state = P::transition(mViewSource.get(),
2662 nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED,
2663 reconsume, pos);
2664 NS_HTML5_BREAK(stateloop);
2665 }
2666 case '\n': {
2667 silentLineFeed();
2668 [[fallthrough]];
2669 }
2670 default: {
2671 state = P::transition(mViewSource.get(),
2672 nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED,
2673 reconsume, pos);
2674 NS_HTML5_BREAK(scriptdataescapeddashdashloop);
2675 }
2676 }
2677 }
2678 scriptdataescapeddashdashloop_end:;
2679 [[fallthrough]];
2680 }
2681 case SCRIPT_DATA_ESCAPED: {
2682 for (;;) {
2683 if (reconsume) {
2684 reconsume = false;
2685 } else {
2686 if (++pos == endPos) {
2687 NS_HTML5_BREAK(stateloop);
2688 }
2689 c = checkChar(buf, pos);
2690 }
2691 switch (c) {
2692 case '-': {
2693 state = P::transition(mViewSource.get(),
2694 nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED_DASH,
2695 reconsume, pos);
2696 NS_HTML5_BREAK(scriptdataescapedloop);
2697 }
2698 case '<': {
2699 flushChars(buf, pos);
2700 state = P::transition(
2701 mViewSource.get(),
2702 nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN,
2703 reconsume, pos);
2704 NS_HTML5_CONTINUE(stateloop);
2705 }
2706 case '\0': {
2707 emitReplacementCharacter(buf, pos);
2708 continue;
2709 }
2710 case '\r': {
2711 emitCarriageReturn(buf, pos);
2712 NS_HTML5_BREAK(stateloop);
2713 }
2714 case '\n': {
2715 silentLineFeed();
2716 [[fallthrough]];
2717 }
2718 default: {
2719 continue;
2720 }
2721 }
2722 }
2723 scriptdataescapedloop_end:;
2724 [[fallthrough]];
2725 }
2726 case SCRIPT_DATA_ESCAPED_DASH: {
2727 for (;;) {
2728 if (++pos == endPos) {
2729 NS_HTML5_BREAK(stateloop);
2730 }
2731 c = checkChar(buf, pos);
2732 switch (c) {
2733 case '-': {
2734 state =
2735 P::transition(mViewSource.get(),
2736 nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED_DASH_DASH,
2737 reconsume, pos);
2738 NS_HTML5_CONTINUE(stateloop);
2739 }
2740 case '<': {
2741 flushChars(buf, pos);
2742 state = P::transition(
2743 mViewSource.get(),
2744 nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN,
2745 reconsume, pos);
2746 NS_HTML5_BREAK(scriptdataescapeddashloop);
2747 }
2748 case '\0': {
2749 emitReplacementCharacter(buf, pos);
2750 state = P::transition(mViewSource.get(),
2751 nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED,
2752 reconsume, pos);
2753 NS_HTML5_CONTINUE(stateloop);
2754 }
2755 case '\r': {
2756 emitCarriageReturn(buf, pos);
2757 state = P::transition(mViewSource.get(),
2758 nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED,
2759 reconsume, pos);
2760 NS_HTML5_BREAK(stateloop);
2761 }
2762 case '\n': {
2763 silentLineFeed();
2764 [[fallthrough]];
2765 }
2766 default: {
2767 state = P::transition(mViewSource.get(),
2768 nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED,
2769 reconsume, pos);
2770 NS_HTML5_CONTINUE(stateloop);
2771 }
2772 }
2773 }
2774 scriptdataescapeddashloop_end:;
2775 [[fallthrough]];
2776 }
2777 case SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN: {
2778 for (;;) {
2779 if (++pos == endPos) {
2780 NS_HTML5_BREAK(stateloop);
2781 }
2782 c = checkChar(buf, pos);
2783 switch (c) {
2784 case '/': {
2785 index = 0;
2786 clearStrBufBeforeUse();
2787 returnState = nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED;
2788 state = P::transition(mViewSource.get(),
2789 nsHtml5Tokenizer::NON_DATA_END_TAG_NAME,
2790 reconsume, pos);
2791 NS_HTML5_CONTINUE(stateloop);
2792 }
2793 case 'S':
2794 case 's': {
2795 tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1);
2796 cstart = pos;
2797 index = 1;
2798 state = P::transition(
2799 mViewSource.get(),
2800 nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPE_START, reconsume,
2801 pos);
2802 NS_HTML5_BREAK(scriptdataescapedlessthanloop);
2803 }
2804 default: {
2805 tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1);
2806 cstart = pos;
2807 reconsume = true;
2808 state = P::transition(mViewSource.get(),
2809 nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED,
2810 reconsume, pos);
2811 NS_HTML5_CONTINUE(stateloop);
2812 }
2813 }
2814 }
2815 scriptdataescapedlessthanloop_end:;
2816 [[fallthrough]];
2817 }
2818 case SCRIPT_DATA_DOUBLE_ESCAPE_START: {
2819 for (;;) {
2820 if (++pos == endPos) {
2821 NS_HTML5_BREAK(stateloop);
2822 }
2823 c = checkChar(buf, pos);
2824 MOZ_ASSERT(index > 0);
2825 if (index < 6) {
2826 char16_t folded = c;
2827 if (c >= 'A' && c <= 'Z') {
2828 folded += 0x20;
2829 }
2830 if (folded != nsHtml5Tokenizer::SCRIPT_ARR[index]) {
2831 reconsume = true;
2832 state = P::transition(mViewSource.get(),
2833 nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED,
2834 reconsume, pos);
2835 NS_HTML5_CONTINUE(stateloop);
2836 }
2837 index++;
2838 continue;
2839 }
2840 switch (c) {
2841 case '\r': {
2842 emitCarriageReturn(buf, pos);
2843 state = P::transition(
2844 mViewSource.get(),
2845 nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
2846 NS_HTML5_BREAK(stateloop);
2847 }
2848 case '\n': {
2849 silentLineFeed();
2850 [[fallthrough]];
2851 }
2852 case ' ':
2853 case '\t':
2854 case '\f':
2855 case '/':
2856 case '>': {
2857 state = P::transition(
2858 mViewSource.get(),
2859 nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
2860 NS_HTML5_BREAK(scriptdatadoubleescapestartloop);
2861 }
2862 default: {
2863 reconsume = true;
2864 state = P::transition(mViewSource.get(),
2865 nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED,
2866 reconsume, pos);
2867 NS_HTML5_CONTINUE(stateloop);
2868 }
2869 }
2870 }
2871 scriptdatadoubleescapestartloop_end:;
2872 [[fallthrough]];
2873 }
2874 case SCRIPT_DATA_DOUBLE_ESCAPED: {
2875 for (;;) {
2876 if (reconsume) {
2877 reconsume = false;
2878 } else {
2879 if (++pos == endPos) {
2880 NS_HTML5_BREAK(stateloop);
2881 }
2882 c = checkChar(buf, pos);
2883 }
2884 switch (c) {
2885 case '-': {
2886 state = P::transition(
2887 mViewSource.get(),
2888 nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED_DASH, reconsume,
2889 pos);
2890 NS_HTML5_BREAK(scriptdatadoubleescapedloop);
2891 }
2892 case '<': {
2893 state = P::transition(
2894 mViewSource.get(),
2895 nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN,
2896 reconsume, pos);
2897 NS_HTML5_CONTINUE(stateloop);
2898 }
2899 case '\0': {
2900 emitReplacementCharacter(buf, pos);
2901 continue;
2902 }
2903 case '\r': {
2904 emitCarriageReturn(buf, pos);
2905 NS_HTML5_BREAK(stateloop);
2906 }
2907 case '\n': {
2908 silentLineFeed();
2909 [[fallthrough]];
2910 }
2911 default: {
2912 continue;
2913 }
2914 }
2915 }
2916 scriptdatadoubleescapedloop_end:;
2917 [[fallthrough]];
2918 }
2919 case SCRIPT_DATA_DOUBLE_ESCAPED_DASH: {
2920 for (;;) {
2921 if (++pos == endPos) {
2922 NS_HTML5_BREAK(stateloop);
2923 }
2924 c = checkChar(buf, pos);
2925 switch (c) {
2926 case '-': {
2927 state = P::transition(
2928 mViewSource.get(),
2929 nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH,
2930 reconsume, pos);
2931 NS_HTML5_BREAK(scriptdatadoubleescapeddashloop);
2932 }
2933 case '<': {
2934 state = P::transition(
2935 mViewSource.get(),
2936 nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN,
2937 reconsume, pos);
2938 NS_HTML5_CONTINUE(stateloop);
2939 }
2940 case '\0': {
2941 emitReplacementCharacter(buf, pos);
2942 state = P::transition(
2943 mViewSource.get(),
2944 nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
2945 NS_HTML5_CONTINUE(stateloop);
2946 }
2947 case '\r': {
2948 emitCarriageReturn(buf, pos);
2949 state = P::transition(
2950 mViewSource.get(),
2951 nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
2952 NS_HTML5_BREAK(stateloop);
2953 }
2954 case '\n': {
2955 silentLineFeed();
2956 [[fallthrough]];
2957 }
2958 default: {
2959 state = P::transition(
2960 mViewSource.get(),
2961 nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
2962 NS_HTML5_CONTINUE(stateloop);
2963 }
2964 }
2965 }
2966 scriptdatadoubleescapeddashloop_end:;
2967 [[fallthrough]];
2968 }
2969 case SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH: {
2970 for (;;) {
2971 if (++pos == endPos) {
2972 NS_HTML5_BREAK(stateloop);
2973 }
2974 c = checkChar(buf, pos);
2975 switch (c) {
2976 case '-': {
2977 continue;
2978 }
2979 case '<': {
2980 state = P::transition(
2981 mViewSource.get(),
2982 nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN,
2983 reconsume, pos);
2984 NS_HTML5_BREAK(scriptdatadoubleescapeddashdashloop);
2985 }
2986 case '>': {
2987 state =
2988 P::transition(mViewSource.get(),
2989 nsHtml5Tokenizer::SCRIPT_DATA, reconsume, pos);
2990 NS_HTML5_CONTINUE(stateloop);
2991 }
2992 case '\0': {
2993 emitReplacementCharacter(buf, pos);
2994 state = P::transition(
2995 mViewSource.get(),
2996 nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
2997 NS_HTML5_CONTINUE(stateloop);
2998 }
2999 case '\r': {
3000 emitCarriageReturn(buf, pos);
3001 state = P::transition(
3002 mViewSource.get(),
3003 nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
3004 NS_HTML5_BREAK(stateloop);
3005 }
3006 case '\n': {
3007 silentLineFeed();
3008 [[fallthrough]];
3009 }
3010 default: {
3011 state = P::transition(
3012 mViewSource.get(),
3013 nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
3014 NS_HTML5_CONTINUE(stateloop);
3015 }
3016 }
3017 }
3018 scriptdatadoubleescapeddashdashloop_end:;
3019 [[fallthrough]];
3020 }
3021 case SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN: {
3022 for (;;) {
3023 if (++pos == endPos) {
3024 NS_HTML5_BREAK(stateloop);
3025 }
3026 c = checkChar(buf, pos);
3027 switch (c) {
3028 case '/': {
3029 index = 0;
3030 state =
3031 P::transition(mViewSource.get(),
3032 nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPE_END,
3033 reconsume, pos);
3034 NS_HTML5_BREAK(scriptdatadoubleescapedlessthanloop);
3035 }
3036 default: {
3037 reconsume = true;
3038 state = P::transition(
3039 mViewSource.get(),
3040 nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
3041 NS_HTML5_CONTINUE(stateloop);
3042 }
3043 }
3044 }
3045 scriptdatadoubleescapedlessthanloop_end:;
3046 [[fallthrough]];
3047 }
3048 case SCRIPT_DATA_DOUBLE_ESCAPE_END: {
3049 for (;;) {
3050 if (++pos == endPos) {
3051 NS_HTML5_BREAK(stateloop);
3052 }
3053 c = checkChar(buf, pos);
3054 if (index < 6) {
3055 char16_t folded = c;
3056 if (c >= 'A' && c <= 'Z') {
3057 folded += 0x20;
3058 }
3059 if (folded != nsHtml5Tokenizer::SCRIPT_ARR[index]) {
3060 reconsume = true;
3061 state = P::transition(
3062 mViewSource.get(),
3063 nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
3064 NS_HTML5_CONTINUE(stateloop);
3065 }
3066 index++;
3067 continue;
3068 }
3069 switch (c) {
3070 case '\r': {
3071 emitCarriageReturn(buf, pos);
3072 state = P::transition(mViewSource.get(),
3073 nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED,
3074 reconsume, pos);
3075 NS_HTML5_BREAK(stateloop);
3076 }
3077 case '\n': {
3078 silentLineFeed();
3079 [[fallthrough]];
3080 }
3081 case ' ':
3082 case '\t':
3083 case '\f':
3084 case '/':
3085 case '>': {
3086 state = P::transition(mViewSource.get(),
3087 nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED,
3088 reconsume, pos);
3089 NS_HTML5_CONTINUE(stateloop);
3090 }
3091 default: {
3092 reconsume = true;
3093 state = P::transition(
3094 mViewSource.get(),
3095 nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
3096 NS_HTML5_CONTINUE(stateloop);
3097 }
3098 }
3099 }
3100 }
3101 case MARKUP_DECLARATION_OCTYPE: {
3102 for (;;) {
3103 if (++pos == endPos) {
3104 NS_HTML5_BREAK(stateloop);
3105 }
3106 c = checkChar(buf, pos);
3107 if (index < 6) {
3108 char16_t folded = c;
3109 if (c >= 'A' && c <= 'Z') {
3110 folded += 0x20;
3111 }
3112 if (folded == nsHtml5Tokenizer::OCTYPE[index]) {
3113 appendStrBuf(c);
3114 } else {
3115 if (P::reportErrors) {
3116 errBogusComment();
3117 }
3118 reconsume = true;
3119 state = P::transition(mViewSource.get(),
3120 nsHtml5Tokenizer::BOGUS_COMMENT, reconsume,
3121 pos);
3122 NS_HTML5_CONTINUE(stateloop);
3123 }
3124 index++;
3125 continue;
3126 } else {
3127 reconsume = true;
3128 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DOCTYPE,
3129 reconsume, pos);
3130 NS_HTML5_BREAK(markupdeclarationdoctypeloop);
3131 }
3132 }
3133 markupdeclarationdoctypeloop_end:;
3134 [[fallthrough]];
3135 }
3136 case DOCTYPE: {
3137 for (;;) {
3138 if (reconsume) {
3139 reconsume = false;
3140 } else {
3141 if (++pos == endPos) {
3142 NS_HTML5_BREAK(stateloop);
3143 }
3144 c = checkChar(buf, pos);
3145 }
3146 initDoctypeFields();
3147 switch (c) {
3148 case '\r': {
3149 silentCarriageReturn();
3150 state = P::transition(mViewSource.get(),
3151 nsHtml5Tokenizer::BEFORE_DOCTYPE_NAME,
3152 reconsume, pos);
3153 NS_HTML5_BREAK(stateloop);
3154 }
3155 case '\n': {
3156 silentLineFeed();
3157 [[fallthrough]];
3158 }
3159 case ' ':
3160 case '\t':
3161 case '\f': {
3162 state = P::transition(mViewSource.get(),
3163 nsHtml5Tokenizer::BEFORE_DOCTYPE_NAME,
3164 reconsume, pos);
3165 NS_HTML5_BREAK(doctypeloop);
3166 }
3167 default: {
3168 if (P::reportErrors) {
3169 errMissingSpaceBeforeDoctypeName();
3170 }
3171 reconsume = true;
3172 state = P::transition(mViewSource.get(),
3173 nsHtml5Tokenizer::BEFORE_DOCTYPE_NAME,
3174 reconsume, pos);
3175 NS_HTML5_BREAK(doctypeloop);
3176 }
3177 }
3178 }
3179 doctypeloop_end:;
3180 [[fallthrough]];
3181 }
3182 case BEFORE_DOCTYPE_NAME: {
3183 for (;;) {
3184 if (reconsume) {
3185 reconsume = false;
3186 } else {
3187 if (++pos == endPos) {
3188 NS_HTML5_BREAK(stateloop);
3189 }
3190 c = checkChar(buf, pos);
3191 }
3192 switch (c) {
3193 case '\r': {
3194 silentCarriageReturn();
3195 NS_HTML5_BREAK(stateloop);
3196 }
3197 case '\n': {
3198 silentLineFeed();
3199 [[fallthrough]];
3200 }
3201 case ' ':
3202 case '\t':
3203 case '\f': {
3204 continue;
3205 }
3206 case '>': {
3207 if (P::reportErrors) {
3208 errNamelessDoctype();
3209 }
3210 forceQuirks = true;
3211 emitDoctypeToken(pos);
3212 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
3213 reconsume, pos);
3214 NS_HTML5_CONTINUE(stateloop);
3215 }
3216 case '\0': {
3217 c = 0xfffd;
3218 [[fallthrough]];
3219 }
3220 default: {
3221 if (c >= 'A' && c <= 'Z') {
3222 c += 0x20;
3223 }
3224 clearStrBufBeforeUse();
3225 appendStrBuf(c);
3226 state =
3227 P::transition(mViewSource.get(),
3228 nsHtml5Tokenizer::DOCTYPE_NAME, reconsume, pos);
3229 NS_HTML5_BREAK(beforedoctypenameloop);
3230 }
3231 }
3232 }
3233 beforedoctypenameloop_end:;
3234 [[fallthrough]];
3235 }
3236 case DOCTYPE_NAME: {
3237 for (;;) {
3238 if (++pos == endPos) {
3239 NS_HTML5_BREAK(stateloop);
3240 }
3241 c = checkChar(buf, pos);
3242 switch (c) {
3243 case '\r': {
3244 silentCarriageReturn();
3245 strBufToDoctypeName();
3246 state = P::transition(mViewSource.get(),
3247 nsHtml5Tokenizer::AFTER_DOCTYPE_NAME,
3248 reconsume, pos);
3249 NS_HTML5_BREAK(stateloop);
3250 }
3251 case '\n': {
3252 silentLineFeed();
3253 [[fallthrough]];
3254 }
3255 case ' ':
3256 case '\t':
3257 case '\f': {
3258 strBufToDoctypeName();
3259 state = P::transition(mViewSource.get(),
3260 nsHtml5Tokenizer::AFTER_DOCTYPE_NAME,
3261 reconsume, pos);
3262 NS_HTML5_BREAK(doctypenameloop);
3263 }
3264 case '>': {
3265 strBufToDoctypeName();
3266 emitDoctypeToken(pos);
3267 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
3268 reconsume, pos);
3269 NS_HTML5_CONTINUE(stateloop);
3270 }
3271 case '\0': {
3272 c = 0xfffd;
3273 [[fallthrough]];
3274 }
3275 default: {
3276 if (c >= 'A' && c <= 'Z') {
3277 c += 0x0020;
3278 }
3279 appendStrBuf(c);
3280 continue;
3281 }
3282 }
3283 }
3284 doctypenameloop_end:;
3285 [[fallthrough]];
3286 }
3287 case AFTER_DOCTYPE_NAME: {
3288 for (;;) {
3289 if (++pos == endPos) {
3290 NS_HTML5_BREAK(stateloop);
3291 }
3292 c = checkChar(buf, pos);
3293 switch (c) {
3294 case '\r': {
3295 silentCarriageReturn();
3296 NS_HTML5_BREAK(stateloop);
3297 }
3298 case '\n': {
3299 silentLineFeed();
3300 [[fallthrough]];
3301 }
3302 case ' ':
3303 case '\t':
3304 case '\f': {
3305 continue;
3306 }
3307 case '>': {
3308 emitDoctypeToken(pos);
3309 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
3310 reconsume, pos);
3311 NS_HTML5_CONTINUE(stateloop);
3312 }
3313 case 'p':
3314 case 'P': {
3315 index = 0;
3316 state = P::transition(mViewSource.get(),
3317 nsHtml5Tokenizer::DOCTYPE_UBLIC, reconsume,
3318 pos);
3319 NS_HTML5_BREAK(afterdoctypenameloop);
3320 }
3321 case 's':
3322 case 'S': {
3323 index = 0;
3324 state = P::transition(mViewSource.get(),
3325 nsHtml5Tokenizer::DOCTYPE_YSTEM, reconsume,
3326 pos);
3327 NS_HTML5_CONTINUE(stateloop);
3328 }
3329 default: {
3330 bogusDoctype();
3331 state = P::transition(mViewSource.get(),
3332 nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume,
3333 pos);
3334 NS_HTML5_CONTINUE(stateloop);
3335 }
3336 }
3337 }
3338 afterdoctypenameloop_end:;
3339 [[fallthrough]];
3340 }
3341 case DOCTYPE_UBLIC: {
3342 for (;;) {
3343 if (++pos == endPos) {
3344 NS_HTML5_BREAK(stateloop);
3345 }
3346 c = checkChar(buf, pos);
3347 if (index < 5) {
3348 char16_t folded = c;
3349 if (c >= 'A' && c <= 'Z') {
3350 folded += 0x20;
3351 }
3352 if (folded != nsHtml5Tokenizer::UBLIC[index]) {
3353 bogusDoctype();
3354 reconsume = true;
3355 state = P::transition(mViewSource.get(),
3356 nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume,
3357 pos);
3358 NS_HTML5_CONTINUE(stateloop);
3359 }
3360 index++;
3361 continue;
3362 } else {
3363 reconsume = true;
3364 state = P::transition(
3365 mViewSource.get(),
3366 nsHtml5Tokenizer::AFTER_DOCTYPE_PUBLIC_KEYWORD, reconsume, pos);
3367 NS_HTML5_BREAK(doctypeublicloop);
3368 }
3369 }
3370 doctypeublicloop_end:;
3371 [[fallthrough]];
3372 }
3373 case AFTER_DOCTYPE_PUBLIC_KEYWORD: {
3374 for (;;) {
3375 if (reconsume) {
3376 reconsume = false;
3377 } else {
3378 if (++pos == endPos) {
3379 NS_HTML5_BREAK(stateloop);
3380 }
3381 c = checkChar(buf, pos);
3382 }
3383 switch (c) {
3384 case '\r': {
3385 silentCarriageReturn();
3386 state = P::transition(
3387 mViewSource.get(),
3388 nsHtml5Tokenizer::BEFORE_DOCTYPE_PUBLIC_IDENTIFIER, reconsume,
3389 pos);
3390 NS_HTML5_BREAK(stateloop);
3391 }
3392 case '\n': {
3393 silentLineFeed();
3394 [[fallthrough]];
3395 }
3396 case ' ':
3397 case '\t':
3398 case '\f': {
3399 state = P::transition(
3400 mViewSource.get(),
3401 nsHtml5Tokenizer::BEFORE_DOCTYPE_PUBLIC_IDENTIFIER, reconsume,
3402 pos);
3403 NS_HTML5_BREAK(afterdoctypepublickeywordloop);
3404 }
3405 case '\"': {
3406 if (P::reportErrors) {
3407 errNoSpaceBetweenDoctypePublicKeywordAndQuote();
3408 }
3409 clearStrBufBeforeUse();
3410 state = P::transition(
3411 mViewSource.get(),
3412 nsHtml5Tokenizer::DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED,
3413 reconsume, pos);
3414 NS_HTML5_CONTINUE(stateloop);
3415 }
3416 case '\'': {
3417 if (P::reportErrors) {
3418 errNoSpaceBetweenDoctypePublicKeywordAndQuote();
3419 }
3420 clearStrBufBeforeUse();
3421 state = P::transition(
3422 mViewSource.get(),
3423 nsHtml5Tokenizer::DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED,
3424 reconsume, pos);
3425 NS_HTML5_CONTINUE(stateloop);
3426 }
3427 case '>': {
3428 if (P::reportErrors) {
3429 errExpectedPublicId();
3430 }
3431 forceQuirks = true;
3432 emitDoctypeToken(pos);
3433 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
3434 reconsume, pos);
3435 NS_HTML5_CONTINUE(stateloop);
3436 }
3437 default: {
3438 bogusDoctype();
3439 state = P::transition(mViewSource.get(),
3440 nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume,
3441 pos);
3442 NS_HTML5_CONTINUE(stateloop);
3443 }
3444 }
3445 }
3446 afterdoctypepublickeywordloop_end:;
3447 [[fallthrough]];
3448 }
3449 case BEFORE_DOCTYPE_PUBLIC_IDENTIFIER: {
3450 for (;;) {
3451 if (++pos == endPos) {
3452 NS_HTML5_BREAK(stateloop);
3453 }
3454 c = checkChar(buf, pos);
3455 switch (c) {
3456 case '\r': {
3457 silentCarriageReturn();
3458 NS_HTML5_BREAK(stateloop);
3459 }
3460 case '\n': {
3461 silentLineFeed();
3462 [[fallthrough]];
3463 }
3464 case ' ':
3465 case '\t':
3466 case '\f': {
3467 continue;
3468 }
3469 case '\"': {
3470 clearStrBufBeforeUse();
3471 state = P::transition(
3472 mViewSource.get(),
3473 nsHtml5Tokenizer::DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED,
3474 reconsume, pos);
3475 NS_HTML5_BREAK(beforedoctypepublicidentifierloop);
3476 }
3477 case '\'': {
3478 clearStrBufBeforeUse();
3479 state = P::transition(
3480 mViewSource.get(),
3481 nsHtml5Tokenizer::DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED,
3482 reconsume, pos);
3483 NS_HTML5_CONTINUE(stateloop);
3484 }
3485 case '>': {
3486 if (P::reportErrors) {
3487 errExpectedPublicId();
3488 }
3489 forceQuirks = true;
3490 emitDoctypeToken(pos);
3491 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
3492 reconsume, pos);
3493 NS_HTML5_CONTINUE(stateloop);
3494 }
3495 default: {
3496 bogusDoctype();
3497 state = P::transition(mViewSource.get(),
3498 nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume,
3499 pos);
3500 NS_HTML5_CONTINUE(stateloop);
3501 }
3502 }
3503 }
3504 beforedoctypepublicidentifierloop_end:;
3505 [[fallthrough]];
3506 }
3507 case DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED: {
3508 for (;;) {
3509 if (++pos == endPos) {
3510 NS_HTML5_BREAK(stateloop);
3511 }
3512 c = checkChar(buf, pos);
3513 switch (c) {
3514 case '\"': {
3515 publicIdentifier = strBufToString();
3516 state = P::transition(
3517 mViewSource.get(),
3518 nsHtml5Tokenizer::AFTER_DOCTYPE_PUBLIC_IDENTIFIER, reconsume,
3519 pos);
3520 NS_HTML5_BREAK(doctypepublicidentifierdoublequotedloop);
3521 }
3522 case '>': {
3523 if (P::reportErrors) {
3524 errGtInPublicId();
3525 }
3526 forceQuirks = true;
3527 publicIdentifier = strBufToString();
3528 emitDoctypeToken(pos);
3529 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
3530 reconsume, pos);
3531 NS_HTML5_CONTINUE(stateloop);
3532 }
3533 case '\r': {
3534 appendStrBufCarriageReturn();
3535 NS_HTML5_BREAK(stateloop);
3536 }
3537 case '\n': {
3538 appendStrBufLineFeed();
3539 continue;
3540 }
3541 case '\0': {
3542 c = 0xfffd;
3543 [[fallthrough]];
3544 }
3545 default: {
3546 appendStrBuf(c);
3547 continue;
3548 }
3549 }
3550 }
3551 doctypepublicidentifierdoublequotedloop_end:;
3552 [[fallthrough]];
3553 }
3554 case AFTER_DOCTYPE_PUBLIC_IDENTIFIER: {
3555 for (;;) {
3556 if (++pos == endPos) {
3557 NS_HTML5_BREAK(stateloop);
3558 }
3559 c = checkChar(buf, pos);
3560 switch (c) {
3561 case '\r': {
3562 silentCarriageReturn();
3563 state = P::transition(
3564 mViewSource.get(),
3565 nsHtml5Tokenizer::
3566 BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS,
3567 reconsume, pos);
3568 NS_HTML5_BREAK(stateloop);
3569 }
3570 case '\n': {
3571 silentLineFeed();
3572 [[fallthrough]];
3573 }
3574 case ' ':
3575 case '\t':
3576 case '\f': {
3577 state = P::transition(
3578 mViewSource.get(),
3579 nsHtml5Tokenizer::
3580 BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS,
3581 reconsume, pos);
3582 NS_HTML5_BREAK(afterdoctypepublicidentifierloop);
3583 }
3584 case '>': {
3585 emitDoctypeToken(pos);
3586 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
3587 reconsume, pos);
3588 NS_HTML5_CONTINUE(stateloop);
3589 }
3590 case '\"': {
3591 if (P::reportErrors) {
3592 errNoSpaceBetweenPublicAndSystemIds();
3593 }
3594 clearStrBufBeforeUse();
3595 state = P::transition(
3596 mViewSource.get(),
3597 nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED,
3598 reconsume, pos);
3599 NS_HTML5_CONTINUE(stateloop);
3600 }
3601 case '\'': {
3602 if (P::reportErrors) {
3603 errNoSpaceBetweenPublicAndSystemIds();
3604 }
3605 clearStrBufBeforeUse();
3606 state = P::transition(
3607 mViewSource.get(),
3608 nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED,
3609 reconsume, pos);
3610 NS_HTML5_CONTINUE(stateloop);
3611 }
3612 default: {
3613 bogusDoctype();
3614 state = P::transition(mViewSource.get(),
3615 nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume,
3616 pos);
3617 NS_HTML5_CONTINUE(stateloop);
3618 }
3619 }
3620 }
3621 afterdoctypepublicidentifierloop_end:;
3622 [[fallthrough]];
3623 }
3624 case BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS: {
3625 for (;;) {
3626 if (++pos == endPos) {
3627 NS_HTML5_BREAK(stateloop);
3628 }
3629 c = checkChar(buf, pos);
3630 switch (c) {
3631 case '\r': {
3632 silentCarriageReturn();
3633 NS_HTML5_BREAK(stateloop);
3634 }
3635 case '\n': {
3636 silentLineFeed();
3637 [[fallthrough]];
3638 }
3639 case ' ':
3640 case '\t':
3641 case '\f': {
3642 continue;
3643 }
3644 case '>': {
3645 emitDoctypeToken(pos);
3646 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
3647 reconsume, pos);
3648 NS_HTML5_CONTINUE(stateloop);
3649 }
3650 case '\"': {
3651 clearStrBufBeforeUse();
3652 state = P::transition(
3653 mViewSource.get(),
3654 nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED,
3655 reconsume, pos);
3656 NS_HTML5_BREAK(betweendoctypepublicandsystemidentifiersloop);
3657 }
3658 case '\'': {
3659 clearStrBufBeforeUse();
3660 state = P::transition(
3661 mViewSource.get(),
3662 nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED,
3663 reconsume, pos);
3664 NS_HTML5_CONTINUE(stateloop);
3665 }
3666 default: {
3667 bogusDoctype();
3668 state = P::transition(mViewSource.get(),
3669 nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume,
3670 pos);
3671 NS_HTML5_CONTINUE(stateloop);
3672 }
3673 }
3674 }
3675 betweendoctypepublicandsystemidentifiersloop_end:;
3676 [[fallthrough]];
3677 }
3678 case DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED: {
3679 for (;;) {
3680 if (++pos == endPos) {
3681 NS_HTML5_BREAK(stateloop);
3682 }
3683 c = checkChar(buf, pos);
3684 switch (c) {
3685 case '\"': {
3686 systemIdentifier = strBufToString();
3687 state = P::transition(
3688 mViewSource.get(),
3689 nsHtml5Tokenizer::AFTER_DOCTYPE_SYSTEM_IDENTIFIER, reconsume,
3690 pos);
3691 NS_HTML5_CONTINUE(stateloop);
3692 }
3693 case '>': {
3694 if (P::reportErrors) {
3695 errGtInSystemId();
3696 }
3697 forceQuirks = true;
3698 systemIdentifier = strBufToString();
3699 emitDoctypeToken(pos);
3700 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
3701 reconsume, pos);
3702 NS_HTML5_CONTINUE(stateloop);
3703 }
3704 case '\r': {
3705 appendStrBufCarriageReturn();
3706 NS_HTML5_BREAK(stateloop);
3707 }
3708 case '\n': {
3709 appendStrBufLineFeed();
3710 continue;
3711 }
3712 case '\0': {
3713 c = 0xfffd;
3714 [[fallthrough]];
3715 }
3716 default: {
3717 appendStrBuf(c);
3718 continue;
3719 }
3720 }
3721 }
3722 }
3723 case AFTER_DOCTYPE_SYSTEM_IDENTIFIER: {
3724 for (;;) {
3725 if (++pos == endPos) {
3726 NS_HTML5_BREAK(stateloop);
3727 }
3728 c = checkChar(buf, pos);
3729 switch (c) {
3730 case '\r': {
3731 silentCarriageReturn();
3732 NS_HTML5_BREAK(stateloop);
3733 }
3734 case '\n': {
3735 silentLineFeed();
3736 [[fallthrough]];
3737 }
3738 case ' ':
3739 case '\t':
3740 case '\f': {
3741 continue;
3742 }
3743 case '>': {
3744 emitDoctypeToken(pos);
3745 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
3746 reconsume, pos);
3747 NS_HTML5_CONTINUE(stateloop);
3748 }
3749 default: {
3750 bogusDoctypeWithoutQuirks();
3751 state = P::transition(mViewSource.get(),
3752 nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume,
3753 pos);
3754 NS_HTML5_BREAK(afterdoctypesystemidentifierloop);
3755 }
3756 }
3757 }
3758 afterdoctypesystemidentifierloop_end:;
3759 [[fallthrough]];
3760 }
3761 case BOGUS_DOCTYPE: {
3762 for (;;) {
3763 if (reconsume) {
3764 reconsume = false;
3765 } else {
3766 if (++pos == endPos) {
3767 NS_HTML5_BREAK(stateloop);
3768 }
3769 c = checkChar(buf, pos);
3770 }
3771 switch (c) {
3772 case '>': {
3773 emitDoctypeToken(pos);
3774 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
3775 reconsume, pos);
3776 NS_HTML5_CONTINUE(stateloop);
3777 }
3778 case '\r': {
3779 silentCarriageReturn();
3780 NS_HTML5_BREAK(stateloop);
3781 }
3782 case '\n': {
3783 silentLineFeed();
3784 [[fallthrough]];
3785 }
3786 default: {
3787 continue;
3788 }
3789 }
3790 }
3791 }
3792 case DOCTYPE_YSTEM: {
3793 for (;;) {
3794 if (++pos == endPos) {
3795 NS_HTML5_BREAK(stateloop);
3796 }
3797 c = checkChar(buf, pos);
3798 if (index < 5) {
3799 char16_t folded = c;
3800 if (c >= 'A' && c <= 'Z') {
3801 folded += 0x20;
3802 }
3803 if (folded != nsHtml5Tokenizer::YSTEM[index]) {
3804 bogusDoctype();
3805 reconsume = true;
3806 state = P::transition(mViewSource.get(),
3807 nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume,
3808 pos);
3809 NS_HTML5_CONTINUE(stateloop);
3810 }
3811 index++;
3812 NS_HTML5_CONTINUE(stateloop);
3813 } else {
3814 reconsume = true;
3815 state = P::transition(
3816 mViewSource.get(),
3817 nsHtml5Tokenizer::AFTER_DOCTYPE_SYSTEM_KEYWORD, reconsume, pos);
3818 NS_HTML5_BREAK(doctypeystemloop);
3819 }
3820 }
3821 doctypeystemloop_end:;
3822 [[fallthrough]];
3823 }
3824 case AFTER_DOCTYPE_SYSTEM_KEYWORD: {
3825 for (;;) {
3826 if (reconsume) {
3827 reconsume = false;
3828 } else {
3829 if (++pos == endPos) {
3830 NS_HTML5_BREAK(stateloop);
3831 }
3832 c = checkChar(buf, pos);
3833 }
3834 switch (c) {
3835 case '\r': {
3836 silentCarriageReturn();
3837 state = P::transition(
3838 mViewSource.get(),
3839 nsHtml5Tokenizer::BEFORE_DOCTYPE_SYSTEM_IDENTIFIER, reconsume,
3840 pos);
3841 NS_HTML5_BREAK(stateloop);
3842 }
3843 case '\n': {
3844 silentLineFeed();
3845 [[fallthrough]];
3846 }
3847 case ' ':
3848 case '\t':
3849 case '\f': {
3850 state = P::transition(
3851 mViewSource.get(),
3852 nsHtml5Tokenizer::BEFORE_DOCTYPE_SYSTEM_IDENTIFIER, reconsume,
3853 pos);
3854 NS_HTML5_BREAK(afterdoctypesystemkeywordloop);
3855 }
3856 case '\"': {
3857 if (P::reportErrors) {
3858 errNoSpaceBetweenDoctypeSystemKeywordAndQuote();
3859 }
3860 clearStrBufBeforeUse();
3861 state = P::transition(
3862 mViewSource.get(),
3863 nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED,
3864 reconsume, pos);
3865 NS_HTML5_CONTINUE(stateloop);
3866 }
3867 case '\'': {
3868 if (P::reportErrors) {
3869 errNoSpaceBetweenDoctypeSystemKeywordAndQuote();
3870 }
3871 clearStrBufBeforeUse();
3872 state = P::transition(
3873 mViewSource.get(),
3874 nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED,
3875 reconsume, pos);
3876 NS_HTML5_CONTINUE(stateloop);
3877 }
3878 case '>': {
3879 if (P::reportErrors) {
3880 errExpectedPublicId();
3881 }
3882 forceQuirks = true;
3883 emitDoctypeToken(pos);
3884 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
3885 reconsume, pos);
3886 NS_HTML5_CONTINUE(stateloop);
3887 }
3888 default: {
3889 bogusDoctype();
3890 state = P::transition(mViewSource.get(),
3891 nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume,
3892 pos);
3893 NS_HTML5_CONTINUE(stateloop);
3894 }
3895 }
3896 }
3897 afterdoctypesystemkeywordloop_end:;
3898 [[fallthrough]];
3899 }
3900 case BEFORE_DOCTYPE_SYSTEM_IDENTIFIER: {
3901 for (;;) {
3902 if (++pos == endPos) {
3903 NS_HTML5_BREAK(stateloop);
3904 }
3905 c = checkChar(buf, pos);
3906 switch (c) {
3907 case '\r': {
3908 silentCarriageReturn();
3909 NS_HTML5_BREAK(stateloop);
3910 }
3911 case '\n': {
3912 silentLineFeed();
3913 [[fallthrough]];
3914 }
3915 case ' ':
3916 case '\t':
3917 case '\f': {
3918 continue;
3919 }
3920 case '\"': {
3921 clearStrBufBeforeUse();
3922 state = P::transition(
3923 mViewSource.get(),
3924 nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED,
3925 reconsume, pos);
3926 NS_HTML5_CONTINUE(stateloop);
3927 }
3928 case '\'': {
3929 clearStrBufBeforeUse();
3930 state = P::transition(
3931 mViewSource.get(),
3932 nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED,
3933 reconsume, pos);
3934 NS_HTML5_BREAK(beforedoctypesystemidentifierloop);
3935 }
3936 case '>': {
3937 if (P::reportErrors) {
3938 errExpectedSystemId();
3939 }
3940 forceQuirks = true;
3941 emitDoctypeToken(pos);
3942 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
3943 reconsume, pos);
3944 NS_HTML5_CONTINUE(stateloop);
3945 }
3946 default: {
3947 bogusDoctype();
3948 state = P::transition(mViewSource.get(),
3949 nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume,
3950 pos);
3951 NS_HTML5_CONTINUE(stateloop);
3952 }
3953 }
3954 }
3955 beforedoctypesystemidentifierloop_end:;
3956 [[fallthrough]];
3957 }
3958 case DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED: {
3959 for (;;) {
3960 if (++pos == endPos) {
3961 NS_HTML5_BREAK(stateloop);
3962 }
3963 c = checkChar(buf, pos);
3964 switch (c) {
3965 case '\'': {
3966 systemIdentifier = strBufToString();
3967 state = P::transition(
3968 mViewSource.get(),
3969 nsHtml5Tokenizer::AFTER_DOCTYPE_SYSTEM_IDENTIFIER, reconsume,
3970 pos);
3971 NS_HTML5_CONTINUE(stateloop);
3972 }
3973 case '>': {
3974 if (P::reportErrors) {
3975 errGtInSystemId();
3976 }
3977 forceQuirks = true;
3978 systemIdentifier = strBufToString();
3979 emitDoctypeToken(pos);
3980 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
3981 reconsume, pos);
3982 NS_HTML5_CONTINUE(stateloop);
3983 }
3984 case '\r': {
3985 appendStrBufCarriageReturn();
3986 NS_HTML5_BREAK(stateloop);
3987 }
3988 case '\n': {
3989 appendStrBufLineFeed();
3990 continue;
3991 }
3992 case '\0': {
3993 c = 0xfffd;
3994 [[fallthrough]];
3995 }
3996 default: {
3997 appendStrBuf(c);
3998 continue;
3999 }
4000 }
4001 }
4002 }
4003 case DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED: {
4004 for (;;) {
4005 if (++pos == endPos) {
4006 NS_HTML5_BREAK(stateloop);
4007 }
4008 c = checkChar(buf, pos);
4009 switch (c) {
4010 case '\'': {
4011 publicIdentifier = strBufToString();
4012 state = P::transition(
4013 mViewSource.get(),
4014 nsHtml5Tokenizer::AFTER_DOCTYPE_PUBLIC_IDENTIFIER, reconsume,
4015 pos);
4016 NS_HTML5_CONTINUE(stateloop);
4017 }
4018 case '>': {
4019 if (P::reportErrors) {
4020 errGtInPublicId();
4021 }
4022 forceQuirks = true;
4023 publicIdentifier = strBufToString();
4024 emitDoctypeToken(pos);
4025 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
4026 reconsume, pos);
4027 NS_HTML5_CONTINUE(stateloop);
4028 }
4029 case '\r': {
4030 appendStrBufCarriageReturn();
4031 NS_HTML5_BREAK(stateloop);
4032 }
4033 case '\n': {
4034 appendStrBufLineFeed();
4035 continue;
4036 }
4037 case '\0': {
4038 c = 0xfffd;
4039 [[fallthrough]];
4040 }
4041 default: {
4042 appendStrBuf(c);
4043 continue;
4044 }
4045 }
4046 }
4047 }
4048 case PROCESSING_INSTRUCTION: {
4049 for (;;) {
4050 if (++pos == endPos) {
4051 NS_HTML5_BREAK(stateloop);
4052 }
4053 c = checkChar(buf, pos);
4054 switch (c) {
4055 case '\?': {
4056 state = P::transition(
4057 mViewSource.get(),
4058 nsHtml5Tokenizer::PROCESSING_INSTRUCTION_QUESTION_MARK,
4059 reconsume, pos);
4060 NS_HTML5_BREAK(processinginstructionloop);
4061 }
4062 default: {
4063 continue;
4064 }
4065 }
4066 }
4067 processinginstructionloop_end:;
4068 [[fallthrough]];
4069 }
4070 case PROCESSING_INSTRUCTION_QUESTION_MARK: {
4071 if (++pos == endPos) {
4072 NS_HTML5_BREAK(stateloop);
4073 }
4074 c = checkChar(buf, pos);
4075 switch (c) {
4076 case '>': {
4077 state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
4078 reconsume, pos);
4079 NS_HTML5_CONTINUE(stateloop);
4080 }
4081 default: {
4082 state = P::transition(mViewSource.get(),
4083 nsHtml5Tokenizer::PROCESSING_INSTRUCTION,
4084 reconsume, pos);
4085 NS_HTML5_CONTINUE(stateloop);
4086 }
4087 }
4088 }
4089 }
4090 }
4091 stateloop_end:;
4092 flushChars(buf, pos);
4093 stateSave = state;
4094 returnStateSave = returnState;
4095 return pos;
4096 }
4097
initDoctypeFields()4098 void nsHtml5Tokenizer::initDoctypeFields() {
4099 clearStrBufAfterUse();
4100 doctypeName = nsGkAtoms::_empty;
4101 if (systemIdentifier) {
4102 systemIdentifier.Release();
4103 systemIdentifier = nullptr;
4104 }
4105 if (publicIdentifier) {
4106 publicIdentifier.Release();
4107 publicIdentifier = nullptr;
4108 }
4109 forceQuirks = false;
4110 }
4111
emitCarriageReturn(char16_t * buf,int32_t pos)4112 void nsHtml5Tokenizer::emitCarriageReturn(char16_t* buf, int32_t pos) {
4113 silentCarriageReturn();
4114 flushChars(buf, pos);
4115 tokenHandler->characters(nsHtml5Tokenizer::LF, 0, 1);
4116 cstart = INT32_MAX;
4117 }
4118
emitReplacementCharacter(char16_t * buf,int32_t pos)4119 void nsHtml5Tokenizer::emitReplacementCharacter(char16_t* buf, int32_t pos) {
4120 flushChars(buf, pos);
4121 tokenHandler->zeroOriginatingReplacementCharacter();
4122 cstart = pos + 1;
4123 }
4124
emitPlaintextReplacementCharacter(char16_t * buf,int32_t pos)4125 void nsHtml5Tokenizer::emitPlaintextReplacementCharacter(char16_t* buf,
4126 int32_t pos) {
4127 flushChars(buf, pos);
4128 tokenHandler->characters(REPLACEMENT_CHARACTER, 0, 1);
4129 cstart = pos + 1;
4130 }
4131
setAdditionalAndRememberAmpersandLocation(char16_t add)4132 void nsHtml5Tokenizer::setAdditionalAndRememberAmpersandLocation(char16_t add) {
4133 additional = add;
4134 }
4135
bogusDoctype()4136 void nsHtml5Tokenizer::bogusDoctype() {
4137 errBogusDoctype();
4138 forceQuirks = true;
4139 }
4140
bogusDoctypeWithoutQuirks()4141 void nsHtml5Tokenizer::bogusDoctypeWithoutQuirks() {
4142 errBogusDoctype();
4143 forceQuirks = false;
4144 }
4145
handleNcrValue(int32_t returnState)4146 void nsHtml5Tokenizer::handleNcrValue(int32_t returnState) {
4147 if (value <= 0xFFFF) {
4148 if (value >= 0x80 && value <= 0x9f) {
4149 errNcrInC1Range();
4150 char16_t* val = nsHtml5NamedCharacters::WINDOWS_1252[value - 0x80];
4151 emitOrAppendOne(val, returnState);
4152 } else if (value == 0x0) {
4153 errNcrZero();
4154 emitOrAppendOne(nsHtml5Tokenizer::REPLACEMENT_CHARACTER, returnState);
4155 } else if ((value & 0xF800) == 0xD800) {
4156 errNcrSurrogate();
4157 emitOrAppendOne(nsHtml5Tokenizer::REPLACEMENT_CHARACTER, returnState);
4158 } else {
4159 char16_t ch = (char16_t)value;
4160 bmpChar[0] = ch;
4161 emitOrAppendOne(bmpChar, returnState);
4162 }
4163 } else if (value <= 0x10FFFF) {
4164 astralChar[0] = (char16_t)(nsHtml5Tokenizer::LEAD_OFFSET + (value >> 10));
4165 astralChar[1] = (char16_t)(0xDC00 + (value & 0x3FF));
4166 emitOrAppendTwo(astralChar, returnState);
4167 } else {
4168 errNcrOutOfRange();
4169 emitOrAppendOne(nsHtml5Tokenizer::REPLACEMENT_CHARACTER, returnState);
4170 }
4171 }
4172
eof()4173 void nsHtml5Tokenizer::eof() {
4174 int32_t state = stateSave;
4175 int32_t returnState = returnStateSave;
4176 eofloop:
4177 for (;;) {
4178 switch (state) {
4179 case SCRIPT_DATA_LESS_THAN_SIGN:
4180 case SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN: {
4181 tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1);
4182 NS_HTML5_BREAK(eofloop);
4183 }
4184 case TAG_OPEN: {
4185 errEofAfterLt();
4186 tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1);
4187 NS_HTML5_BREAK(eofloop);
4188 }
4189 case RAWTEXT_RCDATA_LESS_THAN_SIGN: {
4190 tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1);
4191 NS_HTML5_BREAK(eofloop);
4192 }
4193 case NON_DATA_END_TAG_NAME: {
4194 tokenHandler->characters(nsHtml5Tokenizer::LT_SOLIDUS, 0, 2);
4195 emitStrBuf();
4196 NS_HTML5_BREAK(eofloop);
4197 }
4198 case CLOSE_TAG_OPEN: {
4199 errEofAfterLt();
4200 tokenHandler->characters(nsHtml5Tokenizer::LT_SOLIDUS, 0, 2);
4201 NS_HTML5_BREAK(eofloop);
4202 }
4203 case TAG_NAME: {
4204 errEofInTagName();
4205 NS_HTML5_BREAK(eofloop);
4206 }
4207 case BEFORE_ATTRIBUTE_NAME:
4208 case AFTER_ATTRIBUTE_VALUE_QUOTED:
4209 case SELF_CLOSING_START_TAG: {
4210 errEofWithoutGt();
4211 NS_HTML5_BREAK(eofloop);
4212 }
4213 case ATTRIBUTE_NAME: {
4214 errEofInAttributeName();
4215 NS_HTML5_BREAK(eofloop);
4216 }
4217 case AFTER_ATTRIBUTE_NAME:
4218 case BEFORE_ATTRIBUTE_VALUE: {
4219 errEofWithoutGt();
4220 NS_HTML5_BREAK(eofloop);
4221 }
4222 case ATTRIBUTE_VALUE_DOUBLE_QUOTED:
4223 case ATTRIBUTE_VALUE_SINGLE_QUOTED:
4224 case ATTRIBUTE_VALUE_UNQUOTED: {
4225 errEofInAttributeValue();
4226 NS_HTML5_BREAK(eofloop);
4227 }
4228 case BOGUS_COMMENT: {
4229 emitComment(0, 0);
4230 NS_HTML5_BREAK(eofloop);
4231 }
4232 case BOGUS_COMMENT_HYPHEN: {
4233 emitComment(0, 0);
4234 NS_HTML5_BREAK(eofloop);
4235 }
4236 case MARKUP_DECLARATION_OPEN: {
4237 errBogusComment();
4238 emitComment(0, 0);
4239 NS_HTML5_BREAK(eofloop);
4240 }
4241 case MARKUP_DECLARATION_HYPHEN: {
4242 errBogusComment();
4243 emitComment(0, 0);
4244 NS_HTML5_BREAK(eofloop);
4245 }
4246 case MARKUP_DECLARATION_OCTYPE: {
4247 if (index < 6) {
4248 errBogusComment();
4249 emitComment(0, 0);
4250 } else {
4251 errEofInDoctype();
4252 doctypeName = nsGkAtoms::_empty;
4253 if (systemIdentifier) {
4254 systemIdentifier.Release();
4255 systemIdentifier = nullptr;
4256 }
4257 if (publicIdentifier) {
4258 publicIdentifier.Release();
4259 publicIdentifier = nullptr;
4260 }
4261 forceQuirks = true;
4262 emitDoctypeToken(0);
4263 NS_HTML5_BREAK(eofloop);
4264 }
4265 NS_HTML5_BREAK(eofloop);
4266 }
4267 case COMMENT_START:
4268 case COMMENT: {
4269 errEofInComment();
4270 emitComment(0, 0);
4271 NS_HTML5_BREAK(eofloop);
4272 }
4273 case COMMENT_END: {
4274 errEofInComment();
4275 emitComment(2, 0);
4276 NS_HTML5_BREAK(eofloop);
4277 }
4278 case COMMENT_END_DASH:
4279 case COMMENT_START_DASH: {
4280 errEofInComment();
4281 emitComment(1, 0);
4282 NS_HTML5_BREAK(eofloop);
4283 }
4284 case COMMENT_END_BANG: {
4285 errEofInComment();
4286 emitComment(3, 0);
4287 NS_HTML5_BREAK(eofloop);
4288 }
4289 case DOCTYPE:
4290 case BEFORE_DOCTYPE_NAME: {
4291 errEofInDoctype();
4292 forceQuirks = true;
4293 emitDoctypeToken(0);
4294 NS_HTML5_BREAK(eofloop);
4295 }
4296 case DOCTYPE_NAME: {
4297 errEofInDoctype();
4298 strBufToDoctypeName();
4299 forceQuirks = true;
4300 emitDoctypeToken(0);
4301 NS_HTML5_BREAK(eofloop);
4302 }
4303 case DOCTYPE_UBLIC:
4304 case DOCTYPE_YSTEM:
4305 case AFTER_DOCTYPE_NAME:
4306 case AFTER_DOCTYPE_PUBLIC_KEYWORD:
4307 case AFTER_DOCTYPE_SYSTEM_KEYWORD:
4308 case BEFORE_DOCTYPE_PUBLIC_IDENTIFIER: {
4309 errEofInDoctype();
4310 forceQuirks = true;
4311 emitDoctypeToken(0);
4312 NS_HTML5_BREAK(eofloop);
4313 }
4314 case DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED:
4315 case DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED: {
4316 errEofInPublicId();
4317 forceQuirks = true;
4318 publicIdentifier = strBufToString();
4319 emitDoctypeToken(0);
4320 NS_HTML5_BREAK(eofloop);
4321 }
4322 case AFTER_DOCTYPE_PUBLIC_IDENTIFIER:
4323 case BEFORE_DOCTYPE_SYSTEM_IDENTIFIER:
4324 case BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS: {
4325 errEofInDoctype();
4326 forceQuirks = true;
4327 emitDoctypeToken(0);
4328 NS_HTML5_BREAK(eofloop);
4329 }
4330 case DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED:
4331 case DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED: {
4332 errEofInSystemId();
4333 forceQuirks = true;
4334 systemIdentifier = strBufToString();
4335 emitDoctypeToken(0);
4336 NS_HTML5_BREAK(eofloop);
4337 }
4338 case AFTER_DOCTYPE_SYSTEM_IDENTIFIER: {
4339 errEofInDoctype();
4340 forceQuirks = true;
4341 emitDoctypeToken(0);
4342 NS_HTML5_BREAK(eofloop);
4343 }
4344 case BOGUS_DOCTYPE: {
4345 emitDoctypeToken(0);
4346 NS_HTML5_BREAK(eofloop);
4347 }
4348 case CONSUME_CHARACTER_REFERENCE: {
4349 emitOrAppendCharRefBuf(returnState);
4350 state = returnState;
4351 continue;
4352 }
4353 case CHARACTER_REFERENCE_HILO_LOOKUP: {
4354 errNoNamedCharacterMatch();
4355 emitOrAppendCharRefBuf(returnState);
4356 state = returnState;
4357 continue;
4358 }
4359 case CHARACTER_REFERENCE_TAIL: {
4360 for (;;) {
4361 char16_t c = '\0';
4362 entCol++;
4363 for (;;) {
4364 if (hi == -1) {
4365 NS_HTML5_BREAK(hiloop);
4366 }
4367 if (entCol == nsHtml5NamedCharacters::NAMES[hi].length()) {
4368 NS_HTML5_BREAK(hiloop);
4369 }
4370 if (entCol > nsHtml5NamedCharacters::NAMES[hi].length()) {
4371 NS_HTML5_BREAK(outer);
4372 } else if (c < nsHtml5NamedCharacters::NAMES[hi].charAt(entCol)) {
4373 hi--;
4374 } else {
4375 NS_HTML5_BREAK(hiloop);
4376 }
4377 }
4378 hiloop_end:;
4379 for (;;) {
4380 if (hi < lo) {
4381 NS_HTML5_BREAK(outer);
4382 }
4383 if (entCol == nsHtml5NamedCharacters::NAMES[lo].length()) {
4384 candidate = lo;
4385 charRefBufMark = charRefBufLen;
4386 lo++;
4387 } else if (entCol > nsHtml5NamedCharacters::NAMES[lo].length()) {
4388 NS_HTML5_BREAK(outer);
4389 } else if (c > nsHtml5NamedCharacters::NAMES[lo].charAt(entCol)) {
4390 lo++;
4391 } else {
4392 NS_HTML5_BREAK(loloop);
4393 }
4394 }
4395 loloop_end:;
4396 if (hi < lo) {
4397 NS_HTML5_BREAK(outer);
4398 }
4399 continue;
4400 }
4401 outer_end:;
4402 if (candidate == -1) {
4403 errNoNamedCharacterMatch();
4404 emitOrAppendCharRefBuf(returnState);
4405 state = returnState;
4406 NS_HTML5_CONTINUE(eofloop);
4407 } else {
4408 const nsHtml5CharacterName& candidateName =
4409 nsHtml5NamedCharacters::NAMES[candidate];
4410 if (!candidateName.length() ||
4411 candidateName.charAt(candidateName.length() - 1) != ';') {
4412 if ((returnState & DATA_AND_RCDATA_MASK)) {
4413 char16_t ch;
4414 if (charRefBufMark == charRefBufLen) {
4415 ch = '\0';
4416 } else {
4417 ch = charRefBuf[charRefBufMark];
4418 }
4419 if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') ||
4420 (ch >= 'a' && ch <= 'z')) {
4421 errNoNamedCharacterMatch();
4422 appendCharRefBufToStrBuf();
4423 state = returnState;
4424 NS_HTML5_CONTINUE(eofloop);
4425 }
4426 }
4427 if ((returnState & DATA_AND_RCDATA_MASK)) {
4428 errUnescapedAmpersandInterpretedAsCharacterReference();
4429 } else {
4430 errNotSemicolonTerminated();
4431 }
4432 }
4433 const char16_t* val = nsHtml5NamedCharacters::VALUES[candidate];
4434 if (!val[1]) {
4435 emitOrAppendOne(val, returnState);
4436 } else {
4437 emitOrAppendTwo(val, returnState);
4438 }
4439 if (charRefBufMark < charRefBufLen) {
4440 if ((returnState & DATA_AND_RCDATA_MASK)) {
4441 appendStrBuf(charRefBuf, charRefBufMark,
4442 charRefBufLen - charRefBufMark);
4443 } else {
4444 tokenHandler->characters(charRefBuf, charRefBufMark,
4445 charRefBufLen - charRefBufMark);
4446 }
4447 }
4448 charRefBufLen = 0;
4449 state = returnState;
4450 NS_HTML5_CONTINUE(eofloop);
4451 }
4452 }
4453 case CONSUME_NCR:
4454 case DECIMAL_NRC_LOOP:
4455 case HEX_NCR_LOOP: {
4456 if (!seenDigits) {
4457 errNoDigitsInNCR();
4458 emitOrAppendCharRefBuf(returnState);
4459 state = returnState;
4460 continue;
4461 } else {
4462 errCharRefLacksSemicolon();
4463 }
4464 handleNcrValue(returnState);
4465 state = returnState;
4466 continue;
4467 }
4468 case CDATA_RSQB: {
4469 tokenHandler->characters(nsHtml5Tokenizer::RSQB_RSQB, 0, 1);
4470 NS_HTML5_BREAK(eofloop);
4471 }
4472 case CDATA_RSQB_RSQB: {
4473 tokenHandler->characters(nsHtml5Tokenizer::RSQB_RSQB, 0, 2);
4474 NS_HTML5_BREAK(eofloop);
4475 }
4476 case DATA:
4477 default: {
4478 NS_HTML5_BREAK(eofloop);
4479 }
4480 }
4481 }
4482 eofloop_end:;
4483 tokenHandler->eof();
4484 return;
4485 }
4486
emitDoctypeToken(int32_t pos)4487 void nsHtml5Tokenizer::emitDoctypeToken(int32_t pos) {
4488 cstart = pos + 1;
4489 tokenHandler->doctype(doctypeName, publicIdentifier, systemIdentifier,
4490 forceQuirks);
4491 doctypeName = nullptr;
4492 publicIdentifier.Release();
4493 publicIdentifier = nullptr;
4494 systemIdentifier.Release();
4495 systemIdentifier = nullptr;
4496 }
4497
internalEncodingDeclaration(nsHtml5String internalCharset)4498 bool nsHtml5Tokenizer::internalEncodingDeclaration(
4499 nsHtml5String internalCharset) {
4500 if (encodingDeclarationHandler) {
4501 return encodingDeclarationHandler->internalEncodingDeclaration(
4502 internalCharset);
4503 }
4504 return false;
4505 }
4506
emitOrAppendTwo(const char16_t * val,int32_t returnState)4507 void nsHtml5Tokenizer::emitOrAppendTwo(const char16_t* val,
4508 int32_t returnState) {
4509 if ((returnState & DATA_AND_RCDATA_MASK)) {
4510 appendStrBuf(val[0]);
4511 appendStrBuf(val[1]);
4512 } else {
4513 tokenHandler->characters(val, 0, 2);
4514 }
4515 }
4516
emitOrAppendOne(const char16_t * val,int32_t returnState)4517 void nsHtml5Tokenizer::emitOrAppendOne(const char16_t* val,
4518 int32_t returnState) {
4519 if ((returnState & DATA_AND_RCDATA_MASK)) {
4520 appendStrBuf(val[0]);
4521 } else {
4522 tokenHandler->characters(val, 0, 1);
4523 }
4524 }
4525
end()4526 void nsHtml5Tokenizer::end() {
4527 strBuf = nullptr;
4528 doctypeName = nullptr;
4529 if (systemIdentifier) {
4530 systemIdentifier.Release();
4531 systemIdentifier = nullptr;
4532 }
4533 if (publicIdentifier) {
4534 publicIdentifier.Release();
4535 publicIdentifier = nullptr;
4536 }
4537 tagName = nullptr;
4538 nonInternedTagName->setNameForNonInterned(nullptr, false);
4539 attributeName = nullptr;
4540 nonInternedAttributeName->setNameForNonInterned(nullptr);
4541 tokenHandler->endTokenization();
4542 if (attributes) {
4543 attributes->clear(0);
4544 }
4545 }
4546
requestSuspension()4547 void nsHtml5Tokenizer::requestSuspension() { shouldSuspend = true; }
4548
isInDataState()4549 bool nsHtml5Tokenizer::isInDataState() { return (stateSave == DATA); }
4550
resetToDataState()4551 void nsHtml5Tokenizer::resetToDataState() {
4552 clearStrBufAfterUse();
4553 charRefBufLen = 0;
4554 stateSave = nsHtml5Tokenizer::DATA;
4555 lastCR = false;
4556 index = 0;
4557 forceQuirks = false;
4558 additional = '\0';
4559 entCol = -1;
4560 firstCharKey = -1;
4561 lo = 0;
4562 hi = 0;
4563 candidate = -1;
4564 charRefBufMark = 0;
4565 value = 0;
4566 seenDigits = false;
4567 endTag = false;
4568 shouldSuspend = false;
4569 initDoctypeFields();
4570 containsHyphen = false;
4571 tagName = nullptr;
4572 attributeName = nullptr;
4573 if (newAttributesEachTime) {
4574 if (attributes) {
4575 delete attributes;
4576 attributes = nullptr;
4577 }
4578 }
4579 }
4580
loadState(nsHtml5Tokenizer * other)4581 void nsHtml5Tokenizer::loadState(nsHtml5Tokenizer* other) {
4582 strBufLen = other->strBufLen;
4583 if (strBufLen > strBuf.length) {
4584 strBuf = jArray<char16_t, int32_t>::newJArray(strBufLen);
4585 }
4586 nsHtml5ArrayCopy::arraycopy(other->strBuf, strBuf, strBufLen);
4587 charRefBufLen = other->charRefBufLen;
4588 nsHtml5ArrayCopy::arraycopy(other->charRefBuf, charRefBuf, charRefBufLen);
4589 stateSave = other->stateSave;
4590 returnStateSave = other->returnStateSave;
4591 endTagExpectation = other->endTagExpectation;
4592 endTagExpectationAsArray = other->endTagExpectationAsArray;
4593 lastCR = other->lastCR;
4594 index = other->index;
4595 forceQuirks = other->forceQuirks;
4596 additional = other->additional;
4597 entCol = other->entCol;
4598 firstCharKey = other->firstCharKey;
4599 lo = other->lo;
4600 hi = other->hi;
4601 candidate = other->candidate;
4602 charRefBufMark = other->charRefBufMark;
4603 value = other->value;
4604 seenDigits = other->seenDigits;
4605 endTag = other->endTag;
4606 shouldSuspend = false;
4607 doctypeName = other->doctypeName;
4608 systemIdentifier.Release();
4609 if (!other->systemIdentifier) {
4610 systemIdentifier = nullptr;
4611 } else {
4612 systemIdentifier =
4613 nsHtml5Portability::newStringFromString(other->systemIdentifier);
4614 }
4615 publicIdentifier.Release();
4616 if (!other->publicIdentifier) {
4617 publicIdentifier = nullptr;
4618 } else {
4619 publicIdentifier =
4620 nsHtml5Portability::newStringFromString(other->publicIdentifier);
4621 }
4622 containsHyphen = other->containsHyphen;
4623 if (!other->tagName) {
4624 tagName = nullptr;
4625 } else if (other->tagName->isInterned()) {
4626 tagName = other->tagName;
4627 } else {
4628 nonInternedTagName->setNameForNonInterned(other->tagName->getName(),
4629 other->tagName->isCustom());
4630 tagName = nonInternedTagName;
4631 }
4632 if (!other->attributeName) {
4633 attributeName = nullptr;
4634 } else if (other->attributeName->isInterned()) {
4635 attributeName = other->attributeName;
4636 } else {
4637 nonInternedAttributeName->setNameForNonInterned(
4638 other->attributeName->getLocal(nsHtml5AttributeName::HTML));
4639 attributeName = nonInternedAttributeName;
4640 }
4641 delete attributes;
4642 if (!other->attributes) {
4643 attributes = nullptr;
4644 } else {
4645 attributes = other->attributes->cloneAttributes();
4646 }
4647 }
4648
initializeWithoutStarting()4649 void nsHtml5Tokenizer::initializeWithoutStarting() {
4650 confident = false;
4651 strBuf = nullptr;
4652 line = 1;
4653 attributeLine = 1;
4654 resetToDataState();
4655 }
4656
setEncodingDeclarationHandler(nsHtml5StreamParser * encodingDeclarationHandler)4657 void nsHtml5Tokenizer::setEncodingDeclarationHandler(
4658 nsHtml5StreamParser* encodingDeclarationHandler) {
4659 this->encodingDeclarationHandler = encodingDeclarationHandler;
4660 }
4661
~nsHtml5Tokenizer()4662 nsHtml5Tokenizer::~nsHtml5Tokenizer() {
4663 MOZ_COUNT_DTOR(nsHtml5Tokenizer);
4664 delete nonInternedTagName;
4665 nonInternedTagName = nullptr;
4666 delete nonInternedAttributeName;
4667 nonInternedAttributeName = nullptr;
4668 delete attributes;
4669 attributes = nullptr;
4670 }
4671
initializeStatics()4672 void nsHtml5Tokenizer::initializeStatics() {}
4673
releaseStatics()4674 void nsHtml5Tokenizer::releaseStatics() {}
4675
4676 #include "nsHtml5TokenizerCppSupplement.h"
4677