mirror of
https://github.com/penpot/penpot.git
synced 2026-11-01 07:20:32 +00:00
Unloading or replacing a plugin while its code was still being fetched could leave a late instance running, or block reopening a plugin that closed during startup. Each load now carries an AbortController. Unloading, a newer load of the same plugin or logout aborts it, and the plugin manager closes itself on abort, also while it fetches its code. createPlugin returns nothing for a plugin closed before its sandbox exists, and failed loads clear their pending state so the plugin can be loaded again.
55 lines
1.2 KiB
TypeScript
55 lines
1.2 KiB
TypeScript
import type { Context } from '@penpot/plugin-types';
|
|
import type { Manifest } from './models/manifest.model.js';
|
|
import { createPluginManager } from './plugin-manager.js';
|
|
import { createSandbox, markPluginError } from './create-sandbox.js';
|
|
|
|
export async function createPlugin(
|
|
context: Context,
|
|
manifest: Manifest,
|
|
onCloseCallback: () => void,
|
|
apiExtensions?: object,
|
|
signal?: AbortSignal,
|
|
) {
|
|
// Closing can happen while the manager is still fetching code.
|
|
let sandbox: ReturnType<typeof createSandbox> | undefined = undefined;
|
|
|
|
const evaluateSandbox = async () => {
|
|
if (plugin.destroyed || !sandbox) return;
|
|
try {
|
|
sandbox.evaluate();
|
|
} catch (error) {
|
|
markPluginError(error);
|
|
plugin.close();
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
const plugin = await createPluginManager(
|
|
context,
|
|
manifest,
|
|
function onClose() {
|
|
sandbox?.cleanGlobalThis();
|
|
onCloseCallback();
|
|
},
|
|
function onReloadModal() {
|
|
evaluateSandbox();
|
|
},
|
|
signal,
|
|
);
|
|
|
|
if (plugin.destroyed) return;
|
|
|
|
sandbox = createSandbox(plugin, apiExtensions);
|
|
|
|
await evaluateSandbox();
|
|
|
|
return {
|
|
plugin,
|
|
manifest,
|
|
compartment: sandbox,
|
|
get iframeWindow() {
|
|
return plugin.iframeWindow;
|
|
},
|
|
};
|
|
}
|