From d9b0837975cecb7e3a7d2635f152c952b5791f17 Mon Sep 17 00:00:00 2001 From: snowingfox <1503401882@qq.com> Date: Tue, 11 Aug 2026 23:20:18 +0000 Subject: [PATCH] fix: escape processing-instruction content under fallback raw-content elements Fixes #70146 --- lib/NodeUtils.js | 8 +++++++- test/domino.js | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/lib/NodeUtils.js b/lib/NodeUtils.js index a0a4962..7900a99 100644 --- a/lib/NodeUtils.js +++ b/lib/NodeUtils.js @@ -309,7 +309,13 @@ function serializeOne(kid, parent) { s += ''; break; case 7: //PROCESSING_INSTRUCTION_NODE - const content = escapeProcessingInstructionContent(kid.data); + let content = escapeProcessingInstructionContent(kid.data); + if (content.includes(''; break; case 10: //DOCUMENT_TYPE_NODE diff --git a/test/domino.js b/test/domino.js index 916e09d..8122768 100644 --- a/test/domino.js +++ b/test/domino.js @@ -1556,3 +1556,45 @@ exports.worksWithBase64DataImages = function () { 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII);">' ); }; + +exports.processingInstructionClosingTagEscapedInNoscript = function () { + // A processing-instruction payload that begins with a fallback raw-content + // closing tag (e.g. ` + // element early in the receiving browser (RAWTEXT) and the sibling + // is re-parsed as live HTML. + // Regression for angular/angular#70146: the fc7e40a (#70050) and e0779df + // (#70055) fixes escaped element/text/comment branches of serializeOne() + // but the PROCESSING_INSTRUCTION_NODE branch (case 7) never called + // fallbackRawContentTags(), and escapeProcessingInstructionContent() + // only escapes `>` (leaving `<` alone). + const document = domino.createDocument(''); + const noscript = document.createElement('noscript'); + noscript.appendChild(document.createProcessingInstruction('x', '' + ); + // The PI payload must not leak an unescaped closing-tag prefix. + html.should.not.containEql(''); + html.should.not.containEql('