diff --git a/src/component/component_node.ts b/src/component/component_node.ts index eead3fc6..cf1c587d 100644 --- a/src/component/component_node.ts +++ b/src/component/component_node.ts @@ -1,6 +1,13 @@ import type { App, Env } from "../app/app"; import { BDom, VNode } from "../blockdom"; -import { clearReactivesForCallback, Reactive, reactive, TARGET, NonReactive } from "../reactivity"; +import { + clearReactivesForCallback, + Reactive, + reactive, + TARGET, + NonReactive, + getSubscriptions, +} from "../reactivity"; import { batched, Callback } from "../utils"; import { Component, ComponentConstructor } from "./component"; import { fibersInError, handleError } from "./error_handling"; @@ -51,6 +58,13 @@ export function useState(state: T): Reactive | NonReactive< batchedRenderFunctions.set(node, render); // manual implementation of onWillDestroy to break cyclic dependency node.willDestroy.push(clearReactivesForCallback.bind(null, render)); + if (node.app.dev) { + Object.defineProperty(node, "subscriptions", { + get() { + return getSubscriptions(render); + }, + }); + } } return reactive(state, render); } diff --git a/src/reactivity.ts b/src/reactivity.ts index c7dc3cb2..a4980d91 100644 --- a/src/reactivity.ts +++ b/src/reactivity.ts @@ -153,6 +153,17 @@ export function clearReactivesForCallback(callback: Callback): void { targetsToClear.clear(); } +export function getSubscriptions(callback: Callback) { + const targets = callbacksToTargets.get(callback) || []; + return [...targets].map((target) => { + const keysToCallbacks = targetToKeysToCallbacks.get(target); + return { + target, + keys: keysToCallbacks ? [...keysToCallbacks.keys()] : [], + }; + }); +} + const reactiveCache = new WeakMap>(); /** * Creates a reactive proxy for an object. Reading data on the reactive object