@lvce-editor/extension-management-worker 4.74.4 → 4.75.1
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.
- package/README.md +8 -0
- package/dist/extensionManagementWorkerMain.js +1089 -978
- package/package.json +1 -1
|
@@ -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
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
const
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
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
|
-
|
|
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
|
|
1655
|
+
const setJson = async (cacheKey, data) => {
|
|
1650
1656
|
try {
|
|
1651
|
-
const
|
|
1652
|
-
|
|
1653
|
-
|
|
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
|
-
|
|
1660
|
-
throw createUnsupportedDirectLaunchError(rpcId);
|
|
1661
|
-
}
|
|
1662
|
-
throw error;
|
|
1661
|
+
throw new VError(error, `Failed to add to cache`);
|
|
1663
1662
|
}
|
|
1664
1663
|
};
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
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
|
|
1673
|
+
return value.filter(id => typeof id === 'string');
|
|
1677
1674
|
};
|
|
1678
|
-
const
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
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
|
-
|
|
1690
|
-
const
|
|
1691
|
-
const
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
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
|
|
1701
|
-
if (
|
|
1702
|
-
|
|
1703
|
-
|
|
1702
|
+
const getExtensionEnablement = async (extensionsState, platform) => {
|
|
1703
|
+
if (platform === Test) {
|
|
1704
|
+
return {
|
|
1705
|
+
disabledIds: extensionsState.disabledIds,
|
|
1706
|
+
enabledIds: []
|
|
1707
|
+
};
|
|
1704
1708
|
}
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
if (ids?.size === 0) {
|
|
1708
|
-
applications$1.delete(applicationId);
|
|
1709
|
+
if (platform === Web) {
|
|
1710
|
+
return getWebExtensionEnablement();
|
|
1709
1711
|
}
|
|
1710
|
-
|
|
1711
|
-
|
|
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
|
|
1723
|
-
|
|
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
|
|
1743
|
-
|
|
1721
|
+
const isMissingPlatform = platform => {
|
|
1722
|
+
return typeof platform !== 'number' || platform === 0;
|
|
1744
1723
|
};
|
|
1745
|
-
const
|
|
1746
|
-
|
|
1724
|
+
const isStaticHttpAssetDir = assetDir => {
|
|
1725
|
+
return assetDir.startsWith('/') || assetDir.startsWith('http');
|
|
1747
1726
|
};
|
|
1748
|
-
const
|
|
1749
|
-
return
|
|
1727
|
+
const isHttpLocation = () => {
|
|
1728
|
+
return Reflect.has(globalThis, 'location') && globalThis.location.protocol.startsWith('http');
|
|
1750
1729
|
};
|
|
1751
|
-
const
|
|
1752
|
-
|
|
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
|
|
1756
|
-
|
|
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
|
|
1762
|
-
|
|
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
|
|
1766
|
-
|
|
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
|
|
1776
|
-
|
|
1777
|
-
|
|
1766
|
+
const getWebExtensions = async assetDir => {
|
|
1767
|
+
try {
|
|
1768
|
+
return await getJson(getWebExtensionsUrl(assetDir));
|
|
1769
|
+
} catch {
|
|
1770
|
+
return [];
|
|
1771
|
+
}
|
|
1778
1772
|
};
|
|
1779
1773
|
|
|
1780
|
-
const
|
|
1781
|
-
return
|
|
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
|
-
|
|
1790
|
-
const
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
const
|
|
1794
|
-
|
|
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
|
|
1798
|
-
const
|
|
1799
|
-
|
|
1800
|
-
|
|
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
|
|
1795
|
+
return encodeURIComponent(segment);
|
|
1804
1796
|
};
|
|
1805
|
-
const
|
|
1806
|
-
|
|
1807
|
-
throw new TypeError(`Invalid notification type: ${type}`);
|
|
1808
|
-
}
|
|
1797
|
+
const encodeFilePath = path => {
|
|
1798
|
+
return path.split('/').map(encodePathSegment).join('/');
|
|
1809
1799
|
};
|
|
1810
|
-
const
|
|
1811
|
-
|
|
1812
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1831
|
-
|
|
1832
|
-
}
|
|
1833
|
-
|
|
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
|
|
1839
|
-
|
|
1812
|
+
const joinUri = (base, ...parts) => {
|
|
1813
|
+
const normalizedBase = base.endsWith('/') ? base.slice(0, -1) : base;
|
|
1814
|
+
return [normalizedBase, ...parts].join('/');
|
|
1840
1815
|
};
|
|
1841
|
-
const
|
|
1842
|
-
|
|
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
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1821
|
+
const getWorkspaceUri$1 = async () => {
|
|
1822
|
+
let workspacePath;
|
|
1823
|
+
try {
|
|
1824
|
+
workspacePath = await invoke$4('Workspace.getPath');
|
|
1825
|
+
} catch {
|
|
1826
|
+
return '';
|
|
1849
1827
|
}
|
|
1850
|
-
|
|
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
|
|
1862
|
-
|
|
1863
|
-
string
|
|
1864
|
-
|
|
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
|
-
|
|
1869
|
-
await cache.delete(getRequestUrl(extensionId, key));
|
|
1835
|
+
return configUri;
|
|
1870
1836
|
};
|
|
1871
|
-
const
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
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
|
|
1882
|
-
|
|
1883
|
-
|
|
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
|
-
|
|
1890
|
-
await cache.put(getRequestUrl(extensionId, key), new Response(value));
|
|
1860
|
+
return value.filter(item => typeof item === 'string');
|
|
1891
1861
|
};
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
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
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
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
|
-
|
|
1881
|
+
const content = await readFile$1(location.uri);
|
|
1882
|
+
return parseEnablement(JSON.parse(content));
|
|
1910
1883
|
};
|
|
1911
|
-
const
|
|
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
|
|
1892
|
+
return await promise;
|
|
1914
1893
|
} catch (error) {
|
|
1915
|
-
|
|
1894
|
+
if (cache$1.get(location.key) === promise) {
|
|
1895
|
+
cache$1.delete(location.key);
|
|
1896
|
+
}
|
|
1897
|
+
throw error;
|
|
1916
1898
|
}
|
|
1917
1899
|
};
|
|
1918
|
-
const
|
|
1919
|
-
|
|
1920
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1944
|
-
|
|
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
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
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
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
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$
|
|
2436
|
+
const get$2 = (extensionId, applicationId) => {
|
|
2255
2437
|
if (applicationId !== undefined) {
|
|
2256
2438
|
return applicationRpcs.get(applicationId)?.get(extensionId);
|
|
2257
2439
|
}
|
|
2258
|
-
return rpcs
|
|
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
|
|
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
|
|
2452
|
+
return Object.keys(rpcs);
|
|
2271
2453
|
};
|
|
2272
|
-
const set$
|
|
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
|
|
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
|
|
2292
|
-
delete rpcs
|
|
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
|
|
2301
|
-
delete rpcs
|
|
2482
|
+
for (const key of Object.keys(rpcs)) {
|
|
2483
|
+
delete rpcs[key];
|
|
2302
2484
|
}
|
|
2303
2485
|
};
|
|
2304
2486
|
|
|
2305
|
-
|
|
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
|
|
2308
|
-
|
|
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
|
|
2315
|
-
return
|
|
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
|
|
2318
|
-
if (
|
|
2319
|
-
|
|
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
|
-
|
|
2324
|
-
|
|
2325
|
-
const
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
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
|
|
2358
|
-
|
|
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
|
|
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
|
-
|
|
2363
|
-
|
|
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
|
-
|
|
2372
|
-
|
|
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
|
-
|
|
2584
|
+
port.close();
|
|
2375
2585
|
throw error;
|
|
2376
2586
|
}
|
|
2377
2587
|
};
|
|
2378
|
-
const
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
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
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
}
|
|
2394
|
-
|
|
2395
|
-
|
|
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
|
|
2401
|
-
const
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
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
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
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 (
|
|
2430
|
-
|
|
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
|
-
|
|
2456
|
-
|
|
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
|
-
|
|
2639
|
+
if (isMissingRendererCommand(error, 'ExtensionNodeRpc.supportsDirectConnection')) {
|
|
2640
|
+
throw createUnsupportedDirectLaunchError(rpcId);
|
|
2641
|
+
}
|
|
2642
|
+
throw error;
|
|
2483
2643
|
}
|
|
2484
2644
|
};
|
|
2485
|
-
|
|
2486
|
-
const
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
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
|
|
2503
|
-
|
|
2504
|
-
|
|
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
|
-
|
|
2507
|
-
|
|
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
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
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
|
|
2539
|
-
|
|
2540
|
-
};
|
|
2541
|
-
|
|
2542
|
-
|
|
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
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
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
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
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
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
return
|
|
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
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
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
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
}
|
|
2595
|
-
|
|
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
|
|
2605
|
-
|
|
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
|
-
|
|
2608
|
-
|
|
2723
|
+
|
|
2724
|
+
const state$3 = {
|
|
2725
|
+
nextId: 1,
|
|
2726
|
+
notifications: []
|
|
2609
2727
|
};
|
|
2610
|
-
const
|
|
2611
|
-
|
|
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
|
|
2614
|
-
|
|
2738
|
+
const clear = () => {
|
|
2739
|
+
state$3.notifications = [];
|
|
2615
2740
|
};
|
|
2616
|
-
const
|
|
2617
|
-
|
|
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
|
-
|
|
2633
|
-
return response.statusText || String(response.status) || 'Request failed';
|
|
2744
|
+
const getAll = () => {
|
|
2745
|
+
return state$3.notifications;
|
|
2634
2746
|
};
|
|
2635
|
-
const
|
|
2636
|
-
|
|
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
|
|
2649
|
-
|
|
2751
|
+
const state$2 = {
|
|
2752
|
+
rpc: undefined
|
|
2650
2753
|
};
|
|
2651
|
-
|
|
2652
|
-
|
|
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
|
-
|
|
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
|
|
2665
|
-
|
|
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
|
|
2676
|
-
|
|
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
|
|
2684
|
-
|
|
2767
|
+
const invoke = async (method, ...params) => {
|
|
2768
|
+
await state$1.rpc?.invoke(method, ...params);
|
|
2685
2769
|
};
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
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
|
-
|
|
2699
|
-
|
|
2700
|
-
return
|
|
2775
|
+
|
|
2776
|
+
const getPreference = async key => {
|
|
2777
|
+
return invoke$4('Preferences.get', key);
|
|
2701
2778
|
};
|
|
2702
|
-
const
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2779
|
+
const setPreference = async (key, value) => {
|
|
2780
|
+
await invoke$4('Preferences.update', {
|
|
2781
|
+
[key]: value
|
|
2782
|
+
});
|
|
2706
2783
|
};
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
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
|
|
2791
|
+
return value.filter(item => typeof item === 'string');
|
|
2715
2792
|
};
|
|
2716
|
-
const
|
|
2717
|
-
|
|
2718
|
-
|
|
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
|
|
2724
|
-
const workspaceHash = await hashWorkspaceUri(workspaceUri);
|
|
2798
|
+
const showPopup = async (type, message) => {
|
|
2725
2799
|
try {
|
|
2726
|
-
|
|
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
|
-
|
|
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
|
|
2743
|
-
|
|
2744
|
-
|
|
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
|
-
|
|
2818
|
+
add(extensionId, type, message);
|
|
2819
|
+
await Promise.all([notifyNotificationsChanged(), showPopup(type, message)]);
|
|
2747
2820
|
};
|
|
2748
|
-
const
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
hasWorkspace: true
|
|
2753
|
-
};
|
|
2821
|
+
const dismissNotification = async id => {
|
|
2822
|
+
number(id);
|
|
2823
|
+
dismiss(id);
|
|
2824
|
+
await notifyNotificationsChanged();
|
|
2754
2825
|
};
|
|
2755
|
-
const
|
|
2756
|
-
|
|
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
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
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
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
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
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
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
|
|
2792
|
-
|
|
2793
|
-
|
|
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
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
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
|
|
2877
|
+
const cache = await caches.open(cacheName);
|
|
2878
|
+
await cache.put(getRequestUrl(extensionId, key), new Response(value));
|
|
2813
2879
|
};
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
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
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
const
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
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
|
|
2841
|
-
}
|
|
2842
|
-
|
|
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
|
|
2848
|
-
|
|
2849
|
-
|
|
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
|
-
|
|
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
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
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
|
-
...
|
|
2866
|
-
|
|
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
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
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
|
|
2908
|
-
|
|
2909
|
-
|
|
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
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
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 (
|
|
2921
|
-
return
|
|
2922
|
-
|
|
2923
|
-
|
|
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
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
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
|
-
|
|
2939
|
-
|
|
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
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
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
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
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
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
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
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
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
|
-
|
|
2983
|
-
|
|
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
|
-
|
|
2986
|
-
|
|
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
|
-
|
|
2989
|
-
|
|
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$
|
|
3191
|
+
const getExtensionId$2 = extension => {
|
|
3061
3192
|
return extension.id;
|
|
3062
3193
|
};
|
|
3063
|
-
const getAbsolutePath
|
|
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$
|
|
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$
|
|
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
|
|
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
|
|
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
|
|
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
|
|
3390
|
+
await invoke('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', extensionId);
|
|
3260
3391
|
} catch {
|
|
3261
3392
|
// Older renderer workers only support disposing the extension RPC.
|
|
3262
3393
|
}
|
|
@@ -3390,7 +3521,8 @@ const disposeLanguageServers = async (extensionIds, disposeAll) => {
|
|
|
3390
3521
|
};
|
|
3391
3522
|
const getRetainedExtensionIds = async getExtensions => {
|
|
3392
3523
|
try {
|
|
3393
|
-
const
|
|
3524
|
+
const platform = await invoke$4('Layout.getPlatform');
|
|
3525
|
+
const extensions = await getExtensions('', platform);
|
|
3394
3526
|
return new Set(extensions.filter(extension => extension.preserveRuntimeOnWorkspaceChange === true).map(extension => extension.id).filter(id => typeof id === 'string'));
|
|
3395
3527
|
} catch {
|
|
3396
3528
|
return new Set();
|
|
@@ -3416,11 +3548,11 @@ const disposeExtensionApplication = async applicationId => {
|
|
|
3416
3548
|
const ids = new Set([...getIds(applicationId), ...getPendingExtensionIds(application)]);
|
|
3417
3549
|
const runtimes = ids.values().map(id => ({
|
|
3418
3550
|
id,
|
|
3419
|
-
rpc: get$
|
|
3551
|
+
rpc: get$2(id, applicationId)
|
|
3420
3552
|
})).toArray();
|
|
3421
3553
|
// Invalidate pending activations and extension callbacks before awaiting teardown.
|
|
3422
3554
|
removeApplication(applicationId);
|
|
3423
|
-
clear(applicationId);
|
|
3555
|
+
clear$1(applicationId);
|
|
3424
3556
|
resetAllExtensionActivations(application);
|
|
3425
3557
|
reset(applicationId);
|
|
3426
3558
|
const results = await Promise.allSettled([dispose(application), ...runtimes.map(async ({
|
|
@@ -3428,7 +3560,7 @@ const disposeExtensionApplication = async applicationId => {
|
|
|
3428
3560
|
rpc
|
|
3429
3561
|
}) => {
|
|
3430
3562
|
const runtimeId = getRuntimeId(id, application);
|
|
3431
|
-
const disposal = await Promise.allSettled([Promise.try(() => rpc?.dispose()), invoke('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', runtimeId)]);
|
|
3563
|
+
const disposal = await Promise.allSettled([Promise.try(() => rpc?.dispose()), invoke$2('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', runtimeId)]);
|
|
3432
3564
|
const errors = disposal.filter(result => result.status === 'rejected').map(result => result.reason);
|
|
3433
3565
|
if (errors.length > 0) {
|
|
3434
3566
|
throw new AggregateError(errors, `Failed to dispose extension ${id}`);
|
|
@@ -3463,7 +3595,7 @@ const enableWorkspaceExtension = async id => {
|
|
|
3463
3595
|
|
|
3464
3596
|
/* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
|
|
3465
3597
|
|
|
3466
|
-
const getExtensionId$
|
|
3598
|
+
const getExtensionId$1 = extension => {
|
|
3467
3599
|
return extension.id || interExtensionId(extension.uri || extension.path || '');
|
|
3468
3600
|
};
|
|
3469
3601
|
const contributesCommand = (extension, id) => {
|
|
@@ -3478,8 +3610,11 @@ const getRpcForCommand = async (extensionsState, id, platform) => {
|
|
|
3478
3610
|
if (!extension) {
|
|
3479
3611
|
return undefined;
|
|
3480
3612
|
}
|
|
3481
|
-
|
|
3482
|
-
|
|
3613
|
+
if (extension.workspaceTransport?.command === id) {
|
|
3614
|
+
throw new Error('Workspace transports can only be called by extension management');
|
|
3615
|
+
}
|
|
3616
|
+
const extensionId = getExtensionId$1(extension);
|
|
3617
|
+
const existingRpc = get$2(extensionId, extensionsState.applicationId);
|
|
3483
3618
|
if (existingRpc) {
|
|
3484
3619
|
return existingRpc;
|
|
3485
3620
|
}
|
|
@@ -3488,7 +3623,7 @@ const getRpcForCommand = async (extensionsState, id, platform) => {
|
|
|
3488
3623
|
} else {
|
|
3489
3624
|
await activateByEvent(`onCommand:${id}`, '', platform, extensionsState);
|
|
3490
3625
|
}
|
|
3491
|
-
return get$
|
|
3626
|
+
return get$2(extensionId, extensionsState.applicationId);
|
|
3492
3627
|
};
|
|
3493
3628
|
const executeRendererCommand = (id, args, applicationId) => {
|
|
3494
3629
|
if (applicationId !== undefined) {
|
|
@@ -3623,33 +3758,6 @@ const executeLanguageServerCompletion = async (rpc, extension, textDocument, off
|
|
|
3623
3758
|
return result.map(sanitizeCompletionItem).filter(item => item !== undefined);
|
|
3624
3759
|
};
|
|
3625
3760
|
|
|
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
3761
|
/* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
|
|
3654
3762
|
|
|
3655
3763
|
const contributesCompletionProvider = (extension, languageId) => {
|
|
@@ -4538,7 +4646,7 @@ const getRegisteredOutputChannelIds = snapshot => {
|
|
|
4538
4646
|
return new Set(snapshot.outputChannels.map(outputChannel => outputChannel.id).filter(id => typeof id === 'string'));
|
|
4539
4647
|
};
|
|
4540
4648
|
const getExtensionOutputChannelProviders = async (extension, assetDir, platform) => {
|
|
4541
|
-
const extensionId = getExtensionId$
|
|
4649
|
+
const extensionId = getExtensionId$3(extension);
|
|
4542
4650
|
const rpc = await getRpc$1(extension, assetDir, platform);
|
|
4543
4651
|
let snapshot;
|
|
4544
4652
|
try {
|
|
@@ -4590,7 +4698,7 @@ const resolveOutputChannel = async (extensionsState, uri) => {
|
|
|
4590
4698
|
platform
|
|
4591
4699
|
} = await getRuntimeContext('', extensionsState.platform);
|
|
4592
4700
|
const extensions = await getAllExtensionsWithState(extensionsState, assetDir, platform);
|
|
4593
|
-
const extension = extensions.find(candidate => getExtensionId$
|
|
4701
|
+
const extension = extensions.find(candidate => getExtensionId$3(candidate) === extensionId && hasOutputChannels(candidate));
|
|
4594
4702
|
const isContributed = extension?.outputChannels?.some(outputChannel => outputChannel.id === outputChannelId);
|
|
4595
4703
|
if (!extension || !isContributed) {
|
|
4596
4704
|
throw new Error(`Output channel ${outputChannelId} is not contributed by extension ${extensionId}`);
|
|
@@ -4676,7 +4784,7 @@ const disposeViewOnlyExtensionWorker = async (extensionId, rpc) => {
|
|
|
4676
4784
|
if (hasOtherViewInstances(rpc)) {
|
|
4677
4785
|
return;
|
|
4678
4786
|
}
|
|
4679
|
-
if (get$
|
|
4787
|
+
if (get$2(extensionId) !== rpc) {
|
|
4680
4788
|
return;
|
|
4681
4789
|
}
|
|
4682
4790
|
await disposeIsolatedExtensionHostWorker(extensionId);
|
|
@@ -4695,8 +4803,8 @@ const getRpcForView = async (viewId, assetDir, platform, applicationId) => {
|
|
|
4695
4803
|
platform: resolvedPlatform
|
|
4696
4804
|
} = await getRuntimeContext(assetDir, platform);
|
|
4697
4805
|
const extension = await getExtensionForView(viewId, resolvedAssetDir, resolvedPlatform, applicationId);
|
|
4698
|
-
const extensionId = getExtensionId$
|
|
4699
|
-
const existingRpc = get$
|
|
4806
|
+
const extensionId = getExtensionId$3(extension);
|
|
4807
|
+
const existingRpc = get$2(extensionId, applicationId);
|
|
4700
4808
|
// Application teardown and reload own application workers; global view-only disposal does not.
|
|
4701
4809
|
if (existingRpc) {
|
|
4702
4810
|
return {
|
|
@@ -5253,13 +5361,13 @@ const getRemoteUrlForWebView = async (uri, options = {}) => {
|
|
|
5253
5361
|
if (!webView) {
|
|
5254
5362
|
throw new Error(`webview ${options.webViewId} not found`);
|
|
5255
5363
|
}
|
|
5256
|
-
const [rpc, blob] = await Promise.all([createWebViewIpc(webView), invoke('FileSystem.getBlob', uri)]);
|
|
5364
|
+
const [rpc, blob] = await Promise.all([createWebViewIpc(webView), invoke$2('FileSystem.getBlob', uri)]);
|
|
5257
5365
|
const objectUrl = await rpc.invoke('createObjectUrl', blob);
|
|
5258
5366
|
return objectUrl;
|
|
5259
5367
|
};
|
|
5260
5368
|
|
|
5261
5369
|
const getRpcInfo = rpcId => {
|
|
5262
|
-
const info = get$
|
|
5370
|
+
const info = get$3(rpcId);
|
|
5263
5371
|
if (!info) {
|
|
5264
5372
|
throw new Error(`Rpc not found ${rpcId}`);
|
|
5265
5373
|
}
|
|
@@ -5280,7 +5388,7 @@ const getIcon = (extension, manifestView, assetDir, platform) => {
|
|
|
5280
5388
|
if (isAbsoluteIcon(manifestIcon) || !isRelativeIconPath(manifestIcon)) {
|
|
5281
5389
|
return manifestIcon;
|
|
5282
5390
|
}
|
|
5283
|
-
return getAbsolutePath({
|
|
5391
|
+
return getAbsolutePath$1({
|
|
5284
5392
|
...extension,
|
|
5285
5393
|
browser: manifestIcon
|
|
5286
5394
|
}, assetDir, platform);
|
|
@@ -5341,7 +5449,7 @@ const waitForTimeout = async (timeout, sleep) => {
|
|
|
5341
5449
|
const isResponsive = async (rpc, timeout, sleep) => {
|
|
5342
5450
|
return Promise.race([invokePing(rpc), waitForTimeout(timeout, sleep)]);
|
|
5343
5451
|
};
|
|
5344
|
-
const updateTerminatedExtensionStatuses = async (runtimeStatuses, getRpc = get$
|
|
5452
|
+
const updateTerminatedExtensionStatuses = async (runtimeStatuses, getRpc = get$2, timeout = 250, sleep$1 = sleep) => {
|
|
5345
5453
|
const activatedStatuses = Object.values(runtimeStatuses).filter(status => status.status === Activated);
|
|
5346
5454
|
await Promise.all(activatedStatuses.map(async status => {
|
|
5347
5455
|
const rpc = getRpc(status.id);
|
|
@@ -5403,7 +5511,7 @@ const getItems = async rpc => {
|
|
|
5403
5511
|
return rpc.invoke('ExtensionApi.getStatusBarItems');
|
|
5404
5512
|
};
|
|
5405
5513
|
const getStatusBarItems = async applicationId => {
|
|
5406
|
-
const rpcs = getAll(applicationId);
|
|
5514
|
+
const rpcs = getAll$1(applicationId);
|
|
5407
5515
|
const results = await Promise.all(rpcs.map(getItems));
|
|
5408
5516
|
return results.flat();
|
|
5409
5517
|
};
|
|
@@ -5413,7 +5521,7 @@ const getCss = (extension, manifestView, assetDir, platform) => {
|
|
|
5413
5521
|
if (typeof css !== 'string' || css.length === 0) {
|
|
5414
5522
|
return '';
|
|
5415
5523
|
}
|
|
5416
|
-
return getAbsolutePath({
|
|
5524
|
+
return getAbsolutePath$1({
|
|
5417
5525
|
...extension,
|
|
5418
5526
|
browser: css
|
|
5419
5527
|
}, assetDir, platform);
|
|
@@ -5428,7 +5536,7 @@ const getIframe = (extension, manifestView, assetDir, platform) => {
|
|
|
5428
5536
|
credentialless: iframe.credentialless !== false,
|
|
5429
5537
|
csp: iframe.csp || '',
|
|
5430
5538
|
sandbox: Array.isArray(iframe.sandbox) ? iframe.sandbox.filter(item => typeof item === 'string') : ['allow-scripts'],
|
|
5431
|
-
src: getAbsolutePath({
|
|
5539
|
+
src: getAbsolutePath$1({
|
|
5432
5540
|
...extension,
|
|
5433
5541
|
browser: iframe.path
|
|
5434
5542
|
}, assetDir, platform)
|
|
@@ -5459,7 +5567,7 @@ const toView = (extension, manifestView, assetDir, platform) => {
|
|
|
5459
5567
|
...(type && {
|
|
5460
5568
|
type
|
|
5461
5569
|
}),
|
|
5462
|
-
extensionId: getExtensionId$
|
|
5570
|
+
extensionId: getExtensionId$3(extension),
|
|
5463
5571
|
icon: getIcon(extension, manifestView, assetDir, platform),
|
|
5464
5572
|
id,
|
|
5465
5573
|
iframe: getIframe(extension, manifestView, assetDir, platform),
|
|
@@ -5489,7 +5597,7 @@ const shouldLoadViews = extension => {
|
|
|
5489
5597
|
return false;
|
|
5490
5598
|
}
|
|
5491
5599
|
if (!isExtensionIsolated(extension)) {
|
|
5492
|
-
warn(`Extension "${getExtensionId$
|
|
5600
|
+
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
5601
|
return false;
|
|
5494
5602
|
}
|
|
5495
5603
|
return true;
|
|
@@ -5512,7 +5620,7 @@ const getViews = async (assetDir, platform) => {
|
|
|
5512
5620
|
const handleData = () => {};
|
|
5513
5621
|
|
|
5514
5622
|
const invokeHandler = async (extensionId, changes, applicationId) => {
|
|
5515
|
-
const rpc = get$
|
|
5623
|
+
const rpc = get$2(extensionId, applicationId);
|
|
5516
5624
|
if (!rpc) {
|
|
5517
5625
|
unregister(extensionId, applicationId);
|
|
5518
5626
|
return;
|
|
@@ -5533,9 +5641,9 @@ const handleMessagePort = async (port, rpcId) => {
|
|
|
5533
5641
|
messagePort: port
|
|
5534
5642
|
});
|
|
5535
5643
|
if (rpcId === StatusBarWorker) {
|
|
5536
|
-
set$
|
|
5644
|
+
set$2(rpc);
|
|
5537
5645
|
} else if (rpcId === NotificationCenterWorker) {
|
|
5538
|
-
set$
|
|
5646
|
+
set$3(rpc);
|
|
5539
5647
|
}
|
|
5540
5648
|
};
|
|
5541
5649
|
|
|
@@ -5626,7 +5734,7 @@ const defaultDependencies$2 = {
|
|
|
5626
5734
|
activateByEvent: activateByEvent,
|
|
5627
5735
|
createViewInstance: createViewInstance,
|
|
5628
5736
|
disposeExtensionRuntime,
|
|
5629
|
-
getRpc: get$
|
|
5737
|
+
getRpc: get$2,
|
|
5630
5738
|
getRuntimeStatus: getRuntimeStatus$1,
|
|
5631
5739
|
getViewEntries: getEntries,
|
|
5632
5740
|
removeViewInstance: remove,
|
|
@@ -5873,7 +5981,7 @@ const replace = async (application, extensionId, extension) => {
|
|
|
5873
5981
|
assertCurrentApplication(application);
|
|
5874
5982
|
const rpc = remove$1(extensionId, applicationId);
|
|
5875
5983
|
unregister(extensionId, applicationId);
|
|
5876
|
-
const results = await Promise.allSettled([disposeExtension(application, extensionId), Promise.try(() => rpc?.dispose()), invoke('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', getRuntimeId(extensionId, application))]);
|
|
5984
|
+
const results = await Promise.allSettled([disposeExtension(application, extensionId), Promise.try(() => rpc?.dispose()), invoke$2('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', getRuntimeId(extensionId, application))]);
|
|
5877
5985
|
assertCurrentApplication(application);
|
|
5878
5986
|
resetExtensionActivation(extensionId, application);
|
|
5879
5987
|
resetExtensionRuntimeState(extensionId, applicationId);
|
|
@@ -5972,10 +6080,10 @@ const invokeForApplication = async (applicationId, method, ...args) => {
|
|
|
5972
6080
|
}
|
|
5973
6081
|
switch (method) {
|
|
5974
6082
|
case 'ExtensionApi.readFile':
|
|
5975
|
-
return invoke('Application.execute', applicationId, 'FileSystem.readFile', ...args);
|
|
6083
|
+
return invoke$2('Application.execute', applicationId, 'FileSystem.readFile', ...args);
|
|
5976
6084
|
case 'ExtensionHostQuickPick.showQuickInput':
|
|
5977
6085
|
case 'ExtensionHostQuickPick.showQuickPick':
|
|
5978
|
-
return invoke('Application.execute', applicationId, method, ...args);
|
|
6086
|
+
return invoke$2('Application.execute', applicationId, method, ...args);
|
|
5979
6087
|
case 'Extensions.activateByEvent':
|
|
5980
6088
|
return activateByEvent(args[0], args[1], args[2] ?? application.platform, application);
|
|
5981
6089
|
case 'Extensions.createWebViewWorkerRpc':
|
|
@@ -6002,7 +6110,7 @@ const invokeForApplication = async (applicationId, method, ...args) => {
|
|
|
6002
6110
|
case 'Extensions.sendMessagePortToFileSystemWorker':
|
|
6003
6111
|
return createFileSystemPort(application, args[0]);
|
|
6004
6112
|
case 'Extensions.showNotification':
|
|
6005
|
-
return invoke('Application.execute', applicationId, 'Notification.create', ...args);
|
|
6113
|
+
return invoke$2('Application.execute', applicationId, 'Notification.create', ...args);
|
|
6006
6114
|
default:
|
|
6007
6115
|
throw new Error(`Extension command does not support application context: ${method}`);
|
|
6008
6116
|
}
|
|
@@ -6029,6 +6137,7 @@ const commandMap = {
|
|
|
6029
6137
|
'Extensions.addWebExtension': addWebExtension,
|
|
6030
6138
|
'Extensions.clearNotifications': clearNotifications,
|
|
6031
6139
|
'Extensions.clearOutputChannel': wrapCommand(clearOutputChannel),
|
|
6140
|
+
'Extensions.connectWorkspaceTerminal': connectTerminal,
|
|
6032
6141
|
'Extensions.createApplication': createApplication,
|
|
6033
6142
|
'Extensions.createViewInstance': createViewInstance,
|
|
6034
6143
|
'Extensions.createWebViewWorkerRpc': createWebViewWorkerRpc,
|
|
@@ -6064,6 +6173,7 @@ const commandMap = {
|
|
|
6064
6173
|
'Extensions.executeResolveCompletionItemProvider': wrapCommand(executeResolveCompletionItemProvider),
|
|
6065
6174
|
'Extensions.executeSignatureHelpProvider': wrapCommand(executeSignatureHelpProvider),
|
|
6066
6175
|
'Extensions.executeSourceControlProvider': wrapCommand(executeSourceControlProvider),
|
|
6176
|
+
'Extensions.executeWorkspaceRequest': request,
|
|
6067
6177
|
'Extensions.getAccessToken': getAccessToken,
|
|
6068
6178
|
'Extensions.getAllExtensions': getAllExtensions,
|
|
6069
6179
|
'Extensions.getColorThemeCss': getColorThemeCss,
|
|
@@ -6089,6 +6199,7 @@ const commandMap = {
|
|
|
6089
6199
|
'Extensions.getViewInstanceState': getViewInstanceState,
|
|
6090
6200
|
'Extensions.getViewMenuEntries': getViewMenuEntries,
|
|
6091
6201
|
'Extensions.getViews': getViews,
|
|
6202
|
+
'Extensions.getWorkspaceTransportUri': getWorkspaceTransportUri,
|
|
6092
6203
|
'Extensions.handleData': handleData,
|
|
6093
6204
|
'Extensions.handleFileChanges': handleFileChanges,
|
|
6094
6205
|
'Extensions.handleLinkedExtensionChange': handleLinkedExtensionChange,
|