pre-refactor

This commit is contained in:
2026-06-17 03:41:08 +00:00
parent 318d7169f7
commit 687fa8f52f
19 changed files with 215 additions and 105 deletions
+42 -18
View File
@@ -20,13 +20,19 @@ import { reactive } from './reactivity.js';
import { h } from './vdom.js';
import { _compExpandedCache } from './render.js';
/**
* Registry of mounted components: key → { state, subscriptions, loadAbort, entry }
*/
/** Registry of mounted components: key → { state, subscriptions, loadAbort, entry, isLoading } */
const _mounted = new Map();
/**
* External subscribe function from websocket.js.
/** Check whether a state object belongs to a currently mounted component.
* Used by websocket.js to skip auto-refresh for unmounted pages. */
export function isComponentStateMounted(state) {
for (const entry of _mounted.values()) {
if (entry.state === state) return true;
}
return false;
}
/** External subscribe function from websocket.js.
* Set via setSubscribeFn() when the websocket module initializes.
*/
let _subscribeFn = null;
@@ -67,29 +73,45 @@ export function definePage(def) {
* enters the tree for the first time.
*/
export function mountComponent(key, renderer) {
// Prevent duplicate mounts when normalization loses #comp tracking
if (_mounted.has(key)) return;
const pd = renderer._pageDef;
if (!pd) return;
const entry = {
state: pd.state,
subscriptions: [],
loadAbort: null,
};
let entry = _mounted.get(key);
_mounted.set(key, entry);
if (entry) {
// Re-mount of an already-mounted page: restart load with fresh AbortController
if (entry.loadAbort) {
entry.loadAbort.abort();
}
entry.requestId++;
entry.loadAbort = null;
} else {
// Fresh mount
entry = {
state: pd.state,
subscriptions: [],
loadAbort: null,
requestId: 0,
};
_mounted.set(key, entry);
}
// Fire load
// Clear error on re-mount; load() decides loading vs refreshing
pd.state.error = null;
// Fire load with fresh AbortController
if (pd.load) {
const abortController = new AbortController();
entry.loadAbort = abortController;
pd.load(pd.state, abortController);
entry.requestId++;
entry.isLoading = true;
Promise.resolve()
.then(() => pd.load(pd.state, abortController, entry))
.finally(() => { entry.isLoading = false; });
}
// Register WS subscriptions
if (_subscribeFn && pd.subscribe.length) {
// Register WS subscriptions (only on fresh mount)
if (!entry.subscriptions.length && _subscribeFn && pd.subscribe.length) {
for (const topic of pd.subscribe) {
const unsub = _subscribeFn(renderer, topic, pd.load, pd.state);
if (unsub) entry.subscriptions.push(unsub);
@@ -111,6 +133,8 @@ export function unmountComponent(key, renderer) {
if (entry.loadAbort) {
entry.loadAbort.abort();
}
// Invalidate any in-flight callbacks
entry.requestId++;
// Unsubscribe from WS
for (const unsub of entry.subscriptions) {