diff --git a/libs/plugins-runtime/src/lib/api/index.ts b/libs/plugins-runtime/src/lib/api/index.ts index 151150d..dbb9c6c 100644 --- a/libs/plugins-runtime/src/lib/api/index.ts +++ b/libs/plugins-runtime/src/lib/api/index.ts @@ -70,6 +70,13 @@ export function createApi(context: PenpotContext, manifest: Manifest): Penpot { let modal: PluginModalElement | null = null; const closePlugin = () => { + // remove all event listeners + Object.entries(listeners).forEach(([, map]) => { + map.forEach((id) => { + context.removeListener(id); + }); + }); + if (modal) { modals.delete(modal); diff --git a/libs/plugins-runtime/src/lib/api/plugin-api.spec.ts b/libs/plugins-runtime/src/lib/api/plugin-api.spec.ts index 4d5d3c2..06fb92e 100644 --- a/libs/plugins-runtime/src/lib/api/plugin-api.spec.ts +++ b/libs/plugins-runtime/src/lib/api/plugin-api.spec.ts @@ -129,6 +129,15 @@ describe('Plugin api', () => { expect(mockContext.removeListener).toHaveBeenCalled(); expect((mockContext.removeListener.mock as any).lastCall[0]).toBe(id); }); + + it('remove event on close plugin', () => { + const callback = vi.fn(); + + api.on('pagechange', callback); + api.closePlugin(); + + expect(mockContext.removeListener).toHaveBeenCalled(); + }); }); describe.concurrent('permissions', () => { @@ -227,7 +236,7 @@ describe('Plugin api', () => { expect(modalMock.setTheme).toHaveBeenCalledWith('dark'); }); - it('close puglin', () => { + it('close plugin', () => { const name = 'test'; const url = 'http://fake.com'; const options = { width: 100, height: 100 }; diff --git a/libs/plugins-runtime/src/lib/load-plugin.ts b/libs/plugins-runtime/src/lib/load-plugin.ts index 114e80e..f29df2b 100644 --- a/libs/plugins-runtime/src/lib/load-plugin.ts +++ b/libs/plugins-runtime/src/lib/load-plugin.ts @@ -19,6 +19,14 @@ export function setContextBuilder(builder: ContextBuilder) { export const ɵloadPlugin = async function (manifest: Manifest) { try { + const closeAllPlugins = () => { + createdApis.forEach((pluginApi) => { + pluginApi.closePlugin(); + }); + + createdApis = []; + }; + const context = contextBuilder && contextBuilder(manifest.pluginId); if (!context) { @@ -35,9 +43,7 @@ export const ɵloadPlugin = async function (manifest: Manifest) { } if (createdApis && !multiPlugin) { - createdApis.forEach((pluginApi) => { - pluginApi.closePlugin(); - }); + closeAllPlugins(); } const pluginApi = createApi(context, manifest); @@ -70,9 +76,7 @@ export const ɵloadPlugin = async function (manifest: Manifest) { c.evaluate(code); const listenerId: symbol = context.addListener('finish', () => { - createdApis.forEach((pluginApi) => { - pluginApi.closePlugin(); - }); + closeAllPlugins(); context?.removeListener(listenerId); });