Skip to content

Commit 21dedfa

Browse files
authored
fix(tokenizer): require full --> to close comments in xmlMode (#2383)
In HTML, `<!-->` is a valid empty comment per the spec. However, in XML comments must be closed by `-->`, so `<!-->` should be treated as an opening — not a complete comment. Skip the short-comment shortcut when xmlMode is enabled. Fixes #1823
1 parent f2daa22 commit 21dedfa

3 files changed

Lines changed: 80 additions & 2 deletions

File tree

src/Tokenizer.spec.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,15 @@ describe("Tokenizer", () => {
158158
).toMatchSnapshot();
159159
});
160160

161+
it("should not treat <!--> as a complete comment in xmlMode", () => {
162+
expect(
163+
tokenize(
164+
"<root><node>start</node><!--><node>should ignore</node><--><node>end</node></root>",
165+
{ xmlMode: true },
166+
),
167+
).toMatchSnapshot();
168+
});
169+
161170
it.each([
162171
"script",
163172
"style",

src/Tokenizer.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -622,8 +622,11 @@ export default class Tokenizer {
622622
if (c === CharCodes.Dash) {
623623
this.state = State.InCommentLike;
624624
this.currentSequence = Sequences.CommentEnd;
625-
// Allow short comments (eg. <!-->)
626-
this.sequenceIndex = 2;
625+
/*
626+
* In HTML, `<!-->` is a valid empty comment. In XML, comments
627+
* must be closed by `-->`, so we require the full sequence.
628+
*/
629+
this.sequenceIndex = this.xmlMode ? 0 : 2;
627630
this.sectionStart = this.index + 1;
628631
} else {
629632
this.state = State.InDeclaration;

src/__snapshots__/Tokenizer.spec.ts.snap

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,72 @@ exports[`Tokenizer > should not lose data when pausing 1`] = `
565565
]
566566
`;
567567

568+
exports[`Tokenizer > should not treat <!--> as a complete comment in xmlMode 1`] = `
569+
[
570+
[
571+
"onopentagname",
572+
1,
573+
5,
574+
],
575+
[
576+
"onopentagend",
577+
5,
578+
],
579+
[
580+
"onopentagname",
581+
7,
582+
11,
583+
],
584+
[
585+
"onopentagend",
586+
11,
587+
],
588+
[
589+
"ontext",
590+
12,
591+
17,
592+
],
593+
[
594+
"onclosetag",
595+
19,
596+
23,
597+
],
598+
[
599+
"oncomment",
600+
28,
601+
58,
602+
2,
603+
],
604+
[
605+
"onopentagname",
606+
60,
607+
64,
608+
],
609+
[
610+
"onopentagend",
611+
64,
612+
],
613+
[
614+
"ontext",
615+
65,
616+
68,
617+
],
618+
[
619+
"onclosetag",
620+
70,
621+
74,
622+
],
623+
[
624+
"onclosetag",
625+
77,
626+
81,
627+
],
628+
[
629+
"onend",
630+
],
631+
]
632+
`;
633+
568634
exports[`Tokenizer > should support self-closing special tags > for self-closing script tag 1`] = `
569635
[
570636
[

0 commit comments

Comments
 (0)