fix(syntax): stop swallowing literal backslashes in attribute values

readQuoted treated \X as an escape for any X, so a single literal
backslash in any quoted attribute value was silently dropped
(data-path="C:\Users" parsed as C:Users) and a doubled backslash
collapsed to one. Only the delimiter and the backslash itself are
escapes now; every other backslash is a literal character.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-20 11:42:29 +05:30
co-authored by Claude Opus 5
parent 63316111cb
commit fb24cc7ec3
2 changed files with 58 additions and 4 deletions
+5 -4
View File
@@ -1022,12 +1022,13 @@ export function parseHtmlView(src: string, pos: number): { nodes: ViewNode[]; en
const quote = src[i];
if (quote !== '"' && quote !== "'") return fail("Expected a quoted attribute value");
i++;
// Backslash-escapes the delimiter (and anything else) so an attribute
// value -- e.g. an `api="fn({ a: \"b\" })"` call expression -- can carry
// the same quote character it's wrapped in.
// Backslash escapes the delimiter -- so an attribute value such as the
// call expression `api="fn({ a: \"b\" })"` can carry the same quote
// character it's wrapped in -- and escapes itself. Every other backslash
// is a literal one, so a value like "C:\Users\name" survives intact.
let value = "";
while (i < src.length && src[i] !== quote) {
if (src[i] === "\\" && i + 1 < src.length) {
if (src[i] === "\\" && (src[i + 1] === quote || src[i + 1] === "\\")) {
value += src[i + 1];
i += 2;
continue;