Skip to content

Commit

Permalink
refactor: canvas support cleanUpOnDestroy config, fix memory leak aft…
Browse files Browse the repository at this point in the history
…er destroy
  • Loading branch information
Aarebecca committed Oct 17, 2024
1 parent d391923 commit 259ce4e
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 18 deletions.
11 changes: 10 additions & 1 deletion __tests__/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,13 @@ searchInput.onkeyup = () => {
renderOptions(value);
};

// Render button
const renderBtn = document.createElement('button');
renderBtn.textContent = 'Render';
renderBtn.onclick = () => {
if (selectChart.value) plot();
};

// Span for tips.
const span = document.createElement('span');
span.textContent = 'Press left or right to view more.';
Expand All @@ -140,12 +147,13 @@ app.append(selectChart);
app.append(searchInput);
app.append(selectRenderer);
app.append(span);
app.append(renderBtn);
plot();

async function plot() {
if (currentContainer) {
currentContainer.remove();
if (canvas) canvas.destroy();
if (canvas) canvas.destroy(false, true);
if (prevAfter) prevAfter();
}
currentContainer = document.createElement('div');
Expand Down Expand Up @@ -209,6 +217,7 @@ function createSpecRender(object) {
container: $div,
width: window['CANVAS_WIDTH'] || 640,
height: window['CANVAS_HEIGHT'] || 640,
cleanUpOnDestroy: false,
renderer,
});

Expand Down
33 changes: 26 additions & 7 deletions packages/g-lite/src/Canvas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ export class Canvas extends EventTarget implements ICanvas {
supportsPointerEvents,
supportsTouchEvents,
supportsCSSTransform,
cleanUpOnDestroy = true,
supportsMutipleCanvasesInOneContainer,
useNativeClickEvent,
alwaysTriggerPointerEventOnCanvas,
Expand All @@ -177,7 +178,7 @@ export class Canvas extends EventTarget implements ICanvas {
} = config;

if (!supportsMutipleCanvasesInOneContainer) {
cleanExistedCanvas(container, this);
cleanExistedCanvas(container, this, cleanUpOnDestroy);
}

let canvasWidth = width;
Expand Down Expand Up @@ -244,6 +245,7 @@ export class Canvas extends EventTarget implements ICanvas {
document,
supportsCSSTransform,
useNativeClickEvent,
cleanUpOnDestroy,
alwaysTriggerPointerEventOnCanvas,
});

Expand Down Expand Up @@ -384,7 +386,10 @@ export class Canvas extends EventTarget implements ICanvas {
/**
* `cleanUp` means clean all the internal services of Canvas which happens when calling `canvas.destroy()`.
*/
destroy(cleanUp = true, skipTriggerEvent = false) {
destroy(cleanUp = true, skipTriggerEvent?: boolean) {
if (skipTriggerEvent === undefined)
skipTriggerEvent = this.getConfig().fastCleanExistingCanvas;

if (!skipTriggerEvent) {
this.dispatchEvent(new CustomEvent(CanvasEvent.BEFORE_DESTROY));
}
Expand Down Expand Up @@ -419,6 +424,18 @@ export class Canvas extends EventTarget implements ICanvas {
if (!skipTriggerEvent) {
this.dispatchEvent(new CustomEvent(CanvasEvent.AFTER_DESTROY));
}

const clearEventRetain = (event: CustomEvent) => {
event.currentTarget = null;
event.manager = null;
event.target = null;
};

clearEventRetain(mountedEvent);
clearEventRetain(unmountedEvent);
clearEventRetain(beforeRenderEvent);
clearEventRetain(rerenderEvent);
clearEventRetain(afterRenderEvent);
}

/**
Expand Down Expand Up @@ -649,11 +666,13 @@ export class Canvas extends EventTarget implements ICanvas {
});

if (this.inited) {
if (parent.isMutationObserved) {
parent.dispatchEvent(unmountedEvent);
} else {
unmountedEvent.target = parent;
this.dispatchEvent(unmountedEvent, true);
if (!this.getConfig().cleanUpOnDestroy) {
if (parent.isMutationObserved) {
parent.dispatchEvent(unmountedEvent);
} else {
unmountedEvent.target = parent;
this.dispatchEvent(unmountedEvent, true);
}
}

// skip document.documentElement
Expand Down
5 changes: 5 additions & 0 deletions packages/g-lite/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,11 @@ export interface CanvasConfig {
*/
supportsMutipleCanvasesInOneContainer?: boolean;

/**
* 销毁画布时是否执行清理操作
*/
cleanUpOnDestroy?: boolean;

/**
* 画布宽度
*/
Expand Down
18 changes: 8 additions & 10 deletions packages/g-lite/src/utils/canvas.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
import type { Canvas } from '../Canvas';

const canvasMap: Record<string, Canvas> = {};
let defaultCanvasIdCounter = 0;
const CANVAS_Map = new WeakMap<Element, Canvas>();

/**
* destroy existed canvas with the same id
*/
export function cleanExistedCanvas(
container: string | HTMLElement,
canvas: Canvas,
cleanUp?: boolean,
) {
if (container) {
const id =
const $dom =
typeof container === 'string'
? container
: container.id || defaultCanvasIdCounter++;

if (canvasMap[id]) {
canvasMap[id].destroy();
}
? document.getElementById(container)
: container;

canvasMap[id] = canvas;
if (CANVAS_Map.has($dom)) CANVAS_Map.get($dom).destroy(cleanUp);
else CANVAS_Map.set($dom, canvas);
}
}

Expand Down

0 comments on commit 259ce4e

Please sign in to comment.