a2ui-project / a2ui-project/a2ui

[v0.9] Fix memory leaks and standardize subscription lifecycle in web_core and react renderers

未关闭
#963 12 条评论 0 个 reaction 已指派 1 人 已被 @josemontespg 认领 在 GitHub 查看
component: angular renderer component: react renderer javascript P2 sprint ready type: bug type: feature/enhancement
主要语言
TypeScript
星标
16.4k
派生
1.3k
平均合并
2 天 13 小时
30 天内合并 PR
134

描述

This issue tracks critical memory leaks and architectural redundancies identified in the A2UI v0.9 Web, React, and Angular renderers. These issues lead to unbounded memory growth in long-lived surfaces and leaked background processes (e.g., timers) when components are unmounted.

#### Identified Issues

**Core & Shared Logic:**
1. **Unbounded Signal Cache in `DataModel`**: The `DataModel.signals` Map caches every path ever queried. These are only cleared when the entire surface is disposed. In surfaces with many ephemeral components or large lists, this leads to significant memory growth.
2. **`FormatString` Recursive Leaks**: The `formatString` implementation in `basic_functions.ts` resolves internal expressions into signals using `context.resolveSignal(part)` but never calls `unsubscribe` on them. Any function call (like `${now()}`) inside a string will leak its listeners/timers until the DataModel is disposed.
3. **Broken Cleanup Chain in `DataContext`**: `resolveSignal` in `DataContext.ts` creates recursive effects for function arguments but does not properly take ownership of `unsubscribe` methods on signals returned by function implementations.

**React Renderer:**
4. **Redundant Subscription Layers**: The React adapter wraps the `GenericBinder` in additional `useSyncExternalStore` and `useEffect` layers. While not a leak, it increases complexity and makes cleanup harder to audit.

**Angular Renderer:**
5. **Root-Scoped Leaks in `ComponentBinder`**: `ComponentBinder.ts` injects `DestroyRef` at the root level. All subscriptions created via `bind()` are tied to the application lifetime rather than the component lifetime, causing massive leaks as users navigate surfaces.
6. **Stale Bindings**: Angular does not listen to `ComponentModel.onUpdated`. If component properties change in the protocol (e.g., type remains same but props change), the Angular UI stays stale.

#### Goals
* Implement reference counting or explicit signal removal in `DataModel`.
* Ensure all recursive signals created by `formatString` and function calls are tracked and disposed of via a unified `unsubscribe` chain.
* Fix the `DestroyRef` scoping in the Angular renderer.
* Implement property refresh logic in Angular to match the React `GenericBinder` behavior.
* Add exhaustive regression tests verifying that `AbortSignal` listeners and internal Maps are cleared after component unmount across all frameworks.

贡献指南

打开贡献指南

调研方向

The issue points to specific files: DataModel.signals Map, formatString in basic_functions.ts, DataContext.ts, GenericBinder in React, and ComponentBinder.ts in Angular. Start by examining the signal caching and cleanup chains in these core files. Run existing tests to understand the current behavior, then add regression tests for memory leaks using AbortSignal listeners. Focus on implementing reference counting or explicit signal removal, ensuring all recursive signals are tracked and disposed.

由索引模型根据 Issue 内容生成。

评估

技术栈
angular, react, typescript
领域
backend-api-design, frontend, performance
Issue 类型
缺陷
难度
4/5
预计耗时
3-5 天
活跃度
活跃
描述清晰度
基本清楚
新手友好度
45/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。