[wasm] Introduce unregisterLanguageExtensionPlugin API.
This adds a new method `unregisterLanguageExtensionPlugin()` to the
`LanguageServicesAPI` exposed to DevTools extensions, which allows the
developer to unregister a previously registred language extension
plugin. This is useful for example when the configuration for an
extension changes and the front-end should reload the source mappings.
Drive-by-fix: Also make the registerLanguageExtensionPlugin and the
unregisterLanguageExtensionPlugin methods return promises, so that
the extensions can properly await / chain them.
Fixed: chromium:1151285
Bug: chromium:1151280, chromium:1041362, chromium:1083146
Change-Id: Ib62b70c717754d70cf827ba1a97fb5c3e358ee1f
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2552506
Reviewed-by: Philip Pfaffe <[email protected]>
Commit-Queue: Benedikt Meurer <[email protected]>
Auto-Submit: Benedikt Meurer <[email protected]>
diff --git a/front_end/extensions/ExtensionAPI.js b/front_end/extensions/ExtensionAPI.js
index 94e3b89..4ea1793 100644
--- a/front_end/extensions/ExtensionAPI.js
+++ b/front_end/extensions/ExtensionAPI.js
@@ -102,6 +102,11 @@
GetInlinedFunctionRanges: 'getInlinedFunctionRanges',
GetInlinedCalleesRanges: 'getInlinedCalleesRanges'
};
+
+ /** @enum {string} */
+ apiPrivate.LanguageExtensionPluginEvents = {
+ UnregisteredLanguageExtensionPlugin: 'unregisteredLanguageExtensionPlugin'
+ };
}
/**
@@ -128,6 +133,7 @@
const commands = apiPrivate.Commands;
const languageExtensionPluginCommands = apiPrivate.LanguageExtensionPluginCommands;
+ const languageExtensionPluginEvents = apiPrivate.LanguageExtensionPluginEvents;
const events = apiPrivate.Events;
let userAction = false;
@@ -368,6 +374,7 @@
* @constructor
*/
function LanguageServicesAPIImpl() {
+ /** @type {!Map<*, !MessagePort>} */
this._plugins = new Map();
}
@@ -376,10 +383,11 @@
* @param {*} plugin The language plugin instance to register.
* @param {string} pluginName The plugin name
* @param {{language: string, symbol_types: !Array<string>}} supportedScriptTypes Script language and debug symbol types supported by this extension.
+ * @return {!Promise<void>}
*/
- registerLanguageExtensionPlugin: function(plugin, pluginName, supportedScriptTypes) {
+ registerLanguageExtensionPlugin: async function(plugin, pluginName, supportedScriptTypes) {
if (this._plugins.has(plugin)) {
- throw new Error('Tried to register a plugin twice');
+ throw new Error(`Tried to register plugin '${pluginName}' twice`);
}
const channel = new MessageChannel();
const port = channel.port1;
@@ -425,9 +433,25 @@
throw new Error(`Unknown language plugin method ${method}`);
}
- extensionServer.sendRequest(
- {command: commands.RegisterLanguageExtensionPlugin, pluginName, port: channel.port2, supportedScriptTypes},
- undefined, [channel.port2]);
+ await new Promise(resolve => {
+ extensionServer.sendRequest(
+ {command: commands.RegisterLanguageExtensionPlugin, pluginName, port: channel.port2, supportedScriptTypes},
+ () => resolve(), [channel.port2]);
+ });
+ },
+
+ /**
+ * @param {*} plugin The language plugin instance to unregister.
+ * @return {!Promise<void>}
+ */
+ unregisterLanguageExtensionPlugin: async function(plugin) {
+ const port = this._plugins.get(plugin);
+ if (!port) {
+ throw new Error('Tried to unregister a plugin that was not previously registered');
+ }
+ this._plugins.delete(plugin);
+ port.postMessage({event: languageExtensionPluginEvents.UnregisteredLanguageExtensionPlugin});
+ port.close();
}
};