From 5cd6ed70bd2db7615ed008d7a19e16df8dbd697a Mon Sep 17 00:00:00 2001 From: martinRenou Date: Thu, 6 Feb 2025 18:19:39 +0100 Subject: [PATCH 1/2] Add support for async model creation --- src/model.ts | 21 +++++++++++++++++---- src/notebookrenderer/view.ts | 4 ++++ src/notebookrenderer/widgetManager.ts | 2 ++ src/types.ts | 2 ++ 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/model.ts b/src/model.ts index 8cdf613..52bea12 100644 --- a/src/model.ts +++ b/src/model.ts @@ -1,5 +1,5 @@ import { MapChange } from '@jupyter/ydoc'; -import { JSONExt, JSONObject } from '@lumino/coreutils'; +import { JSONExt, JSONObject, PromiseDelegate } from '@lumino/coreutils'; import { ISignal, Signal } from '@lumino/signaling'; import * as Y from 'yjs'; @@ -8,8 +8,11 @@ import { IJupyterYDoc, IJupyterYModel } from './types'; export class JupyterYModel implements IJupyterYModel { constructor(commMetadata: { [key: string]: any }) { this._yModelName = commMetadata.ymodel_name; - const ydoc = this.ydocFactory(commMetadata); - this._sharedModel = new JupyterYDoc(commMetadata, ydoc); + this.ydocFactory(commMetadata).then(async (ydoc) => { + this._sharedModel = await this.sharedModelFactory(commMetadata, ydoc); + + this._ready.resolve(); + }); } get yModelName(): string { @@ -32,10 +35,18 @@ export class JupyterYModel implements IJupyterYModel { return this._isDisposed; } - ydocFactory(commMetadata: { [key: string]: any }): Y.Doc { + get ready(): Promise { + return this._ready.promise; + } + + async ydocFactory(commMetadata: { [key: string]: any }): Promise { return new Y.Doc(); } + async sharedModelFactory(commMetadata: { [key: string]: any }, ydoc: Y.Doc) { + return new JupyterYDoc(commMetadata, ydoc); + } + dispose(): void { if (this._isDisposed) { return; @@ -59,6 +70,8 @@ export class JupyterYModel implements IJupyterYModel { private _isDisposed = false; + private _ready: PromiseDelegate = new PromiseDelegate(); + private _disposed = new Signal(this); } diff --git a/src/notebookrenderer/view.ts b/src/notebookrenderer/view.ts index a053413..b7d915f 100644 --- a/src/notebookrenderer/view.ts +++ b/src/notebookrenderer/view.ts @@ -30,6 +30,7 @@ export class JupyterYWidget extends Widget implements IRenderMime.IRenderer { this._yModel?.dispose(); super.dispose(); } + async renderModel(mimeModel: IRenderMime.IMimeModel): Promise { const modelId = mimeModel.data[this._mimeType]!['model_id']; @@ -37,6 +38,9 @@ export class JupyterYWidget extends Widget implements IRenderMime.IRenderer { if (!this._yModel) { return; } + + await this._yModel.ready; + this._ywidget = this._modelFactory.createYWidget(modelId, this.node); } diff --git a/src/notebookrenderer/widgetManager.ts b/src/notebookrenderer/widgetManager.ts index ea7cb13..ad2d219 100644 --- a/src/notebookrenderer/widgetManager.ts +++ b/src/notebookrenderer/widgetManager.ts @@ -69,6 +69,8 @@ export class WidgetModelRegistry implements IJupyterYWidgetModelRegistry { ); const yModel: IJupyterYModel = new yModelFactory(msg.metadata); + await yModel.ready; + new YCommProvider({ comm, ydoc: yModel.sharedModel.ydoc diff --git a/src/types.ts b/src/types.ts index 35190db..1fbd7c4 100644 --- a/src/types.ts +++ b/src/types.ts @@ -30,4 +30,6 @@ export interface IJupyterYModel extends IDisposable { sharedAttrsChanged: ISignal; disposed: ISignal; + + ready: Promise; } From de8a89231cb569aa805771b58934d21a7359a445 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Fri, 7 Feb 2025 09:22:03 +0100 Subject: [PATCH 2/2] Backward compat --- src/model.ts | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/model.ts b/src/model.ts index 52bea12..52455da 100644 --- a/src/model.ts +++ b/src/model.ts @@ -8,9 +8,7 @@ import { IJupyterYDoc, IJupyterYModel } from './types'; export class JupyterYModel implements IJupyterYModel { constructor(commMetadata: { [key: string]: any }) { this._yModelName = commMetadata.ymodel_name; - this.ydocFactory(commMetadata).then(async (ydoc) => { - this._sharedModel = await this.sharedModelFactory(commMetadata, ydoc); - + this.initialize(commMetadata).then(() => { this._ready.resolve(); }); } @@ -23,6 +21,18 @@ export class JupyterYModel implements IJupyterYModel { return this._sharedModel; } + get ydoc(): Y.Doc { + return this._ydoc; + } + + protected set sharedModel(value: IJupyterYDoc) { + this._sharedModel = value; + } + + protected set ydoc(value: Y.Doc) { + this._ydoc = value; + } + get sharedAttrsChanged(): ISignal { return this.sharedModel.attrsChanged; } @@ -39,12 +49,13 @@ export class JupyterYModel implements IJupyterYModel { return this._ready.promise; } - async ydocFactory(commMetadata: { [key: string]: any }): Promise { - return new Y.Doc(); + protected async initialize(commMetadata: { [key: string]: any }) { + this.ydoc = this.ydocFactory(commMetadata); + this.sharedModel = new JupyterYDoc(commMetadata, this._ydoc); } - async sharedModelFactory(commMetadata: { [key: string]: any }, ydoc: Y.Doc) { - return new JupyterYDoc(commMetadata, ydoc); + ydocFactory(commMetadata: { [key: string]: any }): Y.Doc { + return new Y.Doc(); } dispose(): void { @@ -65,6 +76,8 @@ export class JupyterYModel implements IJupyterYModel { this.sharedModel.removeAttr(key); } + private _ydoc: Y.Doc; + private _yModelName: string; private _sharedModel: IJupyterYDoc;