@lvce-editor/extension-management-worker 4.74.4 → 4.75.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1382,7 +1382,7 @@ const waitForReconnect = async () => {
1382
1382
  setTimeout(resolve, reconnectDelay);
1383
1383
  });
1384
1384
  };
1385
- const connect = async ({
1385
+ const connect$1 = async ({
1386
1386
  commandMap,
1387
1387
  wsUrl
1388
1388
  }) => {
@@ -1411,13 +1411,13 @@ const create$3 = async ({
1411
1411
  const wsUrl = getWebSocketUrl(type, host, protocol);
1412
1412
  let connection;
1413
1413
  try {
1414
- connection = await connect({
1414
+ connection = await connect$1({
1415
1415
  commandMap,
1416
1416
  wsUrl
1417
1417
  });
1418
1418
  } catch {
1419
1419
  await waitForReconnect();
1420
- connection = await connect({
1420
+ connection = await connect$1({
1421
1421
  commandMap,
1422
1422
  wsUrl
1423
1423
  });
@@ -1623,378 +1623,466 @@ const validateNodeProcessRpc = (extensionId, rpcId) => {
1623
1623
  if (rpc.type !== 'node-process') {
1624
1624
  throw new Error(`Rpc ${rpcId} declared by extension ${extension.id} is not a node process`);
1625
1625
  }
1626
+ return rpc;
1626
1627
  };
1627
1628
 
1628
- const isMissingRendererCommand = (error, command) => {
1629
- const moduleName = command.slice(0, command.indexOf('.'));
1630
- return error instanceof Error && (error.message.includes(command) || error.message.includes(`module ${moduleName} not found`)) && /command not found|not found/i.test(error.message);
1631
- };
1632
- const createUnsupportedDirectLaunchError = rpcId => {
1633
- return new Error(`Node process ${rpcId} requires direct renderer support`);
1634
- };
1635
- const createRemoteConnection = async (extensionId, rpcId) => {
1636
- try {
1637
- const connectionInfo = await invoke$4('ExtensionNodeRpc.createConnection', extensionId, rpcId);
1638
- return {
1639
- ...connectionInfo,
1640
- type: 'websocket'
1641
- };
1642
- } catch (error) {
1643
- if (isMissingRendererCommand(error, 'ExtensionNodeRpc.createConnection')) {
1644
- throw createUnsupportedDirectLaunchError(rpcId);
1629
+ const ContentType = 'Content-Type';
1630
+ const ContentLength = 'Content-Length';
1631
+
1632
+ const createResponseFromData = data => {
1633
+ const responseString = JSON.stringify(data);
1634
+ const response = new Response(responseString, {
1635
+ headers: {
1636
+ [ContentLength]: String(responseString.length),
1637
+ [ContentType]: 'application/json'
1645
1638
  }
1646
- throw error;
1639
+ });
1640
+ return response;
1641
+ };
1642
+
1643
+ const cacheName$1 = 'Extensions'; // TODO
1644
+
1645
+ const getJson$1 = async cacheKey => {
1646
+ const response = await caches.match(cacheKey, {
1647
+ cacheName: cacheName$1
1648
+ });
1649
+ if (!response) {
1650
+ return undefined;
1647
1651
  }
1652
+ const json = await response.json();
1653
+ return json;
1648
1654
  };
1649
- const createElectronConnection = async rpcId => {
1655
+ const setJson = async (cacheKey, data) => {
1650
1656
  try {
1651
- const supported = await invoke$4('ExtensionNodeRpc.supportsDirectConnection');
1652
- if (!supported) {
1653
- throw createUnsupportedDirectLaunchError(rpcId);
1654
- }
1655
- return {
1656
- type: 'message-port'
1657
- };
1657
+ const cache = await caches.open(cacheName$1);
1658
+ const response = createResponseFromData(data);
1659
+ await cache.put(cacheKey, response);
1658
1660
  } catch (error) {
1659
- if (isMissingRendererCommand(error, 'ExtensionNodeRpc.supportsDirectConnection')) {
1660
- throw createUnsupportedDirectLaunchError(rpcId);
1661
- }
1662
- throw error;
1661
+ throw new VError(error, `Failed to add to cache`);
1663
1662
  }
1664
1663
  };
1665
- const createNodeRpcConnection = async (extensionId, rpcId) => {
1666
- validateNodeProcessRpc(extensionId, rpcId);
1667
- const {
1668
- platform
1669
- } = get$7();
1670
- if (platform !== Remote && platform !== Electron) {
1671
- throw new Error('Node rpc is not available on this platform');
1672
- }
1673
- if (platform === Remote) {
1674
- return createRemoteConnection(extensionId, rpcId);
1664
+
1665
+ const disabledExtensionsCacheKey = '/cache/disabledExtensions.json';
1666
+
1667
+ /* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
1668
+
1669
+ const getStringArray$2 = value => {
1670
+ if (!Array.isArray(value)) {
1671
+ return [];
1675
1672
  }
1676
- return createElectronConnection(rpcId);
1673
+ return value.filter(id => typeof id === 'string');
1677
1674
  };
1678
- const createNodeRpcMessagePort = async (extensionId, rpcId, port) => {
1679
- const {
1680
- platform
1681
- } = get$7();
1682
- if (platform !== Electron) {
1683
- throw new Error('Node rpc message ports are only available in Electron');
1675
+ const getExtensionEnablementFromData = data => {
1676
+ return {
1677
+ disabledIds: getStringArray$2(data?.disabledExtensions),
1678
+ enabledIds: getStringArray$2(data?.enabledExtensions)
1679
+ };
1680
+ };
1681
+ const getWebExtensionEnablement = async () => {
1682
+ try {
1683
+ const cached = await getJson$1(disabledExtensionsCacheKey);
1684
+ return getExtensionEnablementFromData(cached);
1685
+ } catch {
1686
+ return getExtensionEnablementFromData(undefined);
1684
1687
  }
1685
- validateNodeProcessRpc(extensionId, rpcId);
1686
- await invokeAndTransfer$1('ExtensionNodeRpc.createMessagePort', port, extensionId, rpcId);
1687
1688
  };
1688
-
1689
- const extensionIds = new Set();
1690
- const applications$1 = new Map();
1691
- const register$1 = (extensionId, applicationId) => {
1692
- if (applicationId === undefined) {
1693
- extensionIds.add(extensionId);
1694
- return;
1689
+ const getRemoteExtensionEnablement = async () => {
1690
+ try {
1691
+ const uri = await invoke$4('WebView.compatSharedProcessInvoke', 'PlatformPaths.getDisabledExtensionsJsonUri');
1692
+ const exists$1 = await exists(uri);
1693
+ if (!exists$1) {
1694
+ return getExtensionEnablementFromData(undefined);
1695
+ }
1696
+ const content = await readFile$1(uri);
1697
+ return getExtensionEnablementFromData(JSON.parse(content));
1698
+ } catch {
1699
+ return getExtensionEnablementFromData(undefined);
1695
1700
  }
1696
- const ids = applications$1.get(applicationId) || new Set();
1697
- ids.add(extensionId);
1698
- applications$1.set(applicationId, ids);
1699
1701
  };
1700
- const unregister = (extensionId, applicationId) => {
1701
- if (applicationId === undefined) {
1702
- extensionIds.delete(extensionId);
1703
- return;
1702
+ const getExtensionEnablement = async (extensionsState, platform) => {
1703
+ if (platform === Test) {
1704
+ return {
1705
+ disabledIds: extensionsState.disabledIds,
1706
+ enabledIds: []
1707
+ };
1704
1708
  }
1705
- const ids = applications$1.get(applicationId);
1706
- ids?.delete(extensionId);
1707
- if (ids?.size === 0) {
1708
- applications$1.delete(applicationId);
1709
+ if (platform === Web) {
1710
+ return getWebExtensionEnablement();
1709
1711
  }
1710
- };
1711
- const getRegisteredExtensionIds = applicationId => {
1712
- return [...(applicationId === undefined ? extensionIds : applications$1.get(applicationId) || [])];
1713
- };
1714
- const reset = applicationId => {
1715
- if (applicationId === undefined) {
1716
- extensionIds.clear();
1717
- } else {
1718
- applications$1.delete(applicationId);
1712
+ if (platform === Remote || platform === Electron) {
1713
+ return getRemoteExtensionEnablement();
1719
1714
  }
1715
+ return getExtensionEnablementFromData(undefined);
1720
1716
  };
1721
1717
 
1722
- const prefix = '[Extension] Uncaught Error: ';
1723
- const handleUncaughtExtensionError = async error => {
1724
- const prettyError = await invoke$7('Errors.prepare', error);
1725
- await invoke$7('Errors.print', prettyError, prefix);
1726
- };
1727
-
1728
- const state$3 = {
1729
- nextId: 1,
1730
- notifications: []
1731
- };
1732
- const add$1 = (extensionId, type, message) => {
1733
- const notification = {
1734
- extensionId,
1735
- id: state$3.nextId++,
1736
- message,
1737
- type
1738
- };
1739
- state$3.notifications = [...state$3.notifications, notification];
1740
- return notification;
1718
+ const isMissingAssetDir = assetDir => {
1719
+ return typeof assetDir !== 'string' || assetDir.length === 0;
1741
1720
  };
1742
- const clear$1 = () => {
1743
- state$3.notifications = [];
1721
+ const isMissingPlatform = platform => {
1722
+ return typeof platform !== 'number' || platform === 0;
1744
1723
  };
1745
- const dismiss = id => {
1746
- state$3.notifications = state$3.notifications.filter(notification => notification.id !== id);
1724
+ const isStaticHttpAssetDir = assetDir => {
1725
+ return assetDir.startsWith('/') || assetDir.startsWith('http');
1747
1726
  };
1748
- const getAll$1 = () => {
1749
- return state$3.notifications;
1727
+ const isHttpLocation = () => {
1728
+ return Reflect.has(globalThis, 'location') && globalThis.location.protocol.startsWith('http');
1750
1729
  };
1751
- const removeByExtension = extensionId => {
1752
- state$3.notifications = state$3.notifications.filter(notification => notification.extensionId !== extensionId);
1730
+ const getRuntimeContext = async (assetDir, platform) => {
1731
+ const shouldInferPlatform = isMissingPlatform(platform);
1732
+ const resolvedAssetDir = isMissingAssetDir(assetDir) ? await invoke$4('Layout.getAssetDir') : assetDir;
1733
+ const resolvedPlatform = shouldInferPlatform ? await invoke$4('Layout.getPlatform') : platform;
1734
+ if (shouldInferPlatform && isHttpLocation() && isStaticHttpAssetDir(resolvedAssetDir)) {
1735
+ return {
1736
+ assetDir: resolvedAssetDir,
1737
+ platform: Web
1738
+ };
1739
+ }
1740
+ return {
1741
+ assetDir: resolvedAssetDir,
1742
+ platform: resolvedPlatform
1743
+ };
1753
1744
  };
1754
1745
 
1755
- const state$2 = {
1756
- rpc: undefined
1757
- };
1758
- const set$4 = value => {
1759
- state$2.rpc = value;
1746
+ const getResponseErrorMessage = response => {
1747
+ return response.statusText || String(response.status) || 'Request failed';
1760
1748
  };
1761
- const invoke$2 = async (method, ...params) => {
1762
- await state$2.rpc?.invoke(method, ...params);
1749
+ const getJson = async url => {
1750
+ try {
1751
+ const response = await fetch(url);
1752
+ if (!response.ok) {
1753
+ throw new Error(getResponseErrorMessage(response));
1754
+ }
1755
+ const json = await response.json();
1756
+ return json;
1757
+ } catch (error) {
1758
+ throw new VError(error, `Failed to get json`);
1759
+ }
1763
1760
  };
1764
1761
 
1765
- const state$1 = {
1766
- rpc: undefined
1767
- };
1768
- const set$3 = value => {
1769
- state$1.rpc = value;
1770
- };
1771
- const invoke$1 = async (method, ...params) => {
1772
- await state$1.rpc?.invoke(method, ...params);
1762
+ const getWebExtensionsUrl = assetDir => {
1763
+ return `${assetDir}/config/extensions.json`;
1773
1764
  };
1774
1765
 
1775
- const notifyNotificationsChanged = async () => {
1776
- const notifications = getAll$1();
1777
- await Promise.all([invoke$2('NotificationCenter.handleNotificationsChanged', notifications), invoke$1('StatusBar.handleNotificationCountChanged', notifications.length)]);
1766
+ const getWebExtensions = async assetDir => {
1767
+ try {
1768
+ return await getJson(getWebExtensionsUrl(assetDir));
1769
+ } catch {
1770
+ return [];
1771
+ }
1778
1772
  };
1779
1773
 
1780
- const getPreference = async key => {
1781
- return invoke$4('Preferences.get', key);
1782
- };
1783
- const setPreference = async (key, value) => {
1784
- await invoke$4('Preferences.update', {
1785
- [key]: value
1786
- });
1774
+ const isExtensionCompatible = (extension, platform) => {
1775
+ return platform !== Web || extension?.compatibility?.web !== false;
1787
1776
  };
1788
1777
 
1789
- /* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
1790
- const invoke = (method, ...params) => {
1791
- return invoke$4(method, ...params);
1792
- };
1793
- const invokeAndTransfer = (method, ...params) => {
1794
- return invokeAndTransfer$1(method, ...params);
1778
+ const WorkspacesFolderName = 'workspaces';
1779
+ const ExtensionEnablementFileName = 'extension-enablement.json';
1780
+ const CacheKeyPrefix = '/cache/workspaces';
1781
+ const UriSchemeRegex = /^[a-zA-Z][a-zA-Z\d+.-]*:/;
1782
+ const WindowsDrivePathRegex = /^[a-zA-Z]:[\\/]/;
1783
+ const WindowsDriveSegmentRegex = /^[a-zA-Z]:$/;
1784
+ const EmptyEnablement = {
1785
+ disabledIds: [],
1786
+ enabledIds: [],
1787
+ hasWorkspace: false
1795
1788
  };
1796
-
1797
- const hiddenExtensionIdsPreference = 'notifications.hiddenExtensionIds';
1798
- const getHiddenExtensionIds = async () => {
1799
- const value = await getPreference(hiddenExtensionIdsPreference);
1800
- if (!Array.isArray(value)) {
1801
- return [];
1789
+ const cache$1 = new Map();
1790
+ const mutationQueues = new Map();
1791
+ const encodePathSegment = (segment, index) => {
1792
+ if (index === 0 && WindowsDriveSegmentRegex.test(segment)) {
1793
+ return segment;
1802
1794
  }
1803
- return value.filter(item => typeof item === 'string');
1795
+ return encodeURIComponent(segment);
1804
1796
  };
1805
- const assertType = type => {
1806
- if (type !== 'error' && type !== 'info' && type !== 'warning') {
1807
- throw new TypeError(`Invalid notification type: ${type}`);
1808
- }
1797
+ const encodeFilePath = path => {
1798
+ return path.split('/').map(encodePathSegment).join('/');
1809
1799
  };
1810
- const showPopup = async (type, message) => {
1811
- try {
1812
- await invoke('Notification.create', type, message);
1813
- } catch {
1814
- // Notification storage must keep working while an older renderer is connected.
1800
+ const toWorkspaceUri = workspacePath => {
1801
+ if (WindowsDrivePathRegex.test(workspacePath)) {
1802
+ return `file:///${encodeFilePath(workspacePath.replaceAll('\\', '/'))}`;
1815
1803
  }
1816
- };
1817
- const clearNotifications = async () => {
1818
- clear$1();
1819
- await notifyNotificationsChanged();
1820
- };
1821
- const createNotification = async (extensionId, type, message) => {
1822
- string(extensionId);
1823
- string(type);
1824
- string(message);
1825
- assertType(type);
1826
- const hiddenExtensionIds = await getHiddenExtensionIds();
1827
- if (hiddenExtensionIds.includes(extensionId)) {
1828
- return;
1804
+ if (UriSchemeRegex.test(workspacePath)) {
1805
+ return workspacePath;
1829
1806
  }
1830
- add$1(extensionId, type, message);
1831
- await Promise.all([notifyNotificationsChanged(), showPopup(type, message)]);
1832
- };
1833
- const dismissNotification = async id => {
1834
- number(id);
1835
- dismiss(id);
1836
- await notifyNotificationsChanged();
1807
+ if (workspacePath.startsWith('/')) {
1808
+ return `file://${encodeFilePath(workspacePath)}`;
1809
+ }
1810
+ return workspacePath;
1837
1811
  };
1838
- const getNotificationCount = () => {
1839
- return getAll$1().length;
1812
+ const joinUri = (base, ...parts) => {
1813
+ const normalizedBase = base.endsWith('/') ? base.slice(0, -1) : base;
1814
+ return [normalizedBase, ...parts].join('/');
1840
1815
  };
1841
- const getNotifications = () => {
1842
- return getAll$1();
1816
+ const hashWorkspaceUri = async workspaceUri => {
1817
+ const bytes = new TextEncoder().encode(workspaceUri);
1818
+ const digest = await crypto.subtle.digest('SHA-256', bytes);
1819
+ return Array.from(new Uint8Array(digest), value => value.toString(16).padStart(2, '0')).join('');
1843
1820
  };
1844
- const hideNotificationsFromExtension = async extensionId => {
1845
- string(extensionId);
1846
- const hiddenExtensionIds = await getHiddenExtensionIds();
1847
- if (!hiddenExtensionIds.includes(extensionId)) {
1848
- await setPreference(hiddenExtensionIdsPreference, [...hiddenExtensionIds, extensionId]);
1821
+ const getWorkspaceUri$1 = async () => {
1822
+ let workspacePath;
1823
+ try {
1824
+ workspacePath = await invoke$4('Workspace.getPath');
1825
+ } catch {
1826
+ return '';
1849
1827
  }
1850
- removeByExtension(extensionId);
1851
- await notifyNotificationsChanged();
1852
- };
1853
-
1854
- const cacheName$1 = 'ExtensionSecrets';
1855
- const getRequestUrl = (extensionId, key) => {
1856
- return `https://secret-storage.invalid/${encodeURIComponent(extensionId)}/${encodeURIComponent(key)}`;
1857
- };
1858
- const isElectron = () => {
1859
- return get$7().platform === Electron;
1828
+ return typeof workspacePath === 'string' ? toWorkspaceUri(workspacePath) : '';
1860
1829
  };
1861
- const deleteSecret = async (extensionId, key) => {
1862
- string(extensionId);
1863
- string(key);
1864
- if (isElectron()) {
1865
- await invoke$5('SecretStorage.delete', extensionId, key);
1866
- return;
1830
+ const getConfigUri = async () => {
1831
+ const configUri = await invoke$4('WebView.compatSharedProcessInvoke', 'Platform.getConfigUri');
1832
+ if (typeof configUri !== 'string' || configUri === '') {
1833
+ throw new Error('Config uri is not available');
1867
1834
  }
1868
- const cache = await caches.open(cacheName$1);
1869
- await cache.delete(getRequestUrl(extensionId, key));
1835
+ return configUri;
1870
1836
  };
1871
- const getSecret = async (extensionId, key) => {
1872
- string(extensionId);
1873
- string(key);
1874
- if (isElectron()) {
1875
- return invoke$5('SecretStorage.get', extensionId, key);
1837
+ const getStorageLocation = async workspaceUri => {
1838
+ const workspaceHash = await hashWorkspaceUri(workspaceUri);
1839
+ try {
1840
+ const configUri = await getConfigUri();
1841
+ const directoryUri = joinUri(configUri, WorkspacesFolderName, workspaceHash);
1842
+ const uri = joinUri(directoryUri, ExtensionEnablementFileName);
1843
+ return {
1844
+ directoryUri,
1845
+ key: uri,
1846
+ type: 'file',
1847
+ uri
1848
+ };
1849
+ } catch {
1850
+ return {
1851
+ key: joinUri(CacheKeyPrefix, workspaceHash, ExtensionEnablementFileName),
1852
+ type: 'cache'
1853
+ };
1876
1854
  }
1877
- const cache = await caches.open(cacheName$1);
1878
- const response = await cache.match(getRequestUrl(extensionId, key));
1879
- return response?.text();
1880
1855
  };
1881
- const storeSecret = async (extensionId, key, value) => {
1882
- string(extensionId);
1883
- string(key);
1884
- string(value);
1885
- if (isElectron()) {
1886
- await invoke$5('SecretStorage.store', extensionId, key, value);
1887
- return;
1856
+ const getStringArray$1 = value => {
1857
+ if (!Array.isArray(value)) {
1858
+ return [];
1888
1859
  }
1889
- const cache = await caches.open(cacheName$1);
1890
- await cache.put(getRequestUrl(extensionId, key), new Response(value));
1860
+ return value.filter(item => typeof item === 'string');
1891
1861
  };
1892
-
1893
- class CommandNotFoundError extends Error {
1894
- constructor(command) {
1895
- super(`Command not found ${command}`);
1896
- Object.defineProperty(this, 'name', {
1897
- value: 'CommandNotFoundError'
1898
- });
1862
+ const parseEnablement = data => {
1863
+ return {
1864
+ disabledIds: getStringArray$1(data.disabledExtensions),
1865
+ enabledIds: getStringArray$1(data.enabledExtensions),
1866
+ hasWorkspace: true
1867
+ };
1868
+ };
1869
+ const readFromLocation = async location => {
1870
+ if (location.type === 'cache') {
1871
+ const data = await getJson$1(location.key);
1872
+ return parseEnablement(data || {});
1899
1873
  }
1900
- }
1901
- const allowedElectronPortCommand = 'HandleMessagePortForEmbedsProcess.handleMessagePortForEmbedsProcess';
1902
- const workspaceSetUriCommand = 'Workspace.setUri';
1903
- const privilegedCommandPrefixes = ['ElectronNet.', 'ClipBoard.', 'DebugSharedProcess.', 'Developer.', 'Electron', 'Exec.', 'ExtensionNodeRpc.', 'FileSystem', 'FileWatcher.', 'IpcParent.', 'PlatformPaths.', 'PersistentFileHandle.', 'Process.', 'RebuildNodePty.', 'SearchProcess.', 'SendMessagePort', 'SharedProcess.', 'TerminalProcess.', 'Transferrable.', 'WebSocketCapability.', 'WebView.compat'];
1904
- const invokeGlobalCommand = (method, ...params) => {
1905
- const command = commandMapRef[method];
1906
- if (!command) {
1907
- throw new CommandNotFoundError(method);
1874
+ const exists$1 = await exists(location.uri);
1875
+ if (!exists$1) {
1876
+ return {
1877
+ ...EmptyEnablement,
1878
+ hasWorkspace: true
1879
+ };
1908
1880
  }
1909
- return command(...params);
1881
+ const content = await readFile$1(location.uri);
1882
+ return parseEnablement(JSON.parse(content));
1910
1883
  };
1911
- const executeDeferredCommand = async (invokeCommand, id, args) => {
1884
+ const readFromLocationCached = async location => {
1885
+ const cached = cache$1.get(location.key);
1886
+ if (cached) {
1887
+ return cached;
1888
+ }
1889
+ const promise = readFromLocation(location);
1890
+ cache$1.set(location.key, promise);
1912
1891
  try {
1913
- await invokeCommand('Extensions.executeCommand', id, ...args);
1892
+ return await promise;
1914
1893
  } catch (error) {
1915
- await handleUncaughtExtensionError(error);
1894
+ if (cache$1.get(location.key) === promise) {
1895
+ cache$1.delete(location.key);
1896
+ }
1897
+ throw error;
1916
1898
  }
1917
1899
  };
1918
- const executeCommand$1 = (invokeCommand, id, ...args) => {
1919
- if (privilegedCommandPrefixes.some(prefix => id.startsWith(prefix))) {
1920
- throw new Error(`Isolated extensions cannot execute privileged command ${id}`);
1921
- }
1922
- if (id === workspaceSetUriCommand) {
1923
- setTimeout(() => {
1924
- void executeDeferredCommand(invokeCommand, id, args).catch(() => {});
1925
- }, 0);
1900
+ const getWorkspaceAndLocation = async () => {
1901
+ const workspaceUri = await getWorkspaceUri$1();
1902
+ if (!workspaceUri) {
1926
1903
  return undefined;
1927
1904
  }
1928
- return invokeCommand('Extensions.executeCommand', id, ...args);
1929
- };
1930
- const createExtensionCommandMap = (extensionId, invokeCommand = invokeGlobalCommand) => {
1931
- const inheritedCommands = invokeCommand === invokeGlobalCommand ? commandMapRef : Object.fromEntries(Object.keys(commandMapRef).map(method => [method, (...args) => invokeCommand(method, ...args)]));
1932
- if (invokeCommand !== invokeGlobalCommand) {
1933
- // Application runtimes must not bypass the scoped router through a legacy
1934
- // callback (notifications, secrets, file watchers, or privileged node ports).
1935
- return {
1936
- ...inheritedCommands,
1937
- 'Extensions.executeCommand': (id, ...args) => executeCommand$1(invokeCommand, id, ...args),
1938
- 'Extensions.registerFileChangeHandler': () => invokeCommand('Extensions.registerFileChangeHandler'),
1939
- 'Extensions.unregisterFileChangeHandler': () => invokeCommand('Extensions.unregisterFileChangeHandler')
1940
- };
1941
- }
1905
+ const location = await getStorageLocation(workspaceUri);
1942
1906
  return {
1943
- ...inheritedCommands,
1944
- 'Extensions.createNodeRpcConnection'(rpcId) {
1945
- return createNodeRpcConnection(extensionId, rpcId);
1946
- },
1947
- 'Extensions.createNodeRpcMessagePort'(rpcId, port) {
1948
- return createNodeRpcMessagePort(extensionId, rpcId, port);
1949
- },
1950
- 'Extensions.deleteSecret'(key) {
1951
- return deleteSecret(extensionId, key);
1952
- },
1953
- 'Extensions.executeCommand'(id, ...args) {
1954
- return executeCommand$1(invokeCommand, id, ...args);
1955
- },
1956
- 'Extensions.getSecret'(key) {
1957
- return getSecret(extensionId, key);
1958
- },
1959
- 'Extensions.registerFileChangeHandler'() {
1960
- register$1(extensionId);
1961
- },
1962
- 'Extensions.sendMessagePortToElectron'(port, initialCommand) {
1963
- if (initialCommand !== allowedElectronPortCommand) {
1964
- throw new Error(`Isolated extensions cannot send a port using ${initialCommand}`);
1965
- }
1966
- return invokeGlobalCommand('Extensions.sendMessagePortToElectron', port, initialCommand);
1967
- },
1968
- 'Extensions.showNotification'(type, message) {
1969
- return createNotification(extensionId, type, message);
1970
- },
1971
- 'Extensions.storeSecret'(key, value) {
1972
- return storeSecret(extensionId, key, value);
1973
- },
1974
- 'Extensions.unregisterFileChangeHandler'() {
1975
- unregister(extensionId);
1976
- }
1907
+ location,
1908
+ workspaceUri
1977
1909
  };
1978
1910
  };
1979
- const createExtensionCommandExecutor = commandMap => {
1980
- return (method, ...params) => {
1981
- const command = commandMap[method];
1982
- if (!command) {
1983
- throw new CommandNotFoundError(method);
1984
- }
1985
- return command(...params);
1911
+ const writeToLocation = async (location, workspaceUri, enablement) => {
1912
+ const data = {
1913
+ disabledExtensions: enablement.disabledIds,
1914
+ enabledExtensions: enablement.enabledIds,
1915
+ workspace: workspaceUri
1986
1916
  };
1917
+ if (location.type === 'cache') {
1918
+ await setJson(location.key, data);
1919
+ } else {
1920
+ const directoryExists = await exists(location.directoryUri);
1921
+ if (!directoryExists) {
1922
+ await mkdir(location.directoryUri);
1923
+ }
1924
+ await writeFile(location.uri, JSON.stringify(data, null, 2) + '\n');
1925
+ }
1926
+ cache$1.set(location.key, Promise.resolve(enablement));
1987
1927
  };
1988
-
1989
- const sourcePathMarker = '/extension-management-worker/src/';
1990
- const getExtensionHostSubWorkerUrl = (currentUrl = import.meta.url) => {
1991
- const relativePath = currentUrl.includes(sourcePathMarker) ? '../../../../extension-host-sub-worker/src/extensionHostSubWorkerMain.js' : '../../extension-host-sub-worker/dist/extensionHostSubWorkerMain.js';
1992
- return new URL(relativePath, currentUrl).href;
1993
- };
1994
- const extensionHostSubWorkerUrl = getExtensionHostSubWorkerUrl();
1995
-
1996
- // TODO
1997
-
1928
+ const mutate = async (update, createIfMissing) => {
1929
+ const workspaceAndLocation = await getWorkspaceAndLocation();
1930
+ if (!workspaceAndLocation) {
1931
+ throw new Error('Cannot change workspace extension enablement without an open workspace');
1932
+ }
1933
+ const {
1934
+ location,
1935
+ workspaceUri
1936
+ } = workspaceAndLocation;
1937
+ const previousMutation = mutationQueues.get(location.key) || Promise.resolve();
1938
+ const runMutation = async () => {
1939
+ try {
1940
+ await previousMutation;
1941
+ } catch {
1942
+ // A failed earlier mutation must not permanently block this workspace.
1943
+ }
1944
+ if (!createIfMissing && location.type === 'file' && !(await exists(location.uri))) {
1945
+ return;
1946
+ }
1947
+ const oldEnablement = await readFromLocation(location);
1948
+ const newEnablement = update(oldEnablement);
1949
+ await writeToLocation(location, workspaceUri, newEnablement);
1950
+ };
1951
+ const mutation = runMutation();
1952
+ mutationQueues.set(location.key, mutation);
1953
+ try {
1954
+ await mutation;
1955
+ } finally {
1956
+ if (mutationQueues.get(location.key) === mutation) {
1957
+ mutationQueues.delete(location.key);
1958
+ }
1959
+ }
1960
+ };
1961
+ const getWorkspaceExtensionEnablement = async () => {
1962
+ const workspaceAndLocation = await getWorkspaceAndLocation();
1963
+ if (!workspaceAndLocation) {
1964
+ return EmptyEnablement;
1965
+ }
1966
+ return readFromLocationCached(workspaceAndLocation.location);
1967
+ };
1968
+ const getWorkspaceExtensionEnablementSafe = async () => {
1969
+ try {
1970
+ return await getWorkspaceExtensionEnablement();
1971
+ } catch {
1972
+ let workspaceUri = '';
1973
+ try {
1974
+ workspaceUri = await getWorkspaceUri$1();
1975
+ } catch {
1976
+ // Ignore unavailable workspace state while recovering from malformed storage.
1977
+ }
1978
+ return {
1979
+ ...EmptyEnablement,
1980
+ hasWorkspace: Boolean(workspaceUri)
1981
+ };
1982
+ }
1983
+ };
1984
+ const disableExtension$1 = async id => {
1985
+ string(id);
1986
+ await mutate(oldEnablement => ({
1987
+ disabledIds: oldEnablement.disabledIds.includes(id) ? oldEnablement.disabledIds : [...oldEnablement.disabledIds, id],
1988
+ enabledIds: oldEnablement.enabledIds.filter(item => item !== id),
1989
+ hasWorkspace: true
1990
+ }), true);
1991
+ };
1992
+ const enableExtension$1 = async id => {
1993
+ string(id);
1994
+ await mutate(oldEnablement => ({
1995
+ disabledIds: oldEnablement.disabledIds.filter(item => item !== id),
1996
+ enabledIds: oldEnablement.enabledIds.includes(id) ? oldEnablement.enabledIds : [...oldEnablement.enabledIds, id],
1997
+ hasWorkspace: true
1998
+ }), true);
1999
+ };
2000
+ const clearExtensionOverride = async id => {
2001
+ string(id);
2002
+ const workspaceAndLocation = await getWorkspaceAndLocation();
2003
+ if (!workspaceAndLocation) {
2004
+ return;
2005
+ }
2006
+ const {
2007
+ location
2008
+ } = workspaceAndLocation;
2009
+ if (location.type === 'file' && !(await exists(location.uri))) {
2010
+ return;
2011
+ }
2012
+ await mutate(oldEnablement => ({
2013
+ disabledIds: oldEnablement.disabledIds.filter(item => item !== id),
2014
+ enabledIds: oldEnablement.enabledIds.filter(item => item !== id),
2015
+ hasWorkspace: true
2016
+ }), false);
2017
+ };
2018
+
2019
+ /* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
2020
+
2021
+ const withDisabledState = (extensions, disabledIds, enabledIds = []) => {
2022
+ if (disabledIds.length === 0 && enabledIds.length === 0) {
2023
+ return extensions;
2024
+ }
2025
+ const disabledIdsSet = new Set(disabledIds);
2026
+ const enabledIdsSet = new Set(enabledIds);
2027
+ return extensions.map(extension => {
2028
+ if (disabledIdsSet.has(extension.id)) {
2029
+ return {
2030
+ ...extension,
2031
+ disabled: true
2032
+ };
2033
+ }
2034
+ if (enabledIdsSet.has(extension.id) && extension.disabled === true) {
2035
+ return {
2036
+ ...extension,
2037
+ disabled: false
2038
+ };
2039
+ }
2040
+ return extension;
2041
+ });
2042
+ };
2043
+ const getExtensionsWithState = async (extensions, extensionsState, platform) => {
2044
+ if (extensionsState.applicationId !== undefined) {
2045
+ const byId = new Map(extensions.map(extension => [extension.id, extension]));
2046
+ return withDisabledState(byId.values().toArray(), extensionsState.disabledIds).map(extension => ({
2047
+ ...extension,
2048
+ applicationGeneration: extensionsState.applicationGeneration,
2049
+ applicationId: extensionsState.applicationId
2050
+ }));
2051
+ }
2052
+ if (extensions.length === 0) {
2053
+ return extensions;
2054
+ }
2055
+ const {
2056
+ disabledIds,
2057
+ enabledIds
2058
+ } = await getExtensionEnablement(extensionsState, platform);
2059
+ const extensionsWithDisabledState = withDisabledState(extensions, disabledIds, enabledIds);
2060
+ if (platform === Test) {
2061
+ return extensionsWithDisabledState;
2062
+ }
2063
+ const {
2064
+ disabledIds: workspaceDisabledIds,
2065
+ enabledIds: workspaceEnabledIds
2066
+ } = await getWorkspaceExtensionEnablementSafe();
2067
+ return withDisabledState(extensionsWithDisabledState, workspaceDisabledIds, workspaceEnabledIds);
2068
+ };
2069
+ const getAllExtensionsWithState = async (extensionsState, assetDir, platform) => {
2070
+ const {
2071
+ assetDir: resolvedAssetDir,
2072
+ platform: resolvedPlatform
2073
+ } = await getRuntimeContext(assetDir, platform);
2074
+ string(resolvedAssetDir);
2075
+ number(resolvedPlatform);
2076
+ const meta = extensionsState.webExtensions;
2077
+ if (resolvedPlatform === Web) {
2078
+ const webExtensions = await getWebExtensions(resolvedAssetDir);
2079
+ const compatibleExtensions = [...webExtensions, ...meta].filter(extension => isExtensionCompatible(extension, resolvedPlatform));
2080
+ return getExtensionsWithState(compatibleExtensions, extensionsState, resolvedPlatform);
2081
+ }
2082
+ const local = await invoke$3('ExtensionManagement.getAllExtensions');
2083
+ return getExtensionsWithState([...local, ...meta], extensionsState, resolvedPlatform);
2084
+ };
2085
+
1998
2086
  const getOrigin = () => {
1999
2087
  return globalThis.location?.origin || 'http://localhost';
2000
2088
  };
@@ -2124,6 +2212,37 @@ const getContentSecurityPolicy = (directives, absolutePath, rpcInfos) => {
2124
2212
  return `default-src 'none'; script-src ${[...scriptSources].join(' ')}; worker-src 'none'; child-src 'none'; connect-src ${connectDirective};`;
2125
2213
  };
2126
2214
 
2215
+ const getExtensionAbsolutePath = (id, isWeb, isBuiltin, path, relativePath, origin, platform, assetDir) => {
2216
+ if (path.startsWith('http')) {
2217
+ if (path.endsWith('/')) {
2218
+ return new URL(relativePath, path).href;
2219
+ }
2220
+ return new URL(relativePath, path + '/').href;
2221
+ }
2222
+ if (!path.startsWith('/')) {
2223
+ path = '/' + path;
2224
+ }
2225
+ if (isWeb) {
2226
+ return path + '/' + relativePath;
2227
+ }
2228
+ if (platform === Web) {
2229
+ return path + '/' + relativePath;
2230
+ }
2231
+ if (isBuiltin) {
2232
+ return `${assetDir}/extensions/${id}/${relativePath}`;
2233
+ }
2234
+ return new URL('/remote' + path + '/' + relativePath, origin).href;
2235
+ };
2236
+
2237
+ const sourcePathMarker = '/extension-management-worker/src/';
2238
+ const getExtensionHostSubWorkerUrl = (currentUrl = import.meta.url) => {
2239
+ const relativePath = currentUrl.includes(sourcePathMarker) ? '../../../../extension-host-sub-worker/src/extensionHostSubWorkerMain.js' : '../../extension-host-sub-worker/dist/extensionHostSubWorkerMain.js';
2240
+ return new URL(relativePath, currentUrl).href;
2241
+ };
2242
+ const extensionHostSubWorkerUrl = getExtensionHostSubWorkerUrl();
2243
+
2244
+ // TODO
2245
+
2127
2246
  const getUrlPrefix = (platform, extensionPath) => {
2128
2247
  if (extensionPath.startsWith('http://') || extensionPath.startsWith('https://')) {
2129
2248
  return extensionPath;
@@ -2137,13 +2256,21 @@ const getUrlPrefix = (platform, extensionPath) => {
2137
2256
  return `/remote/${extensionPath}`;
2138
2257
  };
2139
2258
 
2259
+ /* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
2260
+ const invoke$2 = (method, ...params) => {
2261
+ return invoke$4(method, ...params);
2262
+ };
2263
+ const invokeAndTransfer = (method, ...params) => {
2264
+ return invokeAndTransfer$1(method, ...params);
2265
+ };
2266
+
2140
2267
  /* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
2141
2268
 
2142
- const applications = new Map();
2269
+ const applications$1 = new Map();
2143
2270
  const getServices = application => {
2144
2271
  assertCurrentApplication(application);
2145
2272
  const generation = application.applicationGeneration;
2146
- let services = applications.get(generation);
2273
+ let services = applications$1.get(generation);
2147
2274
  if (!services) {
2148
2275
  services = {
2149
2276
  children: new Map(),
@@ -2152,11 +2279,11 @@ const getServices = application => {
2152
2279
  nextChild: 0,
2153
2280
  ports: new Map()
2154
2281
  };
2155
- applications.set(generation, services);
2282
+ applications$1.set(generation, services);
2156
2283
  }
2157
2284
  return services;
2158
2285
  };
2159
- const register = (extension, platform) => {
2286
+ const register$1 = (extension, platform) => {
2160
2287
  const application = get$7(extension.applicationId);
2161
2288
  assertCurrentApplication(extension);
2162
2289
  const services = getServices(application);
@@ -2190,7 +2317,7 @@ const createWorker$1 = async (application, info, port, legacy = false, extension
2190
2317
  if (!services.children.has(id)) throw new Error('Extension worker was disposed during launch');
2191
2318
  } catch (error) {
2192
2319
  services.children.delete(id);
2193
- await invoke('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', id);
2320
+ await invoke$2('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', id);
2194
2321
  throw error;
2195
2322
  }
2196
2323
  };
@@ -2208,7 +2335,7 @@ const createFileSystemPort = async (application, port, extensionId) => {
2208
2335
  assertCurrentApplication(application);
2209
2336
  const method = command.startsWith('FileSystem.') ? command.slice('FileSystem.'.length) : '';
2210
2337
  if (!fileSystemMethods.has(method)) throw new Error(`Unsupported application filesystem command: ${command}`);
2211
- const value = await invoke('Application.execute', application.applicationId, command, ...args);
2338
+ const value = await invoke$2('Application.execute', application.applicationId, command, ...args);
2212
2339
  return method === 'stat' ? value.type : value;
2213
2340
  };
2214
2341
  try {
@@ -2223,10 +2350,10 @@ const createFileSystemPort = async (application, port, extensionId) => {
2223
2350
  }
2224
2351
  };
2225
2352
  const dispose = async application => {
2226
- const services = applications.get(application.applicationGeneration);
2353
+ const services = applications$1.get(application.applicationGeneration);
2227
2354
  if (!services) return;
2228
- applications.delete(application.applicationGeneration);
2229
- const results = await Promise.allSettled([...Array.from(services.ports.keys(), rpc => Promise.try(() => rpc.dispose())), ...Array.from(services.children.keys(), id => invoke('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', id))]);
2355
+ applications$1.delete(application.applicationGeneration);
2356
+ const results = await Promise.allSettled([...Array.from(services.ports.keys(), rpc => Promise.try(() => rpc.dispose())), ...Array.from(services.children.keys(), id => invoke$2('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', id))]);
2230
2357
  services.ports.clear();
2231
2358
  services.children.clear();
2232
2359
  services.declarations.clear();
@@ -2234,7 +2361,7 @@ const dispose = async application => {
2234
2361
  if (errors.length > 0) throw new AggregateError(errors, 'Failed to dispose application services');
2235
2362
  };
2236
2363
  const disposeExtension = async (application, extensionId) => {
2237
- const services = applications.get(application.applicationGeneration);
2364
+ const services = applications$1.get(application.applicationGeneration);
2238
2365
  if (!services) return;
2239
2366
  services.extensionVersions.set(extensionId, (services.extensionVersions.get(extensionId) || 0) + 1);
2240
2367
  const ports = [...services.ports].filter(([, owner]) => owner === extensionId).map(([rpc]) => rpc);
@@ -2244,39 +2371,94 @@ const disposeExtension = async (application, extensionId) => {
2244
2371
  for (const [id, info] of services.declarations) {
2245
2372
  if (info.extensionId === extensionId) services.declarations.delete(id);
2246
2373
  }
2247
- const results = await Promise.allSettled([...ports.map(rpc => Promise.try(() => rpc.dispose())), ...children.map(id => invoke('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', id))]);
2374
+ const results = await Promise.allSettled([...ports.map(rpc => Promise.try(() => rpc.dispose())), ...children.map(id => invoke$2('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', id))]);
2248
2375
  const errors = results.filter(result => result.status === 'rejected').map(result => result.reason);
2249
2376
  if (errors.length > 0) throw new AggregateError(errors, `Failed to dispose extension services: ${extensionId}`);
2250
2377
  };
2251
2378
 
2252
2379
  const rpcs$1 = Object.create(null);
2380
+ const add$1 = (id, rpc) => {
2381
+ rpcs$1[id] = rpc;
2382
+ };
2383
+ const get$3 = id => {
2384
+ return rpcs$1[id];
2385
+ };
2386
+
2387
+ const handleRpcInfos = (extension, platform) => {
2388
+ if (extension?.applicationId !== undefined) {
2389
+ if (Array.isArray(extension.rpc) && extension.rpc.length > 0) {
2390
+ register$1(extension, platform);
2391
+ }
2392
+ return;
2393
+ }
2394
+ try {
2395
+ if (!extension) {
2396
+ return;
2397
+ }
2398
+ const rpcs = extension.rpc;
2399
+ if (!rpcs) {
2400
+ return;
2401
+ }
2402
+ if (!Array.isArray(rpcs)) {
2403
+ return;
2404
+ }
2405
+ if (typeof extension.id === 'string') {
2406
+ set$5({
2407
+ ...extension,
2408
+ rpc: rpcs.map(rpc => ({
2409
+ ...rpc
2410
+ }))
2411
+ });
2412
+ }
2413
+ const urlPrefix = getUrlPrefix(platform, extension.path);
2414
+ for (const rpc of rpcs) {
2415
+ if (rpc.type === 'node' || rpc.type === 'node-process') {
2416
+ continue;
2417
+ }
2418
+ rpc.url = `${urlPrefix}/${rpc.url}`;
2419
+ add$1(rpc.id, rpc);
2420
+ }
2421
+ } catch (error) {
2422
+ console.warn(`Failed to handle extension rpcs: ${error}`);
2423
+ }
2424
+ };
2425
+
2426
+ const NewLine = '\n';
2427
+ const Slash = '/';
2428
+
2429
+ const interExtensionId = path => {
2430
+ const slashIndex = path.lastIndexOf(Slash);
2431
+ return path.slice(slashIndex + 1);
2432
+ };
2433
+
2434
+ const rpcs = Object.create(null);
2253
2435
  const applicationRpcs = new Map();
2254
- const get$3 = (extensionId, applicationId) => {
2436
+ const get$2 = (extensionId, applicationId) => {
2255
2437
  if (applicationId !== undefined) {
2256
2438
  return applicationRpcs.get(applicationId)?.get(extensionId);
2257
2439
  }
2258
- return rpcs$1[extensionId];
2440
+ return rpcs[extensionId];
2259
2441
  };
2260
- const getAll = applicationId => {
2442
+ const getAll$1 = applicationId => {
2261
2443
  if (applicationId !== undefined) {
2262
2444
  return [...(applicationRpcs.get(applicationId)?.values() || [])];
2263
2445
  }
2264
- return Object.values(rpcs$1);
2446
+ return Object.values(rpcs);
2265
2447
  };
2266
2448
  const getIds = applicationId => {
2267
2449
  if (applicationId !== undefined) {
2268
2450
  return [...(applicationRpcs.get(applicationId)?.keys() || [])];
2269
2451
  }
2270
- return Object.keys(rpcs$1);
2452
+ return Object.keys(rpcs);
2271
2453
  };
2272
- const set$2 = (extensionId, rpc, applicationId) => {
2454
+ const set$4 = (extensionId, rpc, applicationId) => {
2273
2455
  if (applicationId !== undefined) {
2274
2456
  const entries = applicationRpcs.get(applicationId) || new Map();
2275
2457
  entries.set(extensionId, rpc);
2276
2458
  applicationRpcs.set(applicationId, entries);
2277
2459
  return;
2278
2460
  }
2279
- rpcs$1[extensionId] = rpc;
2461
+ rpcs[extensionId] = rpc;
2280
2462
  };
2281
2463
  const remove$1 = (extensionId, applicationId) => {
2282
2464
  if (applicationId !== undefined) {
@@ -2288,720 +2470,669 @@ const remove$1 = (extensionId, applicationId) => {
2288
2470
  }
2289
2471
  return rpc;
2290
2472
  }
2291
- const rpc = rpcs$1[extensionId];
2292
- delete rpcs$1[extensionId];
2473
+ const rpc = rpcs[extensionId];
2474
+ delete rpcs[extensionId];
2293
2475
  return rpc;
2294
2476
  };
2295
- const clear = applicationId => {
2477
+ const clear$1 = applicationId => {
2296
2478
  if (applicationId !== undefined) {
2297
2479
  applicationRpcs.delete(applicationId);
2298
2480
  return;
2299
2481
  }
2300
- for (const key of Object.keys(rpcs$1)) {
2301
- delete rpcs$1[key];
2482
+ for (const key of Object.keys(rpcs)) {
2483
+ delete rpcs[key];
2302
2484
  }
2303
2485
  };
2304
2486
 
2305
- /* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
2487
+ const notifyRunningExtensionsChanged = applicationId => {
2488
+ setTimeout(() => {
2489
+ const notification = applicationId === undefined ? invoke$4('Layout.handleExtensionsChanged') : invoke$4('Application.execute', applicationId, 'Layout.handleExtensionsChanged');
2490
+ void Promise.resolve(notification).catch(() => {});
2491
+ }, 0);
2492
+ };
2306
2493
 
2307
- const pendingRpcs = Object.create(null);
2308
- const getPendingExtensionIds = application => {
2309
- return Object.keys(pendingRpcs).flatMap(key => {
2310
- const [applicationId, generation, extensionId] = JSON.parse(key);
2311
- return applicationId === application.applicationId && generation === application.applicationGeneration ? [extensionId] : [];
2312
- });
2494
+ const getExtensionId$3 = extension => {
2495
+ return extension.id || interExtensionId(extension.uri || extension.path || '');
2313
2496
  };
2314
- const getRuntimeId = (extensionId, application) => {
2315
- return application?.applicationId === undefined ? extensionId : JSON.stringify([application.applicationId, application.applicationGeneration, extensionId]);
2497
+ const getAbsolutePath$1 = (extension, assetDir, platform) => {
2498
+ return getExtensionAbsolutePath(getExtensionId$3(extension), extension.isWeb === true, extension.builtin === true, extension.path || extension.uri || '', extension.browser || '', getOrigin(), platform, assetDir);
2316
2499
  };
2317
- const bindCommandMap = (rpc, commandMap) => {
2318
- if (rpc.ipc) {
2319
- rpc.ipc.execute = createExtensionCommandExecutor(commandMap);
2500
+ const getRpc$1 = async (extension, assetDir, platform, activationEvent = '', getOrCreate = getOrCreateIsolatedExtensionHostWorker, notify = notifyRunningExtensionsChanged) => {
2501
+ if (extension.applicationId !== undefined) {
2502
+ assertCurrentApplication(extension);
2503
+ }
2504
+ const extensionId = getExtensionId$3(extension);
2505
+ const existingRpc = get$2(extensionId, extension.applicationId);
2506
+ if (existingRpc) {
2507
+ return existingRpc;
2508
+ }
2509
+ handleRpcInfos(extension, platform);
2510
+ const absolutePath = getAbsolutePath$1(extension, assetDir, platform);
2511
+ const contentSecurityPolicy = getContentSecurityPolicy(extension.contentSecurityPolicy, absolutePath, extension.rpc);
2512
+ const rpc = await activateIsolatedExtension(extensionId, absolutePath, extension.workerName || '', contentSecurityPolicy, activationEvent, getOrCreate, extension.applicationId);
2513
+ if (extension.applicationId === undefined) {
2514
+ notify();
2515
+ } else {
2516
+ notify(extension.applicationId);
2320
2517
  }
2321
2518
  return rpc;
2322
2519
  };
2323
- const createIsolatedExtensionHostWorker = async (extensionId, absolutePath, workerName, contentSecurityPolicy, createRpc, invokeAndTransfer, application) => {
2324
- const runtimeId = getRuntimeId(extensionId, application);
2325
- const invokeCommand = application === undefined ? undefined : (method, ...args) => {
2326
- assertCurrentApplication(application);
2327
- if (method === 'Extensions.registerFileChangeHandler') {
2328
- return register$1(extensionId, application.applicationId);
2329
- }
2330
- if (method === 'Extensions.unregisterFileChangeHandler') {
2331
- return unregister(extensionId, application.applicationId);
2332
- }
2333
- if (method === 'Extensions.sendMessagePortToFileSystemWorker') {
2334
- return createFileSystemPort(application, args[0], extensionId);
2335
- }
2336
- if (method === 'Extensions.createWebViewWorkerRpc' || method === 'Extensions.createWebViewWorkerRpc2') {
2337
- return createWorker$1(application, args[0], args[1], method === 'Extensions.createWebViewWorkerRpc', extensionId);
2338
- }
2339
- const invokeApplication = commandMapRef['Extensions.invokeForApplication'];
2340
- if (!invokeApplication) {
2341
- throw new Error('Application extension command routing is not initialized');
2342
- }
2343
- return invokeApplication(application.applicationId, method, ...args);
2520
+
2521
+ const getWorkspaceUri = async () => {
2522
+ const uri = await invoke$4('Workspace.getUri');
2523
+ return typeof uri === 'string' ? uri : '';
2524
+ };
2525
+ const isRemoteUri = uri => /^[a-z][a-z0-9+.-]*:\/\//i.test(uri) && !uri.startsWith('file://');
2526
+ const getRemoteWorkspaceUri = async () => {
2527
+ const uri = await getWorkspaceUri();
2528
+ return isRemoteUri(uri) ? uri : '';
2529
+ };
2530
+ const findTransport = async workspaceUri => {
2531
+ const extensionsState = get$7();
2532
+ const {
2533
+ assetDir,
2534
+ platform
2535
+ } = await getRuntimeContext('', extensionsState.platform);
2536
+ const extensions = await getAllExtensionsWithState(extensionsState, assetDir, platform);
2537
+ const scheme = new URL(workspaceUri).protocol.slice(0, -1);
2538
+ const extension = extensions.find(candidate => !candidate.disabled && candidate.isolated === true && candidate.workspaceTransport?.scheme === scheme);
2539
+ return {
2540
+ assetDir,
2541
+ extension,
2542
+ platform
2344
2543
  };
2345
- const commandMap = createExtensionCommandMap(runtimeId, invokeCommand);
2346
- const rpc = await createRpc({
2347
- // PlainMessagePortRpc registers this map process-wide. Bind the restricted
2348
- // callbacks to this port below, never to the shared host command table.
2349
- commandMap: {},
2350
- isMessagePortOpen: true,
2351
- send(port) {
2352
- return invokeAndTransfer('LaunchIsolatedExtensionHostWorker.launchIsolatedExtensionHostWorker', port, runtimeId, absolutePath, workerName, contentSecurityPolicy);
2353
- }
2354
- });
2355
- return bindCommandMap(rpc, commandMap);
2356
2544
  };
2357
- const createWorker = (extensionId, absolutePath, workerName, contentSecurityPolicy, application) => {
2358
- return createIsolatedExtensionHostWorker(extensionId, absolutePath, workerName, contentSecurityPolicy, create$6, invokeAndTransfer, application);
2545
+ const getWorkspaceTransportUri = async () => {
2546
+ const uri = await getRemoteWorkspaceUri();
2547
+ if (!uri) {
2548
+ return '';
2549
+ }
2550
+ const {
2551
+ extension
2552
+ } = await findTransport(uri);
2553
+ return extension?.workspaceTransport?.command ? uri : '';
2359
2554
  };
2360
- const createAndStoreRpc = async (extensionId, absolutePath, workerName, contentSecurityPolicy, create, application) => {
2555
+ const getTransport = async workspaceUri => {
2556
+ const {
2557
+ assetDir,
2558
+ extension,
2559
+ platform
2560
+ } = await findTransport(workspaceUri);
2561
+ if (!extension?.workspaceTransport?.command) {
2562
+ throw new Error(`No workspace transport for ${new URL(workspaceUri).protocol}`);
2563
+ }
2564
+ const rpc = await getRpc$1(extension, assetDir, platform);
2565
+ return {
2566
+ command: extension.workspaceTransport.command,
2567
+ rpc
2568
+ };
2569
+ };
2570
+ const connect = async (workspaceUri, type, port, params = {}) => {
2361
2571
  try {
2362
- const rpc = application === undefined ? await create(extensionId, absolutePath, workerName, contentSecurityPolicy) : await create(extensionId, absolutePath, workerName, contentSecurityPolicy, application);
2363
- if (application !== undefined) {
2364
- try {
2365
- assertCurrentApplication(application);
2366
- } catch (error) {
2367
- await Promise.allSettled([rpc.dispose(), invoke('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', getRuntimeId(extensionId, application))]);
2368
- throw error;
2369
- }
2572
+ if (!isRemoteUri(workspaceUri)) {
2573
+ throw new Error('A remote workspace is required');
2370
2574
  }
2371
- set$2(extensionId, rpc, application?.applicationId);
2372
- return rpc;
2575
+ const {
2576
+ command,
2577
+ rpc
2578
+ } = await getTransport(workspaceUri);
2579
+ if (workspaceUri !== (await getWorkspaceUri())) {
2580
+ throw new Error('Workspace changed while connecting the remote process');
2581
+ }
2582
+ await rpc.invokeAndTransfer('ExtensionApi.executeCommand', command, workspaceUri, type, port, params);
2373
2583
  } catch (error) {
2374
- console.error(`[extension-management-worker] ${extensionId} failed to activate`, error);
2584
+ port.close();
2375
2585
  throw error;
2376
2586
  }
2377
2587
  };
2378
- const getOrCreateIsolatedExtensionHostWorker = async (extensionId, absolutePath, workerName = '', contentSecurityPolicy = '', create = createWorker, applicationId) => {
2379
- const application = applicationId === undefined ? undefined : get$7(applicationId);
2380
- const existingRpc = get$3(extensionId, applicationId);
2381
- if (existingRpc) {
2382
- return existingRpc;
2383
- }
2384
- const key = JSON.stringify([applicationId ?? null, application?.applicationGeneration ?? null, extensionId]);
2385
- const pendingRpc = pendingRpcs[key];
2386
- if (pendingRpc !== undefined) {
2387
- return pendingRpc;
2588
+ const connectTerminal = async (workspaceUri, port) => {
2589
+ await connect(workspaceUri, 'terminal-process', port);
2590
+ };
2591
+ const request = async (workspaceUri, type, ...args) => {
2592
+ if (!isRemoteUri(workspaceUri) || !['text-search', 'file-search', 'terminal-options'].includes(type)) {
2593
+ throw new Error('Unsupported workspace request');
2388
2594
  }
2389
- const newRpc = createAndStoreRpc(extensionId, absolutePath, workerName, contentSecurityPolicy, create, application);
2390
- pendingRpcs[key] = newRpc;
2391
- try {
2392
- return await newRpc;
2393
- } finally {
2394
- if (pendingRpcs[key] === newRpc) {
2395
- delete pendingRpcs[key];
2396
- }
2595
+ const {
2596
+ assetDir,
2597
+ extension,
2598
+ platform
2599
+ } = await findTransport(workspaceUri);
2600
+ const command = extension?.workspaceTransport?.requestCommand;
2601
+ if (!extension || !command) {
2602
+ throw new Error('Workspace transport does not support requests');
2397
2603
  }
2604
+ const rpc = await getRpc$1(extension, assetDir, platform);
2605
+ return rpc.invoke('ExtensionApi.executeCommand', command, workspaceUri, type, ...args);
2398
2606
  };
2399
2607
 
2400
- const activateIsolatedExtension = async (extensionId, absolutePath, workerName, contentSecurityPolicy, activationEvent, getOrCreate = getOrCreateIsolatedExtensionHostWorker, applicationId) => {
2401
- const application = applicationId === undefined ? undefined : get$7(applicationId);
2402
- const updateStatus = status => {
2403
- if (applicationId === undefined) {
2404
- updateRuntimeStatus(extensionId, status);
2405
- return;
2406
- }
2407
- const current = get$7(applicationId);
2408
- if (current.applicationGeneration !== application?.applicationGeneration) {
2409
- throw new Error(`Stale extension application: ${applicationId}`);
2410
- }
2411
- updateRuntimeStatus(extensionId, status, applicationId);
2412
- };
2413
- const startTime = performance.now();
2414
- updateStatus({
2415
- activationEvent,
2416
- activationStartTime: startTime,
2417
- status: Activating
2418
- });
2608
+ const isMissingRendererCommand = (error, command) => {
2609
+ const moduleName = command.slice(0, command.indexOf('.'));
2610
+ return error instanceof Error && (error.message.includes(command) || error.message.includes(`module ${moduleName} not found`)) && /command not found|not found/i.test(error.message);
2611
+ };
2612
+ const createUnsupportedDirectLaunchError = rpcId => {
2613
+ return new Error(`Node process ${rpcId} requires direct renderer support`);
2614
+ };
2615
+ const createRemoteConnection = async (extensionId, rpcId) => {
2419
2616
  try {
2420
- const rpc = applicationId === undefined ? await getOrCreate(extensionId, absolutePath, workerName, contentSecurityPolicy) : await getOrCreate(extensionId, absolutePath, workerName, contentSecurityPolicy, undefined, applicationId);
2421
- const endTime = performance.now();
2422
- updateStatus({
2423
- activationEndTime: endTime,
2424
- activationTime: endTime - startTime,
2425
- status: Activated
2426
- });
2427
- return rpc;
2617
+ const connectionInfo = await invoke$4('ExtensionNodeRpc.createConnection', extensionId, rpcId);
2618
+ return {
2619
+ ...connectionInfo,
2620
+ type: 'websocket'
2621
+ };
2428
2622
  } catch (error) {
2429
- if (application === undefined || isCurrentApplication(application)) {
2430
- updateStatus({
2431
- error: getErrorMessage(error),
2432
- status: Error$1
2433
- });
2623
+ if (isMissingRendererCommand(error, 'ExtensionNodeRpc.createConnection')) {
2624
+ throw createUnsupportedDirectLaunchError(rpcId);
2434
2625
  }
2435
2626
  throw error;
2436
2627
  }
2437
2628
  };
2438
-
2439
- const rpcs = Object.create(null);
2440
- const add = (id, rpc) => {
2441
- rpcs[id] = rpc;
2442
- };
2443
- const get$2 = id => {
2444
- return rpcs[id];
2445
- };
2446
-
2447
- const handleRpcInfos = (extension, platform) => {
2448
- if (extension?.applicationId !== undefined) {
2449
- if (Array.isArray(extension.rpc) && extension.rpc.length > 0) {
2450
- register(extension, platform);
2451
- }
2452
- return;
2453
- }
2629
+ const createElectronConnection = async rpcId => {
2454
2630
  try {
2455
- if (!extension) {
2456
- return;
2457
- }
2458
- const rpcs = extension.rpc;
2459
- if (!rpcs) {
2460
- return;
2461
- }
2462
- if (!Array.isArray(rpcs)) {
2463
- return;
2464
- }
2465
- if (typeof extension.id === 'string') {
2466
- set$5({
2467
- ...extension,
2468
- rpc: rpcs.map(rpc => ({
2469
- ...rpc
2470
- }))
2471
- });
2472
- }
2473
- const urlPrefix = getUrlPrefix(platform, extension.path);
2474
- for (const rpc of rpcs) {
2475
- if (rpc.type === 'node' || rpc.type === 'node-process') {
2476
- continue;
2477
- }
2478
- rpc.url = `${urlPrefix}/${rpc.url}`;
2479
- add(rpc.id, rpc);
2631
+ const supported = await invoke$4('ExtensionNodeRpc.supportsDirectConnection');
2632
+ if (!supported) {
2633
+ throw createUnsupportedDirectLaunchError(rpcId);
2480
2634
  }
2635
+ return {
2636
+ type: 'message-port'
2637
+ };
2481
2638
  } catch (error) {
2482
- console.warn(`Failed to handle extension rpcs: ${error}`);
2639
+ if (isMissingRendererCommand(error, 'ExtensionNodeRpc.supportsDirectConnection')) {
2640
+ throw createUnsupportedDirectLaunchError(rpcId);
2641
+ }
2642
+ throw error;
2483
2643
  }
2484
2644
  };
2485
-
2486
- const NewLine = '\n';
2487
- const Slash = '/';
2488
-
2489
- const interExtensionId = path => {
2490
- const slashIndex = path.lastIndexOf(Slash);
2491
- return path.slice(slashIndex + 1);
2492
- };
2493
-
2494
- const isExtensionIsolated = extension => {
2495
- return extension?.isolated === true;
2496
- };
2497
-
2498
- const activateExtension3 = async (extension, absolutePath, activationEvent, platform) => {
2499
- if (extension.applicationId !== undefined) {
2500
- assertCurrentApplication(extension);
2645
+ const createNodeRpcConnection = async (extensionId, rpcId) => {
2646
+ const declaration = validateNodeProcessRpc(extensionId, rpcId);
2647
+ if (declaration.onRemote === 'runOnRemote' && (await getRemoteWorkspaceUri())) {
2648
+ return {
2649
+ type: 'message-port'
2650
+ };
2501
2651
  }
2502
- const extensionId = extension.id || interExtensionId(extension.uri);
2503
- if (!isExtensionIsolated(extension)) {
2504
- throw new Error(`Extension ${extensionId} does not use the isolated extension API`);
2652
+ const {
2653
+ platform
2654
+ } = get$7();
2655
+ if (platform !== Remote && platform !== Electron) {
2656
+ throw new Error('Node rpc is not available on this platform');
2505
2657
  }
2506
- handleRpcInfos(extension, platform);
2507
- const contentSecurityPolicy = getContentSecurityPolicy(extension.contentSecurityPolicy, absolutePath, extension.rpc);
2508
- if (extension.applicationId === undefined) {
2509
- await activateIsolatedExtension(extensionId, absolutePath, extension.workerName || '', contentSecurityPolicy, activationEvent);
2510
- } else {
2511
- await activateIsolatedExtension(extensionId, absolutePath, extension.workerName || '', contentSecurityPolicy, activationEvent, undefined, extension.applicationId);
2658
+ if (platform === Remote) {
2659
+ return createRemoteConnection(extensionId, rpcId);
2512
2660
  }
2661
+ return createElectronConnection(rpcId);
2513
2662
  };
2514
-
2515
- const ContentType = 'Content-Type';
2516
- const ContentLength = 'Content-Length';
2517
-
2518
- const createResponseFromData = data => {
2519
- const responseString = JSON.stringify(data);
2520
- const response = new Response(responseString, {
2521
- headers: {
2522
- [ContentLength]: String(responseString.length),
2523
- [ContentType]: 'application/json'
2663
+ const createNodeRpcMessagePort = async (extensionId, rpcId, port) => {
2664
+ const declaration = validateNodeProcessRpc(extensionId, rpcId);
2665
+ if (declaration.onRemote === 'runOnRemote') {
2666
+ const workspaceUri = await getRemoteWorkspaceUri();
2667
+ if (workspaceUri) {
2668
+ await connect(workspaceUri, 'extension-node-process', port, {
2669
+ extensionId,
2670
+ rpcId
2671
+ });
2672
+ return;
2524
2673
  }
2525
- });
2526
- return response;
2527
- };
2528
-
2529
- const cacheName = 'Extensions'; // TODO
2530
-
2531
- const getJson$1 = async cacheKey => {
2532
- const response = await caches.match(cacheKey, {
2533
- cacheName
2534
- });
2535
- if (!response) {
2536
- return undefined;
2537
2674
  }
2538
- const json = await response.json();
2539
- return json;
2540
- };
2541
- const setJson = async (cacheKey, data) => {
2542
- try {
2543
- const cache = await caches.open(cacheName);
2544
- const response = createResponseFromData(data);
2545
- await cache.put(cacheKey, response);
2546
- } catch (error) {
2547
- throw new VError(error, `Failed to add to cache`);
2675
+ const {
2676
+ platform
2677
+ } = get$7();
2678
+ if (platform !== Electron) {
2679
+ throw new Error('Node rpc message ports are only available in Electron');
2548
2680
  }
2681
+ validateNodeProcessRpc(extensionId, rpcId);
2682
+ await invokeAndTransfer$1('ExtensionNodeRpc.createMessagePort', port, extensionId, rpcId);
2549
2683
  };
2550
2684
 
2551
- const disabledExtensionsCacheKey = '/cache/disabledExtensions.json';
2552
-
2553
- /* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
2554
-
2555
- const getStringArray$2 = value => {
2556
- if (!Array.isArray(value)) {
2557
- return [];
2685
+ const extensionIds = new Set();
2686
+ const applications = new Map();
2687
+ const register = (extensionId, applicationId) => {
2688
+ if (applicationId === undefined) {
2689
+ extensionIds.add(extensionId);
2690
+ return;
2558
2691
  }
2559
- return value.filter(id => typeof id === 'string');
2560
- };
2561
- const getExtensionEnablementFromData = data => {
2562
- return {
2563
- disabledIds: getStringArray$2(data?.disabledExtensions),
2564
- enabledIds: getStringArray$2(data?.enabledExtensions)
2565
- };
2692
+ const ids = applications.get(applicationId) || new Set();
2693
+ ids.add(extensionId);
2694
+ applications.set(applicationId, ids);
2566
2695
  };
2567
- const getWebExtensionEnablement = async () => {
2568
- try {
2569
- const cached = await getJson$1(disabledExtensionsCacheKey);
2570
- return getExtensionEnablementFromData(cached);
2571
- } catch {
2572
- return getExtensionEnablementFromData(undefined);
2696
+ const unregister = (extensionId, applicationId) => {
2697
+ if (applicationId === undefined) {
2698
+ extensionIds.delete(extensionId);
2699
+ return;
2573
2700
  }
2574
- };
2575
- const getRemoteExtensionEnablement = async () => {
2576
- try {
2577
- const uri = await invoke$4('WebView.compatSharedProcessInvoke', 'PlatformPaths.getDisabledExtensionsJsonUri');
2578
- const exists$1 = await exists(uri);
2579
- if (!exists$1) {
2580
- return getExtensionEnablementFromData(undefined);
2581
- }
2582
- const content = await readFile$1(uri);
2583
- return getExtensionEnablementFromData(JSON.parse(content));
2584
- } catch {
2585
- return getExtensionEnablementFromData(undefined);
2701
+ const ids = applications.get(applicationId);
2702
+ ids?.delete(extensionId);
2703
+ if (ids?.size === 0) {
2704
+ applications.delete(applicationId);
2586
2705
  }
2587
2706
  };
2588
- const getExtensionEnablement = async (extensionsState, platform) => {
2589
- if (platform === Test) {
2590
- return {
2591
- disabledIds: extensionsState.disabledIds,
2592
- enabledIds: []
2593
- };
2594
- }
2595
- if (platform === Web) {
2596
- return getWebExtensionEnablement();
2597
- }
2598
- if (platform === Remote || platform === Electron) {
2599
- return getRemoteExtensionEnablement();
2707
+ const getRegisteredExtensionIds = applicationId => {
2708
+ return [...(applicationId === undefined ? extensionIds : applications.get(applicationId) || [])];
2709
+ };
2710
+ const reset = applicationId => {
2711
+ if (applicationId === undefined) {
2712
+ extensionIds.clear();
2713
+ } else {
2714
+ applications.delete(applicationId);
2600
2715
  }
2601
- return getExtensionEnablementFromData(undefined);
2602
2716
  };
2603
2717
 
2604
- const isMissingAssetDir = assetDir => {
2605
- return typeof assetDir !== 'string' || assetDir.length === 0;
2718
+ const prefix = '[Extension] Uncaught Error: ';
2719
+ const handleUncaughtExtensionError = async error => {
2720
+ const prettyError = await invoke$7('Errors.prepare', error);
2721
+ await invoke$7('Errors.print', prettyError, prefix);
2606
2722
  };
2607
- const isMissingPlatform = platform => {
2608
- return typeof platform !== 'number' || platform === 0;
2723
+
2724
+ const state$3 = {
2725
+ nextId: 1,
2726
+ notifications: []
2609
2727
  };
2610
- const isStaticHttpAssetDir = assetDir => {
2611
- return assetDir.startsWith('/') || assetDir.startsWith('http');
2728
+ const add = (extensionId, type, message) => {
2729
+ const notification = {
2730
+ extensionId,
2731
+ id: state$3.nextId++,
2732
+ message,
2733
+ type
2734
+ };
2735
+ state$3.notifications = [...state$3.notifications, notification];
2736
+ return notification;
2612
2737
  };
2613
- const isHttpLocation = () => {
2614
- return Reflect.has(globalThis, 'location') && globalThis.location.protocol.startsWith('http');
2738
+ const clear = () => {
2739
+ state$3.notifications = [];
2615
2740
  };
2616
- const getRuntimeContext = async (assetDir, platform) => {
2617
- const shouldInferPlatform = isMissingPlatform(platform);
2618
- const resolvedAssetDir = isMissingAssetDir(assetDir) ? await invoke$4('Layout.getAssetDir') : assetDir;
2619
- const resolvedPlatform = shouldInferPlatform ? await invoke$4('Layout.getPlatform') : platform;
2620
- if (shouldInferPlatform && isHttpLocation() && isStaticHttpAssetDir(resolvedAssetDir)) {
2621
- return {
2622
- assetDir: resolvedAssetDir,
2623
- platform: Web
2624
- };
2625
- }
2626
- return {
2627
- assetDir: resolvedAssetDir,
2628
- platform: resolvedPlatform
2629
- };
2741
+ const dismiss = id => {
2742
+ state$3.notifications = state$3.notifications.filter(notification => notification.id !== id);
2630
2743
  };
2631
-
2632
- const getResponseErrorMessage = response => {
2633
- return response.statusText || String(response.status) || 'Request failed';
2744
+ const getAll = () => {
2745
+ return state$3.notifications;
2634
2746
  };
2635
- const getJson = async url => {
2636
- try {
2637
- const response = await fetch(url);
2638
- if (!response.ok) {
2639
- throw new Error(getResponseErrorMessage(response));
2640
- }
2641
- const json = await response.json();
2642
- return json;
2643
- } catch (error) {
2644
- throw new VError(error, `Failed to get json`);
2645
- }
2747
+ const removeByExtension = extensionId => {
2748
+ state$3.notifications = state$3.notifications.filter(notification => notification.extensionId !== extensionId);
2646
2749
  };
2647
2750
 
2648
- const getWebExtensionsUrl = assetDir => {
2649
- return `${assetDir}/config/extensions.json`;
2751
+ const state$2 = {
2752
+ rpc: undefined
2650
2753
  };
2651
-
2652
- const getWebExtensions = async assetDir => {
2653
- try {
2654
- return await getJson(getWebExtensionsUrl(assetDir));
2655
- } catch {
2656
- return [];
2657
- }
2754
+ const set$3 = value => {
2755
+ state$2.rpc = value;
2658
2756
  };
2659
-
2660
- const isExtensionCompatible = (extension, platform) => {
2661
- return platform !== Web || extension?.compatibility?.web !== false;
2757
+ const invoke$1 = async (method, ...params) => {
2758
+ await state$2.rpc?.invoke(method, ...params);
2662
2759
  };
2663
2760
 
2664
- const WorkspacesFolderName = 'workspaces';
2665
- const ExtensionEnablementFileName = 'extension-enablement.json';
2666
- const CacheKeyPrefix = '/cache/workspaces';
2667
- const UriSchemeRegex = /^[a-zA-Z][a-zA-Z\d+.-]*:/;
2668
- const WindowsDrivePathRegex = /^[a-zA-Z]:[\\/]/;
2669
- const WindowsDriveSegmentRegex = /^[a-zA-Z]:$/;
2670
- const EmptyEnablement = {
2671
- disabledIds: [],
2672
- enabledIds: [],
2673
- hasWorkspace: false
2761
+ const state$1 = {
2762
+ rpc: undefined
2674
2763
  };
2675
- const cache$1 = new Map();
2676
- const mutationQueues = new Map();
2677
- const encodePathSegment = (segment, index) => {
2678
- if (index === 0 && WindowsDriveSegmentRegex.test(segment)) {
2679
- return segment;
2680
- }
2681
- return encodeURIComponent(segment);
2764
+ const set$2 = value => {
2765
+ state$1.rpc = value;
2682
2766
  };
2683
- const encodeFilePath = path => {
2684
- return path.split('/').map(encodePathSegment).join('/');
2767
+ const invoke = async (method, ...params) => {
2768
+ await state$1.rpc?.invoke(method, ...params);
2685
2769
  };
2686
- const toWorkspaceUri = workspacePath => {
2687
- if (WindowsDrivePathRegex.test(workspacePath)) {
2688
- return `file:///${encodeFilePath(workspacePath.replaceAll('\\', '/'))}`;
2689
- }
2690
- if (UriSchemeRegex.test(workspacePath)) {
2691
- return workspacePath;
2692
- }
2693
- if (workspacePath.startsWith('/')) {
2694
- return `file://${encodeFilePath(workspacePath)}`;
2695
- }
2696
- return workspacePath;
2770
+
2771
+ const notifyNotificationsChanged = async () => {
2772
+ const notifications = getAll();
2773
+ await Promise.all([invoke$1('NotificationCenter.handleNotificationsChanged', notifications), invoke('StatusBar.handleNotificationCountChanged', notifications.length)]);
2697
2774
  };
2698
- const joinUri = (base, ...parts) => {
2699
- const normalizedBase = base.endsWith('/') ? base.slice(0, -1) : base;
2700
- return [normalizedBase, ...parts].join('/');
2775
+
2776
+ const getPreference = async key => {
2777
+ return invoke$4('Preferences.get', key);
2701
2778
  };
2702
- const hashWorkspaceUri = async workspaceUri => {
2703
- const bytes = new TextEncoder().encode(workspaceUri);
2704
- const digest = await crypto.subtle.digest('SHA-256', bytes);
2705
- return Array.from(new Uint8Array(digest), value => value.toString(16).padStart(2, '0')).join('');
2779
+ const setPreference = async (key, value) => {
2780
+ await invoke$4('Preferences.update', {
2781
+ [key]: value
2782
+ });
2706
2783
  };
2707
- const getWorkspaceUri = async () => {
2708
- let workspacePath;
2709
- try {
2710
- workspacePath = await invoke$4('Workspace.getPath');
2711
- } catch {
2712
- return '';
2784
+
2785
+ const hiddenExtensionIdsPreference = 'notifications.hiddenExtensionIds';
2786
+ const getHiddenExtensionIds = async () => {
2787
+ const value = await getPreference(hiddenExtensionIdsPreference);
2788
+ if (!Array.isArray(value)) {
2789
+ return [];
2713
2790
  }
2714
- return typeof workspacePath === 'string' ? toWorkspaceUri(workspacePath) : '';
2791
+ return value.filter(item => typeof item === 'string');
2715
2792
  };
2716
- const getConfigUri = async () => {
2717
- const configUri = await invoke$4('WebView.compatSharedProcessInvoke', 'Platform.getConfigUri');
2718
- if (typeof configUri !== 'string' || configUri === '') {
2719
- throw new Error('Config uri is not available');
2793
+ const assertType = type => {
2794
+ if (type !== 'error' && type !== 'info' && type !== 'warning') {
2795
+ throw new TypeError(`Invalid notification type: ${type}`);
2720
2796
  }
2721
- return configUri;
2722
2797
  };
2723
- const getStorageLocation = async workspaceUri => {
2724
- const workspaceHash = await hashWorkspaceUri(workspaceUri);
2798
+ const showPopup = async (type, message) => {
2725
2799
  try {
2726
- const configUri = await getConfigUri();
2727
- const directoryUri = joinUri(configUri, WorkspacesFolderName, workspaceHash);
2728
- const uri = joinUri(directoryUri, ExtensionEnablementFileName);
2729
- return {
2730
- directoryUri,
2731
- key: uri,
2732
- type: 'file',
2733
- uri
2734
- };
2800
+ await invoke$2('Notification.create', type, message);
2735
2801
  } catch {
2736
- return {
2737
- key: joinUri(CacheKeyPrefix, workspaceHash, ExtensionEnablementFileName),
2738
- type: 'cache'
2739
- };
2802
+ // Notification storage must keep working while an older renderer is connected.
2740
2803
  }
2741
2804
  };
2742
- const getStringArray$1 = value => {
2743
- if (!Array.isArray(value)) {
2744
- return [];
2805
+ const clearNotifications = async () => {
2806
+ clear();
2807
+ await notifyNotificationsChanged();
2808
+ };
2809
+ const createNotification = async (extensionId, type, message) => {
2810
+ string(extensionId);
2811
+ string(type);
2812
+ string(message);
2813
+ assertType(type);
2814
+ const hiddenExtensionIds = await getHiddenExtensionIds();
2815
+ if (hiddenExtensionIds.includes(extensionId)) {
2816
+ return;
2745
2817
  }
2746
- return value.filter(item => typeof item === 'string');
2818
+ add(extensionId, type, message);
2819
+ await Promise.all([notifyNotificationsChanged(), showPopup(type, message)]);
2747
2820
  };
2748
- const parseEnablement = data => {
2749
- return {
2750
- disabledIds: getStringArray$1(data.disabledExtensions),
2751
- enabledIds: getStringArray$1(data.enabledExtensions),
2752
- hasWorkspace: true
2753
- };
2821
+ const dismissNotification = async id => {
2822
+ number(id);
2823
+ dismiss(id);
2824
+ await notifyNotificationsChanged();
2754
2825
  };
2755
- const readFromLocation = async location => {
2756
- if (location.type === 'cache') {
2757
- const data = await getJson$1(location.key);
2758
- return parseEnablement(data || {});
2759
- }
2760
- const exists$1 = await exists(location.uri);
2761
- if (!exists$1) {
2762
- return {
2763
- ...EmptyEnablement,
2764
- hasWorkspace: true
2765
- };
2766
- }
2767
- const content = await readFile$1(location.uri);
2768
- return parseEnablement(JSON.parse(content));
2826
+ const getNotificationCount = () => {
2827
+ return getAll().length;
2769
2828
  };
2770
- const readFromLocationCached = async location => {
2771
- const cached = cache$1.get(location.key);
2772
- if (cached) {
2773
- return cached;
2829
+ const getNotifications = () => {
2830
+ return getAll();
2831
+ };
2832
+ const hideNotificationsFromExtension = async extensionId => {
2833
+ string(extensionId);
2834
+ const hiddenExtensionIds = await getHiddenExtensionIds();
2835
+ if (!hiddenExtensionIds.includes(extensionId)) {
2836
+ await setPreference(hiddenExtensionIdsPreference, [...hiddenExtensionIds, extensionId]);
2774
2837
  }
2775
- const promise = readFromLocation(location);
2776
- cache$1.set(location.key, promise);
2777
- try {
2778
- return await promise;
2779
- } catch (error) {
2780
- if (cache$1.get(location.key) === promise) {
2781
- cache$1.delete(location.key);
2782
- }
2783
- throw error;
2838
+ removeByExtension(extensionId);
2839
+ await notifyNotificationsChanged();
2840
+ };
2841
+
2842
+ const cacheName = 'ExtensionSecrets';
2843
+ const getRequestUrl = (extensionId, key) => {
2844
+ return `https://secret-storage.invalid/${encodeURIComponent(extensionId)}/${encodeURIComponent(key)}`;
2845
+ };
2846
+ const isElectron = () => {
2847
+ return get$7().platform === Electron;
2848
+ };
2849
+ const deleteSecret = async (extensionId, key) => {
2850
+ string(extensionId);
2851
+ string(key);
2852
+ if (isElectron()) {
2853
+ await invoke$5('SecretStorage.delete', extensionId, key);
2854
+ return;
2784
2855
  }
2856
+ const cache = await caches.open(cacheName);
2857
+ await cache.delete(getRequestUrl(extensionId, key));
2785
2858
  };
2786
- const getWorkspaceAndLocation = async () => {
2787
- const workspaceUri = await getWorkspaceUri();
2788
- if (!workspaceUri) {
2789
- return undefined;
2859
+ const getSecret = async (extensionId, key) => {
2860
+ string(extensionId);
2861
+ string(key);
2862
+ if (isElectron()) {
2863
+ return invoke$5('SecretStorage.get', extensionId, key);
2790
2864
  }
2791
- const location = await getStorageLocation(workspaceUri);
2792
- return {
2793
- location,
2794
- workspaceUri
2795
- };
2865
+ const cache = await caches.open(cacheName);
2866
+ const response = await cache.match(getRequestUrl(extensionId, key));
2867
+ return response?.text();
2796
2868
  };
2797
- const writeToLocation = async (location, workspaceUri, enablement) => {
2798
- const data = {
2799
- disabledExtensions: enablement.disabledIds,
2800
- enabledExtensions: enablement.enabledIds,
2801
- workspace: workspaceUri
2802
- };
2803
- if (location.type === 'cache') {
2804
- await setJson(location.key, data);
2805
- } else {
2806
- const directoryExists = await exists(location.directoryUri);
2807
- if (!directoryExists) {
2808
- await mkdir(location.directoryUri);
2809
- }
2810
- await writeFile(location.uri, JSON.stringify(data, null, 2) + '\n');
2869
+ const storeSecret = async (extensionId, key, value) => {
2870
+ string(extensionId);
2871
+ string(key);
2872
+ string(value);
2873
+ if (isElectron()) {
2874
+ await invoke$5('SecretStorage.store', extensionId, key, value);
2875
+ return;
2811
2876
  }
2812
- cache$1.set(location.key, Promise.resolve(enablement));
2877
+ const cache = await caches.open(cacheName);
2878
+ await cache.put(getRequestUrl(extensionId, key), new Response(value));
2813
2879
  };
2814
- const mutate = async (update, createIfMissing) => {
2815
- const workspaceAndLocation = await getWorkspaceAndLocation();
2816
- if (!workspaceAndLocation) {
2817
- throw new Error('Cannot change workspace extension enablement without an open workspace');
2880
+
2881
+ class CommandNotFoundError extends Error {
2882
+ constructor(command) {
2883
+ super(`Command not found ${command}`);
2884
+ Object.defineProperty(this, 'name', {
2885
+ value: 'CommandNotFoundError'
2886
+ });
2818
2887
  }
2819
- const {
2820
- location,
2821
- workspaceUri
2822
- } = workspaceAndLocation;
2823
- const previousMutation = mutationQueues.get(location.key) || Promise.resolve();
2824
- const runMutation = async () => {
2825
- try {
2826
- await previousMutation;
2827
- } catch {
2828
- // A failed earlier mutation must not permanently block this workspace.
2829
- }
2830
- if (!createIfMissing && location.type === 'file' && !(await exists(location.uri))) {
2831
- return;
2832
- }
2833
- const oldEnablement = await readFromLocation(location);
2834
- const newEnablement = update(oldEnablement);
2835
- await writeToLocation(location, workspaceUri, newEnablement);
2836
- };
2837
- const mutation = runMutation();
2838
- mutationQueues.set(location.key, mutation);
2888
+ }
2889
+ const allowedElectronPortCommand = 'HandleMessagePortForEmbedsProcess.handleMessagePortForEmbedsProcess';
2890
+ const workspaceSetUriCommand = 'Workspace.setUri';
2891
+ const privilegedCommandPrefixes = ['ElectronNet.', 'ClipBoard.', 'DebugSharedProcess.', 'Developer.', 'Electron', 'Exec.', 'ExtensionNodeRpc.', 'FileSystem', 'FileWatcher.', 'IpcParent.', 'PlatformPaths.', 'PersistentFileHandle.', 'Process.', 'RebuildNodePty.', 'SearchProcess.', 'SendMessagePort', 'SharedProcess.', 'TerminalProcess.', 'Transferrable.', 'WebSocketCapability.', 'WebView.compat'];
2892
+ const invokeGlobalCommand = (method, ...params) => {
2893
+ const command = commandMapRef[method];
2894
+ if (!command) {
2895
+ throw new CommandNotFoundError(method);
2896
+ }
2897
+ return command(...params);
2898
+ };
2899
+ const executeDeferredCommand = async (invokeCommand, id, args) => {
2839
2900
  try {
2840
- await mutation;
2841
- } finally {
2842
- if (mutationQueues.get(location.key) === mutation) {
2843
- mutationQueues.delete(location.key);
2844
- }
2901
+ await invokeCommand('Extensions.executeCommand', id, ...args);
2902
+ } catch (error) {
2903
+ await handleUncaughtExtensionError(error);
2845
2904
  }
2846
2905
  };
2847
- const getWorkspaceExtensionEnablement = async () => {
2848
- const workspaceAndLocation = await getWorkspaceAndLocation();
2849
- if (!workspaceAndLocation) {
2850
- return EmptyEnablement;
2906
+ const executeCommand$1 = (invokeCommand, id, ...args) => {
2907
+ if (privilegedCommandPrefixes.some(prefix => id.startsWith(prefix))) {
2908
+ throw new Error(`Isolated extensions cannot execute privileged command ${id}`);
2851
2909
  }
2852
- return readFromLocationCached(workspaceAndLocation.location);
2910
+ if (id === workspaceSetUriCommand) {
2911
+ setTimeout(() => {
2912
+ void executeDeferredCommand(invokeCommand, id, args).catch(() => {});
2913
+ }, 0);
2914
+ return undefined;
2915
+ }
2916
+ return invokeCommand('Extensions.executeCommand', id, ...args);
2853
2917
  };
2854
- const getWorkspaceExtensionEnablementSafe = async () => {
2855
- try {
2856
- return await getWorkspaceExtensionEnablement();
2857
- } catch {
2858
- let workspaceUri = '';
2859
- try {
2860
- workspaceUri = await getWorkspaceUri();
2861
- } catch {
2862
- // Ignore unavailable workspace state while recovering from malformed storage.
2863
- }
2918
+ const createExtensionCommandMap = (extensionId, invokeCommand = invokeGlobalCommand) => {
2919
+ const inheritedCommands = invokeCommand === invokeGlobalCommand ? commandMapRef : Object.fromEntries(Object.keys(commandMapRef).map(method => [method, (...args) => invokeCommand(method, ...args)]));
2920
+ if (invokeCommand !== invokeGlobalCommand) {
2921
+ // Application runtimes must not bypass the scoped router through a legacy
2922
+ // callback (notifications, secrets, file watchers, or privileged node ports).
2864
2923
  return {
2865
- ...EmptyEnablement,
2866
- hasWorkspace: Boolean(workspaceUri)
2924
+ ...inheritedCommands,
2925
+ 'Extensions.executeCommand': (id, ...args) => executeCommand$1(invokeCommand, id, ...args),
2926
+ 'Extensions.registerFileChangeHandler': () => invokeCommand('Extensions.registerFileChangeHandler'),
2927
+ 'Extensions.unregisterFileChangeHandler': () => invokeCommand('Extensions.unregisterFileChangeHandler')
2867
2928
  };
2868
2929
  }
2930
+ return {
2931
+ ...inheritedCommands,
2932
+ 'Extensions.createNodeRpcConnection'(rpcId) {
2933
+ return createNodeRpcConnection(extensionId, rpcId);
2934
+ },
2935
+ 'Extensions.createNodeRpcMessagePort'(rpcId, port) {
2936
+ return createNodeRpcMessagePort(extensionId, rpcId, port);
2937
+ },
2938
+ 'Extensions.deleteSecret'(key) {
2939
+ return deleteSecret(extensionId, key);
2940
+ },
2941
+ 'Extensions.executeCommand'(id, ...args) {
2942
+ return executeCommand$1(invokeCommand, id, ...args);
2943
+ },
2944
+ 'Extensions.getSecret'(key) {
2945
+ return getSecret(extensionId, key);
2946
+ },
2947
+ 'Extensions.registerFileChangeHandler'() {
2948
+ register(extensionId);
2949
+ },
2950
+ 'Extensions.sendMessagePortToElectron'(port, initialCommand) {
2951
+ if (initialCommand !== allowedElectronPortCommand) {
2952
+ throw new Error(`Isolated extensions cannot send a port using ${initialCommand}`);
2953
+ }
2954
+ return invokeGlobalCommand('Extensions.sendMessagePortToElectron', port, initialCommand);
2955
+ },
2956
+ 'Extensions.showNotification'(type, message) {
2957
+ return createNotification(extensionId, type, message);
2958
+ },
2959
+ 'Extensions.storeSecret'(key, value) {
2960
+ return storeSecret(extensionId, key, value);
2961
+ },
2962
+ 'Extensions.unregisterFileChangeHandler'() {
2963
+ unregister(extensionId);
2964
+ }
2965
+ };
2869
2966
  };
2870
- const disableExtension$1 = async id => {
2871
- string(id);
2872
- await mutate(oldEnablement => ({
2873
- disabledIds: oldEnablement.disabledIds.includes(id) ? oldEnablement.disabledIds : [...oldEnablement.disabledIds, id],
2874
- enabledIds: oldEnablement.enabledIds.filter(item => item !== id),
2875
- hasWorkspace: true
2876
- }), true);
2877
- };
2878
- const enableExtension$1 = async id => {
2879
- string(id);
2880
- await mutate(oldEnablement => ({
2881
- disabledIds: oldEnablement.disabledIds.filter(item => item !== id),
2882
- enabledIds: oldEnablement.enabledIds.includes(id) ? oldEnablement.enabledIds : [...oldEnablement.enabledIds, id],
2883
- hasWorkspace: true
2884
- }), true);
2885
- };
2886
- const clearExtensionOverride = async id => {
2887
- string(id);
2888
- const workspaceAndLocation = await getWorkspaceAndLocation();
2889
- if (!workspaceAndLocation) {
2890
- return;
2891
- }
2892
- const {
2893
- location
2894
- } = workspaceAndLocation;
2895
- if (location.type === 'file' && !(await exists(location.uri))) {
2896
- return;
2897
- }
2898
- await mutate(oldEnablement => ({
2899
- disabledIds: oldEnablement.disabledIds.filter(item => item !== id),
2900
- enabledIds: oldEnablement.enabledIds.filter(item => item !== id),
2901
- hasWorkspace: true
2902
- }), false);
2967
+ const createExtensionCommandExecutor = commandMap => {
2968
+ return (method, ...params) => {
2969
+ const command = commandMap[method];
2970
+ if (!command) {
2971
+ throw new CommandNotFoundError(method);
2972
+ }
2973
+ return command(...params);
2974
+ };
2903
2975
  };
2904
2976
 
2905
2977
  /* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
2906
2978
 
2907
- const withDisabledState = (extensions, disabledIds, enabledIds = []) => {
2908
- if (disabledIds.length === 0 && enabledIds.length === 0) {
2909
- return extensions;
2979
+ const pendingRpcs = Object.create(null);
2980
+ const getPendingExtensionIds = application => {
2981
+ return Object.keys(pendingRpcs).flatMap(key => {
2982
+ const [applicationId, generation, extensionId] = JSON.parse(key);
2983
+ return applicationId === application.applicationId && generation === application.applicationGeneration ? [extensionId] : [];
2984
+ });
2985
+ };
2986
+ const getRuntimeId = (extensionId, application) => {
2987
+ return application?.applicationId === undefined ? extensionId : JSON.stringify([application.applicationId, application.applicationGeneration, extensionId]);
2988
+ };
2989
+ const bindCommandMap = (rpc, commandMap) => {
2990
+ if (rpc.ipc) {
2991
+ rpc.ipc.execute = createExtensionCommandExecutor(commandMap);
2910
2992
  }
2911
- const disabledIdsSet = new Set(disabledIds);
2912
- const enabledIdsSet = new Set(enabledIds);
2913
- return extensions.map(extension => {
2914
- if (disabledIdsSet.has(extension.id)) {
2915
- return {
2916
- ...extension,
2917
- disabled: true
2918
- };
2993
+ return rpc;
2994
+ };
2995
+ const createIsolatedExtensionHostWorker = async (extensionId, absolutePath, workerName, contentSecurityPolicy, createRpc, invokeAndTransfer, application) => {
2996
+ const runtimeId = getRuntimeId(extensionId, application);
2997
+ const invokeCommand = application === undefined ? undefined : (method, ...args) => {
2998
+ assertCurrentApplication(application);
2999
+ if (method === 'Extensions.registerFileChangeHandler') {
3000
+ return register(extensionId, application.applicationId);
2919
3001
  }
2920
- if (enabledIdsSet.has(extension.id) && extension.disabled === true) {
2921
- return {
2922
- ...extension,
2923
- disabled: false
2924
- };
3002
+ if (method === 'Extensions.unregisterFileChangeHandler') {
3003
+ return unregister(extensionId, application.applicationId);
3004
+ }
3005
+ if (method === 'Extensions.sendMessagePortToFileSystemWorker') {
3006
+ return createFileSystemPort(application, args[0], extensionId);
3007
+ }
3008
+ if (method === 'Extensions.createWebViewWorkerRpc' || method === 'Extensions.createWebViewWorkerRpc2') {
3009
+ return createWorker$1(application, args[0], args[1], method === 'Extensions.createWebViewWorkerRpc', extensionId);
3010
+ }
3011
+ const invokeApplication = commandMapRef['Extensions.invokeForApplication'];
3012
+ if (!invokeApplication) {
3013
+ throw new Error('Application extension command routing is not initialized');
3014
+ }
3015
+ return invokeApplication(application.applicationId, method, ...args);
3016
+ };
3017
+ const commandMap = createExtensionCommandMap(runtimeId, invokeCommand);
3018
+ const rpc = await createRpc({
3019
+ // PlainMessagePortRpc registers this map process-wide. Bind the restricted
3020
+ // callbacks to this port below, never to the shared host command table.
3021
+ commandMap: {},
3022
+ isMessagePortOpen: true,
3023
+ send(port) {
3024
+ return invokeAndTransfer('LaunchIsolatedExtensionHostWorker.launchIsolatedExtensionHostWorker', port, runtimeId, absolutePath, workerName, contentSecurityPolicy);
2925
3025
  }
2926
- return extension;
2927
3026
  });
3027
+ return bindCommandMap(rpc, commandMap);
2928
3028
  };
2929
- const getExtensionsWithState = async (extensions, extensionsState, platform) => {
2930
- if (extensionsState.applicationId !== undefined) {
2931
- const byId = new Map(extensions.map(extension => [extension.id, extension]));
2932
- return withDisabledState(byId.values().toArray(), extensionsState.disabledIds).map(extension => ({
2933
- ...extension,
2934
- applicationGeneration: extensionsState.applicationGeneration,
2935
- applicationId: extensionsState.applicationId
2936
- }));
3029
+ const createWorker = (extensionId, absolutePath, workerName, contentSecurityPolicy, application) => {
3030
+ return createIsolatedExtensionHostWorker(extensionId, absolutePath, workerName, contentSecurityPolicy, create$6, invokeAndTransfer, application);
3031
+ };
3032
+ const createAndStoreRpc = async (extensionId, absolutePath, workerName, contentSecurityPolicy, create, application) => {
3033
+ try {
3034
+ const rpc = application === undefined ? await create(extensionId, absolutePath, workerName, contentSecurityPolicy) : await create(extensionId, absolutePath, workerName, contentSecurityPolicy, application);
3035
+ if (application !== undefined) {
3036
+ try {
3037
+ assertCurrentApplication(application);
3038
+ } catch (error) {
3039
+ await Promise.allSettled([rpc.dispose(), invoke$2('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', getRuntimeId(extensionId, application))]);
3040
+ throw error;
3041
+ }
3042
+ }
3043
+ set$4(extensionId, rpc, application?.applicationId);
3044
+ return rpc;
3045
+ } catch (error) {
3046
+ console.error(`[extension-management-worker] ${extensionId} failed to activate`, error);
3047
+ throw error;
2937
3048
  }
2938
- if (extensions.length === 0) {
2939
- return extensions;
3049
+ };
3050
+ const getOrCreateIsolatedExtensionHostWorker = async (extensionId, absolutePath, workerName = '', contentSecurityPolicy = '', create = createWorker, applicationId) => {
3051
+ const application = applicationId === undefined ? undefined : get$7(applicationId);
3052
+ const existingRpc = get$2(extensionId, applicationId);
3053
+ if (existingRpc) {
3054
+ return existingRpc;
2940
3055
  }
2941
- const {
2942
- disabledIds,
2943
- enabledIds
2944
- } = await getExtensionEnablement(extensionsState, platform);
2945
- const extensionsWithDisabledState = withDisabledState(extensions, disabledIds, enabledIds);
2946
- if (platform === Test) {
2947
- return extensionsWithDisabledState;
3056
+ const key = JSON.stringify([applicationId ?? null, application?.applicationGeneration ?? null, extensionId]);
3057
+ const pendingRpc = pendingRpcs[key];
3058
+ if (pendingRpc !== undefined) {
3059
+ return pendingRpc;
2948
3060
  }
2949
- const {
2950
- disabledIds: workspaceDisabledIds,
2951
- enabledIds: workspaceEnabledIds
2952
- } = await getWorkspaceExtensionEnablementSafe();
2953
- return withDisabledState(extensionsWithDisabledState, workspaceDisabledIds, workspaceEnabledIds);
2954
- };
2955
- const getAllExtensionsWithState = async (extensionsState, assetDir, platform) => {
2956
- const {
2957
- assetDir: resolvedAssetDir,
2958
- platform: resolvedPlatform
2959
- } = await getRuntimeContext(assetDir, platform);
2960
- string(resolvedAssetDir);
2961
- number(resolvedPlatform);
2962
- const meta = extensionsState.webExtensions;
2963
- if (resolvedPlatform === Web) {
2964
- const webExtensions = await getWebExtensions(resolvedAssetDir);
2965
- const compatibleExtensions = [...webExtensions, ...meta].filter(extension => isExtensionCompatible(extension, resolvedPlatform));
2966
- return getExtensionsWithState(compatibleExtensions, extensionsState, resolvedPlatform);
3061
+ const newRpc = createAndStoreRpc(extensionId, absolutePath, workerName, contentSecurityPolicy, create, application);
3062
+ pendingRpcs[key] = newRpc;
3063
+ try {
3064
+ return await newRpc;
3065
+ } finally {
3066
+ if (pendingRpcs[key] === newRpc) {
3067
+ delete pendingRpcs[key];
3068
+ }
2967
3069
  }
2968
- const local = await invoke$3('ExtensionManagement.getAllExtensions');
2969
- return getExtensionsWithState([...local, ...meta], extensionsState, resolvedPlatform);
2970
3070
  };
2971
3071
 
2972
- const getExtensionAbsolutePath = (id, isWeb, isBuiltin, path, relativePath, origin, platform, assetDir) => {
2973
- if (path.startsWith('http')) {
2974
- if (path.endsWith('/')) {
2975
- return new URL(relativePath, path).href;
3072
+ const activateIsolatedExtension = async (extensionId, absolutePath, workerName, contentSecurityPolicy, activationEvent, getOrCreate = getOrCreateIsolatedExtensionHostWorker, applicationId) => {
3073
+ const application = applicationId === undefined ? undefined : get$7(applicationId);
3074
+ const updateStatus = status => {
3075
+ if (applicationId === undefined) {
3076
+ updateRuntimeStatus(extensionId, status);
3077
+ return;
2976
3078
  }
2977
- return new URL(relativePath, path + '/').href;
2978
- }
2979
- if (!path.startsWith('/')) {
2980
- path = '/' + path;
3079
+ const current = get$7(applicationId);
3080
+ if (current.applicationGeneration !== application?.applicationGeneration) {
3081
+ throw new Error(`Stale extension application: ${applicationId}`);
3082
+ }
3083
+ updateRuntimeStatus(extensionId, status, applicationId);
3084
+ };
3085
+ const startTime = performance.now();
3086
+ updateStatus({
3087
+ activationEvent,
3088
+ activationStartTime: startTime,
3089
+ status: Activating
3090
+ });
3091
+ try {
3092
+ const rpc = applicationId === undefined ? await getOrCreate(extensionId, absolutePath, workerName, contentSecurityPolicy) : await getOrCreate(extensionId, absolutePath, workerName, contentSecurityPolicy, undefined, applicationId);
3093
+ const endTime = performance.now();
3094
+ updateStatus({
3095
+ activationEndTime: endTime,
3096
+ activationTime: endTime - startTime,
3097
+ status: Activated
3098
+ });
3099
+ return rpc;
3100
+ } catch (error) {
3101
+ if (application === undefined || isCurrentApplication(application)) {
3102
+ updateStatus({
3103
+ error: getErrorMessage(error),
3104
+ status: Error$1
3105
+ });
3106
+ }
3107
+ throw error;
2981
3108
  }
2982
- if (isWeb) {
2983
- return path + '/' + relativePath;
3109
+ };
3110
+
3111
+ const isExtensionIsolated = extension => {
3112
+ return extension?.isolated === true;
3113
+ };
3114
+
3115
+ const activateExtension3 = async (extension, absolutePath, activationEvent, platform) => {
3116
+ if (extension.applicationId !== undefined) {
3117
+ assertCurrentApplication(extension);
2984
3118
  }
2985
- if (platform === Web) {
2986
- return path + '/' + relativePath;
3119
+ const extensionId = extension.id || interExtensionId(extension.uri);
3120
+ if (!isExtensionIsolated(extension)) {
3121
+ throw new Error(`Extension ${extensionId} does not use the isolated extension API`);
2987
3122
  }
2988
- if (isBuiltin) {
2989
- return `${assetDir}/extensions/${id}/${relativePath}`;
3123
+ handleRpcInfos(extension, platform);
3124
+ const contentSecurityPolicy = getContentSecurityPolicy(extension.contentSecurityPolicy, absolutePath, extension.rpc);
3125
+ if (extension.applicationId === undefined) {
3126
+ await activateIsolatedExtension(extensionId, absolutePath, extension.workerName || '', contentSecurityPolicy, activationEvent);
3127
+ } else {
3128
+ await activateIsolatedExtension(extensionId, absolutePath, extension.workerName || '', contentSecurityPolicy, activationEvent, undefined, extension.applicationId);
2990
3129
  }
2991
- return new URL('/remote' + path + '/' + relativePath, origin).href;
2992
3130
  };
2993
3131
 
2994
3132
  const getAllExtensions = async (assetDir, platform) => {
2995
3133
  return getAllExtensionsWithState(get$7(), assetDir, platform);
2996
3134
  };
2997
3135
 
2998
- const notifyRunningExtensionsChanged = applicationId => {
2999
- setTimeout(() => {
3000
- const notification = applicationId === undefined ? invoke$4('Layout.handleExtensionsChanged') : invoke$4('Application.execute', applicationId, 'Layout.handleExtensionsChanged');
3001
- void Promise.resolve(notification).catch(() => {});
3002
- }, 0);
3003
- };
3004
-
3005
3136
  /* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
3006
3137
 
3007
3138
  const activatingExtensions = Object.create(null);
@@ -3057,10 +3188,10 @@ const waitForExtensionActivations = async application => {
3057
3188
  const matchesEvent$1 = (extension, event) => {
3058
3189
  return !extension.disabled && isExtensionIsolated(extension) && Array.isArray(extension.activation) && extension.activation.includes(event);
3059
3190
  };
3060
- const getExtensionId$3 = extension => {
3191
+ const getExtensionId$2 = extension => {
3061
3192
  return extension.id;
3062
3193
  };
3063
- const getAbsolutePath$1 = (extension, assetDir, platform) => {
3194
+ const getAbsolutePath = (extension, assetDir, platform) => {
3064
3195
  return getExtensionAbsolutePath(extension.id, extension.isWeb, extension.builtin, extension.path || extension.uri, extension.browser, globalThis.location.origin, platform, assetDir);
3065
3196
  };
3066
3197
  const doActivateExtension = async (extension, absolutePath, event, platform, activation) => {
@@ -3068,7 +3199,7 @@ const doActivateExtension = async (extension, absolutePath, event, platform, act
3068
3199
  activatingExtensions,
3069
3200
  runningExtensions
3070
3201
  } = activation;
3071
- const extensionId = getExtensionId$3(extension);
3202
+ const extensionId = getExtensionId$2(extension);
3072
3203
  try {
3073
3204
  await activateExtension3(extension, absolutePath, event, platform);
3074
3205
  runningExtensions[extensionId] = true;
@@ -3086,12 +3217,12 @@ const activateExtension = async (extension, event, assetDir, platform, activatio
3086
3217
  activatingExtensions,
3087
3218
  runningExtensions
3088
3219
  } = activation;
3089
- const extensionId = getExtensionId$3(extension);
3220
+ const extensionId = getExtensionId$2(extension);
3090
3221
  if (runningExtensions[extensionId]) {
3091
3222
  return;
3092
3223
  }
3093
3224
  if (!Object.hasOwn(activatingExtensions, extensionId)) {
3094
- const absolutePath = getAbsolutePath$1(extension, assetDir, platform);
3225
+ const absolutePath = getAbsolutePath(extension, assetDir, platform);
3095
3226
  activatingExtensions[extensionId] = doActivateExtension(extension, absolutePath, event, platform, activation);
3096
3227
  }
3097
3228
  await activatingExtensions[extensionId];
@@ -3152,7 +3283,7 @@ const handleChange = async _id => {
3152
3283
  if (!statusBarVisible) {
3153
3284
  return;
3154
3285
  }
3155
- await invoke$1('StatusBar.handleChange');
3286
+ await invoke('StatusBar.handleChange');
3156
3287
  };
3157
3288
 
3158
3289
  const hasStatusBarItems = extension => {
@@ -3210,7 +3341,7 @@ const createWebViewWorkerRpc2 = async (rpcInfo, port) => {
3210
3341
  if (rpcInfo.contentSecurityPolicy) {
3211
3342
  const pathName = new URL(rpcInfo.url, 'http://localhost').pathname;
3212
3343
  const contentSecurityPolicy = getContentSecurityPolicy(rpcInfo.contentSecurityPolicy, rpcInfo.url);
3213
- await invoke('ExtensionHostWorkerContentSecurityPolicy.set', pathName, contentSecurityPolicy);
3344
+ await invoke$2('ExtensionHostWorkerContentSecurityPolicy.set', pathName, contentSecurityPolicy);
3214
3345
  }
3215
3346
  await invokeAndTransfer('IpcParent.create', {
3216
3347
  method: ModuleWorkerAndWorkaroundForChromeDevtoolsBug,
@@ -3247,7 +3378,7 @@ const createWebViewWorkerRpc = async (rpcInfo, port) => {
3247
3378
  });
3248
3379
  };
3249
3380
 
3250
- const disposeIsolatedExtensionHostWorker = async (extensionId, invoke$1 = invoke) => {
3381
+ const disposeIsolatedExtensionHostWorker = async (extensionId, invoke = invoke$2) => {
3251
3382
  unregister(extensionId);
3252
3383
  const rpc = remove$1(extensionId);
3253
3384
  if (!rpc) {
@@ -3256,7 +3387,7 @@ const disposeIsolatedExtensionHostWorker = async (extensionId, invoke$1 = invoke
3256
3387
  resetExtensionActivation(extensionId);
3257
3388
  resetExtensionRuntimeState(extensionId);
3258
3389
  try {
3259
- await invoke$1('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', extensionId);
3390
+ await invoke('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', extensionId);
3260
3391
  } catch {
3261
3392
  // Older renderer workers only support disposing the extension RPC.
3262
3393
  }
@@ -3416,11 +3547,11 @@ const disposeExtensionApplication = async applicationId => {
3416
3547
  const ids = new Set([...getIds(applicationId), ...getPendingExtensionIds(application)]);
3417
3548
  const runtimes = ids.values().map(id => ({
3418
3549
  id,
3419
- rpc: get$3(id, applicationId)
3550
+ rpc: get$2(id, applicationId)
3420
3551
  })).toArray();
3421
3552
  // Invalidate pending activations and extension callbacks before awaiting teardown.
3422
3553
  removeApplication(applicationId);
3423
- clear(applicationId);
3554
+ clear$1(applicationId);
3424
3555
  resetAllExtensionActivations(application);
3425
3556
  reset(applicationId);
3426
3557
  const results = await Promise.allSettled([dispose(application), ...runtimes.map(async ({
@@ -3428,7 +3559,7 @@ const disposeExtensionApplication = async applicationId => {
3428
3559
  rpc
3429
3560
  }) => {
3430
3561
  const runtimeId = getRuntimeId(id, application);
3431
- const disposal = await Promise.allSettled([Promise.try(() => rpc?.dispose()), invoke('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', runtimeId)]);
3562
+ const disposal = await Promise.allSettled([Promise.try(() => rpc?.dispose()), invoke$2('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', runtimeId)]);
3432
3563
  const errors = disposal.filter(result => result.status === 'rejected').map(result => result.reason);
3433
3564
  if (errors.length > 0) {
3434
3565
  throw new AggregateError(errors, `Failed to dispose extension ${id}`);
@@ -3463,7 +3594,7 @@ const enableWorkspaceExtension = async id => {
3463
3594
 
3464
3595
  /* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
3465
3596
 
3466
- const getExtensionId$2 = extension => {
3597
+ const getExtensionId$1 = extension => {
3467
3598
  return extension.id || interExtensionId(extension.uri || extension.path || '');
3468
3599
  };
3469
3600
  const contributesCommand = (extension, id) => {
@@ -3478,8 +3609,11 @@ const getRpcForCommand = async (extensionsState, id, platform) => {
3478
3609
  if (!extension) {
3479
3610
  return undefined;
3480
3611
  }
3481
- const extensionId = getExtensionId$2(extension);
3482
- const existingRpc = get$3(extensionId, extensionsState.applicationId);
3612
+ if (extension.workspaceTransport?.command === id) {
3613
+ throw new Error('Workspace transports can only be called by extension management');
3614
+ }
3615
+ const extensionId = getExtensionId$1(extension);
3616
+ const existingRpc = get$2(extensionId, extensionsState.applicationId);
3483
3617
  if (existingRpc) {
3484
3618
  return existingRpc;
3485
3619
  }
@@ -3488,7 +3622,7 @@ const getRpcForCommand = async (extensionsState, id, platform) => {
3488
3622
  } else {
3489
3623
  await activateByEvent(`onCommand:${id}`, '', platform, extensionsState);
3490
3624
  }
3491
- return get$3(extensionId, extensionsState.applicationId);
3625
+ return get$2(extensionId, extensionsState.applicationId);
3492
3626
  };
3493
3627
  const executeRendererCommand = (id, args, applicationId) => {
3494
3628
  if (applicationId !== undefined) {
@@ -3623,33 +3757,6 @@ const executeLanguageServerCompletion = async (rpc, extension, textDocument, off
3623
3757
  return result.map(sanitizeCompletionItem).filter(item => item !== undefined);
3624
3758
  };
3625
3759
 
3626
- const getExtensionId$1 = extension => {
3627
- return extension.id || interExtensionId(extension.uri || extension.path || '');
3628
- };
3629
- const getAbsolutePath = (extension, assetDir, platform) => {
3630
- return getExtensionAbsolutePath(getExtensionId$1(extension), extension.isWeb === true, extension.builtin === true, extension.path || extension.uri || '', extension.browser || '', getOrigin(), platform, assetDir);
3631
- };
3632
- const getRpc$1 = async (extension, assetDir, platform, activationEvent = '', getOrCreate = getOrCreateIsolatedExtensionHostWorker, notify = notifyRunningExtensionsChanged) => {
3633
- if (extension.applicationId !== undefined) {
3634
- assertCurrentApplication(extension);
3635
- }
3636
- const extensionId = getExtensionId$1(extension);
3637
- const existingRpc = get$3(extensionId, extension.applicationId);
3638
- if (existingRpc) {
3639
- return existingRpc;
3640
- }
3641
- handleRpcInfos(extension, platform);
3642
- const absolutePath = getAbsolutePath(extension, assetDir, platform);
3643
- const contentSecurityPolicy = getContentSecurityPolicy(extension.contentSecurityPolicy, absolutePath, extension.rpc);
3644
- const rpc = await activateIsolatedExtension(extensionId, absolutePath, extension.workerName || '', contentSecurityPolicy, activationEvent, getOrCreate, extension.applicationId);
3645
- if (extension.applicationId === undefined) {
3646
- notify();
3647
- } else {
3648
- notify(extension.applicationId);
3649
- }
3650
- return rpc;
3651
- };
3652
-
3653
3760
  /* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
3654
3761
 
3655
3762
  const contributesCompletionProvider = (extension, languageId) => {
@@ -4538,7 +4645,7 @@ const getRegisteredOutputChannelIds = snapshot => {
4538
4645
  return new Set(snapshot.outputChannels.map(outputChannel => outputChannel.id).filter(id => typeof id === 'string'));
4539
4646
  };
4540
4647
  const getExtensionOutputChannelProviders = async (extension, assetDir, platform) => {
4541
- const extensionId = getExtensionId$1(extension);
4648
+ const extensionId = getExtensionId$3(extension);
4542
4649
  const rpc = await getRpc$1(extension, assetDir, platform);
4543
4650
  let snapshot;
4544
4651
  try {
@@ -4590,7 +4697,7 @@ const resolveOutputChannel = async (extensionsState, uri) => {
4590
4697
  platform
4591
4698
  } = await getRuntimeContext('', extensionsState.platform);
4592
4699
  const extensions = await getAllExtensionsWithState(extensionsState, assetDir, platform);
4593
- const extension = extensions.find(candidate => getExtensionId$1(candidate) === extensionId && hasOutputChannels(candidate));
4700
+ const extension = extensions.find(candidate => getExtensionId$3(candidate) === extensionId && hasOutputChannels(candidate));
4594
4701
  const isContributed = extension?.outputChannels?.some(outputChannel => outputChannel.id === outputChannelId);
4595
4702
  if (!extension || !isContributed) {
4596
4703
  throw new Error(`Output channel ${outputChannelId} is not contributed by extension ${extensionId}`);
@@ -4676,7 +4783,7 @@ const disposeViewOnlyExtensionWorker = async (extensionId, rpc) => {
4676
4783
  if (hasOtherViewInstances(rpc)) {
4677
4784
  return;
4678
4785
  }
4679
- if (get$3(extensionId) !== rpc) {
4786
+ if (get$2(extensionId) !== rpc) {
4680
4787
  return;
4681
4788
  }
4682
4789
  await disposeIsolatedExtensionHostWorker(extensionId);
@@ -4695,8 +4802,8 @@ const getRpcForView = async (viewId, assetDir, platform, applicationId) => {
4695
4802
  platform: resolvedPlatform
4696
4803
  } = await getRuntimeContext(assetDir, platform);
4697
4804
  const extension = await getExtensionForView(viewId, resolvedAssetDir, resolvedPlatform, applicationId);
4698
- const extensionId = getExtensionId$1(extension);
4699
- const existingRpc = get$3(extensionId, applicationId);
4805
+ const extensionId = getExtensionId$3(extension);
4806
+ const existingRpc = get$2(extensionId, applicationId);
4700
4807
  // Application teardown and reload own application workers; global view-only disposal does not.
4701
4808
  if (existingRpc) {
4702
4809
  return {
@@ -5253,13 +5360,13 @@ const getRemoteUrlForWebView = async (uri, options = {}) => {
5253
5360
  if (!webView) {
5254
5361
  throw new Error(`webview ${options.webViewId} not found`);
5255
5362
  }
5256
- const [rpc, blob] = await Promise.all([createWebViewIpc(webView), invoke('FileSystem.getBlob', uri)]);
5363
+ const [rpc, blob] = await Promise.all([createWebViewIpc(webView), invoke$2('FileSystem.getBlob', uri)]);
5257
5364
  const objectUrl = await rpc.invoke('createObjectUrl', blob);
5258
5365
  return objectUrl;
5259
5366
  };
5260
5367
 
5261
5368
  const getRpcInfo = rpcId => {
5262
- const info = get$2(rpcId);
5369
+ const info = get$3(rpcId);
5263
5370
  if (!info) {
5264
5371
  throw new Error(`Rpc not found ${rpcId}`);
5265
5372
  }
@@ -5280,7 +5387,7 @@ const getIcon = (extension, manifestView, assetDir, platform) => {
5280
5387
  if (isAbsoluteIcon(manifestIcon) || !isRelativeIconPath(manifestIcon)) {
5281
5388
  return manifestIcon;
5282
5389
  }
5283
- return getAbsolutePath({
5390
+ return getAbsolutePath$1({
5284
5391
  ...extension,
5285
5392
  browser: manifestIcon
5286
5393
  }, assetDir, platform);
@@ -5341,7 +5448,7 @@ const waitForTimeout = async (timeout, sleep) => {
5341
5448
  const isResponsive = async (rpc, timeout, sleep) => {
5342
5449
  return Promise.race([invokePing(rpc), waitForTimeout(timeout, sleep)]);
5343
5450
  };
5344
- const updateTerminatedExtensionStatuses = async (runtimeStatuses, getRpc = get$3, timeout = 250, sleep$1 = sleep) => {
5451
+ const updateTerminatedExtensionStatuses = async (runtimeStatuses, getRpc = get$2, timeout = 250, sleep$1 = sleep) => {
5345
5452
  const activatedStatuses = Object.values(runtimeStatuses).filter(status => status.status === Activated);
5346
5453
  await Promise.all(activatedStatuses.map(async status => {
5347
5454
  const rpc = getRpc(status.id);
@@ -5403,7 +5510,7 @@ const getItems = async rpc => {
5403
5510
  return rpc.invoke('ExtensionApi.getStatusBarItems');
5404
5511
  };
5405
5512
  const getStatusBarItems = async applicationId => {
5406
- const rpcs = getAll(applicationId);
5513
+ const rpcs = getAll$1(applicationId);
5407
5514
  const results = await Promise.all(rpcs.map(getItems));
5408
5515
  return results.flat();
5409
5516
  };
@@ -5413,7 +5520,7 @@ const getCss = (extension, manifestView, assetDir, platform) => {
5413
5520
  if (typeof css !== 'string' || css.length === 0) {
5414
5521
  return '';
5415
5522
  }
5416
- return getAbsolutePath({
5523
+ return getAbsolutePath$1({
5417
5524
  ...extension,
5418
5525
  browser: css
5419
5526
  }, assetDir, platform);
@@ -5428,7 +5535,7 @@ const getIframe = (extension, manifestView, assetDir, platform) => {
5428
5535
  credentialless: iframe.credentialless !== false,
5429
5536
  csp: iframe.csp || '',
5430
5537
  sandbox: Array.isArray(iframe.sandbox) ? iframe.sandbox.filter(item => typeof item === 'string') : ['allow-scripts'],
5431
- src: getAbsolutePath({
5538
+ src: getAbsolutePath$1({
5432
5539
  ...extension,
5433
5540
  browser: iframe.path
5434
5541
  }, assetDir, platform)
@@ -5459,7 +5566,7 @@ const toView = (extension, manifestView, assetDir, platform) => {
5459
5566
  ...(type && {
5460
5567
  type
5461
5568
  }),
5462
- extensionId: getExtensionId$1(extension),
5569
+ extensionId: getExtensionId$3(extension),
5463
5570
  icon: getIcon(extension, manifestView, assetDir, platform),
5464
5571
  id,
5465
5572
  iframe: getIframe(extension, manifestView, assetDir, platform),
@@ -5489,7 +5596,7 @@ const shouldLoadViews = extension => {
5489
5596
  return false;
5490
5597
  }
5491
5598
  if (!isExtensionIsolated(extension)) {
5492
- warn(`Extension "${getExtensionId$1(extension)}" contributes activity bar views but is not isolated. The views will not be shown. Add "isolated": true to extension.json to enable them.`);
5599
+ warn(`Extension "${getExtensionId$3(extension)}" contributes activity bar views but is not isolated. The views will not be shown. Add "isolated": true to extension.json to enable them.`);
5493
5600
  return false;
5494
5601
  }
5495
5602
  return true;
@@ -5512,7 +5619,7 @@ const getViews = async (assetDir, platform) => {
5512
5619
  const handleData = () => {};
5513
5620
 
5514
5621
  const invokeHandler = async (extensionId, changes, applicationId) => {
5515
- const rpc = get$3(extensionId, applicationId);
5622
+ const rpc = get$2(extensionId, applicationId);
5516
5623
  if (!rpc) {
5517
5624
  unregister(extensionId, applicationId);
5518
5625
  return;
@@ -5533,9 +5640,9 @@ const handleMessagePort = async (port, rpcId) => {
5533
5640
  messagePort: port
5534
5641
  });
5535
5642
  if (rpcId === StatusBarWorker) {
5536
- set$3(rpc);
5643
+ set$2(rpc);
5537
5644
  } else if (rpcId === NotificationCenterWorker) {
5538
- set$4(rpc);
5645
+ set$3(rpc);
5539
5646
  }
5540
5647
  };
5541
5648
 
@@ -5626,7 +5733,7 @@ const defaultDependencies$2 = {
5626
5733
  activateByEvent: activateByEvent,
5627
5734
  createViewInstance: createViewInstance,
5628
5735
  disposeExtensionRuntime,
5629
- getRpc: get$3,
5736
+ getRpc: get$2,
5630
5737
  getRuntimeStatus: getRuntimeStatus$1,
5631
5738
  getViewEntries: getEntries,
5632
5739
  removeViewInstance: remove,
@@ -5873,7 +5980,7 @@ const replace = async (application, extensionId, extension) => {
5873
5980
  assertCurrentApplication(application);
5874
5981
  const rpc = remove$1(extensionId, applicationId);
5875
5982
  unregister(extensionId, applicationId);
5876
- const results = await Promise.allSettled([disposeExtension(application, extensionId), Promise.try(() => rpc?.dispose()), invoke('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', getRuntimeId(extensionId, application))]);
5983
+ const results = await Promise.allSettled([disposeExtension(application, extensionId), Promise.try(() => rpc?.dispose()), invoke$2('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', getRuntimeId(extensionId, application))]);
5877
5984
  assertCurrentApplication(application);
5878
5985
  resetExtensionActivation(extensionId, application);
5879
5986
  resetExtensionRuntimeState(extensionId, applicationId);
@@ -5972,10 +6079,10 @@ const invokeForApplication = async (applicationId, method, ...args) => {
5972
6079
  }
5973
6080
  switch (method) {
5974
6081
  case 'ExtensionApi.readFile':
5975
- return invoke('Application.execute', applicationId, 'FileSystem.readFile', ...args);
6082
+ return invoke$2('Application.execute', applicationId, 'FileSystem.readFile', ...args);
5976
6083
  case 'ExtensionHostQuickPick.showQuickInput':
5977
6084
  case 'ExtensionHostQuickPick.showQuickPick':
5978
- return invoke('Application.execute', applicationId, method, ...args);
6085
+ return invoke$2('Application.execute', applicationId, method, ...args);
5979
6086
  case 'Extensions.activateByEvent':
5980
6087
  return activateByEvent(args[0], args[1], args[2] ?? application.platform, application);
5981
6088
  case 'Extensions.createWebViewWorkerRpc':
@@ -6002,7 +6109,7 @@ const invokeForApplication = async (applicationId, method, ...args) => {
6002
6109
  case 'Extensions.sendMessagePortToFileSystemWorker':
6003
6110
  return createFileSystemPort(application, args[0]);
6004
6111
  case 'Extensions.showNotification':
6005
- return invoke('Application.execute', applicationId, 'Notification.create', ...args);
6112
+ return invoke$2('Application.execute', applicationId, 'Notification.create', ...args);
6006
6113
  default:
6007
6114
  throw new Error(`Extension command does not support application context: ${method}`);
6008
6115
  }
@@ -6029,6 +6136,7 @@ const commandMap = {
6029
6136
  'Extensions.addWebExtension': addWebExtension,
6030
6137
  'Extensions.clearNotifications': clearNotifications,
6031
6138
  'Extensions.clearOutputChannel': wrapCommand(clearOutputChannel),
6139
+ 'Extensions.connectWorkspaceTerminal': connectTerminal,
6032
6140
  'Extensions.createApplication': createApplication,
6033
6141
  'Extensions.createViewInstance': createViewInstance,
6034
6142
  'Extensions.createWebViewWorkerRpc': createWebViewWorkerRpc,
@@ -6064,6 +6172,7 @@ const commandMap = {
6064
6172
  'Extensions.executeResolveCompletionItemProvider': wrapCommand(executeResolveCompletionItemProvider),
6065
6173
  'Extensions.executeSignatureHelpProvider': wrapCommand(executeSignatureHelpProvider),
6066
6174
  'Extensions.executeSourceControlProvider': wrapCommand(executeSourceControlProvider),
6175
+ 'Extensions.executeWorkspaceRequest': request,
6067
6176
  'Extensions.getAccessToken': getAccessToken,
6068
6177
  'Extensions.getAllExtensions': getAllExtensions,
6069
6178
  'Extensions.getColorThemeCss': getColorThemeCss,
@@ -6089,6 +6198,7 @@ const commandMap = {
6089
6198
  'Extensions.getViewInstanceState': getViewInstanceState,
6090
6199
  'Extensions.getViewMenuEntries': getViewMenuEntries,
6091
6200
  'Extensions.getViews': getViews,
6201
+ 'Extensions.getWorkspaceTransportUri': getWorkspaceTransportUri,
6092
6202
  'Extensions.handleData': handleData,
6093
6203
  'Extensions.handleFileChanges': handleFileChanges,
6094
6204
  'Extensions.handleLinkedExtensionChange': handleLinkedExtensionChange,