chore: fit the loop-locals fix within the production gate

Three things the gate caught that the test suite could not.

The runtime size budget: writing `data-wrn-loop-locals` on client-rendered
loop items pushed reactive-runtime.ts to 51,603 against a 51,400 budget that
had only 125 bytes of headroom. Trimmed the encoder to the
btoa/encodeURIComponent idiom, recovering 65 bytes and leaving the smallest
form that still handles non-ASCII, then raised the budget to 51,600 with the
reason recorded in the file's own convention -- the remaining 263 bytes buy a
correctness fix, not a feature.

The VS Code extension bundles its own copy of the compiler, so the syntax and
compiler fixes made it stale. Rebuilt.

And a bug in the new test: `\{` inside a template literal is an unnecessary
escape, so the "brace inside a regex" case was testing an unescaped brace.
`\{` tests the case it was written for.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-22 12:08:07 +05:30
co-authored by Claude Opus 5
parent 2d0df4efc9
commit 2299a0726d
6 changed files with 256 additions and 36 deletions
+76 -3
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env node
// WRN editor language server source hash: e55270eb33d7722a82d13d3a79097fea77eca69612aeba104e9cbdd8fc67e8c6
// WRN editor language server source hash: cea070c2eebb5339c7b48f4200d34e51f2adb16eba4d6d3f92e5040081c5b079
// WRN editor language server generator hash: f593a44aaf05495b789ce7a3086bee1eebb951b884d41c0e017bbcfe5f547e72
// @bun @bun-cjs
(function(exports, require, module, __filename, __dirname) {var __create = Object.create;
@@ -169671,6 +169671,64 @@ var isWs = (c) => c === " " || c === "\t" || c === `
` || c === "\r";
var isIdentStart = (c) => /[A-Za-z_]/.test(c);
var isIdentPart = (c) => /[A-Za-z0-9_]/.test(c);
var REGEX_PRECEDING_KEYWORDS = new Set([
"return",
"typeof",
"instanceof",
"in",
"of",
"new",
"delete",
"void",
"do",
"else",
"yield",
"await",
"case"
]);
function opensRegex(src, i) {
let j = i - 1;
while (j >= 0 && (src[j] === " " || src[j] === "\t" || src[j] === "\r" || src[j] === `
`))
j--;
if (j < 0)
return true;
const prev = src[j];
if (/[A-Za-z0-9_$]/.test(prev)) {
let k = j;
while (k >= 0 && /[A-Za-z0-9_$]/.test(src[k]))
k--;
return REGEX_PRECEDING_KEYWORDS.has(src.slice(k + 1, j + 1));
}
return prev !== ")" && prev !== "]" && prev !== "." && prev !== '"' && prev !== "'" && prev !== "`";
}
function skipRegex(src, i) {
let j = i + 1;
let inClass = false;
while (j < src.length) {
const c = src[j];
if (c === `
`)
return null;
if (c === "\\") {
j += 2;
continue;
}
if (inClass) {
if (c === "]")
inClass = false;
} else if (c === "[") {
inClass = true;
} else if (c === "/") {
j++;
while (j < src.length && /[a-z]/.test(src[j]))
j++;
return j;
}
j++;
}
return null;
}
function skipLiteralOrComment(src, i, atLineStart) {
const c = src[i];
if (c === "/" && src[i + 1] === "*") {
@@ -169695,6 +169753,9 @@ function skipLiteralOrComment(src, i, atLineStart) {
}
return src.length;
}
if (c === "/" && opensRegex(src, i)) {
return skipRegex(src, i);
}
return null;
}
@@ -169704,7 +169765,7 @@ class Lexer {
constructor(src) {
this.src = src;
}
skipTrivia() {
skipWhitespaceAndLineComments() {
const { src } = this;
while (this.pos < src.length) {
const c = src[this.pos];
@@ -169721,8 +169782,20 @@ class Lexer {
break;
}
}
skipTrivia() {
const { src } = this;
while (this.pos < src.length) {
this.skipWhitespaceAndLineComments();
if (src[this.pos] === "/" && src[this.pos + 1] === "*") {
const close = src.indexOf("*/", this.pos + 2);
this.pos = close === -1 ? src.length : close + 2;
continue;
}
break;
}
}
startsWithBlockComment() {
this.skipTrivia();
this.skipWhitespaceAndLineComments();
return this.src[this.pos] === "/" && this.src[this.pos + 1] === "*";
}
next() {