@ape-egg/vibe 2.1.13 → 2.1.14
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 +7 -1
- package/package.json +1 -1
- package/runtime/component.js +9 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.1.14] - 2026-06-22
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **Compiler 1.9.8 → 1.9.9 — a component prop referenced *bare* inside an event handler threw at fire time** (`compiler/src/parser/html.rs`, `runtime/component.js`) — prop substitution into `on*` handlers only rewrote the `$.prop` form, so a bare prop reference (`onclick="pick(item)"` where `item` is a prop) was left untouched. Because a native inline handler runs in *global* scope when it fires, that bare identifier resolved to an undefined global and threw a `ReferenceError`. Both the compiler's `substitute_props` and the runtime's `renderPropsAndSlot` now also substitute the bare prop identifier — mirroring the existing `@[...]` binding pass — so the handler receives the live prop with object identity preserved: a loop-alias path (`row.sig`) becomes `(row.sig)`, which `parse.js` rewrites to the scoped accessor, and a literal prop (`limit="5"`) inlines as the numeric `5`. The bare pass skips the `$.prop` form (lookbehind guard) so the two rewrites don't collide. Tests: `e2e-runtime/prop-in-handler.html` + `components/test-prop-handler.html`, exercised by `tests/e2e/component-props.spec.js`.
|
|
8
|
+
|
|
3
9
|
## [2.1.13] - 2026-06-22
|
|
4
10
|
|
|
5
11
|
### Fixed
|
|
Binary file
|
|
Binary file
|
package/compiler/src/Cargo.lock
CHANGED
package/compiler/src/Cargo.toml
CHANGED
|
@@ -690,7 +690,13 @@ fn substitute_props(template: &str, props: &[(String, String)]) -> String {
|
|
|
690
690
|
.replace_all(&html, |c: ®ex::Captures| {
|
|
691
691
|
let ev = c.get(1).unwrap().as_str();
|
|
692
692
|
let body = c.get(2).unwrap().as_str();
|
|
693
|
-
|
|
693
|
+
// First the `$.prop` form, then the bare prop identifier — mirroring
|
|
694
|
+
// the runtime's two-step rewrite so `onclick="pick(item)"` resolves
|
|
695
|
+
// the live prop instead of throwing ReferenceError in global scope.
|
|
696
|
+
// The bare pass skips `$.prop` (its `.`-lookbehind guard) so the two
|
|
697
|
+
// don't collide.
|
|
698
|
+
let after_state = substitute_state_ref(body, prop_name, &state_repl);
|
|
699
|
+
let rewritten = substitute_identifier(&after_state, prop_name, &ident_repl);
|
|
694
700
|
if rewritten == body {
|
|
695
701
|
c.get(0).unwrap().as_str().to_string()
|
|
696
702
|
} else {
|
package/package.json
CHANGED
package/runtime/component.js
CHANGED
|
@@ -369,7 +369,12 @@ const renderPropsAndSlot = (temp, props, slotHtml) => {
|
|
|
369
369
|
);
|
|
370
370
|
const stateRegex = new RegExp(`\\$\\.${escapeRegex(propName)}(?![a-zA-Z0-9_$])`, 'gi');
|
|
371
371
|
transformedHtml = transformedHtml.replace(EVENT_ATTR_REGEX, (match, evName, body) => {
|
|
372
|
-
|
|
372
|
+
// Substitute the bare prop identifier too (not just the `$.prop` form),
|
|
373
|
+
// mirroring the @[...] binding pass above — so `onclick="pick(item)"`
|
|
374
|
+
// resolves the live prop, not a global that throws ReferenceError. A
|
|
375
|
+
// loop-alias path (`row.sig`) becomes `(row.sig)` here; parse.js then
|
|
376
|
+
// rewrites the alias to `$scope(this,'row')`.
|
|
377
|
+
const rewritten = substituteInExpr(body.replace(stateRegex, `$.${path}`), `(${path})`);
|
|
373
378
|
return rewritten === body ? match : `on${evName}="${rewritten}"`;
|
|
374
379
|
});
|
|
375
380
|
} else {
|
|
@@ -395,7 +400,9 @@ const renderPropsAndSlot = (temp, props, slotHtml) => {
|
|
|
395
400
|
);
|
|
396
401
|
const stateRegex = new RegExp(`\\$\\.${escapeRegex(propName)}(?![a-zA-Z0-9_$])`, 'gi');
|
|
397
402
|
transformedHtml = transformedHtml.replace(EVENT_ATTR_REGEX, (match, evName, body) => {
|
|
398
|
-
|
|
403
|
+
// Same bare-identifier substitution for a literal prop: `onclick="set(limit)"`
|
|
404
|
+
// with `limit="5"` becomes `set(5)`.
|
|
405
|
+
const rewritten = substituteInExpr(body.replace(stateRegex, `$.${literal}`), literal);
|
|
399
406
|
return rewritten === body ? match : `on${evName}="${rewritten}"`;
|
|
400
407
|
});
|
|
401
408
|
}
|