Skip to content

Bug report: Yjs observers are never unobserved in BlockModel #9159

@ljho01

Description

@ljho01

File
blocksuite/framework/store/src/model/block/block-model.ts

Describe the bug
In BlockModel, Yjs observers are registered via

  • yBlock.get('sys:children').observe(...)
  • yBlock.observe(...)

but there is no corresponding unobserve call when the block is disposed.
This can cause memory leaks and lingering event listeners, since the observer closures hold references to the BlockModel instance even after the block is deleted.

To Reproduce

  1. Create a block that initializes BlockModel.
  2. Delete/dispose the block.
  3. Observe that the RxJS subscriptions are cleaned up (dispose() is called), but Yjs observers remain active.

Expected behavior
Yjs observers should be properly removed in dispose() or [Symbol.dispose] so that:

  • No memory leaks occur.
  • Deleted blocks do not continue reacting to Yjs updates.

Suggested fix
Store observer references and call unobserve during cleanup:

// inside BlockModel
private _yChildren?: Y.Array<string>;
private _onYChildren?: (e: Y.YArrayEvent<string>) => void;
private _onYBlock?: (e: Y.YMapEvent<unknown>) => void;

private _cleanupYObservers() {
  if (this._yChildren && this._onYChildren) {
    this._yChildren.unobserve(this._onYChildren);
  }
  if (this._onYBlock) {
    this.yBlock.unobserve(this._onYBlock);
  }
  this._onYChildren = undefined;
  this._onYBlock = undefined;
  this._yChildren = undefined;
}

dispose() {
  this._cleanupYObservers();
  this.created.complete();
  this.deleted.complete();
  this.propsUpdated.complete();
}

Environment

  • affine version: (commit hash / branch)
  • Browser/Node: (if applicable)

Additional context
This issue may not surface immediately, but with long editing sessions and frequent block creation/deletion, it can lead to significant memory leaks.


Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions