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 e0c05570c856f..cf985a8ed094f 100644 --- a/packages/plugin-ext/src/hosted/node/plugin-host-rpc.ts +++ b/packages/plugin-ext/src/hosted/node/plugin-host-rpc.ts @@ -97,45 +97,43 @@ export class PluginHostRPC { const pluginManager = new PluginManagerExtImpl({ loadPlugin(plugin: Plugin): void { 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); } }, 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 704fea2f167e4..f62bf8ec61913 100644 --- a/packages/plugin-ext/src/plugin/plugin-manager.ts +++ b/packages/plugin-ext/src/plugin/plugin-manager.ts @@ -220,31 +220,35 @@ export class PluginManagerExtImpl implements PluginManagerExt, PluginManager { let loading = this.loadedPlugins.get(plugin.model.id); if (!loading) { loading = (async () => { - 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; + try { + if (plugin.rawModel.extensionDependencies) { + for (const dependencyId of plugin.rawModel.extensionDependencies) { + const dependency = this.registry.get(dependencyId.toLowerCase()); + if (dependency) { + const loadedSuccessfully = await this.loadPlugin(dependency, configStorage, visited); + if (!loadedSuccessfully) { + throw new Error(`Dependent extension '${dependency.model.displayName || dependency.model.id}' failed to activate.`); + } + } else { + throw new Error(`Dependent extension '${dependencyId}' is not installed.`); } - } 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; } } - } - 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 this.startPlugin(plugin, configStorage, pluginMain); + 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 || {}; + 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; + } })(); } this.loadedPlugins.set(plugin.model.id, loading); @@ -269,7 +273,7 @@ export class PluginManagerExtImpl implements PluginManagerExt, PluginManager { } // tslint:disable-next-line:no-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 @@ -298,29 +302,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)); - - // 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; + 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); } } 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[] {