diff --git a/src/runtime/reactivity.ts b/src/runtime/reactivity.ts
index 7d61f97f..f5e75d2a 100644
--- a/src/runtime/reactivity.ts
+++ b/src/runtime/reactivity.ts
@@ -162,10 +162,15 @@ 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()] : [],
- };
+ let keys = [];
+ if (keysToCallbacks) {
+ for (const [key, cbs] of keysToCallbacks) {
+ if (cbs.has(callback)) {
+ keys.push(key);
+ }
+ }
+ }
+ return { target, keys };
});
}
// Maps reactive objects to the underlying target
diff --git a/tests/components/__snapshots__/reactivity.test.ts.snap b/tests/components/__snapshots__/reactivity.test.ts.snap
index 9f8a4962..7b35b2e9 100644
--- a/tests/components/__snapshots__/reactivity.test.ts.snap
+++ b/tests/components/__snapshots__/reactivity.test.ts.snap
@@ -140,3 +140,39 @@ exports[`reactivity in lifecycle state changes in willUnmount do not trigger rer
}
}"
`;
+
+exports[`subscriptions subscriptions returns the keys and targets observed by the component 1`] = `
+"function anonymous(app, bdom, helpers
+) {
+ let { text, createBlock, list, multi, html, toggler, comment } = bdom;
+
+ return function template(ctx, node, key = \\"\\") {
+ return text(ctx['state'].a);
+ }
+}"
+`;
+
+exports[`subscriptions subscriptions returns the keys observed by the component 1`] = `
+"function anonymous(app, bdom, helpers
+) {
+ let { text, createBlock, list, multi, html, toggler, comment } = bdom;
+ const comp1 = app.createComponent(\`Child\`, true, false, false, false);
+
+ return function template(ctx, node, key = \\"\\") {
+ const b2 = text(ctx['state'].a);
+ const b3 = comp1({state: ctx['state']}, key + \`__1\`, node, this, null);
+ return multi([b2, b3]);
+ }
+}"
+`;
+
+exports[`subscriptions subscriptions returns the keys observed by the component 2`] = `
+"function anonymous(app, bdom, helpers
+) {
+ let { text, createBlock, list, multi, html, toggler, comment } = bdom;
+
+ return function template(ctx, node, key = \\"\\") {
+ return text(ctx['props'].state.b);
+ }
+}"
+`;
diff --git a/tests/components/reactivity.test.ts b/tests/components/reactivity.test.ts
index c336aa0a..da1a960c 100644
--- a/tests/components/reactivity.test.ts
+++ b/tests/components/reactivity.test.ts
@@ -7,6 +7,7 @@ import {
onWillUnmount,
useState,
xml,
+ toRaw,
} from "../../src";
import { makeTestFixture, nextTick, snapshotEverything, useLogLifecycle } from "../helpers";
@@ -232,3 +233,34 @@ describe("reactivity in lifecycle", () => {
expect(fixture.innerHTML).toBe("34");
});
});
+
+describe("subscriptions", () => {
+ test("subscriptions returns the keys and targets observed by the component", async () => {
+ class Comp extends Component {
+ static template = xml``;
+ state = useState({ a: 1, b: 2 });
+ }
+ const comp = await mount(Comp, fixture);
+ expect(fixture.innerHTML).toBe("1");
+ expect(comp.__owl__.subscriptions).toEqual([{ keys: ["a"], target: toRaw(comp.state) }]);
+ });
+
+ test("subscriptions returns the keys observed by the component", async () => {
+ class Child extends Component {
+ static template = xml``;
+ setup() {
+ child = this;
+ }
+ }
+ let child: Child;
+ class Parent extends Component {
+ static template = xml``;
+ static components = { Child };
+ state = useState({ a: 1, b: 2 });
+ }
+ const parent = await mount(Parent, fixture);
+ expect(fixture.innerHTML).toBe("12");
+ expect(parent.__owl__.subscriptions).toEqual([{ keys: ["a"], target: toRaw(parent.state) }]);
+ expect(child!.__owl__.subscriptions).toEqual([{ keys: ["b"], target: toRaw(parent.state) }]);
+ });
+});