From 867ace3cb36ba08e7c5a4b20cad6641476561690 Mon Sep 17 00:00:00 2001 From: Brad Arant Date: Sat, 10 Oct 2026 16:49:53 +0000 Subject: [PATCH] Give jetc a dedicated, fully inert handler at compile time had no special-case in jetc's compiler at all - it fell through to parseFallback(), the generic unknown-tag path, which hunts for a tag's own closing tag via scanBody()/skipQuotedValue(), the same quote-aware, backslash-escape-interpreting scanning real Jet attribute syntax needs. A comment containing an explanatory " sequence (a JSON example in prose, say) or a literal /-looking word - both already confirmed, separately, to corrupt jetc when they turn up inside a JS // comment - hit the exact same corruption here too, just triggered from inside a block instead. Added skipCommentTag(), which only tracks same-tag-name nesting depth via the existing case-insensitive matchTagOpen/matchTagClose and otherwise ignores every character - no quote tracking, no other-tag recognition, nothing a comment's own body could ever trip over. Wired into parseNodes() alongside the other recognized top-level tags; unlike those, it pushes no node at all; the comment contributes nothing to the compiled output, matching the runtime interpreters own __comment behavior but now safe at compile time too. Verified directly: a scratch .jet with five blocks (plain, a bare quote, a backslash-quote JSON example, literal / text, and nested comments with their own quotes) all compiled clean and left zero trace in the generated code, with the immediately following them compiling correctly too - confirming nothing after a tricky comment gets corrupted either. Co-Authored-By: Claude Sonnet 5 --- jetc/JetParser.cpp | 43 +++++++++++++++++++++++++++++++++++++++++++ jetc/JetParser.h | 9 +++++++++ 2 files changed, 52 insertions(+) diff --git a/jetc/JetParser.cpp b/jetc/JetParser.cpp index 537259e..d4c792b 100755 --- a/jetc/JetParser.cpp +++ b/jetc/JetParser.cpp @@ -162,6 +162,48 @@ namespace jetc { } } + // Advances p from '<' of "... construct, including any nested + // tags, counted the same case-insensitive way everything else in this + // file matches tag names. Deliberately does NOT call skipOpenTag/ + // skipQuotedValue/skipEmbeddedTag or any other quote- or tag-aware + // scanning on the body text - a comment containing an explanatory '"' + // or '\"' (about the code itself, say) previously fell through to + // parseFallback()'s generic path, which DOES apply those rules while + // hunting for this same closing tag, and silently mislocated it + // exactly like the already-documented JS-comment-corrupts-jetc bug + // class, just triggered from inside a instead of a // + // comment. This only ever advances past '<'/'>' boundaries it + // recognizes as comment open/close - nothing inside can affect it. + void Parser::skipCommentTag(size_t &p) { + p += 8; // "') selfClosing = true; + p++; + } + if (p < s.size()) p++; // past '>' + if (selfClosing) return; + int depth = 1; + while (p < s.size()) { + if (matchTagOpen("comment", p)) { + depth++; + p++; + continue; + } + if (matchTagClose("comment", p)) { + p += 2; // "') p++; + depth--; + if (depth == 0) return; + continue; + } + p++; + } + } + bool Parser::skipOpenTag(size_t &p) { p++; // '<' while (p < s.size() && isNameChar(s[p])) p++; @@ -555,6 +597,7 @@ namespace jetc { continue; } if (matchTagOpen("container", pos)) { flush(); nodes.push_back(parseContainerSlot()); continue; } + if (matchTagOpen("comment", pos)) { flush(); skipCommentTag(pos); continue; } if (topLevel && matchTagOpen("tag", pos)) { flush(); nodes.push_back(parseTagDef()); continue; } flush(); nodes.push_back(parseFallback()); diff --git a/jetc/JetParser.h b/jetc/JetParser.h index 5b97b05..3d36a18 100755 --- a/jetc/JetParser.h +++ b/jetc/JetParser.h @@ -61,6 +61,15 @@ namespace jetc { void skipQuotedValue(size_t &p); void skipEmbeddedTag(size_t &p); + // ... must be fully inert regardless of what's + // inside it - unlike the generic parseFallback/scanBody path this + // tag used to fall through to (which applies the same quote/ + // backslash-escape and nested-tag scanning real Jet syntax needs), + // this tracks only same-tag-name nesting depth via matchTagOpen/ + // matchTagClose and otherwise ignores every character. See its own + // definition for the quote-corruption bug this specifically closes. + void skipCommentTag(size_t &p); + std::map parseAttrs(bool &hasContainer); // Scans forward from bodyStart (just after the opening tag's '>') for