diff --git a/common/changes/@visactor/vtable/fix-mem_leak_2026-03-02-13-18.json b/common/changes/@visactor/vtable/fix-mem_leak_2026-03-02-13-18.json new file mode 100644 index 0000000000..8df72791a8 --- /dev/null +++ b/common/changes/@visactor/vtable/fix-mem_leak_2026-03-02-13-18.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vtable", + "comment": "fix(core): prevent memory leaks in table cleanup", + "type": "none" + } + ], + "packageName": "@visactor/vtable" +} \ No newline at end of file diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 44b0749de1..62935e6c65 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -307,10 +307,10 @@ importers: '@types/react-dom': ^18.0.0 '@visactor/vchart': 2.0.13-alpha.10 '@visactor/vdataset': ~1.0.17 - '@visactor/vrender-animate': ~1.0.40 - '@visactor/vrender-components': ~1.0.40 - '@visactor/vrender-core': ~1.0.40 - '@visactor/vrender-kits': ~1.0.40 + '@visactor/vrender-animate': ~1.0.41 + '@visactor/vrender-components': ~1.0.41 + '@visactor/vrender-core': ~1.0.41 + '@visactor/vrender-kits': ~1.0.41 '@visactor/vscale': ~1.0.17 '@visactor/vtable-editors': workspace:* '@visactor/vutils': ~1.0.17 @@ -357,10 +357,10 @@ importers: vite-plugin-markdown: ^2.1.0 dependencies: '@visactor/vdataset': 1.0.21 - '@visactor/vrender-animate': 1.0.40 - '@visactor/vrender-components': 1.0.40 - '@visactor/vrender-core': 1.0.40 - '@visactor/vrender-kits': 1.0.40 + '@visactor/vrender-animate': 1.0.41 + '@visactor/vrender-components': 1.0.41 + '@visactor/vrender-core': 1.0.41 + '@visactor/vrender-kits': 1.0.41 '@visactor/vscale': 1.0.21 '@visactor/vtable-editors': link:../vtable-editors '@visactor/vutils': 1.0.21 @@ -4329,10 +4329,10 @@ packages: '@visactor/vrender-core': 1.0.37-alpha.1 '@visactor/vutils': 1.0.21 - /@visactor/vrender-animate/1.0.40: - resolution: {integrity: sha512-/OT+xKwTdRa+bhTF28mQxl+9HsaIncNFGv00G3m2EHQT7Ls8SCDAyD46J36+bU3eYKz/+V+CzL2ApwI/zXP8/A==} + /@visactor/vrender-animate/1.0.41: + resolution: {integrity: sha512-kdMoIh7OEo6z4rZfnJHX7d+izBhGVWq6MR22uppk0LPilfdBd/1hSNAEKO6C9JWAy5uROGFpEkh+kk+ar/zSZg==} dependencies: - '@visactor/vrender-core': 1.0.40 + '@visactor/vrender-core': 1.0.41 '@visactor/vutils': 1.0.21 dev: false @@ -4345,12 +4345,12 @@ packages: '@visactor/vscale': 1.0.21 '@visactor/vutils': 1.0.21 - /@visactor/vrender-components/1.0.40: - resolution: {integrity: sha512-+mooyFfpAaAjhBDN5XHKz1SH0vHe3IjabLJQWYwDZGvpPHieVIlZstkTIRMH63pJek0ViIZLHcxpf/i/qli+sw==} + /@visactor/vrender-components/1.0.41: + resolution: {integrity: sha512-B7iXJE1TdkYapPZN6DNxoaErY4FzGf5AbcbG/z6Q0hnzO4Iw1hKdtlTGOIYA1+JXhehDWcyy+D0bnoNQNf+rgw==} dependencies: - '@visactor/vrender-animate': 1.0.40 - '@visactor/vrender-core': 1.0.40 - '@visactor/vrender-kits': 1.0.40 + '@visactor/vrender-animate': 1.0.41 + '@visactor/vrender-core': 1.0.41 + '@visactor/vrender-kits': 1.0.41 '@visactor/vscale': 1.0.21 '@visactor/vutils': 1.0.21 dev: false @@ -4361,8 +4361,8 @@ packages: '@visactor/vutils': 1.0.21 color-convert: 2.0.1 - /@visactor/vrender-core/1.0.40: - resolution: {integrity: sha512-VNfxYGvNS2k1v2/+H0y9jIxjsFjgy3ieFGTDYz+o1rES2RY4wQIr6xJtdEkzXg6Foavp1gJj4fSf/wl2idEuTA==} + /@visactor/vrender-core/1.0.41: + resolution: {integrity: sha512-P7YVUJ45vwqPA460W6JJjg201ThvxBrjEgTBJ4tHKaHZPP/nVyF8rPyUOCL8QesEFDB+R0e/sUJUVs+ckHhd2w==} dependencies: '@visactor/vutils': 1.0.21 color-convert: 2.0.1 @@ -4378,11 +4378,11 @@ packages: lottie-web: 5.13.0 roughjs: 4.6.6 - /@visactor/vrender-kits/1.0.40: - resolution: {integrity: sha512-tMD2C4vQd5kN2WyDIkel4tId1NYGclKM1exIsJY51rgOjfJsjpRzC5WPe6KYqoIcDO5xDarX8TY4dkTR9S0l6w==} + /@visactor/vrender-kits/1.0.41: + resolution: {integrity: sha512-ffJlKkNseOsnRjvBmxKxQ9dsQXu+K288NFCtB0ZZ2N/mtcTsZUlH5SDCcsAvDhPGEvJ22Ye4MFKcXSEDctpGzA==} dependencies: '@resvg/resvg-js': 2.4.1 - '@visactor/vrender-core': 1.0.40 + '@visactor/vrender-core': 1.0.41 '@visactor/vutils': 1.0.21 gifuct-js: 2.1.2 lottie-web: 5.13.0 diff --git a/packages/vtable/examples/debug/mem.ts b/packages/vtable/examples/debug/mem.ts new file mode 100644 index 0000000000..fe38351985 --- /dev/null +++ b/packages/vtable/examples/debug/mem.ts @@ -0,0 +1,62 @@ +/* eslint-disable */ +import * as VTable from '../../src'; +import VChart from '@visactor/vchart'; +import { bindDebugTool } from '../../src/scenegraph/debug-tool'; + +const CONTAINER_ID = 'vTable'; +VTable.register.chartModule('vchart', VChart); +export function createTable() { + const option = { + columns: [ + { field: 'id', title: 'ID', width: 80 }, + { field: 'name', title: '姓名', width: 120 }, + { field: 'age', title: '年龄', width: 80 }, + { field: 'city', title: '城市', width: 120 } + ], + records: Array.from({ length: 10000 }, (_, i) => ({ + id: i, + name: `张三${i}`, + age: i, + city: `城市${i}` + })) + }; + // document.getElementById(CONTAINER_ID).parentElement.style.display = 'none'; + let tableInstance = new VTable.ListTable(document.getElementById(CONTAINER_ID), option); + // window.tableInstance = instance; + + // tableInstance.onVChartEvent('mouseover', args => { + // console.log('listenChart mouseover', args); + // }); + + // bindDebugTool(tableInstance.scenegraph.stage, { + // customGrapicKeys: ['col', 'row'] + // }); + + const update = async () => { + // 执行20次release / new + for (let i = 0; i < 20; i++) { + await new Promise(resolve => setTimeout(resolve, 200)); + // // tableInstance.release(); + // // instance.scenegraph.component.vScrollBar.release(); + // // instance.scenegraph.component.hScrollBar.release(); + // // instance.scenegraph.stage.removeAllChild(); + // // delete instance.scenegraph.stage.table; + // // instance.scenegraph.clearCells(); + // tableInstance.scenegraph.component.vScrollBar.release(); + // tableInstance.scenegraph.component.hScrollBar.release(); + // tableInstance.animationManager.clear(); + // tableInstance.animationManager.ticker.release(); + // // instance.animationManager.ticker = null; + // // instance.animationManager = null; + // tableInstance.scenegraph.stage.ticker.release(); + tableInstance.release(); + tableInstance = null; + await new Promise(resolve => setTimeout(resolve, 200)); + tableInstance = new VTable.ListTable(document.getElementById(CONTAINER_ID), option); + console.log(`第${i}次new完成`); + } + }; + + window.update = update; + // update(); +} diff --git a/packages/vtable/examples/menu.ts b/packages/vtable/examples/menu.ts index 0d27309193..4d407c4a09 100644 --- a/packages/vtable/examples/menu.ts +++ b/packages/vtable/examples/menu.ts @@ -25,6 +25,10 @@ export const menus = [ { path: 'debug', name: 'scroll' + }, + { + path: 'debug', + name: 'mem' } ] }, diff --git a/packages/vtable/package.json b/packages/vtable/package.json index b8a40972e1..fa296e23b1 100644 --- a/packages/vtable/package.json +++ b/packages/vtable/package.json @@ -53,10 +53,10 @@ }, "dependencies": { "@visactor/vtable-editors": "workspace:*", - "@visactor/vrender-core": "~1.0.40", - "@visactor/vrender-kits": "~1.0.40", - "@visactor/vrender-components": "~1.0.40", - "@visactor/vrender-animate": "~1.0.40", + "@visactor/vrender-core": "~1.0.41", + "@visactor/vrender-kits": "~1.0.41", + "@visactor/vrender-components": "~1.0.41", + "@visactor/vrender-animate": "~1.0.41", "@visactor/vutils": "~1.0.17", "@visactor/vscale": "~1.0.17", "@visactor/vdataset": "~1.0.17", @@ -133,4 +133,4 @@ "url": "https://github.com/VisActor/VTable.git", "directory": "packages/vtable" } -} +} \ No newline at end of file diff --git a/packages/vtable/src/core/BaseTable.ts b/packages/vtable/src/core/BaseTable.ts index 590b1afcde..0ffe5355b3 100644 --- a/packages/vtable/src/core/BaseTable.ts +++ b/packages/vtable/src/core/BaseTable.ts @@ -2610,6 +2610,13 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { * @returns {void} */ release(): void { + // for memory leak of VRender Event + this.scenegraph?.component?.vScrollBar?.release(); + this.scenegraph?.component?.hScrollBar?.release(); + this.animationManager.clear(); + this.animationManager.ticker.release(); + this.scenegraph?.stage?.ticker?.release(); + const internalProps = this.internalProps; if (this.isReleased) { return;