Skip to content

Commit

Permalink
Fix/memory leak (#4009)
Browse files Browse the repository at this point in the history
* fix: memory leak issues

* fix: `Dom.Event.off` error while passing unexist event

* test: Add test case for `Dom.Event.off` bug

---------

Co-authored-by: cluezhang <[email protected]>
  • Loading branch information
cyrilluce and cluezhang authored Nov 6, 2023
1 parent 339cade commit ffbc7ed
Show file tree
Hide file tree
Showing 10 changed files with 67 additions and 15 deletions.
8 changes: 7 additions & 1 deletion packages/x6-common/src/__tests__/dom/event.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,10 +294,16 @@ describe('EventDom', () => {
expect(() => div.off('click', false)).not.toThrowError()
})

it('should do noting for elem which do not bind any events', () => {
it('should do nothing for elem which do not bind any events', () => {
const div = new EventDom()
expect(() => div.off()).not.toThrowError()
})

it('should do nothing for unexist event', () => {
const div = new EventDom()
div.on('whatever', () => {})
expect(() => div.off('unexist')).not.toThrowError()
})
})

describe('trigger()', () => {
Expand Down
10 changes: 9 additions & 1 deletion packages/x6-common/src/common/basecoat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,15 @@ import { EventArgs } from '../event/types'
import { ObjectExt } from '../object'
import { Disposable } from './disposable'

export class Basecoat<A extends EventArgs = any> extends Events<A> {}
export class Basecoat<A extends EventArgs = any>
extends Events<A>
implements Disposable
{
@Disposable.dispose()
dispose() {
this.off()
}
}

export interface Basecoat extends Disposable {}

Expand Down
5 changes: 4 additions & 1 deletion packages/x6-common/src/dom/event/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,10 @@ export namespace Core {
let type = originType
const hook = EventHook.get(type)
type = (selector ? hook.delegateType : hook.bindType) || type
const bag = events[type] || {}
const bag = events[type]
if (!bag) {
return
}
const rns =
namespaces.length > 0
? new RegExp(`(^|\\.)${namespaces.join('\\.(?:.*\\.|)')}(\\.|$)`)
Expand Down
5 changes: 2 additions & 3 deletions packages/x6/src/graph/graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1262,6 +1262,7 @@ export class Graph extends Basecoat<EventArgs> {
const aboutToChangePlugins = this.getPlugins(postPlugins)
aboutToChangePlugins?.forEach((plugin) => {
plugin.dispose()
this.installedPlugins.delete(plugin)
})
return this
}
Expand All @@ -1273,11 +1274,9 @@ export class Graph extends Basecoat<EventArgs> {
@Basecoat.dispose()
dispose(clean = true) {
if (clean) {
this.clearCells()
this.model.dispose()
}

this.off()

this.css.dispose()
this.defs.dispose()
this.grid.dispose()
Expand Down
5 changes: 5 additions & 0 deletions packages/x6/src/model/collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,11 @@ export class Collection extends Basecoat<Collection.EventArgs> {
this.cells = []
this.map = {}
}

@Collection.dispose()
dispose() {
this.reset([])
}
}

export namespace Collection {
Expand Down
5 changes: 5 additions & 0 deletions packages/x6/src/model/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1323,6 +1323,11 @@ export class Model extends Basecoat<Model.EventArgs> {
}

// #endregion

@Model.dispose()
dispose() {
this.collection.dispose()
}
}

export namespace Model {
Expand Down
5 changes: 5 additions & 0 deletions packages/x6/src/renderer/scheduler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,11 @@ export class Scheduler extends Disposable {
@Disposable.dispose()
dispose() {
this.stopListening()
// clear views
Object.keys(this.views).forEach((id) => {
this.views[id].view.dispose()
})
this.views = {}
}
}
export namespace Scheduler {
Expand Down
23 changes: 15 additions & 8 deletions packages/x6/src/shape/html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,17 @@ export namespace HTML {
export class View extends NodeView<HTML> {
protected init() {
super.init()
this.cell.on('change:*', ({ key }) => {
const content = shapeMaps[this.cell.shape]
if (content) {
const { effect } = content
if (!effect || effect.includes(key)) {
this.renderHTMLComponent()
}
this.cell.on('change:*', this.onCellChangeAny, this)
}

protected onCellChangeAny({ key }: Cell.EventArgs['change:*']) {
const content = shapeMaps[this.cell.shape]
if (content) {
const { effect } = content
if (!effect || effect.includes(key)) {
this.renderHTMLComponent()
}
})
}
}

confirmUpdate(flag: number) {
Expand Down Expand Up @@ -58,6 +60,11 @@ export namespace HTML {
}
}
}

@View.dispose()
dispose() {
this.cell.off('change:*', this.onCellChangeAny, this)
}
}

export namespace View {
Expand Down
11 changes: 10 additions & 1 deletion packages/x6/src/view/cell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,11 @@ export class CellView<
}

protected setup() {
this.cell.on('changed', ({ options }) => this.onAttrsChange(options))
this.cell.on('changed', this.onCellChanged, this)
}

protected onCellChanged({ options }: Cell.EventArgs['changed']) {
this.onAttrsChange(options)
}

protected onAttrsChange(options: Cell.MutateOptions) {
Expand Down Expand Up @@ -739,6 +743,11 @@ export class CellView<
view.onMouseEnter(e as Dom.MouseEnterEvent)
}

@CellView.dispose()
dispose() {
this.cell.off('changed', this.onCellChanged, this)
}

// #endregion
}

Expand Down
5 changes: 5 additions & 0 deletions packages/x6/src/view/view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,11 @@ export abstract class View<A extends EventArgs = any> extends Basecoat<A> {
normalizeEvent<T extends Dom.EventObject>(evt: T) {
return View.normalizeEvent(evt)
}

@View.dispose()
dispose() {
this.remove()
}
}

export namespace View {
Expand Down

0 comments on commit ffbc7ed

Please sign in to comment.