Skip to content

perf(adapters): avoid repeated observe()/unobserve() churn for shared contexts #163

@vamgan

Description

@vamgan

Summary

Avoid repeated observe() / unobserve() churn when multiple framework hooks mount against the shared global context.

Why

Today useAskable() in React and Vue calls ctx.observe(document, ...) on mount for the shared singleton context. Since Observer.observe() unconditionally calls unobserve() when a root is already active, multiple hook mounts can trigger:

  • full re-scan of [data-askable] elements
  • detach + reattach of listeners across the page
  • unnecessary MutationObserver teardown / recreation

This is especially likely in apps that:

  • call useAskable() from several components
  • mount the inspector alongside consumer hooks
  • have multiple AI surfaces reading from the same context

The core benchmarks still pass, but this is avoidable runtime churn and likely the biggest practical performance footgun in the current adapter design.

Proposed direction

Introduce idempotent observation for shared contexts.

Options:

  1. Internal reference-counted ensureObserved()

    • first hook mount observes the document
    • subsequent mounts only subscribe to focus state
    • final unmount tears observation down
  2. Provider/root component API

    • <AskableProvider> / <AskableRoot> owns observation once
    • hooks become pure consumers of the existing context

Acceptance criteria

  • Shared/global contexts are observed only once per document
  • Multiple useAskable() mounts do not trigger full re-observation churn
  • Inspector usage does not cause extra observe/unobserve cycles
  • React tests cover repeated mount/unmount scenarios
  • Vue tests cover repeated mount/unmount scenarios
  • No regression for private/provided contexts

Notes

This issue complements, but is separate from, larger context-shaping work like #145 and #121.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: coreCore package and cross-package runtime behaviorarea: reactReact adapter workarea: vueVue adapter workenhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions