@ape-egg/vibe 2.1.15 → 2.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/compiler/native/vibe-compiler-darwin-arm64 +0 -0
- package/compiler/native/vibe-compiler-linux-x64 +0 -0
- package/compiler/src/Cargo.lock +1 -1
- package/compiler/src/Cargo.toml +1 -1
- package/compiler/src/parser/html.rs +26 -1
- package/package.json +1 -1
- package/runtime/component.js +17 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.1.16] - 2026-06-22
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **Compiler 1.9.9 → 2.0.0 — bare prop substitution corrupted matching text inside string literals** (`compiler/src/parser/html.rs`, `runtime/component.js`) — the bare-prop-identifier rewrite added in 2.1.14 (so `onclick="pick(item)"` resolves the live prop) replaced *every* whole-word occurrence of the prop name, including ones inside a quoted string. A prop named `slot` rewrote the selector in `closest('brawler-slot')`, corrupting it. Both the compiler's `substitute_identifier` and the runtime's `substituteInExpr` now track string-literal boundaries (`'`, `"`, and backtick, honouring escapes; template `${…}` counts as part of the literal) and substitute only the code spans between them, leaving identifiers inside string literals intact. The two sides stay byte-for-byte identical, preserving compiled/runtime parity.
|
|
8
|
+
|
|
3
9
|
## [2.1.15] - 2026-06-22
|
|
4
10
|
|
|
5
11
|
### Fixed
|
|
Binary file
|
|
Binary file
|
package/compiler/src/Cargo.lock
CHANGED
package/compiler/src/Cargo.toml
CHANGED
|
@@ -542,7 +542,32 @@ fn substitute_identifier(expr: &str, name: &str, replacement: &str) -> String {
|
|
|
542
542
|
}
|
|
543
543
|
let mut out: Vec<u8> = Vec::with_capacity(bytes.len());
|
|
544
544
|
let mut i = 0;
|
|
545
|
+
// Delimiter of the string literal we're currently inside, or 0 when in code.
|
|
546
|
+
// A prop identifier that appears inside a quoted string (e.g. the selector in
|
|
547
|
+
// `closest('brawler-slot')`) must be left intact, mirroring the runtime's
|
|
548
|
+
// substituteInExpr. Template `${…}` counts as part of the literal here.
|
|
549
|
+
let mut quote: u8 = 0;
|
|
545
550
|
while i < bytes.len() {
|
|
551
|
+
let b = bytes[i];
|
|
552
|
+
if quote != 0 {
|
|
553
|
+
out.push(b);
|
|
554
|
+
if b == b'\\' && i + 1 < bytes.len() {
|
|
555
|
+
out.push(bytes[i + 1]);
|
|
556
|
+
i += 2;
|
|
557
|
+
continue;
|
|
558
|
+
}
|
|
559
|
+
if b == quote {
|
|
560
|
+
quote = 0;
|
|
561
|
+
}
|
|
562
|
+
i += 1;
|
|
563
|
+
continue;
|
|
564
|
+
}
|
|
565
|
+
if b == b'\'' || b == b'"' || b == b'`' {
|
|
566
|
+
quote = b;
|
|
567
|
+
out.push(b);
|
|
568
|
+
i += 1;
|
|
569
|
+
continue;
|
|
570
|
+
}
|
|
546
571
|
if i + nlen <= bytes.len()
|
|
547
572
|
&& bytes[i..i + nlen].eq_ignore_ascii_case(nb)
|
|
548
573
|
&& (i == 0 || (!is_ident_byte(bytes[i - 1]) && bytes[i - 1] != b'.'))
|
|
@@ -551,7 +576,7 @@ fn substitute_identifier(expr: &str, name: &str, replacement: &str) -> String {
|
|
|
551
576
|
out.extend_from_slice(replacement.as_bytes());
|
|
552
577
|
i += nlen;
|
|
553
578
|
} else {
|
|
554
|
-
out.push(
|
|
579
|
+
out.push(b);
|
|
555
580
|
i += 1;
|
|
556
581
|
}
|
|
557
582
|
}
|
package/package.json
CHANGED
package/runtime/component.js
CHANGED
|
@@ -350,7 +350,23 @@ const renderPropsAndSlot = (temp, props, slotHtml) => {
|
|
|
350
350
|
'gi'
|
|
351
351
|
);
|
|
352
352
|
|
|
353
|
-
|
|
353
|
+
// Rewrite the identifier only outside string literals. A prop/alias that also
|
|
354
|
+
// appears inside a quoted string — e.g. the selector in `closest('brawler-slot')`
|
|
355
|
+
// when the prop is `slot` — must be left intact. Split on string literals
|
|
356
|
+
// (single/double/backtick, honouring escapes) and substitute only the code spans
|
|
357
|
+
// between them. Template `${…}` interpolation counts as part of the literal here.
|
|
358
|
+
const stringLiteral = /(['"`])(?:\\.|(?!\1)[^\\])*\1/g;
|
|
359
|
+
const substituteInExpr = (expr, replacement) => {
|
|
360
|
+
let out = '';
|
|
361
|
+
let last = 0;
|
|
362
|
+
let m;
|
|
363
|
+
stringLiteral.lastIndex = 0;
|
|
364
|
+
while ((m = stringLiteral.exec(expr))) {
|
|
365
|
+
out += expr.slice(last, m.index).replace(idRegex, replacement) + m[0];
|
|
366
|
+
last = m.index + m[0].length;
|
|
367
|
+
}
|
|
368
|
+
return out + expr.slice(last).replace(idRegex, replacement);
|
|
369
|
+
};
|
|
354
370
|
|
|
355
371
|
if (bindingMatch) {
|
|
356
372
|
const path = bindingMatch[1];
|