Releases: wfjs-admin/WildflowerJS
Releases · wfjs-admin/WildflowerJS
Release list
WildflowerJS v1.2.0
[1.2.0] - 2026-07-07
Under the hood
- Reactivity rebuilt as a single dependency graph: state, computeds, effects, and bindings are now nodes in one unified graph resolved in a single pass, replacing the split between the reactive state manager and a parallel binding-context system. No API change and nothing to migrate; the result is a smaller core, faster reads of unchanged values, leaner scheduling and dependency re-tracking, and one place where dependency tracking is defined.
- List rendering rebuilt on targeted updates:
data-listno longer creates a reactive effect per row; each list registers its rows' bound fields on one per-list dispatcher, and an in-place field change routes to exactly the bindings that read it, down to a single direct DOM write for plainly bound fields. No API change and nothing to migrate: roughly 20 to 25% less memory per row on lists whose templates use item-level computed properties, faster targeted updates and removals, and one update path where there used to be four, which let this cycle's unification surface and fix several latent inconsistencies before they could ever ship.
Added
wildflower.unregister(name)unified component/store teardown: removes a component definition (destroying its live instances and disposing their reactive resources) and/or disposes a store of that name, freeing the name for a fresh registration. Fills the gap where registration was first-write-wins with no way to replace a definition. Useful for live-preview and HMR teardown, dynamic apps that swap components, and tests. Safe for an unknown name; handles a name used by both a component and a store.- Dev-mode warning (WF-215) when a component or store is re-registered with a different definition: re-registering an existing name is silently skipped (the original kept); when the incoming definition actually differs, development builds now warn and point at
wildflower.unregister. Identical re-registrations stay quiet; the check compares method source, not just shape. Development builds only. - Iteration dependencies are tracked: a computed or binding that iterates a reactive object's keys (
Object.keys,for...in, spread) now re-runs when a key is added or removed. Previously only reassigning the object woke iteration readers. Updating an existing key's value still does not re-run keys-only readers, so hot-path field writes stay quiet. - Dev-mode warning (WF-214) when a zero-arg computed in a list row reads an item property via
this: item-level computeds receive the item as their first argument; a computed declared without parameters evaluates at component scope, sothisreads of item fields silently resolve undefined. The warning fires only when the read misses on the component but the current item has that property, names the computed and property, and suggests the(item)signature. Development builds only; fires once per component and computed. - The
data-csp-safescript attribute: on pages with a strict Content Security Policy, adddata-csp-safeto the framework script tag and WildflowerJS starts directly in CSP-safe mode, never attempting dynamic code evaluation, so the page produces zero CSP violations and zeroreport-urireports. Without it the framework still auto-detects and falls back, at the cost of one benign violation report from the startup capability probe. - Custom directives and lifecycle hooks now ship in every build: the declarative
data-*custom-directive API and component lifecycle hooks, previously bundled only with the plugin system, are now available in all five build variants includingliteandmini.plugin()and dependency injection stay gated to the full / spa / standard builds. - DevTools timeline observability: development-build per-frame timeline recording (microtask drains, effect runs, render-sweep duration). Stripped entirely from production builds; surfaces in the companion DevTools extension.
- Dev-mode warning when a computed reads
pool.length/pool.size: these are non-reactive getters, so a computed that reads one caches a single value and never re-runs, leaving the bound UI silently stale. The warning names the computed and suggests the mirror-in-tick()fix. Development builds only; fires at most once per pool.
Breaking Changes
data-bind-attrrenders a non-boolean attribute bound tofalseas the literalattr="false"instead of removing it. Previously the component binding path removed a non-boolean attribute when its bound value wasfalse; it now writes the literal string, matching the list path and the documented contract that non-boolean attributes hold their literal value. Boolean attributes are unchanged:falsestill removes them, since for a boolean attribute presence is the value. For most bindings the new behavior is more correct.aria-expanded,aria-hidden,aria-checkedand similar now emit="false"instead of vanishing, which is the accessible form (an absentaria-expandedconveys no state;aria-expanded="false"says "collapsed"). The one place it can bite is a CSS attribute-presence selector used as a flag.[data-active] { ... }matches whenever the attribute exists regardless of its value, so an element bound{ 'data-active': isActive }withisActive === falsenow matches[data-active](it rendersdata-active="false") where before the attribute was absent and did not match. Migration: if you relied on a falsey bind removing such an attribute, bind the value asnullorundefined(both still remove the attribute) instead offalse, or select on the value ([data-active="true"]) rather than on presence.
Fixed
wildflower.config({ forceCSPMode: true })now takes effect at runtime: the documented call updated the option without switching the live evaluator, and a switched evaluator would then have failed on its first compile; expressions compiled after the call now use the CSP-safe parser. For zero-violation pages, prefer the newdata-csp-safeattribute.data-actionon a component's own root element now binds:<div data-component="x" data-action="click:save">was silently skipped because the action scan usedquerySelectorAll, which by spec excludes the receiver element.data-bind-htmlexpression bindings re-apply on a targeted single-prop update: an html-expression binding referencing the changed prop resolved the new value but skipped theinnerHTMLwrite, leaving stale markup; the targeted-rebind filter checked only the binding path, not its expression variables.- A nested item prop read only through an expression binding now reacts:
data-bind-class="user.active ? 'on' : 'off'"(and style/attr/show/render expressions) where no other binding co-read the nested leaf did not update on mutation, because only root identifiers were registered, not the full dotted path. - Expression and component-root bindings register their dependencies consistently: a single dependency descriptor now drives all four dependency consumers, closing drift where some passes handled path bindings but missed html/show expressions or root-element bindings.
- Removed an orphaned profiling timer in the
data-render-in-list re-run path: it referenced an uninitialized timer and threw a swallowedTypeErroron every re-run, with two strayperformance.now()calls per item shipping in production. - Reactivity gaps closed in item-level-computed and
data-renderpaths in lists: a per-item computed reading component-level state behind a&&short-circuit now wakes when that state mutates; a stale render-cache read no longer immediately undoes a per-itemdata-renderinsert; adata-renderplaceholder comment node no longer triggers a swallowedTypeError. data-poolbinding errors surface in dev instead of failing silently: adata-bind/-class/-style/-attrexpression in a pool template that threw was caught and skipped on every flush with nothing logged. Development builds now warn once per offending binding, naming the pool and the error; production builds carry zero runtime cost.- Passive
data-pools filled one item at a time no longer wake the animation loop: a passive pool populated via singleadd()calls still started the sharedrequestAnimationFrameloop, an idle-CPU wakeup with no work to do. Single-add now respects the passive guard the bulk-add path already had. data-showtoggles the.wf-showclass on every path, not only inside reactive contexts: the documented anti-flash rule `[data-...
v1.1.0
WildflowerJS v1.1.0 — feature release with reliability hardening.
Highlights
- Browser DevTools integration (drop-in script + MV3 extension)
- Pool entity model (
pools: { entity: { state, computed, methods } }) - New
minibuild variant (lite minus pools) - jQuery 3.x and 4.x coexistence
- Item-level computed properties in every binding type
- Zero-npm-install build pipeline (see
PROVENANCE.md) - 2.7–6x cross-store render speedups
- Better dev-mode error messages — every WF-NNN warning links to docs
Breaking changes
- Action handlers no longer stop event propagation by default — add
data-event-stopto opt back in data-model-debounceattribute removed — migrate todata-action="input.debounce.Xms:handleInput"
Install
npm install wildflowerjs@1.1.0
Or via CDN: https://cdn.jsdelivr.net/npm/wildflowerjs@1.1/dist/wildflower.min.js
Full changelog: https://www.wildflowerjs.com/changelog.html
v1.0.0
A reactive JavaScript framework with no build step, no virtual DOM, and one mental model.
Install
<script defer src="https://cdn.jsdelivr.net/npm/wildflowerjs@1/dist/wildflower.min.js"></script>
Or via npm:
npm install wildflowerjs
What's Included
- Component system with lifecycle hooks, props, and slots
- Reactive state with computed properties and dependency tracking
- Store system for cross-component shared state
- List rendering with keyed reconciliation
- Entity pools for high-frequency DOM rendering
- Client-side routing (history + hash modes)
- Server-side rendering with hydration
- Plugin system, portals, transitions, event modifiers
- Two-way binding with input modifiers (trim, number, debounce)
- 3,646 tests in real Chromium
Links
- https://wildflowerjs.com
- https://www.npmjs.com/package/wildflowerjs
- https://wildflowerjs.com/getting-started/quickstart
- https://wildflowerjs.com/demos