@ape-egg/vibe 1.7.1 → 1.8.0

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 CHANGED
@@ -1,5 +1,67 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.8.0] - 2026-04-10
4
+
5
+ ### Added
6
+
7
+ - **State batching** — Multiple `$.prop = value` assignments in the same microtask now produce a single rerender instead of cascading updates
8
+ - Proxy `set` trap calls `scheduleFlush()` (via `queueMicrotask`) instead of `rerender()` directly
9
+ - Eliminates cascading rerenders from `afterUpdate` hooks setting state
10
+ - Rerender callback now does full diff of `previousState` vs `currentState` (no longer receives individual changed prop)
11
+
12
+ - **DOM ownership tracking** — Two new data structures prevent re-processing of already-managed nodes
13
+ - `managedNodes` (`WeakSet`): Tracks nodes inserted by `mountBranch` / `renderIteration`. `shouldProcessNode` skips them.
14
+ - `branchNodeRegistry` (`WeakMap`): Maps DOM nodes to their conditional branch, so `processComponent`'s `el.replaceWith()` correctly updates conditional tracking
15
+
16
+ - **Parallel component loading** — Same-level `<component src>` elements now fetch in parallel
17
+ - `isNestedInUnprocessedComponent()` filters slot content from premature processing
18
+ - `processSingle()` handles fetch + script execution + DOM replacement per component
19
+ - `processComponent()` fires all top-level fetches simultaneously; nested components discovered after parent finalizes
20
+
21
+ - **Component script imports** — `<script type="module">` in components now supports `import` statements
22
+ - Static imports rewritten to dynamic `await import()` (default, named, namespace, side-effect)
23
+ - `import component from '...'` is stripped (Vibe injects it as a parameter)
24
+ - `AsyncFunction` constructor used only when imports exist; sync path preserved for boot timing
25
+
26
+ - **Bracket notation in paths** — `resolvePath` now handles `teams[0].combatants` via `path.match(/[^.\[\]]+/g)` splitting
27
+
28
+ - **Quoted strings in binding expressions** — `BINDING_REGEX` now supports `@[x.replace('.png', '-mugshot.png')]`
29
+
30
+ ### Changed
31
+
32
+ - **Conditional branch lifecycle** — `mountBranch` now integrates branch tree into both the conditional node's children and the manifest (via `addBranchToManifest`). `unmountBranch` cleans up both. Makes branch content visible to the main update loop and MutationObserver.
33
+
34
+ - **New-node processing** — `processCoreLoop` filters iteration and conditional types from `affectedElements` when `isNewNode = true`. Initial render goes through `renderAllIterations` / `renderAllConditionals`, not the update/diff path.
35
+
36
+ - **Component discovery after state changes** — After hydrate + renderAll in the state callback, scans for unresolved `<component src="">` elements that conditionals/iterations may have mounted while the observer was disconnected.
37
+
38
+ ### Performance
39
+
40
+ - **`evalInScope` function cache** — Compiled `new Function()` objects cached by expression + state keys signature. For 1000 rows × 4 bindings, reduces 4000 Function compilations to ~4.
41
+ - **Bulk iteration replacement** — When old and new arrays share no common keys, skips O(n²) LCS entirely. Uses `Range.deleteContents()` for instant clear + `fastPath.renderFast` (batch string concatenation + single `innerHTML`) for simple templates.
42
+ - **DocumentFragment batching** — `renderIteration` collects all cloned nodes in a DocumentFragment, single `insertBefore` at the end instead of N × M individual DOM mutations.
43
+ - **Scoped state `ownKeys` caching** — `createScopedState` pre-computes the combined key list once at Proxy creation. `ownKeys()` trap returns cached array directly instead of rebuilding 3 arrays + 1 Set per call.
44
+ - **`extractPlainValue` optimization** — Indexed `for` loops, `Object.keys()` instead of `for..in`, inline primitive check, pre-allocated arrays.
45
+ - **Old-array ground truth** — `updateIteration` uses rendered instances as truth when `oldState` disagrees with actual instance count, preventing mismatched diff operations.
46
+
47
+ ### Removed
48
+
49
+ - **`window.__VIBE_FAST_ITERATION__` experimental flag** — Replaced by automatic bulk replacement detection (no opt-in needed)
50
+ - **Per-prop rerender** — State proxy no longer passes `{ [changedProp]: ... }` to rerender; full diff via batching replaces it
51
+
52
+ ---
53
+
54
+ ## [1.7.2] - 2026-02-27
55
+
56
+ ### Fixed
57
+
58
+ - **Component inlining — hyphenated custom elements inside slot content** (`find_matching_close`)
59
+ - `<component-card>`, `<component-grid>`, etc. inside slot content incorrectly matched `<component\b`, incrementing the depth counter without a corresponding close
60
+ - The real `</component>` could never bring the depth back to 0, so `find_matching_close` returned `None` and the outer component was left un-inlined (causing `Cannot GET /components/Layout.html` at runtime)
61
+ - Fixed by replacing `\b` with `(?:\s|>|/>)` — only matches actual `<component` tags followed by whitespace or `>`, not hyphenated variants
62
+
63
+ ---
64
+
3
65
  ## [1.7.1] - 2026-02-27
4
66
 
5
67
  ### Added