From ab1746b5e85bb0c48d90d5275d7dcd2f01ed0720 Mon Sep 17 00:00:00 2001 From: Suzu008 Date: Tue, 24 Mar 2026 08:43:17 +0800 Subject: [PATCH] fix: prevent blob URL memory leaks by tracking and revoking URLs on re-execution and node removal --- ts/cryptioSaveImage.ts | 22 ++++++++++++++++++++++ ts/cryptioUploadImage.ts | 12 ++++++++++++ ts/utils/uploadUtils.ts | 6 ++++++ 3 files changed, 40 insertions(+) diff --git a/ts/cryptioSaveImage.ts b/ts/cryptioSaveImage.ts index 1dde129..cbf2478 100644 --- a/ts/cryptioSaveImage.ts +++ b/ts/cryptioSaveImage.ts @@ -34,12 +34,21 @@ app.registerExtension({ if (message?.cryptio_images) { const autoDownload = this.widgets.find((n: any) => n.name === "auto_download")?.value; + // Revoke previous blob URLs to prevent memory leaks + if (this._cryptioBlobUrls) { + for (const url of this._cryptioBlobUrls) { + URL.revokeObjectURL(url); + } + } + this._cryptioBlobUrls = [] as string[]; + for (let i = 0; i < message.cryptio_images.length; i++) { const imageInfo = message.cryptio_images[i]; if (imageInfo.filename && imageInfo.filename.endsWith(".encrypted")) { // 异步加载并解密图片 loadEncryptedImageFromParams(api, imageInfo) .then((imageUrl) => { + this._cryptioBlobUrls.push(imageUrl); // 更新节点的图片显示 const img = new Image(); img.onload = () => { @@ -89,6 +98,19 @@ app.registerExtension({ }); } }; + // Cleanup blob URLs on node removal + const onRemoved = nodeType.prototype.onRemoved; + nodeType.prototype.onRemoved = function () { + if (this._cryptioBlobUrls) { + for (const url of this._cryptioBlobUrls) { + URL.revokeObjectURL(url); + } + this._cryptioBlobUrls = []; + } + if (onRemoved) { + onRemoved.apply(this, arguments); + } + }; } }, }); diff --git a/ts/cryptioUploadImage.ts b/ts/cryptioUploadImage.ts index e3c0fe3..b9932c8 100644 --- a/ts/cryptioUploadImage.ts +++ b/ts/cryptioUploadImage.ts @@ -136,6 +136,18 @@ app.registerExtension({ return r; }; + + // Cleanup blob URLs on node removal + const onRemoved = nodeType.prototype.onRemoved; + nodeType.prototype.onRemoved = function () { + if (this._cryptioPreviewUrl) { + URL.revokeObjectURL(this._cryptioPreviewUrl); + this._cryptioPreviewUrl = null; + } + if (onRemoved) { + onRemoved.apply(this, arguments); + } + }; } }, }); diff --git a/ts/utils/uploadUtils.ts b/ts/utils/uploadUtils.ts index 90c0e7b..b881f03 100644 --- a/ts/utils/uploadUtils.ts +++ b/ts/utils/uploadUtils.ts @@ -81,7 +81,13 @@ export function createPreviewUpdateFunction(app: ComfyApp) { } try { + // Revoke previous blob URL to prevent memory leak + if (this._cryptioPreviewUrl) { + URL.revokeObjectURL(this._cryptioPreviewUrl); + } + const imageUrl = await loadEncryptedImageFromFilename(filename); + this._cryptioPreviewUrl = imageUrl; // 更新节点的图片显示 const img = new Image();