This document contains release notes for each version of MeoNode UI, including new features, enhancements, bug fixes,
and important changes. Use it to track the evolution of the library and understand what’s new or different in each
release.
core: Overhaul mount tracking, caching, and fix stableKey generation to prevent memory leaks (af1b707)
Replaced the simple Set in MountTrackerUtil with a reference-counting system (Map) to ensure a node is only considered unmounted when all its instances are gone.
The root element of a render cycle is now wrapped with a MeoNodeUnmounter component before being cached to guarantee that the unmount logic is always present, even for cached elements.
Improved stableKey generation in NodeUtil.createPropSignature to correctly differentiate function props by hashing their string representation, preventing cache collisions for components with different onClick or similar handlers.
Added new test suites (leak-repro.test.ts, props-caching-leak.test.ts) to specifically target and verify the leak fixes.
Adjusted the propProcessingCache eviction logic in NodeUtil to be more aggressive, removing enough items to get back to the CACHE_SIZE_LIMIT plus an additional buffer batch, preventing unbounded growth under high load.
react-router: Add integration tests for react-router-dom (8478623)
Introduced a new test suite to verify the proper functioning and caching behavior of MeoNode components when used within a React Router environment.
Includes tests for declarative and programmatic navigation, ensuring that component lifecycles and caching mechanisms interact correctly with React Router's dynamic rendering.
cache: enforce dependency-based caching with shouldCacheElement helper (fab5525)
Introduces NodeUtil.shouldCacheElement() helper to centralize and enforce the opt-in caching strategy where only
nodes with explicit dependencies are cached
Completes the memory optimization by closing loopholes where nodes without dependencies were still being cached
based on stableKey alone
Replaces 4 inconsistent cache eligibility checks in BaseNode.render():
Cache lookup for parent nodes
Cache lookup for child nodes
Cache storage during rendering
MeoNodeUnmounter wrapping decision
Impact: Reduces memory usage, ensures mount tracking and cache operations stay in sync, improves code
maintainability
props: improve prop handling and prevent leakage (73cc696)
This commit refactors prop handling within the MeoNode ecosystem to ensure that internal processing props are not
leaked to the DOM.
Key changes:
The MeoNodeUnmounter is updated to correctly isolate and pass through props intended for the underlying DOM
element, improving compatibility with libraries like MUI.
Internal props such as node, css, and disableEmotion are now explicitly prevented from being rendered as
HTML attributes.
Added comprehensive tests to verify that standard HTML attributes are passed through while internal props are
successfully filtered out.
This improves the robustness and predictability of component rendering.
props: add tests for prop handling and leakage (a508e10)
Added new tests to verify that component props are correctly passed as HTML attributes, handle createNode and
Node() correctly, and crucially, that internal MeoNode props are not leaked to the DOM.
core: enhance MeoNodeUnmounter cleanup logic and support additional props cloning (02c17f7)
Refactor MeoNodeUnmounter to use useEffectEvent for stable cleanup on unmount
Cleanup removes node from BaseNode.elementCache, untracks mount via MountTrackerUtil, unregisters from
BaseNode.cacheCleanupRegistry, and clears lastSignature to prevent memory leaks
Support cloning and forwarding additional props to valid React children elements
perf: add memory leak detection test for navigation cycles and improve formatMemory function (ba139fc)
Added a new performance test to detect memory leaks during repeated navigation cycles between pages
The test measures heap memory usage before, during, and after navigation, ensuring memory growth stays within
acceptable limits
Enhanced the formatMemory utility to correctly handle negative byte values and added JSDoc comments for clarity
Removed an obsolete shallowly equal props performance test to streamline the test suite
unmounter: add regression test for MeoNodeUnmounter to forward implicit props in MUI RadioGroup integration (2ecaabd)
Added a test to ensure MeoNodeUnmounter correctly forwards props injected via React.cloneElement, addressing
issues with libraries like MUI where RadioGroup injects 'checked' and 'onChange' into Radio components
This prevents swallowing of props and verifies proper behavior of controlled radio inputs
Also updated an existing cache size assertion to allow equality, reflecting improved mount tracking
perf: update react-createelement comparison tests with 5000 nested nodes and fix typings (b345ec0)
Changed rerender to use React.cloneElement for proper typing
Updated NUM_NODES constant to 5000 for nested structure tests
Removed redundant comments about node count reduction to prevent stack overflow
core: optimize rendering, caching, and memory management (4f599be)
Reworks the core rendering loop to use a more efficient, manually-managed work stack with exponential growth,
reducing reallocations and improving performance for deep and wide node trees.
Optimizes stable key generation by removing expensive shallow equality checks in favor of strict reference
equality, significantly speeding up prop processing for cached components.
Implements a high-performance MinHeap-based LRU cache eviction strategy for prop processing, replacing a slower
sort-based method. This ensures that the most relevant props are kept in the cache with minimal overhead.
Introduces CSS object hashing to accelerate prop signature generation, avoiding costly serialization of large
style objects.
Fixes several memory leaks by ensuring proper cleanup of node properties (lastSignature, lastPropsObj) and
unregistering nodes from the cache cleanup registry upon eviction.
Decouples element cache deletion from mount tracking to prevent race conditions and ensure reliable cleanup during
component unmounting.
Introduces a new, structured performance reporting system using cli-table3 for clear, grouped metrics.
Refactors the entire performance test suite into logical groups: Layout Rendering, Memory Management, and Prop
Processing.
Adds comprehensive memory leak detection tests for heavy state changes and repeated mount/unmount cycles, using
forced garbage collection for more accurate heap analysis.
Extracts the large, complex CSS object into a dedicated test constant for better separation of concerns.
Updates memoization tests to align with the new, weighted LRU cache eviction scoring.
client: add generic type parameter to render function for stronger type safety (90a770e)
core: improve BaseNode rendering with iterative traversal and memory optimizations (1d5330a)
Introduce WorkItem interface to represent nodes in the iterative work stack during BaseNode rendering.
Replace recursive render traversal with an iterative depth-first approach using a preallocated workStack array for
better performance and reduced call stack usage.
Implement dynamic resizing of workStack array to handle arbitrary tree sizes efficiently.
Update BaseNode’s internal caching fields (lastPropsRef and lastSignature) to be public and consistently used
for stable key generation.
Modify MeoNodeUnmounter component to accept BaseNode instance and clear its lastPropsRef and lastSignature on
unmount to prevent memory leaks.
Refine type annotations across node utilities and factory functions for stronger type safety (
Record<string, unknown> instead of any).
Optimize critical prop extraction logic by replacing Set and startsWith checks with faster inline charCode
comparisons.
Clean up and clarify utility methods related to prop signature creation, shallow equality, and portal management.
Improve node.util.ts by adjusting caching strategies, prop categorization, and React element handling for better
robustness and maintainability.
improve typings and type safety in theme util and styled renderer (dbe1f33)
Added explicit TypeScript types (e.g., CssProp, Record<string, unknown>) for variables and function signatures in
styled-renderer.client.ts and theme.util.ts.
Updated cache maps to use more precise generic types for better type inference and safety.
Enhanced resolveObjWithTheme and related theme resolution logic with stronger typing and nullish coalescing.
Improved error handling for invalid theme path values.
Applied copy-on-write pattern with properly typed arrays and objects during theme resolution.
Strengthened type guards, e.g., isPlainObject type predicate.
Minor fixes to variable declarations with explicit types for clarity and consistency.
core/cache: Enhance memoization & caching system to prevent memory leaks and ensure safe lifecycle management. (253d7d00)
Introduces a robust, three-layered cleanup strategy to ensure cache integrity:
Lifecycle-driven Cleanup:MeoNodeUnmounter component ensures that caches of unmounted nodes are immediately
cleaned when components are removed.
Event-driven SPA Cleanup:NavigationCacheManagerUtil triggers debounced cache clearing during SPA
navigations (pushState/popstate), preventing stale entries.
GC-driven Safety Net: Uses FinalizationRegistry to automatically clean cache entries for objects that are
garbage collected, providing an additional layer of memory safety.
tooling: Enable TypeScript's strict: true mode and update the codebase to comply fully with strict type checks.
tooling: Add CommonJS (require) exports in package.json for improved module compatibility in different
environments.
tooling: Update test scripts to include NODE_OPTIONS='--expose-gc', allowing explicit garbage collection during
tests for more accurate memory testing.
tests: Refine test suite by standardizing afterEach hooks and updating memoization tests to directly validate
internal cache behavior.
cache: Implemented a robust multi-layer cache management system with dedicated theme caching.
This update introduces a more defensive and introspective caching architecture:
Refactored NavigationCacheManager to improve stability under frequent invalidation cycles.
Added memory monitoring hooks to track cache pressure and trigger automated cleanup when thresholds are
exceeded.
Introduced LRU (Least Recently Used) eviction in ThemeResolverCache, ensuring stale theme resolution paths
are removed predictably.
Integrated LRU behaviors with the broader BaseNode cache lifecycle, enabling synchronized clearing across all
caching layers.
(9ed749f6)
test: Split the previously monolithic node.test.ts into multiple focused, domain-specific test files.
This reorganization increases maintainability, readability, and clarity across the test suite:
Introduced memoization.test.ts to isolate tests related to dependency tracking, subtree memoization, and
cache-collision handling.
Cleaned up noisy logs by suppressing a repetitive console.error triggered during a duplicate-key memoization
test.
The suppression preserves test intent while preventing unnecessary noise in CI output.
Tests are now organized by functional concerns, improving long-term scalability of the suite.
(930f998e)
core: Ensured the disableEmotion flag is properly forwarded to _renderProcessedNode, allowing consistent
handling within the rendering pipeline.
This resolves inconsistencies in node processing when Emotion styling is disabled.
(b68e3d4)
test: Adjusted performance test cleanup logic by removing automatic cache clearing within afterEach.
This change ensures performance tests run under realistic caching behavior instead of artificially reset conditions.
(f72cea5e)
core: Implemented intelligent caching and memory management (0e5671b)
A sophisticated caching and memory-safety layer has been introduced to prevent memory leaks and improve SPA performance.
The system now tracks mounted components, cleans up unmounted ones, and maintains a stable, efficient cache across
navigation events.
Highlights:
Navigation-aware Cache Eviction:NavigationCacheManager listens for browser navigation events (popstate,
pushState, etc.) and automatically purges stale cache entries from previous pages.
Mount Tracking: A new MountTracker maps all active BaseNode instances, enabling precise eviction of unused
cached elements.
Advanced Eviction Policies:SafeCacheManager can evict unmounted components, older inactive entries, and even
perform emergency cleanup during memory pressure.
Memory-Safe Portal System: Portal implementation now uses WeakMap, ensuring DOM roots and portal nodes are
garbage-collectable once unused.
Improved Cache Metadata: Cache entries now track timestamps, access counts, and a WeakRef to the node instance
for smarter eviction.
Stable Cache Keys: Component identifiers now rely on WeakMap instead of component names, ensuring stability even
under minification.
core: Implemented an advanced memoization and caching system to optimize rendering performance (3b0a110):
Dependency-Based Memoization: Nodes can now be created with a dependency array, similar to React's useMemo,
to prevent unnecessary re-renders of the node and its entire subtree if dependencies have not changed.
Enhanced Prop Caching: The prop signature generation is now more robust, and the cache uses an advanced LRU
eviction strategy to remain efficient.
API Updates: The Node, createNode, createChildrenFirstNode, and Component HOCs have been updated to
accept an optional deps array to enable memoization.
constApp=()=>{const[state, setState]=useState({ user:'John', role:'Admin'})constupdateUser=()=>setState(s =>({...s, user:'Jane'}))constupdateRole=()=>setState(s =>({...s, role:'Editor'}))returnDiv({ children:[Div({ onClick: updateUser, children:'Update User'}),Div({ onClick: updateRole, children:'Update Role'}),// Static: never re-renders, regardless of state changesDiv({ children:`Initial User: ${state.user}`},[]),// Dependent: re-renders only when `state.user` changesDiv({ children:`User: ${state.user}; Role: ${state.role}`},[state.user]),],}).render()}
With dependency-based memoization, only nodes whose dependencies change are re-rendered — enabling fine-grained
reactivity and significant performance improvements in large trees.
core: Added a comprehensive suite of tests for the new memoization and caching system, covering dependency-based
memoization, reactive and non-reactive children, complex state updates, and memoization of Higher-Order Components (
HOCs) (6bcd1b1).
Core: Introduced the new disableEmotion prop to allow developers to disable Emotion styling. This setting
now propagates to all child nodes for fine-grained control over style rendering (377a9e9).
React Integration: Improved detection logic for isContextProvider and isReactClassComponent, ensuring
more accurate differentiation of React components (e8839e4).
Theme Helper: Fixed an issue where theme functions returning string values were not being processed correctly,
ensuring consistent theme resolution across components (286fd89).
React: Added the new Suspense component along with detailed JSDoc for both Activity and Suspense
components to improve clarity and developer experience (c1760fd).
Core (BaseNode): Removed the child processing cache to resolve a critical bug that caused infinite page loads in
server-side rendering (RSC) environments.
Helper: Corrected element type retrieval logic within the hashing function used for child node processing.
Core: Introduced a top-level render function for a cleaner and simpler API when mounting a MeoNode instance to
the DOM. This abstracts away the need to manually call react-dom/client.
Core (node): Refactored props handling to use a single utility type MergedProps<E, AdditionalProps>, simplifying
and unifying typing for createNode and createChildrenFirstNode.
Improved developer experience for prebuilt components by allowing safer extension and overriding of props.