@ape-egg/vibe 2.1.6 → 2.1.7
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/package.json +1 -1
- package/runtime/component.js +30 -3
- package/runtime/conditionals.js +8 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.1.7] - 2026-06-19
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **Compiled component-local state was lost when a conditional re-mounted** (`runtime/component.js`, `runtime/conditionals.js`) — on compiled pages each component's setup script is inlined as `type="vibe-module"`, but the boot-time pass only runs the scripts present at boot. A `<component>` carrying its own `component({...})` state inside a `<!-- if -->` rendered correctly the first time, then went blank after the conditional was toggled off and back on: the branch markup was restored but its `<!-- each _cN.x -->` read component-local state that had been released on unmount. `mountBranch` now runs the freshly mounted subtree's `vibe-module` scripts via a new `executeCompiledComponentScriptsIn(nodes)` — before nested iterations/conditionals render, so the re-registered state is in place when `<!-- each _cN.x -->` evaluates. The `_cN` id-counter advance and the script runner are factored out so the scoped and boot-time passes share one path. Repro: `e2e-runtime/conditional-component-remount.html`, `tests/e2e/components-in-conditionals.spec.js`.
|
|
8
|
+
|
|
3
9
|
## [2.1.6] - 2026-06-19
|
|
4
10
|
|
|
5
11
|
### Added
|
package/package.json
CHANGED
package/runtime/component.js
CHANGED
|
@@ -158,14 +158,41 @@ const transformScriptContent = (rawContent) => {
|
|
|
158
158
|
export const executeCompiledComponentScripts = () => {
|
|
159
159
|
const scripts = document.querySelectorAll('script[type="vibe-module"]');
|
|
160
160
|
if (!scripts.length) return null;
|
|
161
|
+
advanceComponentCounterPastIds(document);
|
|
162
|
+
return runVibeModuleScripts(scripts);
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
// Same pipeline as the boot-time pass, but scoped to a freshly mounted subtree
|
|
166
|
+
// (a conditional branch or iteration row) rather than the whole document. The
|
|
167
|
+
// boot pass only sees component scripts that are in the page at boot; a branch
|
|
168
|
+
// that mounts later — or RE-mounts after being unmounted — carries its own
|
|
169
|
+
// inlined `vibe-module` scripts that must run each time so component-local state
|
|
170
|
+
// (`component({...})` → `$._cN`) is re-registered. Without this, a re-opened
|
|
171
|
+
// conditional restores its markup but its `<!-- each _cN.x -->` reads state that
|
|
172
|
+
// was released on unmount (the AccountProgression overlay rendering blank on
|
|
173
|
+
// second open).
|
|
174
|
+
export const executeCompiledComponentScriptsIn = (nodes) => {
|
|
175
|
+
const scripts = [];
|
|
176
|
+
for (const node of nodes) {
|
|
177
|
+
if (node.nodeType !== 1) continue;
|
|
178
|
+
if (node.matches?.('script[type="vibe-module"]')) scripts.push(node);
|
|
179
|
+
node.querySelectorAll?.('script[type="vibe-module"]').forEach((s) => scripts.push(s));
|
|
180
|
+
}
|
|
181
|
+
if (!scripts.length) return null;
|
|
182
|
+
advanceComponentCounterPastIds(document);
|
|
183
|
+
return runVibeModuleScripts(scripts);
|
|
184
|
+
};
|
|
161
185
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
186
|
+
// Build-time tagging already assigned _cN ids to wrappers; advance the runtime
|
|
187
|
+
// counter past them so freshly generated ids never collide.
|
|
188
|
+
const advanceComponentCounterPastIds = (root) => {
|
|
189
|
+
root.querySelectorAll('[data-vibe-component-id]').forEach((el) => {
|
|
165
190
|
const m = el.getAttribute('data-vibe-component-id')?.match(/^_c(\d+)$/);
|
|
166
191
|
if (m) componentCounter = Math.max(componentCounter, Number(m[1]) + 1);
|
|
167
192
|
});
|
|
193
|
+
};
|
|
168
194
|
|
|
195
|
+
const runVibeModuleScripts = (scripts) => {
|
|
169
196
|
const asyncTasks = [];
|
|
170
197
|
const claimed = new Set();
|
|
171
198
|
|
package/runtime/conditionals.js
CHANGED
|
@@ -3,7 +3,7 @@ import affected from './affected.js';
|
|
|
3
3
|
import hydrate from './hydrate.js';
|
|
4
4
|
import { createScopedState, renderAllIterations, initializeBlock, resolveIterationComponentProps } from './iterate.js';
|
|
5
5
|
import { evalInScope } from './utils.js';
|
|
6
|
-
import { collectComponentIds, releaseOrphanedComponentState } from './component.js';
|
|
6
|
+
import { collectComponentIds, releaseOrphanedComponentState, executeCompiledComponentScriptsIn } from './component.js';
|
|
7
7
|
|
|
8
8
|
// Registry of DOM nodes owned by conditional branches.
|
|
9
9
|
// Maps a DOM node to { nodes: array_ref, index: number } so that
|
|
@@ -231,6 +231,13 @@ const mountBranch = (node, branchData, state, manifest, parentScope) => {
|
|
|
231
231
|
}
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
+
// Compiled pages inline each component's setup script as type="vibe-module".
|
|
235
|
+
// The boot-time pass only runs scripts present at boot, so a branch that
|
|
236
|
+
// mounts (or re-mounts after unmount) must run its own scripts here to
|
|
237
|
+
// re-register component-local state. Must happen BEFORE rendering nested
|
|
238
|
+
// iterations/conditionals so `<!-- each _cN.x -->` sees the registered state.
|
|
239
|
+
executeCompiledComponentScriptsIn(clonedNodes);
|
|
240
|
+
|
|
234
241
|
// Recursively render any nested iterations and conditionals
|
|
235
242
|
if (branchTree) {
|
|
236
243
|
renderAllIterations(branchTree, scopedState, manifest, parentScope);
|