diff --git a/packages/plugin-ext/src/hosted/node/plugin-host-rpc.ts b/packages/plugin-ext/src/hosted/node/plugin-host-rpc.ts index 10054cac27b9a..4fbc8f817b64b 100644 --- a/packages/plugin-ext/src/hosted/node/plugin-host-rpc.ts +++ b/packages/plugin-ext/src/hosted/node/plugin-host-rpc.ts @@ -102,47 +102,43 @@ export class PluginHostRPC { // eslint-disable-next-line @typescript-eslint/no-explicit-any loadPlugin(plugin: Plugin): any { console.log('PLUGIN_HOST(' + process.pid + '): PluginManagerExtImpl/loadPlugin(' + plugin.pluginPath + ')'); - try { - // cleaning the cache for all files of that plug-in. - Object.keys(require.cache).forEach(function (key): void { - const mod: NodeJS.Module = require.cache[key]; + // cleaning the cache for all files of that plug-in. + Object.keys(require.cache).forEach(function (key): void { + const mod: NodeJS.Module = require.cache[key]; - // attempting to reload a native module will throw an error, so skip them - if (mod.id.endsWith('.node')) { - return; - } + // attempting to reload a native module will throw an error, so skip them + if (mod.id.endsWith('.node')) { + return; + } - // remove children that are part of the plug-in - let i = mod.children.length; - while (i--) { - const childMod: NodeJS.Module = mod.children[i]; - // ensure the child module is not null, is in the plug-in folder, and is not a native module (see above) - if (childMod && childMod.id.startsWith(plugin.pluginFolder) && !childMod.id.endsWith('.node')) { - // cleanup exports - note that some modules (e.g. ansi-styles) define their - // exports in an immutable manner, so overwriting the exports throws an error - delete childMod.exports; - mod.children.splice(i, 1); - for (let j = 0; j < childMod.children.length; j++) { - delete childMod.children[j]; - } + // remove children that are part of the plug-in + let i = mod.children.length; + while (i--) { + const childMod: NodeJS.Module = mod.children[i]; + // ensure the child module is not null, is in the plug-in folder, and is not a native module (see above) + if (childMod && childMod.id.startsWith(plugin.pluginFolder) && !childMod.id.endsWith('.node')) { + // cleanup exports - note that some modules (e.g. ansi-styles) define their + // exports in an immutable manner, so overwriting the exports throws an error + delete childMod.exports; + mod.children.splice(i, 1); + for (let j = 0; j < childMod.children.length; j++) { + delete childMod.children[j]; } } + } - if (key.startsWith(plugin.pluginFolder)) { - // delete entry - delete require.cache[key]; - const ix = mod.parent!.children.indexOf(mod); - if (ix >= 0) { - mod.parent!.children.splice(ix, 1); - } + if (key.startsWith(plugin.pluginFolder)) { + // delete entry + delete require.cache[key]; + const ix = mod.parent!.children.indexOf(mod); + if (ix >= 0) { + mod.parent!.children.splice(ix, 1); } - - }); - if (plugin.pluginPath) { - return require(plugin.pluginPath); } - } catch (e) { - console.error(e); + + }); + if (plugin.pluginPath) { + return require(plugin.pluginPath); } }, async init(raw: PluginMetadata[]): Promise<[Plugin[], Plugin[]]> { diff --git a/packages/plugin-ext/src/plugin/plugin-manager.ts b/packages/plugin-ext/src/plugin/plugin-manager.ts index 87b946bd9ffa5..5159f7248aefa 100644 --- a/packages/plugin-ext/src/plugin/plugin-manager.ts +++ b/packages/plugin-ext/src/plugin/plugin-manager.ts @@ -269,20 +269,13 @@ export class PluginManagerExtImpl implements PluginManagerExt, PluginManager { if (plugin.rawModel.extensionDependencies) { for (const dependencyId of plugin.rawModel.extensionDependencies) { const dependency = this.registry.get(dependencyId.toLowerCase()); - const id = plugin.model.displayName || plugin.model.id; if (dependency) { - const depId = dependency.model.displayName || dependency.model.id; const loadedSuccessfully = await this.loadPlugin(dependency, configStorage, visited); if (!loadedSuccessfully) { - const message = `Cannot activate extension '${id}' because it depends on extension '${depId}', which failed to activate.`; - this.messageRegistryProxy.$showMessage(MainMessageType.Error, message, {}, []); - return false; + throw new Error(`Dependent extension '${dependency.model.displayName || dependency.model.id}' failed to activate.`); } } else { - const message = `Cannot activate the '${id}' extension because it depends on the '${dependencyId}' extension, which is not installed.`; - this.messageRegistryProxy.$showMessage(MainMessageType.Error, message, {}, []); - console.warn(message); - return false; + throw new Error(`Dependent extension '${dependencyId}' is not installed.`); } } } @@ -290,7 +283,16 @@ export class PluginManagerExtImpl implements PluginManagerExt, PluginManager { let pluginMain = this.host.loadPlugin(plugin); // see https://github.com/TypeFox/vscode/blob/70b8db24a37fafc77247de7f7cb5bb0195120ed0/src/vs/workbench/api/common/extHostExtensionService.ts#L372-L376 pluginMain = pluginMain || {}; - return await this.startPlugin(plugin, configStorage, pluginMain); + await this.startPlugin(plugin, configStorage, pluginMain); + return true; + } catch (err) { + if (this.pluginActivationPromises.has(plugin.model.id)) { + this.pluginActivationPromises.get(plugin.model.id)!.reject(err); + } + const message = `Activating extension '${plugin.model.displayName || plugin.model.name}' failed: ${err.message}`; + this.messageRegistryProxy.$showMessage(MainMessageType.Error, message, {}, []); + console.error(message); + return false; } finally { this.notificationMain.$stopProgress(progressId); } @@ -330,7 +332,7 @@ export class PluginManagerExtImpl implements PluginManagerExt, PluginManager { } // eslint-disable-next-line @typescript-eslint/no-explicit-any - private async startPlugin(plugin: Plugin, configStorage: ConfigStorage, pluginMain: any): Promise { + private async startPlugin(plugin: Plugin, configStorage: ConfigStorage, pluginMain: any): Promise { const subscriptions: theia.Disposable[] = []; const asAbsolutePath = (relativePath: string): string => join(plugin.pluginFolder, relativePath); const logPath = join(configStorage.hostLogPath, plugin.model.id); // todo check format @@ -354,29 +356,19 @@ export class PluginManagerExtImpl implements PluginManagerExt, PluginManager { } const id = plugin.model.displayName || plugin.model.id; if (typeof pluginMain[plugin.lifecycle.startMethod] === 'function') { - try { - const pluginExport = await pluginMain[plugin.lifecycle.startMethod].apply(getGlobal(), [pluginContext]); - this.activatedPlugins.set(plugin.model.id, new ActivatedPlugin(pluginContext, pluginExport, stopFn)); + const pluginExport = await pluginMain[plugin.lifecycle.startMethod].apply(getGlobal(), [pluginContext]); + this.activatedPlugins.set(plugin.model.id, new ActivatedPlugin(pluginContext, pluginExport, stopFn)); - // resolve activation promise - if (this.pluginActivationPromises.has(plugin.model.id)) { - this.pluginActivationPromises.get(plugin.model.id)!.resolve(); - this.pluginActivationPromises.delete(plugin.model.id); - } - } catch (err) { - if (this.pluginActivationPromises.has(plugin.model.id)) { - this.pluginActivationPromises.get(plugin.model.id)!.reject(err); - } - this.messageRegistryProxy.$showMessage(MainMessageType.Error, `Activating extension ${id} failed: ${err.message}.`, {}, []); - console.error(`Error on activation of ${plugin.model.name}`, err); - return false; + // resolve activation promise + if (this.pluginActivationPromises.has(plugin.model.id)) { + this.pluginActivationPromises.get(plugin.model.id)!.resolve(); + this.pluginActivationPromises.delete(plugin.model.id); } } else { // https://github.com/TypeFox/vscode/blob/70b8db24a37fafc77247de7f7cb5bb0195120ed0/src/vs/workbench/api/common/extHostExtensionService.ts#L400-L401 console.log(`plugin ${id}, ${plugin.lifecycle.startMethod} method is undefined so the module is the extension's exports`); this.activatedPlugins.set(plugin.model.id, new ActivatedPlugin(pluginContext, pluginMain)); } - return true; } getAllPlugins(): Plugin[] {